[PATCH v4] fuzz: add oss-fuzz build-script
It is neater to keep this in the QEMU repo, since any change that requires an update to the oss-fuzz build configuration, can make the necessary changes in the same series. Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Alexander Bulekov Reviewed-by: Darren Kenny --- v4: adds fatal() for error-handling, as suggested by Darren MAINTAINERS | 1 + scripts/oss-fuzz/build.sh | 105 ++ 2 files changed, 106 insertions(+) create mode 100755 scripts/oss-fuzz/build.sh diff --git a/MAINTAINERS b/MAINTAINERS index 3abe3faa4e..094a37ebb3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2336,6 +2336,7 @@ R: Bandan Das R: Stefan Hajnoczi S: Maintained F: tests/qtest/fuzz/ +F: scripts/oss-fuzz/ Register API M: Alistair Francis diff --git a/scripts/oss-fuzz/build.sh b/scripts/oss-fuzz/build.sh new file mode 100755 index 00..f5cee3d67e --- /dev/null +++ b/scripts/oss-fuzz/build.sh @@ -0,0 +1,105 @@ +#!/bin/sh -e +# +# OSS-Fuzz build script. See: +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh +# +# The file is consumed by: +# https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfiles +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +# build project +# e.g. +# ./autogen.sh +# ./configure +# make -j$(nproc) all + +# build fuzzers +# e.g. +# $CXX $CXXFLAGS -std=c++11 -Iinclude \ +# /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \ +# $LIB_FUZZING_ENGINE /path/to/library.a + +fatal () { +echo "Error : ${*}, exiting." +exit 1 +} + +OSS_FUZZ_BUILD_DIR="./build-oss-fuzz/" + +# There seems to be a bug in clang-11 (used for builds on oss-fuzz) : +# accel/tcg/cputlb.o: In function `load_memop': +# accel/tcg/cputlb.c:1505: undefined reference to `qemu_build_not_reached' +# +# When building with optimization, the compiler is expected to prove that the +# statement cannot be reached, and remove it. For some reason clang-11 doesn't +# remove it, resulting in an unresolved reference to qemu_build_not_reached +# Undefine the __OPTIMIZE__ macro which compiler.h relies on to choose whether +# to " #define qemu_build_not_reached() g_assert_not_reached() " +EXTRA_CFLAGS="$CFLAGS -U __OPTIMIZE__" + +if ! { [ -e "./COPYING" ] && + [ -e "./MAINTAINERS" ] && + [ -e "./Makefile" ] && + [ -e "./docs" ] && + [ -e "./VERSION" ] && + [ -e "./linux-user" ] && + [ -e "./softmmu" ];} ; then +fatal "Please run the script from the top of the QEMU tree" +fi + +mkdir -p $OSS_FUZZ_BUILD_DIR || fatal "mkdir $OSS_FUZZ_BUILD_DIR failed" +cd $OSS_FUZZ_BUILD_DIR || fatal "cd $OSS_FUZZ_BUILD_DIR failed" + + +if [ -z ${LIB_FUZZING_ENGINE+x} ]; then +LIB_FUZZING_ENGINE="-fsanitize=fuzzer" +fi + +if [ -z ${OUT+x} ]; then +DEST_DIR=$(realpath "./DEST_DIR") +else +DEST_DIR=$OUT +fi + +mkdir -p "$DEST_DIR/lib/" # Copy the shared libraries here + +# Build once to get the list of dynamic lib paths, and copy them over +../configure --disable-werror --cc="$CC" --cxx="$CXX" \ +--extra-cflags="$EXTRA_CFLAGS" + +if ! make CONFIG_FUZZ=y CFLAGS="$LIB_FUZZING_ENGINE" "-j$(nproc)" \ +i386-softmmu/fuzz; then +fatal "Build failed. Please specify a compiler with fuzzing support"\ + "using the \$CC and \$CXX environemnt variables, or specify a"\ + "\$LIB_FUZZING_ENGINE compatible with your compiler"\ + "\nFor example: CC=clang CXX=clang++ $0" +fi + +for i in $(ldd ./i386-softmmu/qemu-fuzz-i386 | cut -f3 -d' '); do +cp "$i" "$DEST_DIR/lib/" +done +rm ./i386-softmmu/qemu-fuzz-i386 + +# Build a second time to build the final binary with correct rpath +../configure --bindir="$DEST_DIR" --datadir="$DEST_DIR/data/" --disable-werror \ +--cc="$CC" --cxx="$CXX" --extra-cflags="$EXTRA_CFLAGS" \ +--extra-ldflags="-Wl,-rpath,'\$\$ORIGIN/lib'" +make CONFIG_FUZZ=y CFLAGS="$LIB_FUZZING_ENGINE" "-j$(nproc)" i386-softmmu/fuzz + +# Copy over the datadir +cp -r ../pc-bios/ "$DEST_DIR/pc-bios" + +# Run the fuzzer with no arguments, to print the help-string and get the list +# of available fuzz-targets. Copy over the qemu-fuzz-i386, naming it according +# to each available fuzz target (See 05509c8e6d fuzz: select fuzz target using +# executable name) +for target in $(./i386-softmmu/qemu-fuzz-i386 | awk '$1 ~ /\*/ {print $2}'); +do +cp ./i386-softmmu/qemu-fuzz-i386 "$DEST_DIR/qemu-fuzz-i386-target-$target" +done + +echo "Done. The fuzzers are located in $DEST_DIR" +exit 0 -- 2.26.2
[Bug 1882851] Re: QEMU video freezes with "Guest disabled display" (virtio driver)
** Attachment added: "bisectlog.txt" https://bugs.launchpad.net/qemu/+bug/1882851/+attachment/5383160/+files/bisectlog.txt -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1882851 Title: QEMU video freezes with "Guest disabled display" (virtio driver) Status in QEMU: New Bug description: I am using Arch Linux as my Guest and Host OS, after starting qemu with the following command: $ qemu-system-x86_64 -enable-kvm -hda arch-zoom.qcow2 -m 4G -vga virtio and waiting for a screen blank, I get this message: Guest disabled display And nothing happens after that, I can move the mouse or hit any key, and the message is still there. I can still reboot the VM but that's not optimal. I can reproduce this with the latest QEMU release (5.0.0) or git master, I also tried this with older releases (4.0.0, 3.0.0) and the issue is still there. I can't reproduce this with other video drivers (std, qxl). With std/qxl the screen will blank a bit and then continue as normal. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1882851/+subscriptions
[Bug 1882851] Re: QEMU video freezes with "Guest disabled display" (virtio driver)
OK, I was able to bisect, here is the result: [diego@arch-zoom linux]$ git bisect bad 3954ff10e06e4fbc548fc02ff1fcaaac3228fed5 is the first bad commit commit 3954ff10e06e4fbc548fc02ff1fcaaac3228fed5 Author: Gerd Hoffmann Date: Thu Dec 12 13:53:44 2019 +0100 drm/virtio: skip set_scanout if framebuffer didn't change v2: also check src rect (Chia-I Wu). Signed-off-by: Gerd Hoffmann Reviewed-by: Chia-I Wu Link: http://patchwork.freedesktop.org/patch/msgid/20191212125346.8334-2-kra...@redhat.com drivers/gpu/drm/virtio/virtgpu_plane.c | 35 -- 1 file changed, 21 insertions(+), 14 deletions(-) [diego@arch-zoom linux]$ -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1882851 Title: QEMU video freezes with "Guest disabled display" (virtio driver) Status in QEMU: New Bug description: I am using Arch Linux as my Guest and Host OS, after starting qemu with the following command: $ qemu-system-x86_64 -enable-kvm -hda arch-zoom.qcow2 -m 4G -vga virtio and waiting for a screen blank, I get this message: Guest disabled display And nothing happens after that, I can move the mouse or hit any key, and the message is still there. I can still reboot the VM but that's not optimal. I can reproduce this with the latest QEMU release (5.0.0) or git master, I also tried this with older releases (4.0.0, 3.0.0) and the issue is still there. I can't reproduce this with other video drivers (std, qxl). With std/qxl the screen will blank a bit and then continue as normal. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1882851/+subscriptions
Re: [PATCH 0/5] linux-user: Support extended clone(CLONE_VM)
Patchew URL: https://patchew.org/QEMU/20200612014606.147691-1-...@google.com/ Hi, This series failed the docker-quick@centos7 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #!/bin/bash make docker-image-centos7 V=1 NETWORK=1 time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 === TEST SCRIPT END === +++ /tmp/qemu-test/build/tests/qemu-iotests/041.out.bad 2020-06-12 03:41:14.015076859 + @@ -1,5 +1,30 @@ - +WARNING:qemu.machine:qemu received signal 9: /tmp/qemu-test/build/tests/qemu-iotests/../../x86_64-softmmu/qemu-system-x86_64 -display none -vga none -chardev socket,id=mon,path=/tmp/tmp.YHsXXgjzyL/qemu-22509-monitor.sock -mon chardev=mon,mode=control -qtest unix:path=/tmp/tmp.YHsXXgjzyL/qemu-22509-qtest.sock -accel qtest -nodefaults -display none -accel qtest -drive if=virtio,id=drive0,file=/tmp/qemu-test/test.img,format=qcow2,cache=writeback,aio=threads,node-name=top,backing.node-name=base -drive if=ide,id=drive1,media=cdrom +..E. +== +ERROR: test_pause (__main__.TestSingleBlockdev) +-- +Traceback (most recent call last): + File "041", line 108, in test_pause --- Ran 104 tests -OK +FAILED (errors=1) TESTiotest-qcow2: 042 TESTiotest-qcow2: 043 TESTiotest-qcow2: 046 --- Not run: 259 Failures: 041 Failed 1 of 119 iotests make: *** [check-tests/check-block.sh] Error 1 Traceback (most recent call last): File "./tests/docker/docker.py", line 665, in sys.exit(main()) --- raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=0b953bb4c5534a2f9f54bbb077c4a060', '-u', '1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-fy1xwr_z/src/docker-src.2020-06-11-23.31.14.29203:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2. filter=--filter=label=com.qemu.instance.uuid=0b953bb4c5534a2f9f54bbb077c4a060 make[1]: *** [docker-run] Error 1 make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-fy1xwr_z/src' make: *** [docker-run-test-quick@centos7] Error 2 real17m15.344s user0m8.554s The full log is available at http://patchew.org/logs/20200612014606.147691-1-...@google.com/testing.docker-quick@centos7/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [PATCH 9/9] migration/ram: calculate un/encoded_size only whenneeded.
On 6/12/20 3:05 AM, Dr. David Alan Gilbert wrote: * Mao Zhongyi (maozhon...@cmss.chinamobile.com) wrote: Signed-off-by: Mao Zhongyi --- migration/ram.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 41cc530d9d..ca20030b64 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -910,14 +910,15 @@ static void migration_update_rates(RAMState *rs, int64_t end_time) xbzrle_counters.cache_miss_rate = (double)(xbzrle_counters.cache_miss - rs->xbzrle_cache_miss_prev) / page_count; rs->xbzrle_cache_miss_prev = xbzrle_counters.cache_miss; -encoded_size = (xbzrle_counters.pages - rs->xbzrle_pages_prev) * - TARGET_PAGE_SIZE; -encoded_size = xbzrle_counters.bytes - rs->xbzrle_bytes_prev; if (xbzrle_counters.pages == rs->xbzrle_pages_prev) { xbzrle_counters.encoding_rate = 0; -} else if (!encoded_size) { +} else if (xbzrle_counters.bytes == rs->xbzrle_bytes_prev) { No, I don't think this change is worth it - this is really just the same as 'encoded_size', and then we may as well keep the two together. ok, thanks, let's keep 'encode_size' here. BTW, this change borrows from the behavior of comppressed: ... compressed_size = compression_counters.compressed_size - rs->compressed_size_prev; if (compressed_size) { double uncompressed_size = (compression_counters.pages - rs->compress_pages_prev) * TARGET_PAGE_SIZE; /* Compression-Ratio = Uncompressed-size / Compressed-size */ compression_counters.compression_rate = uncompressed_size / compressed_size; ... It splits 'compressed_size' and 'uncompressed_size', and calculates 'uncompressed_size' only when needed. Although 'unencoded_size' is calculated, it is not necessarily used. if you think this split is unnecessary, just discard it, so do I need to drop this patch and resend the v2? Thanks, Mao Dave xbzrle_counters.encoding_rate = UINT64_MAX; } else { +unencoded_size = (xbzrle_counters.pages - rs->xbzrle_pages_prev) * + TARGET_PAGE_SIZE; +encoded_size = xbzrle_counters.bytes - rs->xbzrle_bytes_prev; + xbzrle_counters.encoding_rate = unencoded_size / encoded_size; } rs->xbzrle_pages_prev = xbzrle_counters.pages; -- 2.17.1 -- Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK
RE: [PATCH] kvm: support to get/set dirty log initial-all-set capability
> -Original Message- > From: Paolo Bonzini [mailto:pbonz...@redhat.com] > Sent: Wednesday, March 18, 2020 6:48 PM > To: Zhoujian (jay) ; qemu-devel@nongnu.org; > k...@vger.kernel.org > Cc: m...@redhat.com; coh...@redhat.com; pet...@redhat.com; wangxin (U) > ; Huangweidong (C) > ; Liujinsong (Paul) > Subject: Re: [PATCH] kvm: support to get/set dirty log initial-all-set > capability > > On 04/03/20 03:55, Jay Zhou wrote: > > Since the new capability KVM_DIRTY_LOG_INITIALLY_SET of > > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 has been introduced in the kernel, > > tweak the userspace side to detect and enable this capability. > > > > Signed-off-by: Jay Zhou > > --- > > accel/kvm/kvm-all.c | 21 ++--- > > linux-headers/linux/kvm.h | 3 +++ > > 2 files changed, 17 insertions(+), 7 deletions(-) > > > > diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index > > 439a4efe52..45ab25be63 100644 > > --- a/accel/kvm/kvm-all.c > > +++ b/accel/kvm/kvm-all.c > > @@ -100,7 +100,7 @@ struct KVMState > > bool kernel_irqchip_required; > > OnOffAuto kernel_irqchip_split; > > bool sync_mmu; > > -bool manual_dirty_log_protect; > > +uint64_t manual_dirty_log_protect; > > /* The man page (and posix) say ioctl numbers are signed int, but > > * they're not. Linux, glibc and *BSD all treat ioctl numbers as > > * unsigned, and treating them as signed here can break things */ > > @@ -1882,6 +1882,7 @@ static int kvm_init(MachineState *ms) > > int ret; > > int type = 0; > > const char *kvm_type; > > +uint64_t dirty_log_manual_caps; > > > > s = KVM_STATE(ms->accelerator); > > > > @@ -2007,14 +2008,20 @@ static int kvm_init(MachineState *ms) > > s->coalesced_pio = s->coalesced_mmio && > > kvm_check_extension(s, > KVM_CAP_COALESCED_PIO); > > > > -s->manual_dirty_log_protect = > > +dirty_log_manual_caps = > > kvm_check_extension(s, > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2); > > -if (s->manual_dirty_log_protect) { > > -ret = kvm_vm_enable_cap(s, > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1); > > +dirty_log_manual_caps &= > (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | > > + KVM_DIRTY_LOG_INITIALLY_SET); > > +s->manual_dirty_log_protect = dirty_log_manual_caps; > > +if (dirty_log_manual_caps) { > > +ret = kvm_vm_enable_cap(s, > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, > > + dirty_log_manual_caps); > > if (ret) { > > -warn_report("Trying to enable > KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 " > > -"but failed. Falling back to the legacy mode. "); > > -s->manual_dirty_log_protect = false; > > +warn_report("Trying to enable capability %"PRIu64" of " > > +"KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 > but failed. " > > +"Falling back to the legacy mode. ", > > +dirty_log_manual_caps); > > +s->manual_dirty_log_protect = 0; > > } > > } > > > > diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h > > index 265099100e..3cb71c2b19 100644 > > --- a/linux-headers/linux/kvm.h > > +++ b/linux-headers/linux/kvm.h > > @@ -1628,4 +1628,7 @@ struct kvm_hyperv_eventfd { > > #define KVM_HYPERV_CONN_ID_MASK0x00ff > > #define KVM_HYPERV_EVENTFD_DEASSIGN(1 << 0) > > > > +#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE(1 << 0) > > +#define KVM_DIRTY_LOG_INITIALLY_SET(1 << 1) > > + > > #endif /* __LINUX_KVM_H */ > > > > Queued, thanks. > Hi Paolo, It seems that this patch isn't included in your last pull request... If there's something else to be done, please let me know. Regards, Jay Zhou
[PATCH 5/6] audio/jack: honour the enable state of the audio device
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 29 + 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 249cbd3265..b2b53985ae 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -56,7 +56,7 @@ typedef struct QJackClient { AudiodevJackPerDirectionOptions *opt; bool out; -bool finished; +bool enabled; bool connect_ports; int packets; @@ -271,9 +271,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg) } if (c->out) { -qjack_buffer_read_l(>fifo, buffers, nframes); +if (likely(c->enabled)) { +qjack_buffer_read_l(>fifo, buffers, nframes); +} else { +for(int i = 0; i < c->nchannels; ++i) { +memset(buffers[i], 0, nframes * sizeof(float)); +} +} } else { -qjack_buffer_write_l(>fifo, buffers, nframes); +if (likely(c->enabled)) { +qjack_buffer_write_l(>fifo, buffers, nframes); +} } return 0; @@ -314,8 +322,8 @@ static void qjack_client_recover(QJackClient *c) if (c->state == QJACK_STATE_DISCONNECTED && c->packets % 100 == 0) { -/* if not finished then attempt to recover */ -if (!c->finished) { +/* if enabled then attempt to recover */ +if (c->enabled) { dolog("attempting to reconnect to server\n"); qjack_client_init(c); } @@ -387,7 +395,6 @@ static int qjack_client_init(QJackClient *c) char client_name[jack_client_name_size()]; jack_options_t options = JackNullOption; -c->finished = false; c->connect_ports = true; snprintf(client_name, sizeof(client_name), "%s-%s", @@ -483,8 +490,10 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, } jo->c.out = true; +jo->c.enabled = false; jo->c.nchannels = as->nchannels; jo->c.opt = dev->u.jack.out; + int ret = qjack_client_init(>c); if (ret != 0) { return ret; @@ -519,8 +528,10 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, } ji->c.out = false; +ji->c.enabled = false; ji->c.nchannels = as->nchannels; ji->c.opt = dev->u.jack.in; + int ret = qjack_client_init(>c); if (ret != 0) { return ret; @@ -568,23 +579,25 @@ static void qjack_client_fini(QJackClient *c) static void qjack_fini_out(HWVoiceOut *hw) { QJackOut *jo = (QJackOut *)hw; -jo->c.finished = true; qjack_client_fini(>c); } static void qjack_fini_in(HWVoiceIn *hw) { QJackIn *ji = (QJackIn *)hw; -ji->c.finished = true; qjack_client_fini(>c); } static void qjack_enable_out(HWVoiceOut *hw, bool enable) { +QJackOut *jo = (QJackOut *)hw; +jo->c.enabled = enable; } static void qjack_enable_in(HWVoiceIn *hw, bool enable) { +QJackIn *ji = (QJackIn *)hw; +ji->c.enabled = enable; } static int qjack_thread_creator(jack_native_thread_t *thread, -- 2.20.1
[PATCH 6/6] audio/jack: simplify the re-init code path
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index b2b53985ae..72ed7c4929 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -395,6 +395,10 @@ static int qjack_client_init(QJackClient *c) char client_name[jack_client_name_size()]; jack_options_t options = JackNullOption; +if (c->state == QJACK_STATE_RUNNING) { +return 0; +} + c->connect_ports = true; snprintf(client_name, sizeof(client_name), "%s-%s", @@ -485,9 +489,7 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, QJackOut *jo = (QJackOut *)hw; Audiodev *dev = (Audiodev *)drv_opaque; -if (jo->c.state != QJACK_STATE_DISCONNECTED) { -return 0; -} +qjack_client_fini(>c); jo->c.out = true; jo->c.enabled = false; @@ -523,9 +525,7 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, QJackIn *ji = (QJackIn *)hw; Audiodev *dev = (Audiodev *)drv_opaque; -if (ji->c.state != QJACK_STATE_DISCONNECTED) { -return 0; -} +qjack_client_fini(>c); ji->c.out = false; ji->c.enabled = false; -- 2.20.1
[PATCH 4/6] audio/jack: do not remove ports when finishing
This fixes a hang when there is a communications issue with the JACK server. Simply closing the connection is enough to completely clean up and as such we do not need to remove the ports first. Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 58c7344497..249cbd3265 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -548,9 +548,6 @@ static void qjack_client_fini(QJackClient *c) { switch (c->state) { case QJACK_STATE_RUNNING: -for (int i = 0; i < c->nchannels; ++i) { -jack_port_unregister(c->client, c->port[i]); -} jack_deactivate(c->client); /* fallthrough */ -- 2.20.1
[PATCH 3/6] audio/jack: remove invalid set of input support bool
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index fb8efd7af7..58c7344497 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -607,9 +607,6 @@ static int qjack_thread_creator(jack_native_thread_t *thread, static void *qjack_init(Audiodev *dev) { assert(dev->driver == AUDIODEV_DRIVER_JACK); - -dev->u.jack.has_in = false; - return dev; } -- 2.20.1
[PATCH 2/6] audio/jack: remove unused stopped state
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 4 1 file changed, 4 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index d0b6f748f2..fb8efd7af7 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -38,7 +38,6 @@ struct QJack; typedef enum QJackState { QJACK_STATE_DISCONNECTED, -QJACK_STATE_STOPPED, QJACK_STATE_RUNNING, QJACK_STATE_SHUTDOWN } @@ -549,9 +548,6 @@ static void qjack_client_fini(QJackClient *c) { switch (c->state) { case QJACK_STATE_RUNNING: -/* fallthrough */ - -case QJACK_STATE_STOPPED: for (int i = 0; i < c->nchannels; ++i) { jack_port_unregister(c->client, c->port[i]); } -- 2.20.1
[PATCH 0/6] audio/jack: fixes to overall jack behaviour
Sorry for the spam, resubmitted due to missing subject on this cover letter. Seems patchew.org can't find the associated patches without it. This patch set addresses several issues that cause inconsistent behaviour in the guest when the sound device is stopped and started or the JACK server stops responding on the host. Geoffrey McRae (6): audio/jack: fix invalid minimum buffer size check audio/jack: remove unused stopped state audio/jack: remove invalid set of input support bool audio/jack: do not remove ports when finishing audio/jack: honour the enable state of the audio device audio/jack: simplify the re-init code path audio/jackaudio.c | 73 --- 1 file changed, 38 insertions(+), 35 deletions(-) -- 2.20.1
[PATCH 1/6] audio/jack: fix invalid minimum buffer size check
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 722ddb1dfe..d0b6f748f2 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -434,17 +434,6 @@ static int qjack_client_init(QJackClient *c) jack_set_xrun_callback(c->client, qjack_xrun, c); jack_on_shutdown(c->client, qjack_shutdown, c); -/* - * ensure the buffersize is no smaller then 512 samples, some (all?) qemu - * virtual devices do not work correctly otherwise - */ -if (c->buffersize < 512) { -c->buffersize = 512; -} - -/* create a 2 period buffer */ -qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2); - /* allocate and register the ports */ c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels); for (int i = 0; i < c->nchannels; ++i) { @@ -468,6 +457,17 @@ static int qjack_client_init(QJackClient *c) jack_activate(c->client); c->buffersize = jack_get_buffer_size(c->client); +/* + * ensure the buffersize is no smaller then 512 samples, some (all?) qemu + * virtual devices do not work correctly otherwise + */ +if (c->buffersize < 512) { +c->buffersize = 512; +} + +/* create a 2 period buffer */ +qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2); + qjack_client_connect_ports(c); c->state = QJACK_STATE_RUNNING; return 0; -- 2.20.1
Re: [PULL 000/115] Huge miscellaneous pull request for 2020-06-11
Patchew URL: https://patchew.org/QEMU/20200611194449.31468-1-pbonz...@redhat.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20200611194449.31468-1-pbonz...@redhat.com Subject: [PULL 000/115] Huge miscellaneous pull request for 2020-06-11 Type: series === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu * [new tag] patchew/20200612014606.147691-1-...@google.com -> patchew/20200612014606.147691-1-...@google.com Switched to a new branch 'test' b258374 target/i386: Remove obsolete TODO file ed8ffec stubs: move Xen stubs to accel/ 9da3214 replay: fix replay shutdown for console mode 8cf1910 exec/cpu-common: Move MUSB specific typedefs to 'hw/usb/hcd-musb.h' b4bf922 hw/usb: Move device-specific declarations to new 'hcd-musb.h' header 5988475 exec/memory: Remove unused MemoryRegionMmio type 79d4c74 checkpatch: reversed logic with acpi test checks 11943a6 target/i386: sev: Unify SEVState and SevGuestState 722d1df target/i386: sev: Remove redundant handle field ef7e4eb target/i386: sev: Remove redundant policy field c0fa653 target/i386: sev: Remove redundant cbitpos and reduced_phys_bits fields 832d459 target/i386: sev: Partial cleanup to sev_state global 560d42b target/i386: sev: Embed SEVState in SevGuestState 56fe4d8 target/i386: sev: Rename QSevGuestInfo 4902392 target/i386: sev: Move local structure definitions into .c file b8dc835 target/i386: sev: Remove unused QSevGuestInfoClass 5ec6d66 xen: fix build without pci passthrough 93262a0 i386: hvf: Drop HVFX86EmulatorState b52a4bf i386: hvf: Move mmio_buf into CPUX86State 20208b4 i386: hvf: Move lazy_flags into CPUX86State df05641 i386: hvf: Drop regs in HVFX86EmulatorState e978983 i386: hvf: Drop copy of RFLAGS defines 0141723 i386: hvf: Drop rflags from HVFX86EmulatorState e1de961 i386: hvf: Drop fetch_rip from HVFX86EmulatorState ed88ce7 i386: hvf: Use IP from CPUX86State ddb005d i386: hvf: Use ins_len to advance IP c4d282b i386: hvf: Drop unused variable b587a1b i386: hvf: Drop useless declarations in sysemu 7e1a493 i386: hvf: Move HVFState definition into hvf 709b437 target/ppc: Restrict PPCVirtualHypervisorClass to system-mode 238000a sysemu/hvf: Only declare hvf_allowed when HVF is available 3b8e276 sysemu/tcg: Only declare tcg_allowed when TCG is available acb8d15 sysemu/accel: Restrict machine methods to system-mode f9bd95e target/i386: correct fix for pcmpxstrx substring search 136df11 target/i386: fix IEEE x87 floating-point exception raising f843bd2 exec: set map length to zero when returning NULL 3bd81db configure: Do not ignore malloc value 98e8ed2 qemu/thread: Mark qemu_thread_exit() with 'noreturn' attribute 3f5bb0f memory: Make 'info mtree' not display disabled regions by default a3aaf5e util/oslib: Returns the real thread identifier on FreeBSD and NetBSD 6aa0a68 target/i386: define a new MSR based feature word - FEAT_PERF_CAPABILITIES f21430a i386: Remove unused define's from hax and hvf c130d2b replay: implement fair mutex 06644d9 hw/i386/amd_iommu: Fix the reserved bits definition of IOMMU commands 0abe63e tests: machine-none-test: Enable MicroBlaze testing 85f319e chardev/char-socket: Properly make qio connections non blocking d0110c6 KVM: Kick resamplefd for split kernel irqchip 1ead965 KVM: Pass EventNotifier into kvm_irqchip_assign_irqfd 2b7dab6 vfio/pci: Use kvm_irqchip_add_irqfd_notifier_gsi() for irqfds dd32581 x86/cpu: Enable AVX512_VP2INTERSECT cpu feature 7ee3b5d hw/i386/vmport: Allow QTest use without crashing c79f240 target/i386: fix fisttpl, fisttpll handling of out-of-range values 7e360a8 target/i386: fix fbstp handling of out-of-range values 9f11ae8 target/i386: fix fbstp handling of negative zero 59ce66a target/i386: fix fxam handling of invalid encodings 68d8ffc target/i386: fix floating-point load-constant rounding 8d4006e hw/elf_ops: Do not ignore write failures when loading ELF 3a3c475 disas: Let disas::read_memory() handler return EIO on error 6bfda5f exec: Propagate cpu_memory_rw_debug() error 63d6911 exec: Let address_space_read/write_cached() propagate MemTxResult 85733ec target/i386: fix fscale handling of rounding precision 22d5344 target/i386: fix fscale handling of infinite exponents d9e4f5b target/i386: fix fscale handling of invalid exponent encodings 23a2034 target/i386: fix fscale handling of signaling NaN e197304 target/i386: implement special cases for fxtract 3aed295 megasas: use unsigned type for positive numeric fields ca61e75 megasas: avoid NULL pointer dereference dc1d959 megasas: use unsigned type for reply_queue_head and check index 7af8d9c i386/kvm: fix a use-after-free when vcpu plug/unplug e79558f hax: Dynamic
[PATCH 5/5] linux-user: Add PDEATHSIG test for clone process hierarchy.
Certain process-level linux features like subreapers, and PDEATHSIG, depend on the guest's process hierarchy being emulated correctly on the host. This change adds a test that makes sure PDEATHSIG works for a guest process created with `clone`. Signed-off-by: Josh Kunz --- tests/tcg/multiarch/Makefile.target | 3 + tests/tcg/multiarch/linux-test.c| 160 ++-- 2 files changed, 153 insertions(+), 10 deletions(-) diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index cb49cc9ccb..d937b4c59b 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -60,3 +60,6 @@ endif # Update TESTS TESTS += $(MULTIARCH_TESTS) + +# linux-test.c depends on -pthread. +LDFLAGS += -pthread diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c index a7723556c2..1824a5a0c2 100644 --- a/tests/tcg/multiarch/linux-test.c +++ b/tests/tcg/multiarch/linux-test.c @@ -20,16 +20,19 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -41,6 +44,7 @@ #include #include #include +#include #define STACK_SIZE 16384 @@ -368,14 +372,12 @@ static void test_pipe(void) chk_error(close(fds[1])); } -static int thread1_res; -static int thread2_res; - static int thread1_func(void *arg) { +int *res = (int *) arg; int i; for(i=0;i<5;i++) { -thread1_res++; +(*res)++; usleep(10 * 1000); } return 0; @@ -383,9 +385,10 @@ static int thread1_func(void *arg) static int thread2_func(void *arg) { +int *res = (int *) arg; int i; for(i=0;i<6;i++) { -thread2_res++; +(*res)++; usleep(10 * 1000); } return 0; @@ -405,25 +408,27 @@ static void test_clone(void) uint8_t *stack1, *stack2; pid_t pid1, pid2; +int t1 = 0, t2 = 0; + stack1 = malloc(STACK_SIZE); pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE, CLONE_VM | SIGCHLD, -"hello1")); +)); stack2 = malloc(STACK_SIZE); pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | SIGCHLD, - "hello2")); + )); wait_for_child(pid1); free(stack1); wait_for_child(pid2); free(stack2); -if (thread1_res != 5 || -thread2_res != 6) +if (t1 != 5 || t2 != 6) { error("clone"); +} } /***/ @@ -562,6 +567,7 @@ static void test_clone_signal_count(void) * SIGCHLD. */ chk_error(waitpid(pid, , __WCLONE)); +free(child_stack); chk_error(sigaction(SIGRTMIN, , NULL)); @@ -571,6 +577,139 @@ static void test_clone_signal_count(void) } } +struct test_clone_pdeathsig_info { +uint8_t *child_stack; +pthread_mutex_t notify_test_mutex; +pthread_cond_t notify_test_cond; +pthread_mutex_t notify_parent_mutex; +pthread_cond_t notify_parent_cond; +bool signal_received; +}; + +static int test_clone_pdeathsig_child(void *arg) +{ +struct test_clone_pdeathsig_info *info = +(struct test_clone_pdeathsig_info *) arg; +sigset_t wait_on, block_all; +siginfo_t sinfo; +struct timespec timeout; +int ret; + +/* Block all signals, so SIGUSR1 will be pending when we wait on it. */ +sigfillset(_all); +chk_error(sigprocmask(SIG_BLOCK, _all, NULL)); + +chk_error(prctl(PR_SET_PDEATHSIG, SIGUSR1)); + +pthread_mutex_lock(>notify_parent_mutex); +pthread_cond_broadcast(>notify_parent_cond); +pthread_mutex_unlock(>notify_parent_mutex); + +sigemptyset(_on); +sigaddset(_on, SIGUSR1); +timeout.tv_sec = 0; +timeout.tv_nsec = 300 * 1000 * 1000; /* 300ms */ + +ret = sigtimedwait(_on, , ); + +if (ret < 0 && errno != EAGAIN) { +error("%m (ret=%d, errno=%d/%s)", ret, errno, strerror(errno)); +} +if (ret == SIGUSR1) { +info->signal_received = true; +} +pthread_mutex_lock(>notify_test_mutex); +pthread_cond_broadcast(>notify_test_cond); +pthread_mutex_unlock(>notify_test_mutex); +_exit(0); +} + +static int test_clone_pdeathsig_parent(void *arg) +{ +struct test_clone_pdeathsig_info *info = +(struct test_clone_pdeathsig_info *) arg; + +pthread_mutex_lock(>notify_parent_mutex); + +chk_error(clone( +test_clone_pdeathsig_child, +info->child_stack + STACK_SIZE, +CLONE_VM, +info +)); + +/* No need to reap the child, it will get reaped by init. */ + +/* Wait for the child to signal that they have set up PDEATHSIG. */ +
[PATCH 2/5] linux-user: Make fd_trans task-specific.
The file-descriptor translation subsystem used by QEMU uses some global variables to track file descriptors an their associated state. In the future (when clone is implemented) it may be possible to have two processes that share memory, but have a unique set of file descriptors. This change associates the file-descriptor translation table with the per-task TaskState structure. Since many tasks will share file descriptors (e.g., threads), a structure similar to the existing structure is used. Each task has a pointer to a global table. That table can be shared by multiple tasks, or changed if a task needs to use a different FD table. Signed-off-by: Josh Kunz --- linux-user/Makefile.objs | 2 +- linux-user/fd-trans-tbl.c | 13 +++ linux-user/fd-trans-type.h | 17 + linux-user/fd-trans.c | 3 -- linux-user/fd-trans.h | 75 -- linux-user/main.c | 1 + linux-user/qemu.h | 24 linux-user/syscall.c | 12 ++ 8 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 linux-user/fd-trans-tbl.c create mode 100644 linux-user/fd-trans-type.h diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index d6788f012c..d19102e244 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -1,7 +1,7 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \ elfload.o linuxload.o uaccess.o uname.o \ safe-syscall.o $(TARGET_ABI_DIR)/signal.o \ -$(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o clone.o +$(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o clone.o fd-trans-tbl.o obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o diff --git a/linux-user/fd-trans-tbl.c b/linux-user/fd-trans-tbl.c new file mode 100644 index 00..6afe91096e --- /dev/null +++ b/linux-user/fd-trans-tbl.c @@ -0,0 +1,13 @@ +#include "qemu/osdep.h" +#include "fd-trans.h" + +struct fd_trans_table *fd_trans_table_clone(struct fd_trans_table *tbl) +{ +struct fd_trans_table *new_tbl = g_new0(struct fd_trans_table, 1); +new_tbl->fd_max = tbl->fd_max; +new_tbl->entries = g_new0(TargetFdTrans*, tbl->fd_max); +memcpy(new_tbl->entries, + tbl->entries, + sizeof(*new_tbl->entries) * tbl->fd_max); +return new_tbl; +} diff --git a/linux-user/fd-trans-type.h b/linux-user/fd-trans-type.h new file mode 100644 index 00..06c4427642 --- /dev/null +++ b/linux-user/fd-trans-type.h @@ -0,0 +1,17 @@ +#ifndef FD_TRANS_TYPE_H +#define FD_TRANS_TYPE_H + +/* + * Break out the TargetFdTrans typedefs into a separate file, to break + * the circular dependency between qemu.h and fd-trans.h. + */ + +typedef abi_long (*TargetFdDataFunc)(void *, size_t); +typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t); +typedef struct TargetFdTrans { +TargetFdDataFunc host_to_target_data; +TargetFdDataFunc target_to_host_data; +TargetFdAddrFunc target_to_host_addr; +} TargetFdTrans; + +#endif /* FD_TRANS_TYPE_H */ diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index c0687c52e6..c552034a5e 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -261,9 +261,6 @@ enum { QEMU___RTA_MAX }; -TargetFdTrans **target_fd_trans; -unsigned int target_fd_max; - static void tswap_nlmsghdr(struct nlmsghdr *nlh) { nlh->nlmsg_len = tswap32(nlh->nlmsg_len); diff --git a/linux-user/fd-trans.h b/linux-user/fd-trans.h index a3fcdaabc7..07ae04dad7 100644 --- a/linux-user/fd-trans.h +++ b/linux-user/fd-trans.h @@ -16,38 +16,45 @@ #ifndef FD_TRANS_H #define FD_TRANS_H -typedef abi_long (*TargetFdDataFunc)(void *, size_t); -typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t); -typedef struct TargetFdTrans { -TargetFdDataFunc host_to_target_data; -TargetFdDataFunc target_to_host_data; -TargetFdAddrFunc target_to_host_addr; -} TargetFdTrans; +#include "qemu.h" +#include "fd-trans-type.h" -extern TargetFdTrans **target_fd_trans; - -extern unsigned int target_fd_max; +/* + * Return a duplicate of the given fd_trans_table. This function always + * succeeds. Ownership of the pointed-to table is yielded to the caller. The + * caller is responsible for freeing the table when it is no longer in-use. + */ +struct fd_trans_table *fd_trans_table_clone(struct fd_trans_table *tbl); static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd) { -if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) { -return target_fd_trans[fd]->target_to_host_data; +TaskState *ts = (TaskState *)thread_cpu->opaque; +struct fd_trans_table *tbl = ts->fd_trans_tbl; + +if (fd >= 0 && fd < tbl->fd_max && tbl->entries[fd]) { +return tbl->entries[fd]->target_to_host_data; } return NULL; } static inline TargetFdDataFunc fd_trans_host_to_target_data(int fd) { -if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) { -return
[PATCH 4/5] linux-user: Support CLONE_VM and extended clone options
The `clone` system call can be used to create new processes that share attributes with their parents, such as virtual memory, file system location, file descriptor tables, etc. These can be useful to a variety of guest programs. Before this patch, QEMU had support for a limited set of these attributes. Basically the ones needed for threads, and the options used by fork. This change adds support for all flag combinations involving CLONE_VM. In theory, almost all clone options could be supported, but invocations not using CLONE_VM are likely to run afoul of linux-user's inherently multi-threaded design. To add this support, this patch updates the `qemu_clone` helper. An overview of the mechanism used to support general `clone` options with CLONE_VM is described below. This patch also enables by-default the `clone` unit-tests in tests/tcg/multiarch/linux-test.c, and adds an additional test for duplicate exit signals, based on a bug found during development. !! Overview Adding support for CLONE_VM is tricky. The parent and guest process will share an address space (similar to threads), so the emulator must coordinate between the parent and the child. Currently, QEMU relies heavily on Thread Local Storage (TLS) as part of this coordination strategy. For threads, this works fine, because libc manages the thread-local data region used for TLS, when we create new threads using `pthread_create`. Ideally we could use the same mechanism for "process-local storage" needed to allow the parent/child processes to emulate in tandem. Unfortunately TLS is tightly integrated into libc. The only way to create TLS data regions is via the `pthread_create` API which also spawns a new thread (rather than a new processes, which is what we want). Worse still, TLS itself is a complicated arch-specific feature that is tightly integrated into the rest of libc and the dynamic linker. Re-implementing TLS support for QEMU would likely require a special dynamic linker / libc. Alternatively, the popular libcs could be extended, to allow for users to create TLS regions without creating threads. Even if major libcs decide to add this support, QEMU will still need a temporary work around until those libcs are widely deployed. It's also unclear if libcs will be interested in supporting this case, since TLS image creation is generally deeply integrated with thread setup. In this patch, I've employed an alternative approach: spawning a thread an "stealing" its TLS image for use in the child process. This approach leaves a dangling thread while the TLS image is in use, but by design that thread will not become schedulable until after the TLS data is no longer in-use by the child (as described in a moment). Therefore, it should cause relatively minimal overhead. When considered in the larger context, this seems like a reasonable tradeoff. A major complication of this approach knowing when it is safe to clean up the stack, and TLS image, used by a child process. When a child is created with `CLONE_VM` its stack, and TLS data, need to remain valid until that child has either exited, or successfully called `execve` (on `execve` the child is given a new VMM by the kernel). One approach would be to use `waitid(WNOWAIT)` (the `WNOWAIT` allows the guest to reap the child). The problem is that the `wait` family of calls only waits for termination. The pattern of `clone() ... execve()` for long running child processes is pretty common. If we waited for child processes to exit, it's likely we would end up using substantially more memory, and keep the suspended TLS thread around much longer than necessary. Instead, in this patch, I've used an "trampoline" process. The real parent first clones a trampoline, the trampoline then clones the ultimate child using the `CLONE_VFORK` option. `CLONE_VFORK` suspends the trampoline process until the child has exited, or called `execve`. Once the trampoline is re-scheduled, we know it is safe to clean up after the child. This creates one more suspended process, but typically, the trampoline only exists for a short period of time. !! CLONE_VM setup, step by step 1. First, the suspended thread whose TLS we will use is created using `pthread_create`. The thread fetches and returns it's "TLS pointer" (an arch-specific value given to the kernel) to the parent. It then blocks on a lock to prevent its TLS data from being cleaned up. Ultimately the lock will be unlocked by the trampoline once the child exits. 2. Once the TLS thread has fetched the TLS pointer, it notifies the real parent thread, which calls `clone()` to create the trampoline process. For ease of implementation, the TLS image is set for the trampoline process during this step. This allows the trampoline to use functions that require TLS if needed (e.g., printf). TLS location is inherited when a new child is spawned, so this TLS data will automatically be inherited by the child. 3. Once the trampoline has been spawned, it
[PATCH 0/5] linux-user: Support extended clone(CLONE_VM)
This patch series implements extended support for the `clone` system call. As best I can tell, any option combination including `CLONE_VM` should be supported with the addition of this patch series. The implementation is described in greater detail in the patches themselves. Testing: * All targets built on x86_64. * `make check` and `make check-tcg` are passing. Additional tests have been added to `linux-test.c` to validate clone behavior. Caveats: * This series touches, but does not fix, several bits of code that are racey (namely the sigact table and the fd trans table). * `exit_group` does not perform the appropriate cleanup for non-thread children created with `CLONE_VM`. CPUs for such children are never cleaned up. The correct implementation of exit-group is non-trivial (since it also needs to track/handle cleanup for threads in the clone'd child process). Also, I don't fully understand the interaction between QOM<->linux-user. My naive implementation based on the current implementation `exit(2)` was regularly crashing. If maintainers have suggestions for better ways to handle exit_group, they would be greatly appreciated. * execve does not clean up the CPUs of clone'd children, for the same reasons as `exit_group`. Josh Kunz (5): linux-user: Refactor do_fork to use new `qemu_clone` linux-user: Make fd_trans task-specific. linux-user: Make sigact_table part of the task state. linux-user: Support CLONE_VM and extended clone options linux-user: Add PDEATHSIG test for clone process hierarchy. linux-user/Makefile.objs| 2 +- linux-user/clone.c | 565 linux-user/clone.h | 27 ++ linux-user/fd-trans-tbl.c | 13 + linux-user/fd-trans-type.h | 17 + linux-user/fd-trans.c | 3 - linux-user/fd-trans.h | 75 ++-- linux-user/main.c | 1 + linux-user/qemu.h | 49 +++ linux-user/signal.c | 84 - linux-user/syscall.c| 452 -- tests/tcg/multiarch/Makefile.target | 3 + tests/tcg/multiarch/linux-test.c| 227 ++- 13 files changed, 1264 insertions(+), 254 deletions(-) create mode 100644 linux-user/clone.c create mode 100644 linux-user/clone.h create mode 100644 linux-user/fd-trans-tbl.c create mode 100644 linux-user/fd-trans-type.h -- 2.27.0.290.gba653c62da-goog
[PATCH 3/5] linux-user: Make sigact_table part of the task state.
sigact_table stores the signal handlers for the given process. Once we support CLONE_VM, two tasks using the same virtual memory may need different signal handler tables (e.g., if CLONE_SIGHAND is not provided). Here we make sigact_table part of the TaskState, so it can be duplicated as needed when cloning children. Signed-off-by: Josh Kunz --- linux-user/qemu.h| 8 linux-user/signal.c | 35 +++ linux-user/syscall.c | 17 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 989e01ad8d..54bf4f47be 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -177,6 +177,12 @@ typedef struct TaskState { * the table itself should be guarded. */ struct fd_trans_table *fd_trans_tbl; + +/* + * A table containing signal actions for the target. It should have at + * least TARGET_NSIG entries + */ +struct target_sigaction *sigact_tbl; } __attribute__((aligned(16))) TaskState; extern char *exec_path; @@ -419,7 +425,9 @@ void print_syscall_ret(int num, abi_long arg1); */ void print_taken_signal(int target_signum, const target_siginfo_t *tinfo); + /* signal.c */ +struct target_sigaction *sigact_table_clone(struct target_sigaction *orig); void process_pending_signals(CPUArchState *cpu_env); void signal_init(void); int queue_signal(CPUArchState *env, int sig, int si_type, diff --git a/linux-user/signal.c b/linux-user/signal.c index 8cf51ffecd..dc98def6d1 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -25,7 +25,13 @@ #include "trace.h" #include "signal-common.h" -static struct target_sigaction sigact_table[TARGET_NSIG]; +struct target_sigaltstack target_sigaltstack_used = { +.ss_sp = 0, +.ss_size = 0, +.ss_flags = TARGET_SS_DISABLE, +}; + +typedef struct target_sigaction sigact_table[TARGET_NSIG]; static void host_signal_handler(int host_signum, siginfo_t *info, void *puc); @@ -542,6 +548,11 @@ static void signal_table_init(void) } } +struct target_sigaction *sigact_table_clone(struct target_sigaction *orig) +{ +return memcpy(g_new(sigact_table, 1), orig, sizeof(sigact_table)); +} + void signal_init(void) { TaskState *ts = (TaskState *)thread_cpu->opaque; @@ -556,6 +567,12 @@ void signal_init(void) /* Set the signal mask from the host mask. */ sigprocmask(0, 0, >signal_mask); +/* + * Set all host signal handlers. ALL signals are blocked during + * the handlers to serialize them. + */ +ts->sigact_tbl = (struct target_sigaction *) g_new0(sigact_table, 1); + sigfillset(_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = host_signal_handler; @@ -568,9 +585,9 @@ void signal_init(void) host_sig = target_to_host_signal(i); sigaction(host_sig, NULL, ); if (oact.sa_sigaction == (void *)SIG_IGN) { -sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN; +ts->sigact_tbl[i - 1]._sa_handler = TARGET_SIG_IGN; } else if (oact.sa_sigaction == (void *)SIG_DFL) { -sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL; +ts->sigact_tbl[i - 1]._sa_handler = TARGET_SIG_DFL; } /* If there's already a handler installed then something has gone horribly wrong, so don't even try to handle that case. */ @@ -608,11 +625,12 @@ void force_sig(int sig) #if !defined(TARGET_RISCV) void force_sigsegv(int oldsig) { +TaskState *ts = (TaskState *)thread_cpu->opaque; if (oldsig == SIGSEGV) { /* Make sure we don't try to deliver the signal again; this will * end up with handle_pending_signal() calling dump_core_and_abort(). */ -sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL; +ts->sigact_tbl[oldsig - 1]._sa_handler = TARGET_SIG_DFL; } force_sig(TARGET_SIGSEGV); } @@ -837,6 +855,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, struct sigaction act1; int host_sig; int ret = 0; +TaskState* ts = (TaskState *)thread_cpu->opaque; trace_signal_do_sigaction_guest(sig, TARGET_NSIG); @@ -848,7 +867,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, return -TARGET_ERESTARTSYS; } -k = _table[sig - 1]; +k = >sigact_tbl[sig - 1]; if (oact) { __put_user(k->_sa_handler, >_sa_handler); __put_user(k->sa_flags, >sa_flags); @@ -930,7 +949,7 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig, sa = NULL; handler = TARGET_SIG_IGN; } else { -sa = _table[sig - 1]; +sa = >sigact_tbl[sig - 1]; handler = sa->_sa_handler; } @@ -1022,9 +1041,9 @@ void process_pending_signals(CPUArchState *cpu_env) * looping round and round indefinitely. */ if (sigismember(>signal_mask,
[PATCH 1/5] linux-user: Refactor do_fork to use new `qemu_clone`
This is pre-work for adding full support for the `CLONE_VM` `clone` flag. In a follow-up patch, we'll add support to `clone.c` for `clone_vm`-type clones beyond threads. CLONE_VM support is more complicated, so first we're splitting existing clone mechanisms (pthread_create, and fork) into a separate file. Signed-off-by: Josh Kunz --- linux-user/Makefile.objs | 2 +- linux-user/clone.c | 152 linux-user/clone.h | 27 +++ linux-user/syscall.c | 376 +++ 4 files changed, 365 insertions(+), 192 deletions(-) create mode 100644 linux-user/clone.c create mode 100644 linux-user/clone.h diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 1940910a73..d6788f012c 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -1,7 +1,7 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \ elfload.o linuxload.o uaccess.o uname.o \ safe-syscall.o $(TARGET_ABI_DIR)/signal.o \ -$(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o +$(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o clone.o obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o diff --git a/linux-user/clone.c b/linux-user/clone.c new file mode 100644 index 00..f02ae8c464 --- /dev/null +++ b/linux-user/clone.c @@ -0,0 +1,152 @@ +#include "qemu/osdep.h" +#include "qemu.h" +#include "clone.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const unsigned long NEW_STACK_SIZE = 0x4UL; + +/* + * A completion tracks an event that can be completed. It's based on the + * kernel concept with the same name, but implemented with userspace locks. + */ +struct completion { +/* done is set once this completion has been completed. */ +bool done; +/* mu syncronizes access to this completion. */ +pthread_mutex_t mu; +/* cond is used to broadcast completion status to awaiting threads. */ +pthread_cond_t cond; +}; + +static void completion_init(struct completion *c) +{ +c->done = false; +pthread_mutex_init(>mu, NULL); +pthread_cond_init(>cond, NULL); +} + +/* + * Block until the given completion finishes. Returns immediately if the + * completion has already finished. + */ +static void completion_await(struct completion *c) +{ +pthread_mutex_lock(>mu); +if (c->done) { +pthread_mutex_unlock(>mu); +return; +} +pthread_cond_wait(>cond, >mu); +assert(c->done && "returned from cond wait without being marked as done"); +pthread_mutex_unlock(>mu); +} + +/* + * Finish the completion. Unblocks all awaiters. + */ +static void completion_finish(struct completion *c) +{ +pthread_mutex_lock(>mu); +assert(!c->done && "trying to finish an already finished completion"); +c->done = true; +pthread_cond_broadcast(>cond); +pthread_mutex_unlock(>mu); +} + +struct clone_thread_info { +struct completion running; +int tid; +int (*callback)(void *); +void *payload; +}; + +static void *clone_thread_run(void *raw_info) +{ +struct clone_thread_info *info = (struct clone_thread_info *) raw_info; +info->tid = syscall(SYS_gettid); + +/* + * Save out callback/payload since lifetime of info is only guaranteed + * until we finish the completion. + */ +int (*callback)(void *) = info->callback; +void *payload = info->payload; +completion_finish(>running); + +_exit(callback(payload)); +} + +static int clone_thread(int flags, int (*callback)(void *), void *payload) +{ +struct clone_thread_info info; +pthread_attr_t attr; +int ret; +pthread_t thread_unused; + +memset(, 0, sizeof(info)); + +completion_init(); +info.callback = callback; +info.payload = payload; + +(void)pthread_attr_init(); +(void)pthread_attr_setstacksize(, NEW_STACK_SIZE); +(void)pthread_attr_setdetachstate(, PTHREAD_CREATE_DETACHED); + +ret = pthread_create(_unused, , clone_thread_run, (void *) ); +/* pthread_create returns errors directly, instead of via errno. */ +if (ret != 0) { +errno = ret; +ret = -1; +} else { +completion_await(); +ret = info.tid; +} + +pthread_attr_destroy(); +return ret; +} + +int qemu_clone(int flags, int (*callback)(void *), void *payload) +{ +int ret; + +if (clone_flags_are_thread(flags)) { +/* + * The new process uses the same flags as pthread_create, so we can + * use pthread_create directly. This is an optimization. + */ +return clone_thread(flags, callback, payload); +} + +if (clone_flags_are_fork(flags)) { +/* + * Special case a true `fork` clone call. This is so we can take + * advantage of special pthread_atfork handlers in libraries we + * depend on (e.g., glibc). Without this, existing users of `fork` + * in multi-threaded environments
[PATCH 3/6] audio/jack: remove invalid set of input support bool
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index fb8efd7af7..58c7344497 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -607,9 +607,6 @@ static int qjack_thread_creator(jack_native_thread_t *thread, static void *qjack_init(Audiodev *dev) { assert(dev->driver == AUDIODEV_DRIVER_JACK); - -dev->u.jack.has_in = false; - return dev; } -- 2.20.1
[PATCH 4/6] audio/jack: do not remove ports when finishing
This fixes a hang when there is a communications issue with the JACK server. Simply closing the connection is enough to completely clean up and as such we do not need to remove the ports first. Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 58c7344497..249cbd3265 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -548,9 +548,6 @@ static void qjack_client_fini(QJackClient *c) { switch (c->state) { case QJACK_STATE_RUNNING: -for (int i = 0; i < c->nchannels; ++i) { -jack_port_unregister(c->client, c->port[i]); -} jack_deactivate(c->client); /* fallthrough */ -- 2.20.1
[PATCH 2/6] audio/jack: remove unused stopped state
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 4 1 file changed, 4 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index d0b6f748f2..fb8efd7af7 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -38,7 +38,6 @@ struct QJack; typedef enum QJackState { QJACK_STATE_DISCONNECTED, -QJACK_STATE_STOPPED, QJACK_STATE_RUNNING, QJACK_STATE_SHUTDOWN } @@ -549,9 +548,6 @@ static void qjack_client_fini(QJackClient *c) { switch (c->state) { case QJACK_STATE_RUNNING: -/* fallthrough */ - -case QJACK_STATE_STOPPED: for (int i = 0; i < c->nchannels; ++i) { jack_port_unregister(c->client, c->port[i]); } -- 2.20.1
[PATCH 5/6] audio/jack: honour the enable state of the audio device
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 29 + 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 249cbd3265..b2b53985ae 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -56,7 +56,7 @@ typedef struct QJackClient { AudiodevJackPerDirectionOptions *opt; bool out; -bool finished; +bool enabled; bool connect_ports; int packets; @@ -271,9 +271,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg) } if (c->out) { -qjack_buffer_read_l(>fifo, buffers, nframes); +if (likely(c->enabled)) { +qjack_buffer_read_l(>fifo, buffers, nframes); +} else { +for(int i = 0; i < c->nchannels; ++i) { +memset(buffers[i], 0, nframes * sizeof(float)); +} +} } else { -qjack_buffer_write_l(>fifo, buffers, nframes); +if (likely(c->enabled)) { +qjack_buffer_write_l(>fifo, buffers, nframes); +} } return 0; @@ -314,8 +322,8 @@ static void qjack_client_recover(QJackClient *c) if (c->state == QJACK_STATE_DISCONNECTED && c->packets % 100 == 0) { -/* if not finished then attempt to recover */ -if (!c->finished) { +/* if enabled then attempt to recover */ +if (c->enabled) { dolog("attempting to reconnect to server\n"); qjack_client_init(c); } @@ -387,7 +395,6 @@ static int qjack_client_init(QJackClient *c) char client_name[jack_client_name_size()]; jack_options_t options = JackNullOption; -c->finished = false; c->connect_ports = true; snprintf(client_name, sizeof(client_name), "%s-%s", @@ -483,8 +490,10 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, } jo->c.out = true; +jo->c.enabled = false; jo->c.nchannels = as->nchannels; jo->c.opt = dev->u.jack.out; + int ret = qjack_client_init(>c); if (ret != 0) { return ret; @@ -519,8 +528,10 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, } ji->c.out = false; +ji->c.enabled = false; ji->c.nchannels = as->nchannels; ji->c.opt = dev->u.jack.in; + int ret = qjack_client_init(>c); if (ret != 0) { return ret; @@ -568,23 +579,25 @@ static void qjack_client_fini(QJackClient *c) static void qjack_fini_out(HWVoiceOut *hw) { QJackOut *jo = (QJackOut *)hw; -jo->c.finished = true; qjack_client_fini(>c); } static void qjack_fini_in(HWVoiceIn *hw) { QJackIn *ji = (QJackIn *)hw; -ji->c.finished = true; qjack_client_fini(>c); } static void qjack_enable_out(HWVoiceOut *hw, bool enable) { +QJackOut *jo = (QJackOut *)hw; +jo->c.enabled = enable; } static void qjack_enable_in(HWVoiceIn *hw, bool enable) { +QJackIn *ji = (QJackIn *)hw; +ji->c.enabled = enable; } static int qjack_thread_creator(jack_native_thread_t *thread, -- 2.20.1
[PATCH 1/6] audio/jack: fix invalid minimum buffer size check
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 722ddb1dfe..d0b6f748f2 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -434,17 +434,6 @@ static int qjack_client_init(QJackClient *c) jack_set_xrun_callback(c->client, qjack_xrun, c); jack_on_shutdown(c->client, qjack_shutdown, c); -/* - * ensure the buffersize is no smaller then 512 samples, some (all?) qemu - * virtual devices do not work correctly otherwise - */ -if (c->buffersize < 512) { -c->buffersize = 512; -} - -/* create a 2 period buffer */ -qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2); - /* allocate and register the ports */ c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels); for (int i = 0; i < c->nchannels; ++i) { @@ -468,6 +457,17 @@ static int qjack_client_init(QJackClient *c) jack_activate(c->client); c->buffersize = jack_get_buffer_size(c->client); +/* + * ensure the buffersize is no smaller then 512 samples, some (all?) qemu + * virtual devices do not work correctly otherwise + */ +if (c->buffersize < 512) { +c->buffersize = 512; +} + +/* create a 2 period buffer */ +qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2); + qjack_client_connect_ports(c); c->state = QJACK_STATE_RUNNING; return 0; -- 2.20.1
[PATCH 6/6] audio/jack: simplify the re-init code path
Signed-off-by: Geoffrey McRae --- audio/jackaudio.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index b2b53985ae..72ed7c4929 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -395,6 +395,10 @@ static int qjack_client_init(QJackClient *c) char client_name[jack_client_name_size()]; jack_options_t options = JackNullOption; +if (c->state == QJACK_STATE_RUNNING) { +return 0; +} + c->connect_ports = true; snprintf(client_name, sizeof(client_name), "%s-%s", @@ -485,9 +489,7 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as, QJackOut *jo = (QJackOut *)hw; Audiodev *dev = (Audiodev *)drv_opaque; -if (jo->c.state != QJACK_STATE_DISCONNECTED) { -return 0; -} +qjack_client_fini(>c); jo->c.out = true; jo->c.enabled = false; @@ -523,9 +525,7 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as, QJackIn *ji = (QJackIn *)hw; Audiodev *dev = (Audiodev *)drv_opaque; -if (ji->c.state != QJACK_STATE_DISCONNECTED) { -return 0; -} +qjack_client_fini(>c); ji->c.out = false; ji->c.enabled = false; -- 2.20.1
[PATCH 0/6] *** SUBJECT HERE ***
This patch set addresses several issues that cause inconsistent behaviour in the guest when the sound device is stopped and started or the JACK server stops responding on the host. Geoffrey McRae (6): audio/jack: fix invalid minimum buffer size check audio/jack: remove unused stopped state audio/jack: remove invalid set of input support bool audio/jack: do not remove ports when finishing audio/jack: honour the enable state of the audio device audio/jack: simplify the re-init code path audio/jackaudio.c | 73 --- 1 file changed, 38 insertions(+), 35 deletions(-) -- 2.20.1
[PATCH v7 6/9] qcow2_format.py: Dump bitmap table serialized entries
Add bitmap table information to the QCOW2 metadata dump. It extends the output of the test case #291 Bitmap name bitmap-1 ... Bitmap table typeoffset size 0 serialized 4718592 65536 1 serialized 4294967296 65536 2 serialized 5348033147437056 65536 3 serialized 1379227385882214465536 4 serialized 4718592 65536 5 serialized 4294967296 65536 6 serialized 4503608217305088 65536 7 serialized 1407374883553280065536 Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake --- tests/qemu-iotests/291.out | 50 ++ tests/qemu-iotests/qcow2_format.py | 40 ++ 2 files changed, 90 insertions(+) diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out index d847419..595327c 100644 --- a/tests/qemu-iotests/291.out +++ b/tests/qemu-iotests/291.out @@ -42,6 +42,16 @@ type 1 granularity_bits 19 name_size 2 extra_data_size 0 +Bitmap table typeoffset size +0 serialized 5046272 65536 +1 all-zeroes 065536 +2 all-zeroes 065536 +3 all-zeroes 065536 +4 all-zeroes 065536 +5 all-zeroes 065536 +6 all-zeroes 065536 +7 all-zeroes 065536 + Bitmap name b2 flag auto @@ -53,6 +63,16 @@ type 1 granularity_bits 16 name_size 2 extra_data_size 0 +Bitmap table typeoffset size +0 serialized 5177344 65536 +1 all-zeroes 065536 +2 all-zeroes 065536 +3 all-zeroes 065536 +4 all-zeroes 065536 +5 all-zeroes 065536 +6 all-zeroes 065536 +7 all-zeroes 065536 + === Bitmap preservation not possible to non-qcow2 === @@ -128,6 +148,16 @@ type 1 granularity_bits 19 name_size 2 extra_data_size 0 +Bitmap table typeoffset size +0 serialized 4587520 65536 +1 all-zeroes 065536 +2 all-zeroes 065536 +3 all-zeroes 065536 +4 all-zeroes 065536 +5 all-zeroes 065536 +6 all-zeroes 065536 +7 all-zeroes 065536 + Bitmap name b2 flag auto @@ -139,6 +169,16 @@ type 1 granularity_bits 16 name_size 2 extra_data_size 0 +Bitmap table typeoffset size +0 serialized 4718592 65536 +1 serialized 4294967296 65536 +2 serialized 5348033147437056 65536 +3 serialized 1379227385882214465536 +4 serialized 4718592 65536 +5 serialized 4294967296 65536 +6 serialized 4503608217305088 65536 +7 serialized 1407374883553280065536 + Bitmap name b0 table size8 (bytes) @@ -149,6 +189,16 @@ type 1 granularity_bits 16 name_size 2 extra_data_size 0 +Bitmap table typeoffset size +0 serialized 5242880 65536 +1 all-zeroes 065536 +2 all-zeroes 065536 +3 all-zeroes 065536 +4 all-zeroes 065536 +5 all-zeroes 065536 +6 all-zeroes 065536 +7 all-zeroes 065536 + === Check bitmap contents === diff --git a/tests/qemu-iotests/qcow2_format.py
[PATCH v7 5/9] qcow2_format.py: pass cluster size to substructures
The cluster size of an image is the QcowHeader class member and may be obtained by dependent extension structures such as Qcow2BitmapExt for further bitmap table details print. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 90eff92..eb99119 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -116,6 +116,10 @@ class Qcow2BitmapExt(Qcow2Struct): ('u64', '{:#x}', 'bitmap_directory_offset') ) +def __init__(self, data, cluster_size): +super().__init__(data=data) +self.cluster_size = cluster_size + def read_bitmap_directory(self, fd): self.bitmaps = [] fd.seek(self.bitmap_directory_offset) @@ -123,7 +127,8 @@ class Qcow2BitmapExt(Qcow2Struct): for n in range(self.nb_bitmaps): buf = fd.read(buf_size) -dir_entry = Qcow2BitmapDirEntry(data=buf) +dir_entry = Qcow2BitmapDirEntry(data=buf, +cluster_size=self.cluster_size) fd.seek(dir_entry.extra_data_size, FROM_CURRENT) bitmap_name = fd.read(dir_entry.name_size) dir_entry.name = bitmap_name.decode('ascii') @@ -159,8 +164,9 @@ class Qcow2BitmapDirEntry(Qcow2Struct): ('u32', '{}','extra_data_size') ) -def __init__(self, data): +def __init__(self, data, cluster_size): super().__init__(data=data) +self.cluster_size = cluster_size self.bitmap_table_bytes = self.bitmap_table_size \ * struct.calcsize('Q') @@ -205,11 +211,13 @@ class QcowHeaderExtension(Qcow2Struct): # then padding to next multiply of 8 ) -def __init__(self, magic=None, length=None, data=None, fd=None): +def __init__(self, magic=None, length=None, data=None, fd=None, + cluster_size=None): """ Support both loading from fd and creation from user data. For fd-based creation current position in a file will be used to read the data. +The cluster_size value may be obtained by dependent structures. This should be somehow refactored and functionality should be moved to superclass (to allow creation of any qcow2 struct), but then, fields @@ -243,7 +251,8 @@ class QcowHeaderExtension(Qcow2Struct): self.data_str = data_str if self.magic == QCOW2_EXT_MAGIC_BITMAPS: -self.obj = Qcow2BitmapExt(data=self.data) +self.obj = Qcow2BitmapExt(data=self.data, + cluster_size=cluster_size) else: self.obj = None @@ -318,7 +327,7 @@ class QcowHeader(Qcow2Struct): end = self.cluster_size while fd.tell() < end: -ext = QcowHeaderExtension(fd=fd) +ext = QcowHeaderExtension(fd=fd, cluster_size=self.cluster_size) if ext.magic == 0: break else: -- 1.8.3.1
[PATCH v7 2/9] qcow2: Fix capitalization of header extension constant.
Make the capitalization of the hexadecimal numbers consistent for the QCOW2 header extension constants in docs/interop/qcow2.txt. Suggested-by: Eric Blake Signed-off-by: Andrey Shinkevich --- block/qcow2.c | 2 +- docs/interop/qcow2.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 0cd2e67..80dfe5f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -66,7 +66,7 @@ typedef struct { } QEMU_PACKED QCowExtension; #define QCOW2_EXT_MAGIC_END 0 -#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA +#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xe2792aca #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 #define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 #define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index cb72346..f072e27 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -231,7 +231,7 @@ be stored. Each extension has a structure like the following: Byte 0 - 3: Header extension type: 0x - End of the header extension area -0xE2792ACA - Backing file format name string +0xe2792aca - Backing file format name string 0x6803f857 - Feature name table 0x23852875 - Bitmaps extension 0x0537be77 - Full disk encryption header pointer -- 1.8.3.1
[PATCH v7 9/9] qcow2_format.py: support dumping metadata in JSON format
Implementation of dumping QCOW2 image metadata. The sample output: { "Header_extensions": [ { "name": "Feature table", "magic": 1745090647, "length": 192, "data_str": "" }, { "name": "Bitmaps", "magic": 595929205, "length": 24, "data": { "nb_bitmaps": 2, "reserved32": 0, "bitmap_directory_size": 64, "bitmap_directory_offset": 1048576, "entries": [ { "name": "bitmap-1", "bitmap_table_offset": 589824, "bitmap_table_size": 1, "flags": [ "auto" ], "type": 1, "granularity_bits": 16, "name_size": 8, "extra_data_size": 0, "bitmap_table": { "table_entries": [ { "type": "serialized", "offset": 655360 }, ... Suggested-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 60 ++ 1 file changed, 60 insertions(+) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index bdd5f68..35daec9 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -18,6 +18,15 @@ import struct import string +import json + + +class ComplexEncoder(json.JSONEncoder): +def default(self, obj): +if hasattr(obj, 'get_fields_dict'): +return obj.get_fields_dict() +else: +return json.JSONEncoder.default(self, obj) class Qcow2Field: @@ -95,6 +104,11 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.fields_dict = self.__dict__.copy() def dump(self, dump_json=None): +if dump_json: +print(json.dumps(self.get_fields_dict(), indent=4, + cls=ComplexEncoder)) +return + for f in self.fields: value = self.__dict__[f[2]] if isinstance(f[1], str): @@ -150,6 +164,9 @@ class Qcow2BitmapExt(Qcow2Struct): for bm in self.bitmaps: bm.dump_bitmap_dir_entry(dump_json) +def get_fields_dict(self): +return self.fields_dict + BME_FLAG_IN_USE = 1 << 0 BME_FLAG_AUTO = 1 << 1 @@ -202,6 +219,12 @@ class Qcow2BitmapDirEntry(Qcow2Struct): super().dump() self.bitmap_table.print_bitmap_table(self.cluster_size) +def get_fields_dict(self): +bmp_name = dict(name=self.name) +bme_dict = {**bmp_name, **self.fields_dict} +bme_dict['flags'] = self.bitmap_flags +return bme_dict + class Qcow2BitmapTableEntry: @@ -217,6 +240,9 @@ class Qcow2BitmapTableEntry: else: self.type = 'all-zeroes' +def get_fields_dict(self): +return dict(type=self.type, offset=self.offset) + class Qcow2BitmapTable: @@ -232,6 +258,18 @@ class Qcow2BitmapTable: print(f'{i:<14} {entry.type:<15} {entry.offset:<24} {cluster_size}') print("") +def get_fields_dict(self): +return dict(table_entries=self.entries) + + +class Qcow2HeaderExtensionsDoc: + +def __init__(self, extensions): +self.extensions = extensions + +def get_fields_dict(self): +return dict(Header_extensions=self.extensions) + QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 @@ -247,6 +285,9 @@ class QcowHeaderExtension(Qcow2Struct): 0x44415441: 'Data file' } +def get_fields_dict(self): +return self.mapping.get(self.value, "") + fields = ( ('u32', Magic, 'magic'), ('u32', '{}', 'length') @@ -307,6 +348,16 @@ class QcowHeaderExtension(Qcow2Struct): else: self.obj.dump(dump_json) +def get_fields_dict(self): +ext_name = dict(name=self.Magic(self.magic)) +he_dict = {**ext_name, **self.fields_dict} +if self.obj is not None: +he_dict.update(data=self.obj) +else: +he_dict.update(data_str=self.data_str) + +return he_dict + @classmethod def create(cls, magic, data): return QcowHeaderExtension(magic, len(data), data) @@ -409,7 +460,16 @@ class QcowHeader(Qcow2Struct): fd.write(buf) def dump_extensions(self, dump_json=None): +if dump_json: +ext_doc = Qcow2HeaderExtensionsDoc(self.extensions) +print(json.dumps(ext_doc.get_fields_dict(), indent=4, + cls=ComplexEncoder)) +return + for ex in self.extensions:
[PATCH v7 0/9] iotests: Dump QCOW2 dirty bitmaps metadata
Note: based on the Vladimir's series [v5 00/13] iotests: Dump QCOW2 dirty bitmaps metadata Add dirty bitmap information to QCOW2 metadata dump in the qcow2_format.py. v7: 01: Fix for magic hexadecimal output in 291 02: Bitmap table output format improvement. 03: Incremental change in the test 291 output. v6: 01: Fixing capitalization of header extension constant. (Suggested by Eric) 02: The cluster size global variable discarded and passed as a parameter. 03: Re-based to Vladimir's v5 series. 04: The code of passing qcow2.py JSON format key moved to separate patch. 05: Making dict(s) for dumping in JSON format was substituted with a copy of __dict__. v5: The Vladimir's preliminary series v4: The Vladimir's preliminary series Andrey Shinkevich (9): iotests: Fix for magic hexadecimal output in 291 qcow2: Fix capitalization of header extension constant. qcow2_format.py: make printable data an extension class member qcow2_format.py: Dump bitmap directory information qcow2_format.py: pass cluster size to substructures qcow2_format.py: Dump bitmap table serialized entries qcow2.py: Introduce '-j' key to dump in JSON format qcow2_format.py: collect fields to dump in JSON format qcow2_format.py: support dumping metadata in JSON format block/qcow2.c | 2 +- docs/interop/qcow2.txt | 2 +- tests/qemu-iotests/291.out | 112 ++- tests/qemu-iotests/qcow2.py| 20 +++- tests/qemu-iotests/qcow2_format.py | 217 ++--- 5 files changed, 327 insertions(+), 26 deletions(-) -- 1.8.3.1
[PATCH v7 8/9] qcow2_format.py: collect fields to dump in JSON format
As __dict__ is being extended with class members we do not want to print in JSON format dump, make a light copy of the initial __dict__ and extend the copy by adding lists we have to print in the JSON output. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index a19f3b3..bdd5f68 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -92,6 +92,8 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.__dict__ = dict((field[2], values[i]) for i, field in enumerate(self.fields)) +self.fields_dict = self.__dict__.copy() + def dump(self, dump_json=None): for f in self.fields: value = self.__dict__[f[2]] @@ -102,7 +104,6 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): print('{:<25} {}'.format(f[2], value_str)) - # seek relative to the current position in the file FROM_CURRENT = 1 @@ -142,6 +143,7 @@ class Qcow2BitmapExt(Qcow2Struct): def load(self, fd): self.read_bitmap_directory(fd) +self.fields_dict.update(entries=self.bitmaps) def dump(self, dump_json=None): super().dump(dump_json) @@ -189,6 +191,7 @@ class Qcow2BitmapDirEntry(Qcow2Struct): table_size = self.bitmap_table_bytes * struct.calcsize('Q') table = [e[0] for e in struct.iter_unpack('>Q', fd.read(table_size))] self.bitmap_table = Qcow2BitmapTable(table) +self.fields_dict.update(bitmap_table=self.bitmap_table) def dump_bitmap_dir_entry(self, dump_json=None): print() -- 1.8.3.1
[PATCH v7 4/9] qcow2_format.py: Dump bitmap directory information
Read and dump entries from the bitmap directory of QCOW2 image. It extends the output in the test case #291. Header extension: magic 0x23852875 (Bitmaps) ... Bitmap name bitmap-1 flag auto table size8 (bytes) bitmap_table_offset 0x9 bitmap_table_size 1 flags 0 type 1 granularity_bits 16 name_size 8 extra_data_size 0 Suggested-by: Kevin Wolf Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/291.out | 52 ++ tests/qemu-iotests/qcow2_format.py | 75 ++ 2 files changed, 127 insertions(+) diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out index ccfcdc5..d847419 100644 --- a/tests/qemu-iotests/291.out +++ b/tests/qemu-iotests/291.out @@ -33,6 +33,27 @@ reserved320 bitmap_directory_size 0x40 bitmap_directory_offset 0x51 +Bitmap name b1 +table size8 (bytes) +bitmap_table_offset 0x4e +bitmap_table_size 1 +flags 0 +type 1 +granularity_bits 19 +name_size 2 +extra_data_size 0 + +Bitmap name b2 +flag auto +table size8 (bytes) +bitmap_table_offset 0x50 +bitmap_table_size 1 +flags 2 +type 1 +granularity_bits 16 +name_size 2 +extra_data_size 0 + === Bitmap preservation not possible to non-qcow2 === @@ -98,6 +119,37 @@ reserved320 bitmap_directory_size 0x60 bitmap_directory_offset 0x52 +Bitmap name b1 +table size8 (bytes) +bitmap_table_offset 0x47 +bitmap_table_size 1 +flags 0 +type 1 +granularity_bits 19 +name_size 2 +extra_data_size 0 + +Bitmap name b2 +flag auto +table size8 (bytes) +bitmap_table_offset 0x49 +bitmap_table_size 1 +flags 2 +type 1 +granularity_bits 16 +name_size 2 +extra_data_size 0 + +Bitmap name b0 +table size8 (bytes) +bitmap_table_offset 0x51 +bitmap_table_size 1 +flags 0 +type 1 +granularity_bits 16 +name_size 2 +extra_data_size 0 + === Check bitmap contents === diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index d4f..90eff92 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -103,6 +103,10 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): print('{:<25} {}'.format(f[2], value_str)) +# seek relative to the current position in the file +FROM_CURRENT = 1 + + class Qcow2BitmapExt(Qcow2Struct): fields = ( @@ -112,6 +116,73 @@ class Qcow2BitmapExt(Qcow2Struct): ('u64', '{:#x}', 'bitmap_directory_offset') ) +def read_bitmap_directory(self, fd): +self.bitmaps = [] +fd.seek(self.bitmap_directory_offset) +buf_size = struct.calcsize(Qcow2BitmapDirEntry.fmt) + +for n in range(self.nb_bitmaps): +buf = fd.read(buf_size) +dir_entry = Qcow2BitmapDirEntry(data=buf) +fd.seek(dir_entry.extra_data_size, FROM_CURRENT) +bitmap_name = fd.read(dir_entry.name_size) +dir_entry.name = bitmap_name.decode('ascii') +self.bitmaps.append(dir_entry) +entry_raw_size = dir_entry.bitmap_dir_entry_raw_size() +shift = ((entry_raw_size + 7) & ~7) - entry_raw_size +fd.seek(shift, FROM_CURRENT) + +def load(self, fd): +self.read_bitmap_directory(fd) + +def dump(self): +super().dump() +for bm in self.bitmaps: +bm.dump_bitmap_dir_entry() + + +BME_FLAG_IN_USE = 1 << 0 +BME_FLAG_AUTO = 1 << 1 + + +class Qcow2BitmapDirEntry(Qcow2Struct): + +name = '' + +fields = ( +('u64', '{:#x}', 'bitmap_table_offset'), +('u32', '{}','bitmap_table_size'), +('u32', '{}','flags'), +('u8', '{}','type'), +('u8', '{}','granularity_bits'), +('u16', '{}','name_size'), +('u32', '{}','extra_data_size') +) + +def __init__(self, data): +super().__init__(data=data) + +self.bitmap_table_bytes = self.bitmap_table_size \ +* struct.calcsize('Q') + +self.bitmap_flags = [] +if (self.flags & BME_FLAG_IN_USE): +self.bitmap_flags.append("in-use") +if (self.flags &
[PATCH v7 1/9] iotests: Fix for magic hexadecimal output in 291
This issue was introduced in the earlier patch: "qcow2_format: refactor QcowHeaderExtension as a subclass of Qcow2Struct". Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/291.out | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out index 1d4f9cd..ccfcdc5 100644 --- a/tests/qemu-iotests/291.out +++ b/tests/qemu-iotests/291.out @@ -16,17 +16,17 @@ wrote 1048576/1048576 bytes at offset 2097152 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Check resulting qcow2 header extensions: Header extension: -magic 3799591626 (Backing format) +magic 0xe2792aca (Backing format) length5 data 'qcow2' Header extension: -magic 1745090647 (Feature table) +magic 0x6803f857 (Feature table) length336 data Header extension: -magic 595929205 (Bitmaps) +magic 0x23852875 (Bitmaps) length24 nb_bitmaps2 reserved320 @@ -86,12 +86,12 @@ Format specific information: corrupt: false Check resulting qcow2 header extensions: Header extension: -magic 1745090647 (Feature table) +magic 0x6803f857 (Feature table) length336 data Header extension: -magic 595929205 (Bitmaps) +magic 0x23852875 (Bitmaps) length24 nb_bitmaps3 reserved320 -- 1.8.3.1
[PATCH v7 3/9] qcow2_format.py: make printable data an extension class member
Let us differ binary data type from string one for the extension data variable and keep the string as the QcowHeaderExtension class member. Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/qcow2_format.py | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 0f65fd1..d4f 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -164,6 +164,13 @@ class QcowHeaderExtension(Qcow2Struct): self.data = fd.read(padded) assert self.data is not None +data_str = self.data[:self.length] +if all(c in string.printable.encode('ascii') for c in data_str): +data_str = f"'{ data_str.decode('ascii') }'" +else: +data_str = '' +self.data_str = data_str + if self.magic == QCOW2_EXT_MAGIC_BITMAPS: self.obj = Qcow2BitmapExt(data=self.data) else: @@ -173,12 +180,7 @@ class QcowHeaderExtension(Qcow2Struct): super().dump() if self.obj is None: -data = self.data[:self.length] -if all(c in string.printable.encode('ascii') for c in data): -data = f"'{ data.decode('ascii') }'" -else: -data = '' -print(f'{"data":<25} {data}') +print(f'{"data":<25} {self.data_str}') else: self.obj.dump() -- 1.8.3.1
[PATCH v7 7/9] qcow2.py: Introduce '-j' key to dump in JSON format
Add the command key to the qcow2.py arguments list to dump QCOW2 metadata in JSON format. Here is the suggested way to do that. The implementation of the dump in JSON format is in the patch that follows. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2.py| 20 +++- tests/qemu-iotests/qcow2_format.py | 18 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 8c187e9..b08d8fc 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -24,16 +24,19 @@ from qcow2_format import ( ) +dump_json = False + + def cmd_dump_header(fd): h = QcowHeader(fd) -h.dump() +h.dump(dump_json) print() -h.dump_extensions() +h.dump_extensions(dump_json) def cmd_dump_header_exts(fd): h = QcowHeader(fd) -h.dump_extensions() +h.dump_extensions(dump_json) def cmd_set_header(fd, name, value): @@ -132,6 +135,11 @@ cmds = [ def main(filename, cmd, args): +global dump_json +dump_json = '-j' in sys.argv +if dump_json: +sys.argv.remove('-j') +args.remove('-j') fd = open(filename, "r+b") try: for name, handler, num_args, desc in cmds: @@ -149,12 +157,14 @@ def main(filename, cmd, args): def usage(): -print("Usage: %s [, ...]" % sys.argv[0]) +print("Usage: %s [, ...] [, ...]" % sys.argv[0]) print("") print("Supported commands:") for name, handler, num_args, desc in cmds: print("%-20s - %s" % (name, desc)) - +print("") +print("Supported keys:") +print("%-20s - %s" % ('-j', 'Dump in JSON format')) if __name__ == '__main__': if len(sys.argv) < 3: diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index c1c2773..a19f3b3 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -92,7 +92,7 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.__dict__ = dict((field[2], values[i]) for i, field in enumerate(self.fields)) -def dump(self): +def dump(self, dump_json=None): for f in self.fields: value = self.__dict__[f[2]] if isinstance(f[1], str): @@ -143,10 +143,10 @@ class Qcow2BitmapExt(Qcow2Struct): def load(self, fd): self.read_bitmap_directory(fd) -def dump(self): -super().dump() +def dump(self, dump_json=None): +super().dump(dump_json) for bm in self.bitmaps: -bm.dump_bitmap_dir_entry() +bm.dump_bitmap_dir_entry(dump_json) BME_FLAG_IN_USE = 1 << 0 @@ -190,7 +190,7 @@ class Qcow2BitmapDirEntry(Qcow2Struct): table = [e[0] for e in struct.iter_unpack('>Q', fd.read(table_size))] self.bitmap_table = Qcow2BitmapTable(table) -def dump_bitmap_dir_entry(self): +def dump_bitmap_dir_entry(self, dump_json=None): print() print(f'{"Bitmap name":<25} {self.name}') for fl in self.bitmap_flags: @@ -296,13 +296,13 @@ class QcowHeaderExtension(Qcow2Struct): else: self.obj = None -def dump(self): +def dump(self, dump_json=None): super().dump() if self.obj is None: print(f'{"data":<25} {self.data_str}') else: -self.obj.dump() +self.obj.dump(dump_json) @classmethod def create(cls, magic, data): @@ -405,8 +405,8 @@ class QcowHeader(Qcow2Struct): buf = buf[0:header_bytes-1] fd.write(buf) -def dump_extensions(self): +def dump_extensions(self, dump_json=None): for ex in self.extensions: print('Header extension:') -ex.dump() +ex.dump(dump_json) print() -- 1.8.3.1
Re: [PATCH] tests: disassemble-asm.sh: generate AML in readable format
Patchew URL: https://patchew.org/QEMU/20200611165112.30979-1-...@redhat.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20200611165112.30979-1-...@redhat.com Subject: [PATCH] tests: disassemble-asm.sh: generate AML in readable format Type: series === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 96571e6 tests: disassemble-asm.sh: generate AML in readable format === OUTPUT BEGIN === WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #16: new file mode 100755 WARNING: line over 80 characters #30: FILE: tests/data/acpi/disassemle-aml.sh:10: +echo "Usage: ./tests/data/acpi/disassemle-aml.sh [-o ]" ERROR: trailing whitespace #33: FILE: tests/data/acpi/disassemle-aml.sh:13: +$ ERROR: trailing whitespace #70: FILE: tests/data/acpi/disassemle-aml.sh:50: +iasl -d -p ${asl} ${extra} ${aml} $ total: 2 errors, 2 warnings, 52 lines checked Commit 96571e631bfb (tests: disassemble-asm.sh: generate AML in readable format) has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 The full log is available at http://patchew.org/logs/20200611165112.30979-1-...@redhat.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
[PATCH] target/i386: reimplement f2xm1 using floatx80 operations
The x87 f2xm1 emulation is currently based around conversion to double. This is inherently unsuitable for a good emulation of any floatx80 operation, even before considering that it is a particularly naive implementation using double (computing with pow and then subtracting 1 rather than attempting a better emulation using expm1). Reimplement using the soft-float operations, including additions and multiplications with higher precision where appropriate to limit accumulation of errors. I considered reusing some of the m68k code for transcendental operations, but the instructions don't generally correspond exactly to x87 operations (for example, m68k has 2^x and e^x - 1, but not 2^x - 1); to avoid possible accumulation of errors from applying multiple such operations each rounding to floatx80 precision, I wrote a direct implementation of 2^x - 1 instead. It would be possible in principle to make the implementation more efficient by doing the intermediate operations directly with significands, signs and exponents and not packing / unpacking floatx80 format for each operation, but that would make it significantly more complicated and it's not clear that's worthwhile; the m68k emulation doesn't try to do that. A test is included with many randomly generated inputs. The assumption of the test is that the result in round-to-nearest mode should always be one of the two closest floating-point numbers to the mathematical value of 2^x - 1; the implementation aims to do somewhat better than that (about 70 correct bits before rounding). I haven't investigated how accurate hardware is. Signed-off-by: Joseph Myers --- This patch depends on at least some of my previous x87 emulation fixes being present (probably only the ones in the recent pull request; I don't think it depends on any of the most recent series fixing fprem and fprem1). I expect to make similar fixes for fyl2xp1, fyl2x and fpatan. (The other transcendental instructions (fcos, fptan, fsin, fsincos) may follow, but as a lower priority, as I'm aiming at getting reasonable glibc test results under QEMU and those trigonometric instructions - with their documented semantics that they are defined to do range reduction using a specific 66-bit approximation to pi - aren't used in glibc.) checkpatch.pl has its usual false-positive complaints about hex floating-point constants in the testcase. It also complains about lines over 80 columns in that test; I can reformat the test if desired, but it's not clear line length matters for such a randomly generated table of test inputs and expected results. --- target/i386/fpu_helper.c | 385 +- tests/tcg/i386/test-i386-f2xm1.c | 1140 ++ 2 files changed, 1522 insertions(+), 3 deletions(-) create mode 100644 tests/tcg/i386/test-i386-f2xm1.c diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 0e531e3821..8f34ea9776 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -25,6 +25,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "fpu/softfloat.h" +#include "fpu/softfloat-macros.h" #ifdef CONFIG_SOFTMMU #include "hw/irq.h" @@ -836,12 +837,390 @@ void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) merge_exception_flags(env, old_flags); } +/* 128-bit significand of log(2). */ +#define ln2_sig_high 0xb17217f7d1cf79abULL +#define ln2_sig_low 0xc9e3b39803f2f6afULL + +/* + * Polynomial coefficients for an approximation to (2^x - 1) / x, on + * the interval [-1/64, 1/64]. + */ +#define f2xm1_coeff_0 make_floatx80(0x3ffe, 0xb17217f7d1cf79acULL) +#define f2xm1_coeff_0_low make_floatx80(0xbfbc, 0xd87edabf495b3762ULL) +#define f2xm1_coeff_1 make_floatx80(0x3ffc, 0xf5fdeffc162c7543ULL) +#define f2xm1_coeff_2 make_floatx80(0x3ffa, 0xe35846b82505fcc7ULL) +#define f2xm1_coeff_3 make_floatx80(0x3ff8, 0x9d955b7dd273b899ULL) +#define f2xm1_coeff_4 make_floatx80(0x3ff5, 0xaec3ff3c4ef4ac0cULL) +#define f2xm1_coeff_5 make_floatx80(0x3ff2, 0xa184897c3a7f0de9ULL) +#define f2xm1_coeff_6 make_floatx80(0x3fee, 0xffe634d0ec30d504ULL) +#define f2xm1_coeff_7 make_floatx80(0x3feb, 0xb160111d2db515e4ULL) + +struct f2xm1_data { +/* + * A value very close to a multiple of 1/32, such that 2^t and 2^t - 1 + * are very close to exact floatx80 values. + */ +floatx80 t; +/* The value of 2^t. */ +floatx80 exp2; +/* The value of 2^t - 1. */ +floatx80 exp2m1; +}; + +static const struct f2xm1_data f2xm1_table[65] = { +{ make_floatx80(0xbfff, 0x8000ULL), + make_floatx80(0x3ffe, 0x8000ULL), + make_floatx80(0xbffe, 0x8000ULL) }, +{ make_floatx80(0xbffe, 0xf8002e7eULL), + make_floatx80(0x3ffe, 0x82cd8698ac2b9160ULL), + make_floatx80(0xbffd, 0xfa64f2cea7a8dd40ULL) }, +{ make_floatx80(0xbffe, 0xefffe960ULL), + make_floatx80(0x3ffe, 0x85aac367cc488345ULL), + make_floatx80(0xbffd, 0xf4aa7930676ef976ULL) }, +
Re: [PATCH 00/10] target/arm: Convert 2-reg-scalar to decodetree
Patchew URL: https://patchew.org/QEMU/20200611144529.8873-1-peter.mayd...@linaro.org/ Hi, This series failed the docker-mingw@fedora build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #! /bin/bash export ARCH=x86_64 make docker-image-fedora V=1 NETWORK=1 time make docker-test-mingw@fedora J=14 NETWORK=1 === TEST SCRIPT END === CC aarch64-softmmu/target/arm/psci.o CC aarch64-softmmu/target/arm/translate-a64.o CC aarch64-softmmu/target/arm/helper-a64.o /tmp/qemu-test/src/target/arm/neon-dp.decode:416: error: ('definition has 0 bits',) make[1]: *** [/tmp/qemu-test/src/target/arm/Makefile.objs:27: target/arm/decode-neon-dp.inc.c] Error 1 make[1]: *** Waiting for unfinished jobs GEN aarch64-softmmu/target/arm/decode-sve.inc.c GEN x86_64-softmmu/qemu-system-x86_64.exe make: *** [Makefile:527: aarch64-softmmu/all] Error 2 Traceback (most recent call last): File "./tests/docker/docker.py", line 665, in sys.exit(main()) --- raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=a093840cf7c04ee4bf8dfca6073b2aea', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-asai5w4d/src/docker-src.2020-06-11-19.39.07.24908:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2. filter=--filter=label=com.qemu.instance.uuid=a093840cf7c04ee4bf8dfca6073b2aea make[1]: *** [docker-run] Error 1 make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-asai5w4d/src' make: *** [docker-run-test-mingw@fedora] Error 2 real3m22.484s user0m8.758s The full log is available at http://patchew.org/logs/20200611144529.8873-1-peter.mayd...@linaro.org/testing.docker-mingw@fedora/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [PATCH 00/10] target/arm: Convert 2-reg-scalar to decodetree
Patchew URL: https://patchew.org/QEMU/20200611144529.8873-1-peter.mayd...@linaro.org/ Hi, This series failed the docker-quick@centos7 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. === TEST SCRIPT BEGIN === #!/bin/bash make docker-image-centos7 V=1 NETWORK=1 time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 === TEST SCRIPT END === CC aarch64-softmmu/target/arm/helper-a64.o GEN aarch64-softmmu/target/arm/decode-sve.inc.c CC aarch64-softmmu/target/arm/sve_helper.o /tmp/qemu-test/src/target/arm/neon-dp.decode:416: error: ('definition has 0 bits',) CC aarch64-softmmu/target/arm/pauth_helper.o make[1]: *** [target/arm/decode-neon-dp.inc.c] Error 1 make[1]: *** Waiting for unfinished jobs make: *** [aarch64-softmmu/all] Error 2 Traceback (most recent call last): File "./tests/docker/docker.py", line 665, in sys.exit(main()) --- raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=652e5daeb9d74258b3b1583fbf30fe7a', '-u', '1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-plvski0d/src/docker-src.2020-06-11-19.13.01.2188:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2. filter=--filter=label=com.qemu.instance.uuid=652e5daeb9d74258b3b1583fbf30fe7a make[1]: *** [docker-run] Error 1 make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-plvski0d/src' make: *** [docker-run-test-quick@centos7] Error 2 real3m6.470s user0m8.159s The full log is available at http://patchew.org/logs/20200611144529.8873-1-peter.mayd...@linaro.org/testing.docker-quick@centos7/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
[Bug 1882851] Re: QEMU video freezes with "Guest disabled display" (virtio driver)
I can reproduce it with current linux git master[1]. 1. git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1882851 Title: QEMU video freezes with "Guest disabled display" (virtio driver) Status in QEMU: New Bug description: I am using Arch Linux as my Guest and Host OS, after starting qemu with the following command: $ qemu-system-x86_64 -enable-kvm -hda arch-zoom.qcow2 -m 4G -vga virtio and waiting for a screen blank, I get this message: Guest disabled display And nothing happens after that, I can move the mouse or hit any key, and the message is still there. I can still reboot the VM but that's not optimal. I can reproduce this with the latest QEMU release (5.0.0) or git master, I also tried this with older releases (4.0.0, 3.0.0) and the issue is still there. I can't reproduce this with other video drivers (std, qxl). With std/qxl the screen will blank a bit and then continue as normal. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1882851/+subscriptions
[PATCH v2 11/12] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
This allows these NPCM7xx-based boards to boot from a flash image, e.g. one built with OpenBMC. For example like this: IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc qemu-system-arm -machine quanta-gsj -nographic \ -bios ~/qemu/bootrom/npcm7xx_bootrom.bin \ -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on Change-Id: I158a4d9952c0e90f2b1b7280443a7305b6ae57cf Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- hw/arm/npcm7xx_boards.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 86e18af2d7..1ec772fa59 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -18,6 +18,7 @@ #include "hw/arm/boot.h" #include "hw/arm/npcm7xx.h" #include "hw/core/cpu.h" +#include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu/units.h" @@ -40,6 +41,20 @@ static void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc) arm_load_kernel(>cpu[0], machine, _binfo); } +static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no, + const char *flash_type, DriveInfo *dinfo) { +DeviceState *flash; +qemu_irq flash_cs; + +flash = ssi_create_slave_no_init(fiu->spi, flash_type); +qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo), +_abort); +qdev_init_nofail(flash); + +flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0); +sysbus_connect_irq(SYS_BUS_DEVICE(fiu), cs_no, flash_cs); +} + static NPCM7xxState *npcm7xx_create_soc(MachineState *machine) { NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine); @@ -57,18 +72,30 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine) static void npcm750_evb_init(MachineState *machine) { NPCM7xxState *soc; +DriveInfo *dinfo; soc = npcm7xx_create_soc(machine); +dinfo = drive_get(IF_MTD, 0, 0); +if (dinfo) { +npcm7xx_connect_flash(>fiu[0], 0, "w25q256", dinfo); +} + npcm7xx_load_kernel(machine, soc); } static void quanta_gsj_init(MachineState *machine) { NPCM7xxState *soc; +DriveInfo *dinfo; soc = npcm7xx_create_soc(machine); +dinfo = drive_get(IF_MTD, 0, 0); +if (dinfo) { +npcm7xx_connect_flash(>fiu[0], 0, "mx25l25635e", dinfo); +} + npcm7xx_load_kernel(machine, soc); } -- 2.27.0.290.gba653c62da-goog
[PATCH v2 12/12] docs/system: Add Nuvoton machine documentation
Change-Id: I88e437cb22a8441e0c0e672dfb57568ac81172d8 Signed-off-by: Havard Skinnemoen --- docs/system/arm/nuvoton.rst | 89 + docs/system/target-arm.rst | 1 + 2 files changed, 90 insertions(+) create mode 100644 docs/system/arm/nuvoton.rst diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst new file mode 100644 index 00..1ca34c0051 --- /dev/null +++ b/docs/system/arm/nuvoton.rst @@ -0,0 +1,89 @@ +Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``) += + +The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are +designed to be used as Baseboard Management Controllers (BMCs) in various +servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an +assortment of peripherals targeted for either Enterprise or Data Center / +Hyperscale applications. The former is a superset of the latter, so NPCM750 has +all the peripherals of NPCM730 and more. + +.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/ + +The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise +segment. The following machines are based on this chip : + +- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board + +The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and +Hyperscale applications. The following machines are based on this chip : + +- ``quanta-gsj``Quanta GSJ server BMC + +There are also two more SoCs, NPCM710 and NPCM705, which are single-core +variants of NPCM750 and NPCM730, respectively. These are currently not +supported by QEMU. + +Supported devices +- + + * SMP (Dual Core Cortex-A9) + * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer + and Watchdog. + * SRAM, ROM and DRAM mappings + * System Global Control Registers (GCR) + * Clock and reset controller (CLK) + * Timer controller (TIM) + * Serial ports (16550-based) + * DDR4 memory controller (dummy interface indicating memory training is done) + * OTP controllers (no protection features) + * Flash Interface Unit (FIU; no protection features) + +Missing devices +--- + + * GPIO controller + * LPC/eSPI host-to-BMC interface, including + + * Keyboard and mouse controller interface (KBCI) + * Keyboard Controller Style (KCS) channels + * BIOS POST code FIFO + * System Wake-up Control (SWC) + * Shared memory (SHM) + * eSPI slave interface + + * Ethernet controllers (GMAC and EMC) + * USB host (USBH) + * USB device (USBD) + * SMBus controller (SMBF) + * Peripheral SPI controller (PSPI) + * Analog to Digital Converter (ADC) + * SD/MMC host + * Random Number Generator (RNG) + * PECI interface + * Pulse Width Modulation (PWM) + * Tachometer + * PCI and PCIe root complex and bridges + * VDM and MCTP support + * Serial I/O expansion + * LPC/eSPI host + * Coprocessor + * Graphics + * Video capture + * Encoding compression engine + * Security features + +Boot options + + +The Nuvoton machines can boot from an OpenBMC firmware image, or directly into +a kernel using the ``-kernel`` option. + +Booting a full firmware image requires a Boot ROM specified via the ``-bios`` +option to QEMU. The firmware image should be attached as an MTD drive. Example : + +.. code-block:: bash + + $ qemu-system-arm -machine quanta-gsj -nographic \ + -bios npcm7xx_bootrom.bin \ + -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst index 1bd477a293..38a9daa9b9 100644 --- a/docs/system/target-arm.rst +++ b/docs/system/target-arm.rst @@ -84,6 +84,7 @@ undocumented; you can get a complete list by running arm/aspeed arm/musicpal arm/nseries + arm/nuvoton arm/orangepi arm/palm arm/xscale -- 2.27.0.290.gba653c62da-goog
[PATCH v2 09/12] hw/mem: Stubbed out NPCM7xx Memory Controller model
This just implements the bare minimum to cause the boot block to skip memory intialization. Change-Id: I26fd5f3b2af5d07a24911e7e58789f7b52f78d71 Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/npcm7xx.c| 11 + hw/mem/Makefile.objs| 1 + hw/mem/npcm7xx_mc.c | 83 + include/hw/arm/npcm7xx.h| 2 + include/hw/mem/npcm7xx_mc.h | 35 6 files changed, 134 insertions(+) create mode 100644 hw/mem/npcm7xx_mc.c create mode 100644 include/hw/mem/npcm7xx_mc.h diff --git a/MAINTAINERS b/MAINTAINERS index 9814e7b4c4..9a289366ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -727,10 +727,12 @@ M: Tyrone Ting L: qemu-...@nongnu.org S: Supported F: hw/arm/npcm7xx* +F: hw/mem/npcm7xx* F: hw/misc/npcm7xx* F: hw/nvram/npcm7xx* F: hw/timer/npcm7xx* F: include/hw/arm/npcm7xx* +F: include/hw/mem/npcm7xx* F: include/hw/misc/npcm7xx* F: include/hw/nvram/npcm7xx* F: include/hw/timer/npcm7xx* diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index f9e3b5842b..54d84bafa1 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -46,6 +46,7 @@ #define NPCM7XX_CPUP_BA (0xF03FE000) #define NPCM7XX_GCR_BA (0xF080) #define NPCM7XX_CLK_BA (0xF0801000) +#define NPCM7XX_MC_BA (0xF0824000) /* Memory blocks at the end of the address space */ #define NPCM7XX_RAM2_BA (0xFFFD) @@ -161,6 +162,8 @@ static void npcm7xx_init(Object *obj) sizeof(s->key_storage), TYPE_NPCM7XX_KEY_STORAGE); sysbus_init_child_obj(obj, "otp2", OBJECT(>fuse_array), sizeof(s->fuse_array), TYPE_NPCM7XX_FUSE_ARRAY); +sysbus_init_child_obj(obj, "mc", OBJECT(>mc), sizeof(s->mc), + TYPE_NPCM7XX_MC); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { sysbus_init_child_obj(obj, "tim[*]", OBJECT(>tim[i]), @@ -258,6 +261,14 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA); npcm7xx_init_fuses(s); +/* Fake Memory Controller (MC) */ +object_property_set_bool(OBJECT(>mc), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>mc), 0, NPCM7XX_MC_BA); + /* Timer Modules (TIM) */ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs index 56345befd0..9a33ef7b35 100644 --- a/hw/mem/Makefile.objs +++ b/hw/mem/Makefile.objs @@ -1,3 +1,4 @@ common-obj-$(CONFIG_DIMM) += pc-dimm.o common-obj-y += memory-device.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_mc.o common-obj-$(CONFIG_NVDIMM) += nvdimm.o diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c new file mode 100644 index 00..03a7fb53dc --- /dev/null +++ b/hw/mem/npcm7xx_mc.c @@ -0,0 +1,83 @@ +/* + * Nuvoton NPCM7xx Memory Controller stub + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/mem/npcm7xx_mc.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#define NPCM7XX_MC_REGS_SIZE (4 * KiB) + +static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size) +{ +/* + * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory + * controller has already been initialized and will skip DDR training. + */ +if (addr == 0) { +return 0x100; +} + +qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); + +return 0; +} + +static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ +qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); +} + +static const MemoryRegionOps npcm7xx_mc_ops = { +.read = npcm7xx_mc_read, +.write = npcm7xx_mc_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 4, +.max_access_size = 4, +.unaligned = false, +}, +}; + +static void npcm7xx_mc_realize(DeviceState *dev, Error **errp) +{ +NPCM7xxMCState *s = NPCM7XX_MC(dev); + +memory_region_init_io(>mmio, OBJECT(s), _mc_ops, s, "regs", + NPCM7XX_MC_REGS_SIZE); +sysbus_init_mmio(>parent, >mmio); +} + +static void npcm7xx_mc_class_init(ObjectClass *klass, void *data) +{ +
[PATCH v2 08/12] hw/nvram: NPCM7xx OTP device model
This supports reading and writing OTP fuses and keys. Only fuse reading has been tested. Protection is not implemented. Change-Id: Ie67d7e2ed5e1010061b7383c71a8ba0611794103 Reviewed-by: Avi Fishman Signed-off-by: Havard Skinnemoen --- MAINTAINERS| 2 + hw/arm/npcm7xx.c | 32 +++ hw/nvram/Makefile.objs | 1 + hw/nvram/npcm7xx_otp.c | 391 + include/hw/arm/npcm7xx.h | 3 + include/hw/nvram/npcm7xx_otp.h | 93 6 files changed, 522 insertions(+) create mode 100644 hw/nvram/npcm7xx_otp.c create mode 100644 include/hw/nvram/npcm7xx_otp.h diff --git a/MAINTAINERS b/MAINTAINERS index 077c86643c..9814e7b4c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -728,9 +728,11 @@ L: qemu-...@nongnu.org S: Supported F: hw/arm/npcm7xx* F: hw/misc/npcm7xx* +F: hw/nvram/npcm7xx* F: hw/timer/npcm7xx* F: include/hw/arm/npcm7xx* F: include/hw/misc/npcm7xx* +F: include/hw/nvram/npcm7xx* F: include/hw/timer/npcm7xx* nSeries diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 417bc16b5c..f9e3b5842b 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -37,6 +37,10 @@ #define NPCM7XX_MMIO_BA (0x8000) #define NPCM7XX_MMIO_SZ (0x7FFD) +/* OTP key storage and fuse strap array */ +#define NPCM7XX_OTP1_BA (0xF0189000) +#define NPCM7XX_OTP2_BA (0xF018a000) + /* Core system modules. */ #define NPCM7XX_L2C_BA (0xF03FC000) #define NPCM7XX_CPUP_BA (0xF03FE000) @@ -121,6 +125,15 @@ void npcm7xx_write_secondary_boot(ARMCPU *cpu, const struct arm_boot_info *info) NPCM7XX_SMP_LOADER_START); } +static void npcm7xx_init_fuses(NPCM7xxState *s) +{ +NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s); +uint32_t value; + +value = tswap32(nc->disabled_modules); +npcm7xx_otp_array_write(>fuse_array, , 64, sizeof(value)); +} + static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n) { return qdev_get_gpio_in(DEVICE(>a9mpcore), n); @@ -144,6 +157,10 @@ static void npcm7xx_init(Object *obj) TYPE_NPCM7XX_GCR); sysbus_init_child_obj(obj, "clk", OBJECT(>clk), sizeof(s->clk), TYPE_NPCM7XX_CLK); +sysbus_init_child_obj(obj, "otp1", OBJECT(>key_storage), + sizeof(s->key_storage), TYPE_NPCM7XX_KEY_STORAGE); +sysbus_init_child_obj(obj, "otp2", OBJECT(>fuse_array), + sizeof(s->fuse_array), TYPE_NPCM7XX_FUSE_ARRAY); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { sysbus_init_child_obj(obj, "tim[*]", OBJECT(>tim[i]), @@ -226,6 +243,21 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(>clk), 0, NPCM7XX_CLK_BA); +/* OTP key storage and fuse strap array */ +object_property_set_bool(OBJECT(>key_storage), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>key_storage), 0, NPCM7XX_OTP1_BA); +object_property_set_bool(OBJECT(>fuse_array), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA); +npcm7xx_init_fuses(s); + /* Timer Modules (TIM) */ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs index f3ad921382..0270f0bbf7 100644 --- a/hw/nvram/Makefile.objs +++ b/hw/nvram/Makefile.objs @@ -4,5 +4,6 @@ common-obj-$(CONFIG_AT24C) += eeprom_at24c.o common-obj-y += fw_cfg.o common-obj-$(CONFIG_CHRP_NVRAM) += chrp_nvram.o common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_otp.o common-obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o obj-$(CONFIG_PSERIES) += spapr_nvram.o diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c new file mode 100644 index 00..71fc728a2d --- /dev/null +++ b/hw/nvram/npcm7xx_otp.c @@ -0,0 +1,391 @@ +/* + * Nuvoton NPCM7xx OTP (Fuse Array) Interface + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/nvram/npcm7xx_otp.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +/* Each module has 4 KiB of register space. Only a fraction of it is used. */ +#define NPCM7XX_OTP_REGS_SIZE (4 * KiB) + +/* Register field definitions.
[PATCH v2 10/12] hw/ssi: NPCM7xx Flash Interface Unit device model
This implements a device model for the NPCM7xx SPI flash controller. Direct reads and writes, and user-mode transactions have been tested in various modes. Protection features are not implemented yet. All the FIU instances are available in the SoC's address space, regardless of whether or not they're connected to actual flash chips. Change-Id: Ia4985761931714c6ca35b505f47aef3f4008c1d8 Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/Kconfig | 1 + hw/arm/npcm7xx.c | 59 + hw/ssi/Makefile.objs | 1 + hw/ssi/npcm7xx_fiu.c | 497 +++ hw/ssi/trace-events | 9 + include/hw/arm/npcm7xx.h | 2 + include/hw/ssi/npcm7xx_fiu.h | 99 +++ 8 files changed, 670 insertions(+) create mode 100644 hw/ssi/npcm7xx_fiu.c create mode 100644 include/hw/ssi/npcm7xx_fiu.h diff --git a/MAINTAINERS b/MAINTAINERS index 9a289366ba..8a5c08c2c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -730,11 +730,13 @@ F: hw/arm/npcm7xx* F: hw/mem/npcm7xx* F: hw/misc/npcm7xx* F: hw/nvram/npcm7xx* +F: hw/ssi/npcm7xx* F: hw/timer/npcm7xx* F: include/hw/arm/npcm7xx* F: include/hw/mem/npcm7xx* F: include/hw/misc/npcm7xx* F: include/hw/nvram/npcm7xx* +F: include/hw/ssi/npcm7xx* F: include/hw/timer/npcm7xx* nSeries diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 3738c1f5cd..8cc99f6190 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -360,6 +360,7 @@ config NPCM7XX select ARM_GIC select PL310 # cache controller select SERIAL +select SSI select UNIMP config FSL_IMX25 diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 54d84bafa1..50319d0d33 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -98,6 +98,37 @@ static const hwaddr npcm7xx_uart_addr[] = { 0xF0004000, }; +static const hwaddr npcm7xx_fiu0_flash_addr[] = { +0x8000, +0x8800, +}; + +static const hwaddr npcm7xx_fiu3_flash_addr[] = { +0xa000, +0xa800, +0xb000, +0xb800, +}; + +static const struct { +const char *name; +hwaddr regs_addr; +int cs_count; +const hwaddr *flash_addr; +} npcm7xx_fiu[] = { +{ +.name = "fiu0", +.regs_addr = 0xfb00, +.cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr), +.flash_addr = npcm7xx_fiu0_flash_addr, +}, { +.name = "fiu3", +.regs_addr = 0xc000, +.cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr), +.flash_addr = npcm7xx_fiu3_flash_addr, +}, +}; + void npcm7xx_write_secondary_boot(ARMCPU *cpu, const struct arm_boot_info *info) { /* @@ -169,6 +200,13 @@ static void npcm7xx_init(Object *obj) sysbus_init_child_obj(obj, "tim[*]", OBJECT(>tim[i]), sizeof(s->tim[i]), TYPE_NPCM7XX_TIMER); } + +QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu)); +for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { +sysbus_init_child_obj(obj, npcm7xx_fiu[i].name, + OBJECT(>fiu[i]), sizeof(s->fiu[i]), + TYPE_NPCM7XX_FIU); +} } static void npcm7xx_realize(DeviceState *dev, Error **errp) @@ -297,6 +335,27 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) serial_hd(i), DEVICE_LITTLE_ENDIAN); } +/* Flash Interface Unit (FIU) */ +QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu)); +for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { +Object *o = OBJECT(>fiu[i]); +int j; + +object_property_set_int(o, npcm7xx_fiu[i].cs_count, "cs-count", +_abort); +object_property_set_bool(o, true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} + +sysbus_mmio_map(SYS_BUS_DEVICE(o), 0, npcm7xx_fiu[i].regs_addr); +for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) { +sysbus_mmio_map(SYS_BUS_DEVICE(o), j + 1, +npcm7xx_fiu[i].flash_addr[j]); +} +} + /* RAM2 (SRAM) */ memory_region_init_ram(>sram, OBJECT(dev), "ram2", NPCM7XX_RAM2_SZ, ); diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs index 07a85f1967..cab48e72c9 100644 --- a/hw/ssi/Makefile.objs +++ b/hw/ssi/Makefile.objs @@ -5,6 +5,7 @@ common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o common-obj-$(CONFIG_MSF2) += mss-spi.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_fiu.o common-obj-$(CONFIG_OMAP) += omap_spi.o common-obj-$(CONFIG_IMX) += imx_spi.o diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c new file mode 100644 index 00..dd7e1c8a4e --- /dev/null +++ b/hw/ssi/npcm7xx_fiu.c @@ -0,0 +1,497 @@ +/* + * Nuvoton NPCM7xx Flash Interface Unit (FIU) + * + *
[PATCH v2 04/12] hw/timer: Add NPCM7xx Timer device model
The NPCM730 and NPCM750 SoCs have three timer modules each holding five timers and some shared registers (e.g. interrupt status). Each timer runs at 25 MHz divided by a prescaler, and counts down from a configurable initial value to zero. When zero is reached, the interrupt flag for the timer is set, and the timer is disabled (one-shot mode) or reloaded from its initial value (periodic mode). This implementation is sufficient to boot a Linux kernel configured for NPCM750. Note that the kernel does not seem to actually turn on the interrupts. Change-Id: I4305fc6bd81b81930737a9c06d0f7dd06f017797 Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/timer/Makefile.objs | 1 + hw/timer/npcm7xx_timer.c | 437 +++ hw/timer/trace-events| 5 + include/hw/timer/npcm7xx_timer.h | 95 +++ 5 files changed, 540 insertions(+) create mode 100644 hw/timer/npcm7xx_timer.c create mode 100644 include/hw/timer/npcm7xx_timer.h diff --git a/MAINTAINERS b/MAINTAINERS index efe7f499e3..97d24b1443 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -727,7 +727,9 @@ M: Tyrone Ting L: qemu-...@nongnu.org S: Supported F: hw/misc/npcm7xx* +F: hw/timer/npcm7xx* F: include/hw/misc/npcm7xx* +F: include/hw/timer/npcm7xx* nSeries M: Andrzej Zaborowski diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index dece235fd7..6ea6d644ad 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -14,6 +14,7 @@ common-obj-$(CONFIG_IMX) += imx_epit.o common-obj-$(CONFIG_IMX) += imx_gpt.o common-obj-$(CONFIG_LM32) += lm32_timer.o common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_timer.o common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o common-obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c new file mode 100644 index 00..9aae4b09b9 --- /dev/null +++ b/hw/timer/npcm7xx_timer.c @@ -0,0 +1,437 @@ +/* + * Nuvoton NPCM7xx Timer Controller + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/irq.h" +#include "hw/timer/npcm7xx_timer.h" +#include "qemu/bitops.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "trace.h" + +/* Register field definitions. */ +#define NPCM7XX_TCSR_CENBIT(30) +#define NPCM7XX_TCSR_IE BIT(29) +#define NPCM7XX_TCSR_PERIODIC BIT(27) +#define NPCM7XX_TCSR_CRST BIT(26) +#define NPCM7XX_TCSR_CACT BIT(25) +#define NPCM7XX_TCSR_RSVD 0x2100 +#define NPCM7XX_TCSR_PRESCALE_START 0 +#define NPCM7XX_TCSR_PRESCALE_LEN 8 + +/* The reference clock frequency is always 25 MHz. */ +#define NPCM7XX_TIMER_REF_HZ(2500) + +/* Return the value by which to divide the reference clock rate. */ +static uint32_t npcm7xx_timer_prescaler(const NPCM7xxTimer *t) +{ +return extract32(t->tcsr, NPCM7XX_TCSR_PRESCALE_START, + NPCM7XX_TCSR_PRESCALE_LEN) + 1; +} + +/* Convert a timer cycle count to a time interval in nanoseconds. */ +static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count) +{ +int64_t ns = count; + +ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ; +ns *= npcm7xx_timer_prescaler(t); + +return ns; +} + +/* Convert a time interval in nanoseconds to a timer cycle count. */ +static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns) +{ +int64_t count; + +count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ); +count /= npcm7xx_timer_prescaler(t); + +return count; +} + +/* + * Raise the interrupt line if there's a pending interrupt and interrupts are + * enabled for this timer. If not, lower it. + */ +static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t) +{ +NPCM7xxTimerCtrlState *tc = t->ctrl; +/* Find the array index of this timer. */ +int index = t - tc->timer; + +g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL); + +if ((t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index))) { +qemu_irq_raise(t->irq); +trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, 1); +} else { +qemu_irq_lower(t->irq); +trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, 0); +} +} + +/* Start or resume the timer. */ +static void
[PATCH v2 07/12] hw/arm: Load -bios image as a boot ROM for npcm7xx
If a -bios option is specified on the command line, load the image into the internal ROM memory region, which contains the first instructions run by the CPU after reset. A minimal Apache-2.0-licensed boot ROM can be found at https://github.com/google/vbootrom It is by no means feature complete, but it is enough to launch the Nuvoton bootblock[1] from offset 0 in the flash, which in turn will launch u-boot and finally the Linux kernel. [1] https://github.com/Nuvoton-Israel/bootblock Change-Id: I41eae4fc7786d33f532c14087e930bf1b5012562 Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- hw/arm/npcm7xx.c | 17 + 1 file changed, 17 insertions(+) diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index a5dbf08c00..417bc16b5c 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -22,6 +22,7 @@ #include "hw/misc/unimp.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qemu-common.h" #include "qemu/units.h" #include "sysemu/sysemu.h" @@ -270,6 +271,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) } memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, >irom); +if (bios_name) { +g_autofree char *filename = NULL; +int ret; + +filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); +if (!filename) { +error_setg(errp, "Could not find ROM image '%s'", bios_name); +return; +} +ret = load_image_mr(filename, >irom); +if (ret < 0) { +error_setg(errp, "Failed to load ROM image '%s'", filename); +return; +} +} + /* External DDR4 SDRAM */ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, s->dram); } -- 2.27.0.290.gba653c62da-goog
[PATCH v2 05/12] hw/arm: Add NPCM730 and NPCM750 SoC models
The Nuvoton NPCM7xx SoC family are used to implement Baseboard Management Controllers in servers. While the family includes four SoCs, this patch implements limited support for two of them: NPCM730 (targeted for Data Center applications) and NPCM750 (targeted for Enterprise applications). This patch includes little more than the bare minimum needed to boot a Linux kernel built with NPCM7xx support in direct-kernel mode: - Two Cortex-A9 CPU cores with built-in periperhals. - Global Configuration Registers. - Clock Management. - 3 Timer Modules with 5 timers each. - 4 serial ports. The chips themselves have a lot more features, some of which will be added to the model at a later stage. Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/Makefile.objs | 1 + hw/arm/npcm7xx.c | 330 +++ include/hw/arm/npcm7xx.h | 80 ++ 4 files changed, 413 insertions(+) create mode 100644 hw/arm/npcm7xx.c create mode 100644 include/hw/arm/npcm7xx.h diff --git a/MAINTAINERS b/MAINTAINERS index 97d24b1443..077c86643c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -726,8 +726,10 @@ M: Havard Skinnemoen M: Tyrone Ting L: qemu-...@nongnu.org S: Supported +F: hw/arm/npcm7xx* F: hw/misc/npcm7xx* F: hw/timer/npcm7xx* +F: include/hw/arm/npcm7xx* F: include/hw/misc/npcm7xx* F: include/hw/timer/npcm7xx* diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 534a6a119e..13d163a599 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -41,6 +41,7 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o +obj-$(CONFIG_NPCM7XX) += npcm7xx.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c new file mode 100644 index 00..a5dbf08c00 --- /dev/null +++ b/hw/arm/npcm7xx.c @@ -0,0 +1,330 @@ +/* + * Nuvoton NPCM7xx SoC family. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "exec/address-spaces.h" +#include "hw/arm/npcm7xx.h" +#include "hw/char/serial.h" +#include "hw/loader.h" +#include "hw/misc/unimp.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" + +/* The first half of the address space is reserved for DDR4 DRAM. */ +#define NPCM7XX_DRAM_BA (0x) +#define NPCM7XX_DRAM_SZ (2 * GiB) + +/* + * This covers the whole MMIO space. We'll use this to catch any MMIO accesses + * that aren't handled by any device. + */ +#define NPCM7XX_MMIO_BA (0x8000) +#define NPCM7XX_MMIO_SZ (0x7FFD) + +/* Core system modules. */ +#define NPCM7XX_L2C_BA (0xF03FC000) +#define NPCM7XX_CPUP_BA (0xF03FE000) +#define NPCM7XX_GCR_BA (0xF080) +#define NPCM7XX_CLK_BA (0xF0801000) + +/* Memory blocks at the end of the address space */ +#define NPCM7XX_RAM2_BA (0xFFFD) +#define NPCM7XX_RAM2_SZ (128 * KiB) +#define NPCM7XX_ROM_BA (0x) +#define NPCM7XX_ROM_SZ (64 * KiB) + +/* + * Interrupt lines going into the GIC. This does not include internal Cortex-A9 + * interrupts. + */ +enum NPCM7xxInterrupt { +NPCM7XX_UART0_IRQ = 2, +NPCM7XX_UART1_IRQ, +NPCM7XX_UART2_IRQ, +NPCM7XX_UART3_IRQ, +NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ +NPCM7XX_TIMER1_IRQ, +NPCM7XX_TIMER2_IRQ, +NPCM7XX_TIMER3_IRQ, +NPCM7XX_TIMER4_IRQ, +NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */ +NPCM7XX_TIMER6_IRQ, +NPCM7XX_TIMER7_IRQ, +NPCM7XX_TIMER8_IRQ, +NPCM7XX_TIMER9_IRQ, +NPCM7XX_TIMER10_IRQ,/* Timer Module 2 */ +NPCM7XX_TIMER11_IRQ, +NPCM7XX_TIMER12_IRQ, +NPCM7XX_TIMER13_IRQ, +NPCM7XX_TIMER14_IRQ, +}; + +/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */ +#define NPCM7XX_NUM_IRQ (160) + +/* Register base address for each Timer Module */ +static const hwaddr npcm7xx_tim_addr[] = { +0xF0008000, +0xF0009000, +0xF000A000, +}; + +/* Register base address for each 16550 UART */ +static const hwaddr npcm7xx_uart_addr[] = { +0xF0001000, +0xF0002000, +0xF0003000, +0xF0004000, +}; + +void
[PATCH v2 06/12] hw/arm: Add two NPCM7xx-based machines
This adds two new machines, both supported by OpenBMC: - npcm750-evb: Nuvoton NPCM750 Evaluation Board. - quanta-gsj: A board with a NPCM730 chip. They rely on the NPCM7xx SoC device to do the heavy lifting. They are almost completely identical at the moment, apart from the SoC type, which currently only changes the reset contents of one register (GCR.MDLR), but they might grow apart a bit more as more functionality is added. Both machines can boot the Linux kernel into /bin/sh. Change-Id: I852dd93020f849888979bc659a32d5da37ab9915 Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Reviewed-by: Cédric Le Goater Signed-off-by: Havard Skinnemoen --- hw/arm/Makefile.objs | 2 +- hw/arm/npcm7xx_boards.c | 141 +++ include/hw/arm/npcm7xx.h | 19 ++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 hw/arm/npcm7xx_boards.c diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 13d163a599..c333548ce1 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -41,7 +41,7 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o -obj-$(CONFIG_NPCM7XX) += npcm7xx.o +obj-$(CONFIG_NPCM7XX) += npcm7xx.o npcm7xx_boards.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c new file mode 100644 index 00..86e18af2d7 --- /dev/null +++ b/hw/arm/npcm7xx_boards.c @@ -0,0 +1,141 @@ +/* + * Machine definitions for boards featuring an NPCM7xx SoC. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/arm/boot.h" +#include "hw/arm/npcm7xx.h" +#include "hw/core/cpu.h" +#include "qapi/error.h" +#include "qemu/units.h" + +static struct arm_boot_info npcm7xx_binfo = { +.loader_start = NPCM7XX_LOADER_START, +.smp_loader_start = NPCM7XX_SMP_LOADER_START, +.smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR, +.gic_cpu_if_addr= NPCM7XX_GIC_CPU_IF_ADDR, +.write_secondary_boot = npcm7xx_write_secondary_boot, +.board_id = -1, +}; + +static 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(>cpu[0], machine, _binfo); +} + +static NPCM7xxState *npcm7xx_create_soc(MachineState *machine) +{ +NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine); +NPCM7xxState *soc; + +soc = NPCM7XX(object_new_with_props(nmc->soc_type, OBJECT(machine), "soc", +_abort, NULL)); +object_property_set_link(OBJECT(soc), OBJECT(machine->ram), "dram", + _abort); +object_property_set_bool(OBJECT(soc), true, "realized", _abort); + +return soc; +} + +static void npcm750_evb_init(MachineState *machine) +{ +NPCM7xxState *soc; + +soc = npcm7xx_create_soc(machine); + +npcm7xx_load_kernel(machine, soc); +} + +static void quanta_gsj_init(MachineState *machine) +{ +NPCM7xxState *soc; + +soc = npcm7xx_create_soc(machine); + +npcm7xx_load_kernel(machine, soc); +} + +static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type) +{ +NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type)); +MachineClass *mc = MACHINE_CLASS(nmc); + +nmc->soc_type = type; +mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus; +} + +static void npcm7xx_machine_class_init(ObjectClass *oc, void *data) +{ +MachineClass *mc = MACHINE_CLASS(oc); + +mc->no_floppy = 1; +mc->no_cdrom= 1; +mc->no_parallel = 1; +mc->default_ram_id = "ram"; +} + +/* + * Schematics: + * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf + */ +static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data) +{ +NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc); +MachineClass *mc = MACHINE_CLASS(oc); + +npcm7xx_set_soc_type(nmc, TYPE_NPCM750); + +mc->desc= "Nuvoton NPCM750 Evaluation Board (Cortex A9)"; +mc->init= npcm750_evb_init; +mc->default_ram_size = 512 * MiB; +}; + +static void
[PATCH v2 02/12] hw/misc: Add NPCM7xx System Global Control Registers device model
Implement a device model for the System Global Control Registers in the NPCM730 and NPCM750 BMC SoCs. This is primarily used to enable SMP boot (the boot ROM spins reading the SCRPAD register) and DDR memory initialization; other registers are best effort for now. The reset values of the MDLR and PWRON registers are determined by the SoC variant (730 vs 750) and board straps respectively. Change-Id: Ifeb596be28f4d5463f0b386df38b357677d1 Reviewed-by: Joel Stanley Reviewed-by: Cédric Le Goater Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 8 ++ hw/misc/Makefile.objs | 1 + hw/misc/npcm7xx_gcr.c | 211 ++ hw/misc/trace-events | 4 + include/hw/misc/npcm7xx_gcr.h | 76 5 files changed, 300 insertions(+) create mode 100644 hw/misc/npcm7xx_gcr.c create mode 100644 include/hw/misc/npcm7xx_gcr.h diff --git a/MAINTAINERS b/MAINTAINERS index 3abe3faa4e..efe7f499e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -721,6 +721,14 @@ S: Odd Fixes F: hw/arm/musicpal.c F: docs/system/arm/musicpal.rst +Nuvoton NPCM7xx +M: Havard Skinnemoen +M: Tyrone Ting +L: qemu-...@nongnu.org +S: Supported +F: hw/misc/npcm7xx* +F: include/hw/misc/npcm7xx* + nSeries M: Andrzej Zaborowski M: Peter Maydell diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 5aaca8a039..40a9d1c01e 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -51,6 +51,7 @@ common-obj-$(CONFIG_IMX) += imx_rngc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_gcr.o common-obj-$(CONFIG_OMAP) += omap_clk.o common-obj-$(CONFIG_OMAP) += omap_gpmc.o common-obj-$(CONFIG_OMAP) += omap_l4.o diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c new file mode 100644 index 00..af03bf4a01 --- /dev/null +++ b/hw/misc/npcm7xx_gcr.c @@ -0,0 +1,211 @@ +/* + * Nuvoton NPCM7xx System Global Control Registers. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_gcr.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#include "trace.h" + +static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = { +[NPCM7XX_GCR_PDID] = 0x04A92750, /* Poleg A1 */ +[NPCM7XX_GCR_MISCPE]= 0x, +[NPCM7XX_GCR_SPSWC] = 0x0003, +[NPCM7XX_GCR_INTCR] = 0x035E, +[NPCM7XX_GCR_HIFCR] = 0x004E, +[NPCM7XX_GCR_INTCR2]= (1U << 19), /* DDR initialized */ +[NPCM7XX_GCR_RESSR] = 0x8000, +[NPCM7XX_GCR_DSCNT] = 0x00c0, +[NPCM7XX_GCR_DAVCLVLR] = 0x5A00F3CF, +[NPCM7XX_GCR_SCRPAD]= 0x0008, +[NPCM7XX_GCR_USB1PHYCTL]= 0x034730E4, +[NPCM7XX_GCR_USB2PHYCTL]= 0x034730E4, +}; + +static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size) +{ +uint32_t reg = offset / sizeof(uint32_t); +NPCM7xxGCRState *s = opaque; + +if (reg >= NPCM7XX_GCR_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%04x out of range\n", + __func__, (unsigned int)offset); +return 0; +} + +trace_npcm7xx_gcr_read(offset, s->regs[reg]); + +return s->regs[reg]; +} + +static void npcm7xx_gcr_write(void *opaque, hwaddr offset, + uint64_t v, unsigned size) +{ +uint32_t reg = offset / sizeof(uint32_t); +NPCM7xxGCRState *s = opaque; +uint32_t value = v; + +trace_npcm7xx_gcr_write(offset, value); + +if (reg >= NPCM7XX_GCR_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%04x out of range\n", + __func__, (unsigned int)offset); +return; +} + +switch (reg) { +case NPCM7XX_GCR_PDID: +case NPCM7XX_GCR_PWRON: +case NPCM7XX_GCR_INTSR: +qemu_log_mask(LOG_GUEST_ERROR, "%s: register @ 0x%04x is read-only\n", + __func__, (unsigned int)offset); +return; + +case NPCM7XX_GCR_RESSR: +case NPCM7XX_GCR_CP2BST: +/* Write 1 to clear */ +value = s->regs[reg] & ~value; +break; + +case NPCM7XX_GCR_RLOCKR1: +case NPCM7XX_GCR_MDLR: +/* Write 1 to set */ +value |= s->regs[reg]; +break; +}; + +s->regs[reg] = value; +} + +static const struct MemoryRegionOps
[PATCH v2 01/12] npcm7xx: Add config symbol
Add a config symbol for the NPCM7xx BMC SoC family that subsequent patches can use in Makefiles. Change-Id: I6e4d5c58716cb6fe4ea5d06f148beeafda55f9a5 Reviewed-by: Tyrone Ting Acked-by: Joel Stanley Signed-off-by: Havard Skinnemoen --- default-configs/arm-softmmu.mak | 1 + hw/arm/Kconfig | 8 2 files changed, 9 insertions(+) diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 8fc09a4a51..9a94ebd0be 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -27,6 +27,7 @@ CONFIG_GUMSTIX=y CONFIG_SPITZ=y CONFIG_TOSA=y CONFIG_Z2=y +CONFIG_NPCM7XX=y CONFIG_COLLIE=y CONFIG_ASPEED_SOC=y CONFIG_NETDUINO2=y diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 9afa6eee79..3738c1f5cd 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -354,6 +354,14 @@ config XLNX_VERSAL select VIRTIO_MMIO select UNIMP +config NPCM7XX +bool +select A9MPCORE +select ARM_GIC +select PL310 # cache controller +select SERIAL +select UNIMP + config FSL_IMX25 bool select IMX -- 2.27.0.290.gba653c62da-goog
[PATCH v2 03/12] hw/misc: Add NPCM7xx Clock Controller device model
Enough functionality to boot the Linux kernel has been implemented. This includes: - Correct power-on reset values so the various clock rates can be accurately calculated. - Clock enables stick around when written. In addition, a best effort attempt to implement SECCNT and CNTR25M was made even though I don't think the kernel needs them. Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Reviewed-by: Cédric Le Goater Signed-off-by: Havard Skinnemoen --- hw/misc/Makefile.objs | 1 + hw/misc/npcm7xx_clk.c | 216 ++ hw/misc/trace-events | 4 + include/hw/misc/npcm7xx_clk.h | 65 ++ 4 files changed, 286 insertions(+) create mode 100644 hw/misc/npcm7xx_clk.c create mode 100644 include/hw/misc/npcm7xx_clk.h diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 40a9d1c01e..2e74803005 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -51,6 +51,7 @@ common-obj-$(CONFIG_IMX) += imx_rngc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_clk.o common-obj-$(CONFIG_NPCM7XX) += npcm7xx_gcr.o common-obj-$(CONFIG_OMAP) += omap_clk.o common-obj-$(CONFIG_OMAP) += omap_gpmc.o diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c new file mode 100644 index 00..2348683305 --- /dev/null +++ b/hw/misc/npcm7xx_clk.c @@ -0,0 +1,216 @@ +/* + * Nuvoton NPCM7xx Clock Control Registers. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_clk.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "trace.h" + +#define PLLCON_LOKI BIT(31) +#define PLLCON_LOKS BIT(30) +#define PLLCON_PWDENBIT(12) + +/* + * These reset values were taken from version 0.91 of the NPCM750R data sheet. + * + * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on + * core domain reset, but this reset type is not yet supported by QEMU. + */ +static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = { +[NPCM7XX_CLK_CLKEN1]= 0x, +[NPCM7XX_CLK_CLKSEL]= 0x004a, +[NPCM7XX_CLK_CLKDIV1] = 0x5413f855, +[NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI, +[NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI, +[NPCM7XX_CLK_IPSRST1] = 0x1000, +[NPCM7XX_CLK_IPSRST2] = 0x8000, +[NPCM7XX_CLK_CLKEN2]= 0x, +[NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f, +[NPCM7XX_CLK_CLKEN3]= 0x, +[NPCM7XX_CLK_IPSRST3] = 0x0300, +[NPCM7XX_CLK_WD0RCR]= 0x, +[NPCM7XX_CLK_WD1RCR]= 0x, +[NPCM7XX_CLK_WD2RCR]= 0x, +[NPCM7XX_CLK_SWRSTC1] = 0x0003, +[NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI, +[NPCM7XX_CLK_CORSTC]= 0x0403, +[NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI, +[NPCM7XX_CLK_AHBCKFI] = 0x00c8, +}; + +static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size) +{ +uint32_t reg = offset / sizeof(uint32_t); +NPCM7xxCLKState *s = opaque; +int64_t now_ns; +uint32_t value = 0; + +if (reg >= NPCM7XX_CLK_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%04x out of range\n", + __func__, (unsigned int)offset); +return 0; +} + +switch (reg) { +case NPCM7XX_CLK_SWRSTR: +qemu_log_mask(LOG_GUEST_ERROR, "%s: register @ 0x%04x is write-only\n", + __func__, (unsigned int)offset); +break; + +case NPCM7XX_CLK_SECCNT: +now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND; +break; + +case NPCM7XX_CLK_CNTR25M: +now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +/* + * This register counts 25 MHz cycles, updating every 640 ns. It rolls + * over to zero every second. + * + * The 4 LSBs are always zero: (1e9 / 640) << 4 = 2500. + */ +value = (((now_ns - s->ref_ns) / 640) << 4) % 2500; +break; + +default: +value = s->regs[reg]; +break; +}; + +trace_npcm7xx_clk_read(offset, value); + +return value; +} + +static void npcm7xx_clk_write(void *opaque, hwaddr
[PATCH v2 00/12] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines
This patch series models enough of the Nuvoton NPCM730 and NPCM750 SoCs to boot an OpenBMC image built for quanta-gsj. This includes device models for: - Global Configuration Registers - Clock Control - Timers - Fuses - Memory Controller - Flash Controller These modules, along with the existing Cortex A9 CPU cores and built-in peripherals, are integrated into a NPCM730 or NPCM750 SoC, which in turn form the foundation for the quanta-gsj and npcm750-evb machines, respectively. The two SoCs are very similar; the only difference is that NPCM730 is missing some peripherals that NPCM750 has, and which are not considered essential for datacenter use (e.g. graphics controllers). For more information, see https://www.nuvoton.com/products/cloud-computing/ibmc/ Both quanta-gsj and npcm750-evb correspond to real boards supported by OpenBMC. While this initial series uses a stripped-down kernel for testing, future series will be tested using OpenBMC images built from public sources. I'm currently putting the finishing touches on flash controller support, which is necessary to boot a full OpenBMC image, and will be enabled by the next series. The patches in this series were developed by Google and reviewed by Nuvoton. We will be maintaining the machine and peripheral support together. The data sheet for these SoCs is not generally available. Please let me know if more comments are needed to understand the device behavior. Changes since v1 (requested by reviewers): - Clarify the source of CLK reset values. - Made smpboot a constant byte array, eliinated byte swapping. - NPCM7xxState now stores an array of ARMCPUs, not pointers to ARMCPUs. - Clarify why EL3 is disabled. - Introduce NPCM7XX_NUM_IRQ constant. - Set the number of CPUs according to SoC variant, and disallow command line overrides (i.e. you can no longer override the number of CPUs with the -smp parameter). This is trying to follow the spirit of https://patchwork.kernel.org/patch/11595407/. - Switch register operations to DEVICE_LITTLE_ENDIAN throughout. - Machine documentation added (new patch). Changes since v1 to support flash booting: - GCR reset value changes to get past memory initialization when booting from flash (patches 2 and 5): - INTCR2 now indicates that the DDR controller is initialized. - INTCR3 is initialized according to DDR memory size. A realize() method was implemented to achieve this. - Refactor the machine initialization a bit to make it easier to drop in machine-specific flash initialization (patch 6). - Extend the series with additional patches to enable booting from flash: - Boot ROM (through the -bios option). - OTP (fuse) controller. - Memory Controller stub (just enough to skip memory training). - Flash controller. - Board-specific flash initialization. Thanks for reviewing, Havard Havard Skinnemoen (12): npcm7xx: Add config symbol hw/misc: Add NPCM7xx System Global Control Registers device model hw/misc: Add NPCM7xx Clock Controller device model hw/timer: Add NPCM7xx Timer device model hw/arm: Add NPCM730 and NPCM750 SoC models hw/arm: Add two NPCM7xx-based machines hw/arm: Load -bios image as a boot ROM for npcm7xx hw/nvram: NPCM7xx OTP device model hw/mem: Stubbed out NPCM7xx Memory Controller model hw/ssi: NPCM7xx Flash Interface Unit device model hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj docs/system: Add Nuvoton machine documentation MAINTAINERS | 18 ++ default-configs/arm-softmmu.mak | 1 + docs/system/arm/nuvoton.rst | 89 ++ docs/system/target-arm.rst | 1 + hw/arm/Kconfig | 9 + hw/arm/Makefile.objs | 1 + hw/arm/npcm7xx.c | 449 hw/arm/npcm7xx_boards.c | 168 +++ hw/mem/Makefile.objs | 1 + hw/mem/npcm7xx_mc.c | 83 ++ hw/misc/Makefile.objs| 2 + hw/misc/npcm7xx_clk.c| 216 ++ hw/misc/npcm7xx_gcr.c| 211 + hw/misc/trace-events | 8 + hw/nvram/Makefile.objs | 1 + hw/nvram/npcm7xx_otp.c | 391 hw/ssi/Makefile.objs | 1 + hw/ssi/npcm7xx_fiu.c | 497 +++ hw/ssi/trace-events | 9 + hw/timer/Makefile.objs | 1 + hw/timer/npcm7xx_timer.c | 437 +++ hw/timer/trace-events| 5 + include/hw/arm/npcm7xx.h | 106 +++ include/hw/mem/npcm7xx_mc.h | 35 +++ include/hw/misc/npcm7xx_clk.h| 65 include/hw/misc/npcm7xx_gcr.h| 76 + include/hw/nvram/npcm7xx_otp.h | 93 ++ include/hw/ssi/npcm7xx_fiu.h | 99 ++ include/hw/timer/npcm7xx_timer.h | 95 ++ 29 files changed, 3168 insertions(+) create mode 100644
Re: [PATCH v6 1/8] qcow2: Fix capitalization of header extension constant.
On 6/11/20 4:19 PM, Andrey Shinkevich wrote: Make the capitalization of the hexadecimal numbers consistent for the QCOW2 header extension constants in docs/interop/qcow2.txt. Suggested-by: Eric Blake Signed-off-by: Andrey Shinkevich --- block/qcow2.c | 2 +- docs/interop/qcow2.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) tests/qemu-iotests/114 has an instance that could be adjusted as well (no change to 114.out). With that added, Reviewed-by: Eric Blake -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Re: [PULL v2 0/3] NBD patches through 2020-06-09
On Wed, 10 Jun 2020 at 19:07, Eric Blake wrote: > > The following changes since commit 31d321c2b3574dcc74e9f6411af06bca6b5d10f4: > > Merge remote-tracking branch > 'remotes/philmd-gitlab/tags/sparc-next-20200609' into staging (2020-06-09 > 17:29:47 +0100) > > are available in the Git repository at: > > https://repo.or.cz/qemu/ericb.git tags/pull-nbd-2020-06-09-v2 > > for you to fetch changes up to 5c86bdf1208916ece0b87e1151c9b48ee54faa3e: > > block: Call attention to truncation of long NBD exports (2020-06-10 > 12:58:59 -0500) > > In v2: patch 2 adjusted per review (only sending the changed patch) > > > NBD patches for 2020-06-09 > > - fix iotest 194 race > - fix CVE-2020-10761: server DoS from assertion on long NBD error messages > Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/5.1 for any user-visible changes. -- PMM
[PATCH v6 0/8] iotests: Dump QCOW2 dirty bitmaps metadata
Note: based on the Vladimir's series [v5 00/13] iotests: Dump QCOW2 dirty bitmaps metadata Add dirty bitmap information to QCOW2 metadata dump in the qcow2_format.py. v6: 01: Fixing capitalization of header extension constant. (Suggested by Eric) 02: The cluster size global variable discarded and passed as a parameter. 03: Re-based to Vladimir's v5 series. 04: The code of passing qcow2.py JSON format key moved to separate patch. 05: Making dict(s) for dumping in JSON format was substituted with a copy of __dict__. v5: The Vladimir's preliminary series v4: The Vladimir's preliminary series Andrey Shinkevich (8): qcow2: Fix capitalization of header extension constant. qcow2_format.py: make printable data an extension class member qcow2_format.py: Dump bitmap directory info qcow2_format.py: pass cluster size to substructures qcow2_format.py: Dump bitmap table serialized entries qcow2.py: Introduce '-j' key to dump in JSON format qcow2_format.py: collect fields to dump in JSON format qcow2_format.py: support dumping metadata in JSON format block/qcow2.c | 2 +- docs/interop/qcow2.txt | 2 +- tests/qemu-iotests/qcow2.py| 20 +++- tests/qemu-iotests/qcow2_format.py | 219 ++--- 4 files changed, 222 insertions(+), 21 deletions(-) -- 1.8.3.1
[PATCH v6 1/8] qcow2: Fix capitalization of header extension constant.
Make the capitalization of the hexadecimal numbers consistent for the QCOW2 header extension constants in docs/interop/qcow2.txt. Suggested-by: Eric Blake Signed-off-by: Andrey Shinkevich --- block/qcow2.c | 2 +- docs/interop/qcow2.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 0cd2e67..80dfe5f 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -66,7 +66,7 @@ typedef struct { } QEMU_PACKED QCowExtension; #define QCOW2_EXT_MAGIC_END 0 -#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA +#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xe2792aca #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 #define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 #define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index cb72346..f072e27 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -231,7 +231,7 @@ be stored. Each extension has a structure like the following: Byte 0 - 3: Header extension type: 0x - End of the header extension area -0xE2792ACA - Backing file format name string +0xe2792aca - Backing file format name string 0x6803f857 - Feature name table 0x23852875 - Bitmaps extension 0x0537be77 - Full disk encryption header pointer -- 1.8.3.1
[PATCH v6 3/8] qcow2_format.py: Dump bitmap directory info
Read and dump entries from the bitmap directory of QCOW2 image with the script qcow2.py. Header extension: magic 0x23852875 (Bitmaps) ... Bitmap name bitmap-1 flag auto table size8 (bytes) bitmap_table_offset 0x9 bitmap_table_size 1 flags 0 type 1 granularity_bits 16 name_size 8 extra_data_size 0 Suggested-by: Kevin Wolf Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/qcow2_format.py | 75 ++ 1 file changed, 75 insertions(+) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index d4f..a7868a7 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -103,6 +103,10 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): print('{:<25} {}'.format(f[2], value_str)) +# seek relative to the current position in the file +FROM_CURRENT = 1 + + class Qcow2BitmapExt(Qcow2Struct): fields = ( @@ -112,6 +116,73 @@ class Qcow2BitmapExt(Qcow2Struct): ('u64', '{:#x}', 'bitmap_directory_offset') ) +def read_bitmap_directory(self, fd): +self.bitmaps = [] +fd.seek(self.bitmap_directory_offset) +buf_size = struct.calcsize(Qcow2BitmapDirEntry.fmt) + +for n in range(self.nb_bitmaps): +buf = fd.read(buf_size) +dir_entry = Qcow2BitmapDirEntry(data=buf) +fd.seek(dir_entry.extra_data_size, FROM_CURRENT) +bitmap_name = fd.read(dir_entry.name_size) +dir_entry.name = bitmap_name.decode('ascii') +self.bitmaps.append(dir_entry) +entry_raw_size = dir_entry.bitmap_dir_entry_raw_size() +shift = ((entry_raw_size + 7) & ~7) - entry_raw_size +fd.seek(shift, FROM_CURRENT) + +def load(self, fd): +self.read_bitmap_directory(fd) + +def dump(self): +super().dump() +for bm in self.bitmaps: +bm.dump_bitmap_dir_entry() + + +BME_FLAG_IN_USE = 1 << 0 +BME_FLAG_AUTO = 1 << 1 + + +class Qcow2BitmapDirEntry(Qcow2Struct): + +name = '' + +fields = ( +('u64', '{:#x}', 'bitmap_table_offset'), +('u32', '{}','bitmap_table_size'), +('u32', '{}','flags'), +('u8', '{}','type'), +('u8', '{}','granularity_bits'), +('u16', '{}','name_size'), +('u32', '{}','extra_data_size') +) + +def __init__(self, data): +super().__init__(data=data) + +self.bitmap_table_bytes = self.bitmap_table_size \ +* struct.calcsize('Q') + +self.bitmap_flags = [] +if (self.flags & BME_FLAG_IN_USE): +self.bitmap_flags.append("in-use") +if (self.flags & BME_FLAG_AUTO): +self.bitmap_flags.append("auto") + +def bitmap_dir_entry_raw_size(self): +return struct.calcsize(self.fmt) + self.name_size + \ +self.extra_data_size + +def dump_bitmap_dir_entry(self): +print() +print(f'{"Bitmap name":<25} {self.name}') +for fl in self.bitmap_flags: +print(f'{"flag":<25} {fl}') +print(f'{"table size ":<25} {self.bitmap_table_bytes} {"(bytes)"}') +super().dump() + QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 @@ -253,6 +324,10 @@ class QcowHeader(Qcow2Struct): else: self.extensions.append(ext) +for ext in self.extensions: +if ext.obj is not None: +ext.obj.load(fd) + def update_extensions(self, fd): fd.seek(self.header_length) -- 1.8.3.1
[PATCH v6 5/8] qcow2_format.py: Dump bitmap table serialized entries
Add bitmap table information to the QCOW2 metadata dump. Bitmap name bitmap-1 ... Bitmap tabletypeoffset size 0 serialized 0xa 65536 1 all-zeroes 0x0 65536 2 all-zeroes 0x0 65536 3 all-zeroes 0x0 65536 4 all-zeroes 0x0 65536 5 all-zeroes 0x0 65536 6 all-zeroes 0x0 65536 7 all-zeroes 0x0 65536 Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake --- tests/qemu-iotests/qcow2_format.py | 42 ++ 1 file changed, 42 insertions(+) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 6589f68..2e7c058 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -137,6 +137,9 @@ class Qcow2BitmapExt(Qcow2Struct): shift = ((entry_raw_size + 7) & ~7) - entry_raw_size fd.seek(shift, FROM_CURRENT) +for bm in self.bitmaps: +bm.read_bitmap_table(fd) + def load(self, fd): self.read_bitmap_directory(fd) @@ -181,6 +184,12 @@ class Qcow2BitmapDirEntry(Qcow2Struct): return struct.calcsize(self.fmt) + self.name_size + \ self.extra_data_size +def read_bitmap_table(self, fd): +fd.seek(self.bitmap_table_offset) +table_size = self.bitmap_table_bytes * struct.calcsize('Q') +table = [e[0] for e in struct.iter_unpack('>Q', fd.read(table_size))] +self.bitmap_table = Qcow2BitmapTable(table) + def dump_bitmap_dir_entry(self): print() print(f'{"Bitmap name":<25} {self.name}') @@ -188,6 +197,39 @@ class Qcow2BitmapDirEntry(Qcow2Struct): print(f'{"flag":<25} {fl}') print(f'{"table size ":<25} {self.bitmap_table_bytes} {"(bytes)"}') super().dump() +self.bitmap_table.print_bitmap_table(self.cluster_size) + + +class Qcow2BitmapTableEntry: + +BME_TABLE_ENTRY_OFFSET_MASK = 0x00fffe00 +BME_TABLE_ENTRY_FLAG_ALL_ONES = 1 +bmte_type = ['all-zeroes', 'all-ones', 'serialized'] + +def __init__(self, entry): +self.offset = entry & self.BME_TABLE_ENTRY_OFFSET_MASK +if self.offset: +self.type = 'serialized' +elif entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES: +self.type = 'all-ones' +else: +self.type = 'all-zeroes' + + +class Qcow2BitmapTable: + +def __init__(self, raw_table): +self.entries = [] +for entry in raw_table: +self.entries.append(Qcow2BitmapTableEntry(entry)) + +def print_bitmap_table(self, cluster_size): +bitmap_table = enumerate(self.entries) +print("Bitmap table\ttype\t\toffset\t\tsize") +for i, entry in bitmap_table: +print("\t%-4d\t%s\t%#x\t\t%d" % (i, entry.type, entry.offset, + cluster_size)) +print("") QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 -- 1.8.3.1
[PATCH v6 8/8] qcow2_format.py: support dumping metadata in JSON format
Implementation of dumping QCOW2 image metadata. The sample output: { "Header_extensions": [ { "name": "Feature table", "magic": 1745090647, "length": 192, "data_str": "" }, { "name": "Bitmaps", "magic": 595929205, "length": 24, "data": { "nb_bitmaps": 2, "reserved32": 0, "bitmap_directory_size": 64, "bitmap_directory_offset": 1048576, "entries": [ { "name": "bitmap-1", "bitmap_table_offset": 589824, "bitmap_table_size": 1, "flags": [ "auto" ], "type": 1, "granularity_bits": 16, "name_size": 8, "extra_data_size": 0, "bitmap_table": { "table_entries": [ { "type": "serialized", "offset": 655360 }, ... Suggested-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 60 ++ 1 file changed, 60 insertions(+) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index bb2f13b..d87f8e0 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -18,6 +18,15 @@ import struct import string +import json + + +class ComplexEncoder(json.JSONEncoder): +def default(self, obj): +if hasattr(obj, 'get_fields_dict'): +return obj.get_fields_dict() +else: +return json.JSONEncoder.default(self, obj) class Qcow2Field: @@ -95,6 +104,11 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.fields_dict = self.__dict__.copy() def dump(self, dump_json=None): +if dump_json: +print(json.dumps(self.get_fields_dict(), indent=4, + cls=ComplexEncoder)) +return + for f in self.fields: value = self.__dict__[f[2]] if isinstance(f[1], str): @@ -150,6 +164,9 @@ class Qcow2BitmapExt(Qcow2Struct): for bm in self.bitmaps: bm.dump_bitmap_dir_entry(dump_json) +def get_fields_dict(self): +return self.fields_dict + BME_FLAG_IN_USE = 1 << 0 BME_FLAG_AUTO = 1 << 1 @@ -202,6 +219,12 @@ class Qcow2BitmapDirEntry(Qcow2Struct): super().dump() self.bitmap_table.print_bitmap_table(self.cluster_size) +def get_fields_dict(self): +bmp_name = dict(name=self.name) +bme_dict = {**bmp_name, **self.fields_dict} +bme_dict['flags'] = self.bitmap_flags +return bme_dict + class Qcow2BitmapTableEntry: @@ -218,6 +241,9 @@ class Qcow2BitmapTableEntry: else: self.type = 'all-zeroes' +def get_fields_dict(self): +return dict(type=self.type, offset=self.offset) + class Qcow2BitmapTable: @@ -234,6 +260,18 @@ class Qcow2BitmapTable: cluster_size)) print("") +def get_fields_dict(self): +return dict(table_entries=self.entries) + + +class Qcow2HeaderExtensionsDoc: + +def __init__(self, extensions): +self.extensions = extensions + +def get_fields_dict(self): +return dict(Header_extensions=self.extensions) + QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 @@ -249,6 +287,9 @@ class QcowHeaderExtension(Qcow2Struct): 0x44415441: 'Data file' } +def get_fields_dict(self): +return self.mapping.get(self.value, "") + fields = ( ('u32', Magic, 'magic'), ('u32', '{}', 'length') @@ -309,6 +350,16 @@ class QcowHeaderExtension(Qcow2Struct): else: self.obj.dump(dump_json) +def get_fields_dict(self): +ext_name = dict(name=self.Magic(self.magic)) +he_dict = {**ext_name, **self.fields_dict} +if self.obj is not None: +he_dict.update(data=self.obj) +else: +he_dict.update(data_str=self.data_str) + +return he_dict + @classmethod def create(cls, magic, data): return QcowHeaderExtension(magic, len(data), data) @@ -411,7 +462,16 @@ class QcowHeader(Qcow2Struct): fd.write(buf) def dump_extensions(self, dump_json=None): +if dump_json: +ext_doc = Qcow2HeaderExtensionsDoc(self.extensions) +print(json.dumps(ext_doc.get_fields_dict(), indent=4, + cls=ComplexEncoder)) +return + for ex in self.extensions: print('Header
[PATCH v6 7/8] qcow2_format.py: collect fields to dump in JSON format
As __dict__ is being extended with class members we do not want to print in JSON format dump, make a light copy of the initial __dict__ and extend the copy by adding lists we have to print in the JSON output. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 95db7a9..bb2f13b 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -92,6 +92,8 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.__dict__ = dict((field[2], values[i]) for i, field in enumerate(self.fields)) +self.fields_dict = self.__dict__.copy() + def dump(self, dump_json=None): for f in self.fields: value = self.__dict__[f[2]] @@ -102,7 +104,6 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): print('{:<25} {}'.format(f[2], value_str)) - # seek relative to the current position in the file FROM_CURRENT = 1 @@ -142,6 +143,7 @@ class Qcow2BitmapExt(Qcow2Struct): def load(self, fd): self.read_bitmap_directory(fd) +self.fields_dict.update(entries=self.bitmaps) def dump(self, dump_json=None): super().dump(dump_json) @@ -189,6 +191,7 @@ class Qcow2BitmapDirEntry(Qcow2Struct): table_size = self.bitmap_table_bytes * struct.calcsize('Q') table = [e[0] for e in struct.iter_unpack('>Q', fd.read(table_size))] self.bitmap_table = Qcow2BitmapTable(table) +self.fields_dict.update(bitmap_table=self.bitmap_table) def dump_bitmap_dir_entry(self, dump_json=None): print() -- 1.8.3.1
[PATCH v6 2/8] qcow2_format.py: make printable data an extension class member
Let us differ binary data type from string one for the extension data variable and keep the string as the QcowHeaderExtension class member. Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/qcow2_format.py | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 0f65fd1..d4f 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -164,6 +164,13 @@ class QcowHeaderExtension(Qcow2Struct): self.data = fd.read(padded) assert self.data is not None +data_str = self.data[:self.length] +if all(c in string.printable.encode('ascii') for c in data_str): +data_str = f"'{ data_str.decode('ascii') }'" +else: +data_str = '' +self.data_str = data_str + if self.magic == QCOW2_EXT_MAGIC_BITMAPS: self.obj = Qcow2BitmapExt(data=self.data) else: @@ -173,12 +180,7 @@ class QcowHeaderExtension(Qcow2Struct): super().dump() if self.obj is None: -data = self.data[:self.length] -if all(c in string.printable.encode('ascii') for c in data): -data = f"'{ data.decode('ascii') }'" -else: -data = '' -print(f'{"data":<25} {data}') +print(f'{"data":<25} {self.data_str}') else: self.obj.dump() -- 1.8.3.1
[PATCH v6 6/8] qcow2.py: Introduce '-j' key to dump in JSON format
Add the command key to the qcow2.py arguments list to dump QCOW2 metadata in JSON format. Here is the suggested way to do that. The implementation of the dump in JSON format is in the patch that follows. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2.py| 20 +++- tests/qemu-iotests/qcow2_format.py | 18 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 8c187e9..b08d8fc 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -24,16 +24,19 @@ from qcow2_format import ( ) +dump_json = False + + def cmd_dump_header(fd): h = QcowHeader(fd) -h.dump() +h.dump(dump_json) print() -h.dump_extensions() +h.dump_extensions(dump_json) def cmd_dump_header_exts(fd): h = QcowHeader(fd) -h.dump_extensions() +h.dump_extensions(dump_json) def cmd_set_header(fd, name, value): @@ -132,6 +135,11 @@ cmds = [ def main(filename, cmd, args): +global dump_json +dump_json = '-j' in sys.argv +if dump_json: +sys.argv.remove('-j') +args.remove('-j') fd = open(filename, "r+b") try: for name, handler, num_args, desc in cmds: @@ -149,12 +157,14 @@ def main(filename, cmd, args): def usage(): -print("Usage: %s [, ...]" % sys.argv[0]) +print("Usage: %s [, ...] [, ...]" % sys.argv[0]) print("") print("Supported commands:") for name, handler, num_args, desc in cmds: print("%-20s - %s" % (name, desc)) - +print("") +print("Supported keys:") +print("%-20s - %s" % ('-j', 'Dump in JSON format')) if __name__ == '__main__': if len(sys.argv) < 3: diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index 2e7c058..95db7a9 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -92,7 +92,7 @@ class Qcow2Struct(metaclass=Qcow2StructMeta): self.__dict__ = dict((field[2], values[i]) for i, field in enumerate(self.fields)) -def dump(self): +def dump(self, dump_json=None): for f in self.fields: value = self.__dict__[f[2]] if isinstance(f[1], str): @@ -143,10 +143,10 @@ class Qcow2BitmapExt(Qcow2Struct): def load(self, fd): self.read_bitmap_directory(fd) -def dump(self): -super().dump() +def dump(self, dump_json=None): +super().dump(dump_json) for bm in self.bitmaps: -bm.dump_bitmap_dir_entry() +bm.dump_bitmap_dir_entry(dump_json) BME_FLAG_IN_USE = 1 << 0 @@ -190,7 +190,7 @@ class Qcow2BitmapDirEntry(Qcow2Struct): table = [e[0] for e in struct.iter_unpack('>Q', fd.read(table_size))] self.bitmap_table = Qcow2BitmapTable(table) -def dump_bitmap_dir_entry(self): +def dump_bitmap_dir_entry(self, dump_json=None): print() print(f'{"Bitmap name":<25} {self.name}') for fl in self.bitmap_flags: @@ -298,13 +298,13 @@ class QcowHeaderExtension(Qcow2Struct): else: self.obj = None -def dump(self): +def dump(self, dump_json=None): super().dump() if self.obj is None: print(f'{"data":<25} {self.data_str}') else: -self.obj.dump() +self.obj.dump(dump_json) @classmethod def create(cls, magic, data): @@ -407,8 +407,8 @@ class QcowHeader(Qcow2Struct): buf = buf[0:header_bytes-1] fd.write(buf) -def dump_extensions(self): +def dump_extensions(self, dump_json=None): for ex in self.extensions: print('Header extension:') -ex.dump() +ex.dump(dump_json) print() -- 1.8.3.1
[PATCH v6 4/8] qcow2_format.py: pass cluster size to substructures
The cluster size of an image is the QcowHeader class member and may be obtained by dependent extension structures such as Qcow2BitmapExt for further bitmap table details print. Signed-off-by: Andrey Shinkevich --- tests/qemu-iotests/qcow2_format.py | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py index a7868a7..6589f68 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -116,6 +116,10 @@ class Qcow2BitmapExt(Qcow2Struct): ('u64', '{:#x}', 'bitmap_directory_offset') ) +def __init__(self, data, cluster_size): +super().__init__(data=data) +self.cluster_size = cluster_size + def read_bitmap_directory(self, fd): self.bitmaps = [] fd.seek(self.bitmap_directory_offset) @@ -123,7 +127,8 @@ class Qcow2BitmapExt(Qcow2Struct): for n in range(self.nb_bitmaps): buf = fd.read(buf_size) -dir_entry = Qcow2BitmapDirEntry(data=buf) +dir_entry = Qcow2BitmapDirEntry(data=buf, +cluster_size=self.cluster_size) fd.seek(dir_entry.extra_data_size, FROM_CURRENT) bitmap_name = fd.read(dir_entry.name_size) dir_entry.name = bitmap_name.decode('ascii') @@ -159,8 +164,9 @@ class Qcow2BitmapDirEntry(Qcow2Struct): ('u32', '{}','extra_data_size') ) -def __init__(self, data): +def __init__(self, data, cluster_size): super().__init__(data=data) +self.cluster_size = cluster_size self.bitmap_table_bytes = self.bitmap_table_size \ * struct.calcsize('Q') @@ -205,11 +211,13 @@ class QcowHeaderExtension(Qcow2Struct): # then padding to next multiply of 8 ) -def __init__(self, magic=None, length=None, data=None, fd=None): +def __init__(self, magic=None, length=None, data=None, fd=None, + cluster_size=None): """ Support both loading from fd and creation from user data. For fd-based creation current position in a file will be used to read the data. +The cluster_size value may be obtained by dependent structures. This should be somehow refactored and functionality should be moved to superclass (to allow creation of any qcow2 struct), but then, fields @@ -243,7 +251,8 @@ class QcowHeaderExtension(Qcow2Struct): self.data_str = data_str if self.magic == QCOW2_EXT_MAGIC_BITMAPS: -self.obj = Qcow2BitmapExt(data=self.data) +self.obj = Qcow2BitmapExt(data=self.data, + cluster_size=cluster_size) else: self.obj = None @@ -318,7 +327,7 @@ class QcowHeader(Qcow2Struct): end = self.cluster_size while fd.tell() < end: -ext = QcowHeaderExtension(fd=fd) +ext = QcowHeaderExtension(fd=fd, cluster_size=self.cluster_size) if ext.magic == 0: break else: -- 1.8.3.1
Re: [PATCH v3 1/2] PCI: vmd: Filter resource type bits from shadow register
On Fri, 2020-05-29 at 17:18 +0100, Lorenzo Pieralisi wrote: > On Fri, May 29, 2020 at 03:53:37PM +, Derrick, Jonathan wrote: > > On Fri, 2020-05-29 at 11:33 +0100, Lorenzo Pieralisi wrote: > > > On Wed, May 27, 2020 at 11:02:39PM -0400, Jon Derrick wrote: > > > > Versions of VMD with the Host Physical Address shadow register use this > > > > register to calculate the bus address offset needed to do guest > > > > passthrough of the domain. This register shadows the Host Physical > > > > Address registers including the resource type bits. After calculating > > > > the offset, the extra resource type bits lead to the VMD resources being > > > > over-provisioned at the front and under-provisioned at the back. > > > > > > > > Example: > > > > pci 1:80:02.0: reg 0x10: [mem 0xf801fffc-0xf803fffb 64bit] > > > > > > > > Expected: > > > > pci 1:80:02.0: reg 0x10: [mem 0xf802-0xf803 64bit] > > > > > > > > If other devices are mapped in the over-provisioned front, it could lead > > > > to resource conflict issues with VMD or those devices. > > > > > > > > Fixes: a1a30170138c9 ("PCI: vmd: Fix shadow offsets to reflect spec > > > > changes") > > > > Signed-off-by: Jon Derrick > > > > --- > > > > drivers/pci/controller/vmd.c | 6 -- > > > > 1 file changed, 4 insertions(+), 2 deletions(-) > > > > > > Hi Jon, > > > > > > it looks like I can take this patch for v5.8 whereas patch 2 depends > > > on the QEMU changes acceptance and should probably wait. > > > > > > Please let me know your thoughts asap and I will try to at least > > > squeeze this patch in. > > > > > > Lorenzo > > > > Hi Lorenzo, > > > > This is fine. Please take Patch 1. > > Patch 2 is harmless without the QEMU changes, but may always need a > > different approach. > > Pulled patch 1 into pci/vmd, thanks. > > Lorenzo Hi Lorenzo, Alex has pr-ed the QEMU patch [1] Is it too late to pull patch 2/2 for v5.8? [1] https://github.com/awilliam/qemu-vfio/releases/tag/vfio-update-20200611.0
[PULL 106/115] target/i386: sev: Remove redundant policy field
From: David Gibson SEVState::policy is set from the final value of the policy field in the parameter structure for the KVM_SEV_LAUNCH_START ioctl(). But, AFAICT that ioctl() won't ever change it from the original supplied value which comes from SevGuestState::policy. So, remove this field and just use SevGuestState::policy directly. Signed-off-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-8-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index d25af37136..4b261beaa7 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -39,7 +39,6 @@ struct SEVState { uint8_t api_major; uint8_t api_minor; uint8_t build_id; -uint32_t policy; uint64_t me_mask; uint32_t handle; int sev_fd; @@ -397,7 +396,7 @@ sev_get_info(void) info->api_major = sev_guest->state.api_major; info->api_minor = sev_guest->state.api_minor; info->build_id = sev_guest->state.build_id; -info->policy = sev_guest->state.policy; +info->policy = sev_guest->policy; info->state = sev_guest->state.state; info->handle = sev_guest->state.handle; } @@ -520,8 +519,7 @@ sev_launch_start(SevGuestState *sev) start->handle = object_property_get_int(OBJECT(sev), "handle", _abort); -start->policy = object_property_get_int(OBJECT(sev), "policy", -_abort); +start->policy = sev->policy; if (sev->session_file) { if (sev_read_file_base64(sev->session_file, , ) < 0) { goto out; @@ -550,7 +548,6 @@ sev_launch_start(SevGuestState *sev) _abort); sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE); s->handle = start->handle; -s->policy = start->policy; ret = 0; out: -- 2.26.2
[PULL 113/115] replay: fix replay shutdown for console mode
From: Pavel Dovgalyuk When QEMU is used without any graphical window, QEMU execution is terminated with the signal (e.g., Ctrl-C). Signal processing in QEMU does not include qemu_system_shutdown_request call. That is why shutdown event is not recorded by record/replay in this case. This patch adds shutdown event to the end of the record log. Now every replay will shutdown the machine at the end. Signed-off-by: Pavel Dovgalyuk Message-Id: <159012995470.27967.18129611453659045726.stgit@pasha-ThinkPad-X280> Signed-off-by: Paolo Bonzini --- replay/replay.c | 5 + 1 file changed, 5 insertions(+) diff --git a/replay/replay.c b/replay/replay.c index 706c7b4f4b..7d93746c73 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -366,6 +366,11 @@ void replay_finish(void) /* finalize the file */ if (replay_file) { if (replay_mode == REPLAY_MODE_RECORD) { +/* + * Can't do it in the signal handler, therefore + * add shutdown event here for the case of Ctrl-C. + */ +replay_shutdown_request(SHUTDOWN_CAUSE_HOST_SIGNAL); /* write end event */ replay_put_event(EVENT_END); -- 2.26.2
[PULL 109/115] checkpatch: reversed logic with acpi test checks
From: "Michael S. Tsirkin" Logic reversed: allowed list should just be ignored. Instead we only take that into account :( Fixes: e11b06a880ca ("checkpatch: ignore allowed diff list") Signed-off-by: Michael S. Tsirkin Message-Id: <20200602053614.54745-1-...@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Eric Auger Tested-by: Eric Auger Signed-off-by: Paolo Bonzini --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0ba213e9f2..2d2e922d89 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1267,7 +1267,7 @@ sub checkfilename { # files and when changing tests. if ($name =~ m#^tests/data/acpi/# and not $name =~ m#^\.sh$#) { $$acpi_testexpected = $name; - } elsif ($name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { + } elsif ($name !~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { $$acpi_nontestexpected = $name; } if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) { -- 2.26.2
[PATCH 1/1] util/getauxval: Porting to FreeBSD getauxval feature
0001-util-getauxval-Porting-to-FreeBSD-the-getauxval-feat.patch Description: Binary data
[PULL 108/115] target/i386: sev: Unify SEVState and SevGuestState
From: David Gibson SEVState is contained with SevGuestState. We've now fixed redundancies and name conflicts, so there's no real point to the nested structure. Just move all the fields of SEVState into SevGuestState. This eliminates the SEVState structure, which as a bonus removes the confusion with the SevState enum. Signed-off-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-10-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 79 --- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 24e2dea9b8..d273174ad3 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -35,18 +35,6 @@ typedef struct SevGuestState SevGuestState; -struct SEVState { -uint8_t api_major; -uint8_t api_minor; -uint8_t build_id; -uint64_t me_mask; -int sev_fd; -SevState state; -gchar *measurement; -}; - -typedef struct SEVState SEVState; - /** * SevGuestState: * @@ -70,7 +58,13 @@ struct SevGuestState { /* runtime state */ uint32_t handle; -SEVState state; +uint8_t api_major; +uint8_t api_minor; +uint8_t build_id; +uint64_t me_mask; +int sev_fd; +SevState state; +gchar *measurement; }; #define DEFAULT_GUEST_POLICY0x1 /* disable debug */ @@ -158,7 +152,7 @@ static bool sev_check_state(const SevGuestState *sev, SevState state) { assert(sev); -return sev->state.state == state ? true : false; +return sev->state == state ? true : false; } static void @@ -167,9 +161,9 @@ sev_set_guest_state(SevGuestState *sev, SevState new_state) assert(new_state < SEV_STATE__MAX); assert(sev); -trace_kvm_sev_change_state(SevState_str(sev->state.state), +trace_kvm_sev_change_state(SevState_str(sev->state), SevState_str(new_state)); -sev->state.state = new_state; +sev->state = new_state; } static void @@ -368,7 +362,7 @@ sev_enabled(void) uint64_t sev_get_me_mask(void) { -return sev_guest ? sev_guest->state.me_mask : ~0; +return sev_guest ? sev_guest->me_mask : ~0; } uint32_t @@ -392,11 +386,11 @@ sev_get_info(void) info->enabled = sev_enabled(); if (info->enabled) { -info->api_major = sev_guest->state.api_major; -info->api_minor = sev_guest->state.api_minor; -info->build_id = sev_guest->state.build_id; +info->api_major = sev_guest->api_major; +info->api_minor = sev_guest->api_minor; +info->build_id = sev_guest->build_id; info->policy = sev_guest->policy; -info->state = sev_guest->state.state; +info->state = sev_guest->state; info->handle = sev_guest->handle; } @@ -507,7 +501,6 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len) static int sev_launch_start(SevGuestState *sev) { -SEVState *s = >state; gsize sz; int ret = 1; int fw_error, rc; @@ -535,7 +528,7 @@ sev_launch_start(SevGuestState *sev) } trace_kvm_sev_launch_start(start->policy, session, dh_cert); -rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, _error); +rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, _error); if (rc < 0) { error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); @@ -566,7 +559,7 @@ sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len) update.uaddr = (__u64)(unsigned long)addr; update.len = len; trace_kvm_sev_launch_update_data(addr, len); -ret = sev_ioctl(sev->state.sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, +ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, , _error); if (ret) { error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'", @@ -582,7 +575,6 @@ sev_launch_get_measure(Notifier *notifier, void *unused) SevGuestState *sev = sev_guest; int ret, error; guchar *data; -SEVState *s = >state; struct kvm_sev_launch_measure *measurement; if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) { @@ -592,7 +584,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused) measurement = g_new0(struct kvm_sev_launch_measure, 1); /* query the measurement blob length */ -ret = sev_ioctl(sev->state.sev_fd, KVM_SEV_LAUNCH_MEASURE, +ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE, measurement, ); if (!measurement->len) { error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", @@ -604,7 +596,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused) measurement->uaddr = (unsigned long)data; /* get the measurement blob */ -ret = sev_ioctl(sev->state.sev_fd, KVM_SEV_LAUNCH_MEASURE, +ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
[PULL 103/115] target/i386: sev: Embed SEVState in SevGuestState
From: David Gibson Currently SevGuestState contains only configuration information. For runtime state another non-QOM struct SEVState is allocated separately. Simplify things by instead embedding the SEVState structure in SevGuestState. Signed-off-by: David Gibson Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200604064219.436242-5-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 54 +-- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index b6ed719fb5..b4ab9720d6 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -35,6 +35,22 @@ typedef struct SevGuestState SevGuestState; +struct SEVState { +uint8_t api_major; +uint8_t api_minor; +uint8_t build_id; +uint32_t policy; +uint64_t me_mask; +uint32_t cbitpos; +uint32_t reduced_phys_bits; +uint32_t handle; +int sev_fd; +SevState state; +gchar *measurement; +}; + +typedef struct SEVState SEVState; + /** * SevGuestState: * @@ -48,6 +64,7 @@ typedef struct SevGuestState SevGuestState; struct SevGuestState { Object parent_obj; +/* configuration parameters */ char *sev_device; uint32_t policy; uint32_t handle; @@ -55,25 +72,11 @@ struct SevGuestState { char *session_file; uint32_t cbitpos; uint32_t reduced_phys_bits; -}; -struct SEVState { -SevGuestState *sev_info; -uint8_t api_major; -uint8_t api_minor; -uint8_t build_id; -uint32_t policy; -uint64_t me_mask; -uint32_t cbitpos; -uint32_t reduced_phys_bits; -uint32_t handle; -int sev_fd; -SevState state; -gchar *measurement; +/* runtime state */ +SEVState state; }; -typedef struct SEVState SEVState; - #define DEFAULT_GUEST_POLICY0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" @@ -506,12 +509,12 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len) } static int -sev_launch_start(SEVState *s) +sev_launch_start(SevGuestState *sev) { +SEVState *s = >state; gsize sz; int ret = 1; int fw_error, rc; -SevGuestState *sev = s->sev_info; struct kvm_sev_launch_start *start; guchar *session = NULL, *dh_cert = NULL; @@ -686,6 +689,7 @@ sev_vm_state_change(void *opaque, int running, RunState state) void * sev_guest_init(const char *id) { +SevGuestState *sev; SEVState *s; char *devname; int ret, fw_error; @@ -693,27 +697,27 @@ sev_guest_init(const char *id) uint32_t host_cbitpos; struct sev_user_data_status status = {}; -sev_state = s = g_new0(SEVState, 1); -s->sev_info = lookup_sev_guest_info(id); -if (!s->sev_info) { +sev = lookup_sev_guest_info(id); +if (!sev) { error_report("%s: '%s' is not a valid '%s' object", __func__, id, TYPE_SEV_GUEST); goto err; } +sev_state = s = >state; s->state = SEV_STATE_UNINIT; host_cpuid(0x801F, 0, NULL, , NULL, NULL); host_cbitpos = ebx & 0x3f; -s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL); +s->cbitpos = object_property_get_int(OBJECT(sev), "cbitpos", NULL); if (host_cbitpos != s->cbitpos) { error_report("%s: cbitpos check failed, host '%d' requested '%d'", __func__, host_cbitpos, s->cbitpos); goto err; } -s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info), +s->reduced_phys_bits = object_property_get_int(OBJECT(sev), "reduced-phys-bits", NULL); if (s->reduced_phys_bits < 1) { error_report("%s: reduced_phys_bits check failed, it should be >=1," @@ -723,7 +727,7 @@ sev_guest_init(const char *id) s->me_mask = ~(1UL << s->cbitpos); -devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL); +devname = object_property_get_str(OBJECT(sev), "sev-device", NULL); s->sev_fd = open(devname, O_RDWR); if (s->sev_fd < 0) { error_report("%s: Failed to open %s '%s'", __func__, @@ -754,7 +758,7 @@ sev_guest_init(const char *id) goto err; } -ret = sev_launch_start(s); +ret = sev_launch_start(sev); if (ret) { error_report("%s: failed to create encryption context", __func__); goto err; -- 2.26.2
[PULL 105/115] target/i386: sev: Remove redundant cbitpos and reduced_phys_bits fields
From: David Gibson The SEVState structure has cbitpos and reduced_phys_bits fields which are simply copied from the SevGuestState structure and never changed. Now that SEVState is embedded in SevGuestState we can just access the original copy directly. Signed-off-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-7-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 19 +++ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 9e8ab7b056..d25af37136 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -41,8 +41,6 @@ struct SEVState { uint8_t build_id; uint32_t policy; uint64_t me_mask; -uint32_t cbitpos; -uint32_t reduced_phys_bits; uint32_t handle; int sev_fd; SevState state; @@ -378,13 +376,13 @@ sev_get_me_mask(void) uint32_t sev_get_cbit_position(void) { -return sev_guest ? sev_guest->state.cbitpos : 0; +return sev_guest ? sev_guest->cbitpos : 0; } uint32_t sev_get_reduced_phys_bits(void) { -return sev_guest ? sev_guest->state.reduced_phys_bits : 0; +return sev_guest ? sev_guest->reduced_phys_bits : 0; } SevInfo * @@ -713,22 +711,19 @@ sev_guest_init(const char *id) host_cpuid(0x801F, 0, NULL, , NULL, NULL); host_cbitpos = ebx & 0x3f; -s->cbitpos = object_property_get_int(OBJECT(sev), "cbitpos", NULL); -if (host_cbitpos != s->cbitpos) { +if (host_cbitpos != sev->cbitpos) { error_report("%s: cbitpos check failed, host '%d' requested '%d'", - __func__, host_cbitpos, s->cbitpos); + __func__, host_cbitpos, sev->cbitpos); goto err; } -s->reduced_phys_bits = object_property_get_int(OBJECT(sev), -"reduced-phys-bits", NULL); -if (s->reduced_phys_bits < 1) { +if (sev->reduced_phys_bits < 1) { error_report("%s: reduced_phys_bits check failed, it should be >=1," - " requested '%d'", __func__, s->reduced_phys_bits); + " requested '%d'", __func__, sev->reduced_phys_bits); goto err; } -s->me_mask = ~(1UL << s->cbitpos); +s->me_mask = ~(1UL << sev->cbitpos); devname = object_property_get_str(OBJECT(sev), "sev-device", NULL); s->sev_fd = open(devname, O_RDWR); -- 2.26.2
[PULL 102/115] target/i386: sev: Rename QSevGuestInfo
From: David Gibson At the moment this is a purely passive object which is just a container for information used elsewhere, hence the name. I'm going to change that though, so as a preliminary rename it to SevGuestState. That name risks confusion with both SEVState and SevState, but I'll be working on that in following patches. Signed-off-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-4-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 87 --- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 53def5f41a..b6ed719fb5 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -29,22 +29,23 @@ #include "trace.h" #include "migration/blocker.h" -#define TYPE_QSEV_GUEST_INFO "sev-guest" -#define QSEV_GUEST_INFO(obj) \ -OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO) +#define TYPE_SEV_GUEST "sev-guest" +#define SEV_GUEST(obj) \ +OBJECT_CHECK(SevGuestState, (obj), TYPE_SEV_GUEST) -typedef struct QSevGuestInfo QSevGuestInfo; +typedef struct SevGuestState SevGuestState; /** - * QSevGuestInfo: + * SevGuestState: * - * The QSevGuestInfo object is used for creating a SEV guest. + * The SevGuestState object is used for creating and managing a SEV + * guest. * * # $QEMU \ * -object sev-guest,id=sev0 \ * -machine ...,memory-encryption=sev0 */ -struct QSevGuestInfo { +struct SevGuestState { Object parent_obj; char *sev_device; @@ -57,7 +58,7 @@ struct QSevGuestInfo { }; struct SEVState { -QSevGuestInfo *sev_info; +SevGuestState *sev_info; uint8_t api_major; uint8_t api_minor; uint8_t build_id; @@ -235,82 +236,82 @@ static struct RAMBlockNotifier sev_ram_notifier = { }; static void -qsev_guest_finalize(Object *obj) +sev_guest_finalize(Object *obj) { } static char * -qsev_guest_get_session_file(Object *obj, Error **errp) +sev_guest_get_session_file(Object *obj, Error **errp) { -QSevGuestInfo *s = QSEV_GUEST_INFO(obj); +SevGuestState *s = SEV_GUEST(obj); return s->session_file ? g_strdup(s->session_file) : NULL; } static void -qsev_guest_set_session_file(Object *obj, const char *value, Error **errp) +sev_guest_set_session_file(Object *obj, const char *value, Error **errp) { -QSevGuestInfo *s = QSEV_GUEST_INFO(obj); +SevGuestState *s = SEV_GUEST(obj); s->session_file = g_strdup(value); } static char * -qsev_guest_get_dh_cert_file(Object *obj, Error **errp) +sev_guest_get_dh_cert_file(Object *obj, Error **errp) { -QSevGuestInfo *s = QSEV_GUEST_INFO(obj); +SevGuestState *s = SEV_GUEST(obj); return g_strdup(s->dh_cert_file); } static void -qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) +sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) { -QSevGuestInfo *s = QSEV_GUEST_INFO(obj); +SevGuestState *s = SEV_GUEST(obj); s->dh_cert_file = g_strdup(value); } static char * -qsev_guest_get_sev_device(Object *obj, Error **errp) +sev_guest_get_sev_device(Object *obj, Error **errp) { -QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); +SevGuestState *sev = SEV_GUEST(obj); return g_strdup(sev->sev_device); } static void -qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp) +sev_guest_set_sev_device(Object *obj, const char *value, Error **errp) { -QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); +SevGuestState *sev = SEV_GUEST(obj); sev->sev_device = g_strdup(value); } static void -qsev_guest_class_init(ObjectClass *oc, void *data) +sev_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_str(oc, "sev-device", - qsev_guest_get_sev_device, - qsev_guest_set_sev_device); + sev_guest_get_sev_device, + sev_guest_set_sev_device); object_class_property_set_description(oc, "sev-device", "SEV device to use"); object_class_property_add_str(oc, "dh-cert-file", - qsev_guest_get_dh_cert_file, - qsev_guest_set_dh_cert_file); + sev_guest_get_dh_cert_file, + sev_guest_set_dh_cert_file); object_class_property_set_description(oc, "dh-cert-file", "guest owners DH certificate (encoded with base64)"); object_class_property_add_str(oc, "session-file", - qsev_guest_get_session_file, - qsev_guest_set_session_file); + sev_guest_get_session_file, +
[PULL 096/115] i386: hvf: Move lazy_flags into CPUX86State
From: Roman Bolshakov The lazy flags are still needed for instruction decoder. Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-12-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- include/sysemu/hvf.h| 7 + target/i386/cpu.h | 2 ++ target/i386/hvf/x86.h | 6 target/i386/hvf/x86_flags.c | 57 ++--- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index 2af32e505e..9e09144a64 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -21,10 +21,17 @@ #include #include #include "target/i386/cpu.h" +#include "exec/cpu-defs.h" + uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg); extern bool hvf_allowed; #define hvf_enabled() (hvf_allowed) + +typedef struct hvf_lazy_flags { +target_ulong result; +target_ulong auxbits; +} hvf_lazy_flags; #else /* !CONFIG_HVF */ #define hvf_enabled() 0 #define hvf_get_supported_cpuid(func, idx, reg) 0 diff --git a/target/i386/cpu.h b/target/i386/cpu.h index c2b8bdcbde..86f4da1b66 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -20,6 +20,7 @@ #ifndef I386_CPU_H #define I386_CPU_H +#include "sysemu/hvf.h" #include "sysemu/tcg.h" #include "cpu-qom.h" #include "hyperv-proto.h" @@ -1597,6 +1598,7 @@ typedef struct CPUX86State { struct kvm_nested_state *nested_state; #endif #if defined(CONFIG_HVF) +hvf_lazy_flags hvf_lflags; HVFX86EmulatorState *hvf_emul; #endif diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index 6048b5cc74..2363616c07 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -228,14 +228,8 @@ typedef struct x68_segment_selector { }; } __attribute__ ((__packed__)) x68_segment_selector; -typedef struct lazy_flags { -target_ulong result; -target_ulong auxbits; -} lazy_flags; - /* Definition of hvf_x86_state is here */ struct HVFX86EmulatorState { -struct lazy_flags lflags; uint8_t mmio_buf[4096]; }; diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index 1152cd7234..5ca4f41f5c 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -63,7 +63,7 @@ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ -env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ +env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ if ((size) == 32) { \ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ } else if ((size) == 16) { \ @@ -73,7 +73,7 @@ } else { \ VM_PANIC("unimplemented"); \ } \ -env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)temp; \ +env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \ } /* carries, result */ @@ -100,10 +100,10 @@ } else { \ VM_PANIC("unimplemented"); \ } \ -env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ -target_ulong delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \ +env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ +target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ -env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ +env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ } /* carries, result */ @@ -117,9 +117,8 @@ void SET_FLAGS_OC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; -env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); -env->hvf_emul->lflags.auxbits |= (temp_po << LF_BIT_PO) | - (new_cf << LF_BIT_CF); +env->hvf_lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); +env->hvf_lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); } void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, @@ -215,27 +214,27 @@ void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, bool get_PF(CPUX86State *env) { -uint32_t temp = (255 & env->hvf_emul->lflags.result); -temp = temp ^ (255 & (env->hvf_emul->lflags.auxbits >> LF_BIT_PDB)); +uint32_t temp = (255 & env->hvf_lflags.result); +temp = temp ^ (255 & (env->hvf_lflags.auxbits >> LF_BIT_PDB)); temp = (temp ^ (temp >> 4)) & 0x0F; return (0x9669U >> temp) & 1; } void set_PF(CPUX86State *env, bool val) { -uint32_t temp = (255 & env->hvf_emul->lflags.result) ^ (!val); -env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PDB); -env->hvf_emul->lflags.auxbits |= (temp << LF_BIT_PDB); +uint32_t temp = (255 & env->hvf_lflags.result) ^ (!val); +env->hvf_lflags.auxbits &= ~(LF_MASK_PDB); +
Re: [PULL v2 00/16] Trivial branch for 5.1 patches
On Wed, 10 Jun 2020 at 14:12, Laurent Vivier wrote: > > The following changes since commit 49ee11555262a256afec592dfed7c5902d5eefd2: > > Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.1-pull-= > request' into staging (2020-06-08 11:04:57 +0100) > > are available in the Git repository at: > > git://github.com/vivier/qemu.git tags/trivial-branch-for-5.1-pull-request > > for you to fetch changes up to fe18e6eecdd45d3dff0c8968cbb07c5e02fbe4c8: > > semihosting: remove the pthread include which seems unused (2020-06-10 11:2= > 9:44 +0200) > > > Trivial branch pull request 20200610 > > Convert DPRINTF() to traces or qemu_logs > Use IEC binary prefix definitions > Use qemu_semihosting_log_out() in target/unicore32 > Some code and doc cleanup Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/5.1 for any user-visible changes. -- PMM
[PULL 094/115] i386: hvf: Drop copy of RFLAGS defines
From: Roman Bolshakov Use the ones provided in target/i386/cpu.h instead. Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-10-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86.c| 2 +- target/i386/hvf/x86.h| 20 target/i386/hvf/x86_decode.c | 16 +++- target/i386/hvf/x86_task.c | 2 +- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index 7ebb5b45bd..fdb11c8db9 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -131,7 +131,7 @@ bool x86_is_v8086(struct CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = _cpu->env; -return x86_is_protected(cpu) && (env->eflags & RFLAGS_VM); +return x86_is_protected(cpu) && (env->eflags & VM_MASK); } bool x86_is_long_mode(struct CPUState *cpu) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index e309b8f203..f0d03faff9 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -42,26 +42,6 @@ typedef struct x86_register { }; } __attribute__ ((__packed__)) x86_register; -typedef enum x86_rflags { -RFLAGS_CF = (1L << 0), -RFLAGS_PF = (1L << 2), -RFLAGS_AF = (1L << 4), -RFLAGS_ZF = (1L << 6), -RFLAGS_SF = (1L << 7), -RFLAGS_TF = (1L << 8), -RFLAGS_IF = (1L << 9), -RFLAGS_DF = (1L << 10), -RFLAGS_OF = (1L << 11), -RFLAGS_IOPL = (3L << 12), -RFLAGS_NT = (1L << 14), -RFLAGS_RF = (1L << 16), -RFLAGS_VM = (1L << 17), -RFLAGS_AC = (1L << 18), -RFLAGS_VIF = (1L << 19), -RFLAGS_VIP = (1L << 20), -RFLAGS_ID = (1L << 21), -} x86_rflags; - typedef enum x86_reg_cr0 { CR0_PE =(1L << 0), CR0_MP =(1L << 1), diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index d881542181..34c5e3006c 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -697,15 +697,13 @@ static void decode_db_4(CPUX86State *env, struct x86_decode *decode) #define RFLAGS_MASK_NONE0 -#define RFLAGS_MASK_OSZAPC (RFLAGS_OF | RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | \ - RFLAGS_PF | RFLAGS_CF) -#define RFLAGS_MASK_LAHF(RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | \ - RFLAGS_CF) -#define RFLAGS_MASK_CF (RFLAGS_CF) -#define RFLAGS_MASK_IF (RFLAGS_IF) -#define RFLAGS_MASK_TF (RFLAGS_TF) -#define RFLAGS_MASK_DF (RFLAGS_DF) -#define RFLAGS_MASK_ZF (RFLAGS_ZF) +#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_LAHF(CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_CF (CC_C) +#define RFLAGS_MASK_IF (IF_MASK) +#define RFLAGS_MASK_TF (TF_MASK) +#define RFLAGS_MASK_DF (DF_MASK) +#define RFLAGS_MASK_ZF (CC_Z) struct decode_tbl _1op_inst[] = { {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 6ea8508946..6f04478b3a 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -158,7 +158,7 @@ void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int rea } if (reason == TSR_IRET) -env->eflags &= ~RFLAGS_NT; +env->eflags &= ~NT_MASK; if (reason != TSR_CALL && reason != TSR_IDT_GATE) old_tss_sel.sel = 0x; -- 2.26.2
[PULL 091/115] i386: hvf: Use IP from CPUX86State
From: Roman Bolshakov Drop and replace rip field from HVFX86EmulatorState in favor of eip from common CPUX86State. Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-7-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- target/i386/hvf/hvf.c| 6 +-- target/i386/hvf/x86.h| 3 -- target/i386/hvf/x86_decode.c | 6 +-- target/i386/hvf/x86_emu.c| 86 ++-- target/i386/hvf/x86_task.c | 4 +- 5 files changed, 51 insertions(+), 54 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 8ff1d25521..45ae55dd27 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -797,7 +797,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { RAX(env) = (uint64_t)val; } -RIP(env) += ins_len; +env->eip += ins_len; store_regs(cpu); break; } else if (!string && !in) { @@ -871,7 +871,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { simulate_wrmsr(cpu); } -RIP(env) += ins_len; +env->eip += ins_len; store_regs(cpu); break; } @@ -907,7 +907,7 @@ int hvf_vcpu_exec(CPUState *cpu) error_report("Unrecognized CR %d", cr); abort(); } -RIP(env) += ins_len; +env->eip += ins_len; store_regs(cpu); break; } diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index 56fcde13c6..e3ab7c5137 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -294,7 +294,6 @@ typedef struct lazy_flags { /* Definition of hvf_x86_state is here */ struct HVFX86EmulatorState { uint64_t fetch_rip; -uint64_t rip; struct x86_register regs[16]; struct x86_reg_flags rflags; struct lazy_flags lflags; @@ -302,8 +301,6 @@ struct HVFX86EmulatorState { }; /* useful register access macros */ -#define RIP(cpu)(cpu->hvf_emul->rip) -#define EIP(cpu)((uint32_t)cpu->hvf_emul->rip) #define RFLAGS(cpu) (cpu->hvf_emul->rflags.rflags) #define EFLAGS(cpu) (cpu->hvf_emul->rflags.eflags) diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index 77c346605f..a590088f54 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -75,7 +75,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, VM_PANIC_EX("%s invalid size %d\n", __func__, size); break; } -target_ulong va = linear_rip(env_cpu(env), RIP(env)) + decode->len; +target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; vmx_read_mem(env_cpu(env), , va, size); decode->len += size; @@ -1771,7 +1771,7 @@ void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, ptr += get_sib_val(env, decode, ); } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { if (x86_is_long_mode(env_cpu(env))) { -ptr += RIP(env) + decode->len; +ptr += env->eip + decode->len; } else { ptr = decode->displacement; } @@ -1807,7 +1807,7 @@ void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, if (4 == rm) { ptr = get_sib_val(env, decode, ) + offset; } else if (0 == mod && 5 == rm) { -ptr = RIP(env) + decode->len + (int32_t) offset; +ptr = env->eip + decode->len + (int32_t) offset; } else { ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) + (int64_t) offset; diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 92ab815f5d..0efd9f9928 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -267,49 +267,49 @@ static void exec_mov(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, decode->op[1].val, decode->operand_size); -RIP(env) += decode->len; +env->eip += decode->len; } static void exec_add(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); -RIP(env) += decode->len; +env->eip += decode->len; } static void exec_or(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); -RIP(env) += decode->len; +env->eip += decode->len; } static void exec_adc(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); -RIP(env) += decode->len; +env->eip += decode->len; } static void exec_sbb(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); -RIP(env) += decode->len; +
[PULL 069/115] KVM: Kick resamplefd for split kernel irqchip
From: Peter Xu This is majorly only for X86 because that's the only one that supports split irqchip for now. When the irqchip is split, we face a dilemma that KVM irqfd will be enabled, however the slow irqchip is still running in the userspace. It means that the resamplefd in the kernel irqfds won't take any effect and it will miss to ack INTx interrupts on EOIs. One example is split irqchip with VFIO INTx, which will break if we use the VFIO INTx fast path. This patch can potentially supports the VFIO fast path again for INTx, that the IRQ delivery will still use the fast path, while we don't need to trap MMIOs in QEMU for the device to emulate the EIOs (see the callers of vfio_eoi() hook). However the EOI of the INTx will still need to be done from the userspace by caching all the resamplefds in QEMU and kick properly for IOAPIC EOI broadcast. This is tricky because in this case the userspace ioapic irr & remote-irr will be bypassed. However such a change will greatly boost performance for assigned devices using INTx irqs (TCP_RR boosts 46% after this patch applied). When the userspace is responsible for the resamplefd kickup, don't register it on the kvm_irqfd anymore, because on newer kernels (after commit 654f1f13ea56, 5.2+) the KVM_IRQFD will fail if with both split irqchip and resamplefd. This will make sure that the fast path will work for all supported kernels. https://patchwork.kernel.org/patch/10738541/#22609933 Suggested-by: Paolo Bonzini Signed-off-by: Peter Xu Message-Id: <20200318145204.74483-5-pet...@redhat.com> Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c| 79 -- accel/kvm/trace-events | 1 + hw/intc/ioapic.c | 19 ++ include/sysemu/kvm.h | 4 +++ 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b048c10af9..f24d7da783 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -160,9 +160,59 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = { static NotifierList kvm_irqchip_change_notifiers = NOTIFIER_LIST_INITIALIZER(kvm_irqchip_change_notifiers); +struct KVMResampleFd { +int gsi; +EventNotifier *resample_event; +QLIST_ENTRY(KVMResampleFd) node; +}; +typedef struct KVMResampleFd KVMResampleFd; + +/* + * Only used with split irqchip where we need to do the resample fd + * kick for the kernel from userspace. + */ +static QLIST_HEAD(, KVMResampleFd) kvm_resample_fd_list = +QLIST_HEAD_INITIALIZER(kvm_resample_fd_list); + #define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock) #define kvm_slots_unlock(kml)qemu_mutex_unlock(&(kml)->slots_lock) +static inline void kvm_resample_fd_remove(int gsi) +{ +KVMResampleFd *rfd; + +QLIST_FOREACH(rfd, _resample_fd_list, node) { +if (rfd->gsi == gsi) { +QLIST_REMOVE(rfd, node); +g_free(rfd); +break; +} +} +} + +static inline void kvm_resample_fd_insert(int gsi, EventNotifier *event) +{ +KVMResampleFd *rfd = g_new0(KVMResampleFd, 1); + +rfd->gsi = gsi; +rfd->resample_event = event; + +QLIST_INSERT_HEAD(_resample_fd_list, rfd, node); +} + +void kvm_resample_fd_notify(int gsi) +{ +KVMResampleFd *rfd; + +QLIST_FOREACH(rfd, _resample_fd_list, node) { +if (rfd->gsi == gsi) { +event_notifier_set(rfd->resample_event); +trace_kvm_resample_fd_notify(gsi); +return; +} +} +} + int kvm_get_max_memslots(void) { KVMState *s = KVM_STATE(current_accel()); @@ -1676,8 +1726,33 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event, }; if (rfd != -1) { -irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE; -irqfd.resamplefd = rfd; +assert(assign); +if (kvm_irqchip_is_split()) { +/* + * When the slow irqchip (e.g. IOAPIC) is in the + * userspace, KVM kernel resamplefd will not work because + * the EOI of the interrupt will be delivered to userspace + * instead, so the KVM kernel resamplefd kick will be + * skipped. The userspace here mimics what the kernel + * provides with resamplefd, remember the resamplefd and + * kick it when we receive EOI of this IRQ. + * + * This is hackery because IOAPIC is mostly bypassed + * (except EOI broadcasts) when irqfd is used. However + * this can bring much performance back for split irqchip + * with INTx IRQs (for VFIO, this gives 93% perf of the + * full fast path, which is 46% perf boost comparing to + * the INTx slow path). + */ +kvm_resample_fd_insert(virq, resample); +} else { +irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE; +irqfd.resamplefd = rfd; +} +} else if (!assign) { +if
Re: [PATCH v3 0/6] Add strace support for printing arguments of selected syscalls
Patchew URL: https://patchew.org/QEMU/20200611155109.3648-1-filip.boz...@syrmia.com/ Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20200611155109.3648-1-filip.boz...@syrmia.com Subject: [PATCH v3 0/6] Add strace support for printing arguments of selected syscalls Type: series === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 013fd5b linux-user: Add strace support for printing arguments of fallocate() 5e6db1c linux-user: Add strace support for printing arguments of chown()/lchown() 1a68f0d linux-user: Add strace support for printing arguments of lseek() f6287a2 linux-user: Add strace support for printing argument of syscalls used for extended attributes a6be0b5 linux-user: Add strace support for a group of syscalls 065de90 linux-user: Extend strace support to enable argument printing after syscall execution === OUTPUT BEGIN === 1/6 Checking commit 065de9028073 (linux-user: Extend strace support to enable argument printing after syscall execution) 2/6 Checking commit a6be0b55e6e5 (linux-user: Add strace support for a group of syscalls) 3/6 Checking commit f6287a23537e (linux-user: Add strace support for printing argument of syscalls used for extended attributes) 4/6 Checking commit 1a68f0dc91b3 (linux-user: Add strace support for printing arguments of lseek()) 5/6 Checking commit 5e6db1ccb67c (linux-user: Add strace support for printing arguments of chown()/lchown()) 6/6 Checking commit 013fd5b8be2f (linux-user: Add strace support for printing arguments of fallocate()) ERROR: storage class should be at the beginning of the declaration #70: FILE: linux-user/strace.c:1147: +UNUSED static struct flags falloc_flags[] = { total: 1 errors, 0 warnings, 104 lines checked Patch 6/6 has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 The full log is available at http://patchew.org/logs/20200611155109.3648-1-filip.boz...@syrmia.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
[PULL 088/115] i386: hvf: Drop useless declarations in sysemu
From: Roman Bolshakov They're either declared elsewhere or have no use. While at it, rename _hvf_cpu_synchronize_post_init() to do_hvf_cpu_synchronize_post_init(). Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-3-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- include/sysemu/hvf.h | 22 -- target/i386/hvf/hvf.c | 7 --- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index 644bdfc722..2af32e505e 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -30,35 +30,13 @@ extern bool hvf_allowed; #define hvf_get_supported_cpuid(func, idx, reg) 0 #endif /* !CONFIG_HVF */ -/* Disable HVF if |disable| is 1, otherwise, enable it iff it is supported by - * the host CPU. Use hvf_enabled() after this to get the result. */ -void hvf_disable(int disable); - -/* Returns non-0 if the host CPU supports the VMX "unrestricted guest" feature - * which allows the virtual CPU to directly run in "real mode". If true, this - * allows QEMU to run several vCPU threads in parallel (see cpus.c). Otherwise, - * only a a single TCG thread can run, and it will call HVF to run the current - * instructions, except in case of "real mode" (paging disabled, typically at - * boot time), or MMIO operations. */ - -int hvf_sync_vcpus(void); - int hvf_init_vcpu(CPUState *); int hvf_vcpu_exec(CPUState *); -int hvf_smp_cpu_exec(CPUState *); void hvf_cpu_synchronize_state(CPUState *); void hvf_cpu_synchronize_post_reset(CPUState *); void hvf_cpu_synchronize_post_init(CPUState *); -void _hvf_cpu_synchronize_post_init(CPUState *, run_on_cpu_data); - void hvf_vcpu_destroy(CPUState *); -void hvf_raise_event(CPUState *); -/* void hvf_reset_vcpu_state(void *opaque); */ void hvf_reset_vcpu(CPUState *); -void vmx_update_tpr(CPUState *); -void update_apic_tpr(CPUState *); -int hvf_put_registers(CPUState *); -void vmx_clear_int_window_exiting(CPUState *cpu); #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf") diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index d72543dc31..9ccdb7e7c7 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -251,7 +251,7 @@ void vmx_update_tpr(CPUState *cpu) } } -void update_apic_tpr(CPUState *cpu) +static void update_apic_tpr(CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); int tpr = rreg(cpu->hvf_fd, HV_X86_TPR) >> 4; @@ -312,7 +312,8 @@ void hvf_cpu_synchronize_post_reset(CPUState *cpu_state) run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); } -void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) +static void do_hvf_cpu_synchronize_post_init(CPUState *cpu, + run_on_cpu_data arg) { CPUState *cpu_state = cpu; hvf_put_registers(cpu_state); @@ -321,7 +322,7 @@ void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) void hvf_cpu_synchronize_post_init(CPUState *cpu_state) { -run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); +run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual) -- 2.26.2
[PULL 111/115] hw/usb: Move device-specific declarations to new 'hcd-musb.h' header
From: Philippe Mathieu-Daudé Move the declarations for the MUSB-HDRC USB2.0 OTG compliant core into a separate header. Reviewed-by: Peter Maydell Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200601141536.15192-3-f4...@amsat.org> Signed-off-by: Paolo Bonzini --- hw/usb/hcd-musb.c | 1 + hw/usb/tusb6010.c | 1 + include/hw/usb.h | 30 - include/hw/usb/hcd-musb.h | 46 +++ 4 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 include/hw/usb/hcd-musb.h diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index c29fbef6fc..5ab13feb3a 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "qemu/timer.h" #include "hw/usb.h" +#include "hw/usb/hcd-musb.h" #include "hw/irq.h" #include "hw/hw.h" diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c index 17580876c6..27eb28d3e4 100644 --- a/hw/usb/tusb6010.c +++ b/hw/usb/tusb6010.c @@ -23,6 +23,7 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "hw/usb.h" +#include "hw/usb/hcd-musb.h" #include "hw/arm/omap.h" #include "hw/hw.h" #include "hw/irq.h" diff --git a/include/hw/usb.h b/include/hw/usb.h index 1cf1cd9584..e2128c7c45 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -474,36 +474,6 @@ bool usb_host_dev_is_scsi_storage(USBDevice *usbdev); #define VM_USB_HUB_SIZE 8 -/* hw/usb/hdc-musb.c */ - -enum musb_irq_source_e { -musb_irq_suspend = 0, -musb_irq_resume, -musb_irq_rst_babble, -musb_irq_sof, -musb_irq_connect, -musb_irq_disconnect, -musb_irq_vbus_request, -musb_irq_vbus_error, -musb_irq_rx, -musb_irq_tx, -musb_set_vbus, -musb_set_session, -/* Add new interrupts here */ -musb_irq_max, /* total number of interrupts defined */ -}; - -typedef struct MUSBState MUSBState; - -extern CPUReadMemoryFunc * const musb_read[]; -extern CPUWriteMemoryFunc * const musb_write[]; - -MUSBState *musb_init(DeviceState *parent_device, int gpio_base); -void musb_reset(MUSBState *s); -uint32_t musb_core_intr_get(MUSBState *s); -void musb_core_intr_clear(MUSBState *s, uint32_t mask); -void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); - /* usb-bus.c */ #define TYPE_USB_BUS "usb-bus" diff --git a/include/hw/usb/hcd-musb.h b/include/hw/usb/hcd-musb.h new file mode 100644 index 00..26b50132ff --- /dev/null +++ b/include/hw/usb/hcd-musb.h @@ -0,0 +1,46 @@ +/* + * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics, + * USB2.0 OTG compliant core used in various chips. + * + * Only host-mode and non-DMA accesses are currently supported. + * + * Copyright (C) 2008 Nokia Corporation + * Written by Andrzej Zaborowski + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_USB_MUSB_H +#define HW_USB_MUSB_H + +#include "exec/cpu-common.h" + +enum musb_irq_source_e { +musb_irq_suspend = 0, +musb_irq_resume, +musb_irq_rst_babble, +musb_irq_sof, +musb_irq_connect, +musb_irq_disconnect, +musb_irq_vbus_request, +musb_irq_vbus_error, +musb_irq_rx, +musb_irq_tx, +musb_set_vbus, +musb_set_session, +/* Add new interrupts here */ +musb_irq_max /* total number of interrupts defined */ +}; + +extern CPUReadMemoryFunc * const musb_read[]; +extern CPUWriteMemoryFunc * const musb_write[]; + +typedef struct MUSBState MUSBState; + +MUSBState *musb_init(DeviceState *parent_device, int gpio_base); +void musb_reset(MUSBState *s); +uint32_t musb_core_intr_get(MUSBState *s); +void musb_core_intr_clear(MUSBState *s, uint32_t mask); +void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); + +#endif -- 2.26.2
[PULL 050/115] megasas: use unsigned type for positive numeric fields
From: Prasad J Pandit Use unsigned type for the MegasasState fields which hold positive numeric values. Signed-off-by: Prasad J Pandit Reviewed-by: Darren Kenny Message-Id: <20200513192540.1583887-4-ppan...@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/megasas.c | 38 +++--- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index b531d88a9b..634af0bbb8 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -86,34 +86,34 @@ typedef struct MegasasState { MemoryRegion queue_io; uint32_t frame_hi; -int fw_state; +uint32_t fw_state; uint32_t fw_sge; uint32_t fw_cmds; uint32_t flags; -int fw_luns; -int intr_mask; -int doorbell; -int busy; -int diag; -int adp_reset; +uint32_t fw_luns; +uint32_t intr_mask; +uint32_t doorbell; +uint32_t busy; +uint32_t diag; +uint32_t adp_reset; OnOffAuto msi; OnOffAuto msix; MegasasCmd *event_cmd; -int event_locale; +uint16_t event_locale; int event_class; -int event_count; -int shutdown_event; -int boot_event; +uint32_t event_count; +uint32_t shutdown_event; +uint32_t boot_event; uint64_t sas_addr; char *hba_serial; uint64_t reply_queue_pa; void *reply_queue; -int reply_queue_len; +uint16_t reply_queue_len; uint16_t reply_queue_head; -int reply_queue_tail; +uint16_t reply_queue_tail; uint64_t consumer_pa; uint64_t producer_pa; @@ -2259,9 +2259,9 @@ static const VMStateDescription vmstate_megasas_gen1 = { VMSTATE_PCI_DEVICE(parent_obj, MegasasState), VMSTATE_MSIX(parent_obj, MegasasState), -VMSTATE_INT32(fw_state, MegasasState), -VMSTATE_INT32(intr_mask, MegasasState), -VMSTATE_INT32(doorbell, MegasasState), +VMSTATE_UINT32(fw_state, MegasasState), +VMSTATE_UINT32(intr_mask, MegasasState), +VMSTATE_UINT32(doorbell, MegasasState), VMSTATE_UINT64(reply_queue_pa, MegasasState), VMSTATE_UINT64(consumer_pa, MegasasState), VMSTATE_UINT64(producer_pa, MegasasState), @@ -2278,9 +2278,9 @@ static const VMStateDescription vmstate_megasas_gen2 = { VMSTATE_PCI_DEVICE(parent_obj, MegasasState), VMSTATE_MSIX(parent_obj, MegasasState), -VMSTATE_INT32(fw_state, MegasasState), -VMSTATE_INT32(intr_mask, MegasasState), -VMSTATE_INT32(doorbell, MegasasState), +VMSTATE_UINT32(fw_state, MegasasState), +VMSTATE_UINT32(intr_mask, MegasasState), +VMSTATE_UINT32(doorbell, MegasasState), VMSTATE_UINT64(reply_queue_pa, MegasasState), VMSTATE_UINT64(consumer_pa, MegasasState), VMSTATE_UINT64(producer_pa, MegasasState), -- 2.26.2
[PULL 086/115] target/ppc: Restrict PPCVirtualHypervisorClass to system-mode
From: Philippe Mathieu-Daudé The code related to PPC Virtual Hypervisor is pointless in user-mode. Acked-by: David Gibson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200526172427.17460-5-f4...@amsat.org> Signed-off-by: Paolo Bonzini --- target/ppc/cpu.h| 4 ++-- target/ppc/kvm_ppc.h| 22 +++--- target/ppc/translate_init.inc.c | 4 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 1988b436cb..e7d382ac10 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1202,6 +1202,7 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc); +#ifndef CONFIG_USER_ONLY struct PPCVirtualHypervisorClass { InterfaceClass parent; void (*hypercall)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); @@ -1215,10 +1216,8 @@ struct PPCVirtualHypervisorClass { void (*hpte_set_r)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1); void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry); target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp); -#ifndef CONFIG_USER_ONLY void (*cpu_exec_enter)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); void (*cpu_exec_exit)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); -#endif }; #define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor" @@ -1230,6 +1229,7 @@ struct PPCVirtualHypervisorClass { #define PPC_VIRTUAL_HYPERVISOR_GET_CLASS(obj) \ OBJECT_GET_CLASS(PPCVirtualHypervisorClass, (obj), \ TYPE_PPC_VIRTUAL_HYPERVISOR) +#endif /* CONFIG_USER_ONLY */ void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index fcaf745516..701c0c262b 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -280,6 +280,17 @@ static inline bool kvmppc_has_cap_spapr_vfio(void) return false; } +static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, + hwaddr ptex, int n) +{ +abort(); +} + +static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) +{ +abort(); +} + #endif /* !CONFIG_USER_ONLY */ static inline bool kvmppc_has_cap_epr(void) @@ -310,17 +321,6 @@ static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, abort(); } -static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, - hwaddr ptex, int n) -{ -abort(); -} - -static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) -{ -abort(); -} - static inline bool kvmppc_has_cap_fixup_hcalls(void) { abort(); diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 38cb773ab4..a40888411c 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -10942,16 +10942,20 @@ static const TypeInfo ppc_cpu_type_info = { .class_init = ppc_cpu_class_init, }; +#ifndef CONFIG_USER_ONLY static const TypeInfo ppc_vhyp_type_info = { .name = TYPE_PPC_VIRTUAL_HYPERVISOR, .parent = TYPE_INTERFACE, .class_size = sizeof(PPCVirtualHypervisorClass), }; +#endif static void ppc_cpu_register_types(void) { type_register_static(_cpu_type_info); +#ifndef CONFIG_USER_ONLY type_register_static(_vhyp_type_info); +#endif } type_init(ppc_cpu_register_types) -- 2.26.2
[PULL 099/115] xen: fix build without pci passthrough
From: Anthony PERARD Xen PCI passthrough support may not be available and thus the global variable "has_igd_gfx_passthru" might be compiled out. Common code should not access it in that case. Unfortunately, we can't use CONFIG_XEN_PCI_PASSTHROUGH directly in xen-common.c so this patch instead move access to the has_igd_gfx_passthru variable via function and those functions are also implemented as stubs. The stubs will be used when QEMU is built without passthrough support. Now, when one will want to enable igd-passthru via the -machine property, they will get an error message if QEMU is built without passthrough support. Fixes: 46472d82322d0 ('xen: convert "-machine igd-passthru" to an accelerator property') Reported-by: Roger Pau Monné Signed-off-by: Anthony PERARD Message-Id: <20200603160442.3151170-1-anthony.per...@citrix.com> Signed-off-by: Paolo Bonzini --- accel/xen/xen-all.c | 4 ++-- hw/Makefile.objs | 2 +- hw/i386/pc_piix.c| 2 +- hw/xen/Makefile.objs | 3 ++- hw/xen/xen_pt.c | 12 +++- hw/xen/xen_pt.h | 6 -- hw/xen/xen_pt_stub.c | 22 ++ 7 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 hw/xen/xen_pt_stub.c diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c index f3edc65ec9..0c24d4b191 100644 --- a/accel/xen/xen-all.c +++ b/accel/xen/xen-all.c @@ -137,12 +137,12 @@ static void xen_change_state_handler(void *opaque, int running, static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp) { -return has_igd_gfx_passthru; +return xen_igd_gfx_pt_enabled(); } static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) { -has_igd_gfx_passthru = value; +xen_igd_gfx_pt_set(value, errp); } static void xen_setup_post(MachineState *ms, AccelState *accel) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 660e2b4373..4cbe5e4e57 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -35,7 +35,7 @@ devices-dirs-y += usb/ devices-dirs-$(CONFIG_VFIO) += vfio/ devices-dirs-y += virtio/ devices-dirs-y += watchdog/ -devices-dirs-y += xen/ +devices-dirs-$(CONFIG_XEN) += xen/ devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ devices-dirs-$(CONFIG_NUBUS) += nubus/ devices-dirs-y += semihosting/ diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index eea964e72b..054d3aa9f7 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -377,7 +377,7 @@ static void pc_init_isa(MachineState *machine) #ifdef CONFIG_XEN static void pc_xen_hvm_init_pci(MachineState *machine) { -const char *pci_type = has_igd_gfx_passthru ? +const char *pci_type = xen_igd_gfx_pt_enabled() ? TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE; pc_init1(machine, diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index 340b2c5096..3fc715e595 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,6 +1,7 @@ # xen backend driver support -common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-bus.o xen-bus-helper.o xen-backend.o +common-obj-y += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-bus.o xen-bus-helper.o xen-backend.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt_load_rom.o +obj-$(call $(lnot, $(CONFIG_XEN_PCI_PASSTHROUGH))) += xen_pt_stub.o diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 81d5ad8da7..ab84443d5e 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -65,7 +65,17 @@ #include "qemu/range.h" #include "exec/address-spaces.h" -bool has_igd_gfx_passthru; +static bool has_igd_gfx_passthru; + +bool xen_igd_gfx_pt_enabled(void) +{ +return has_igd_gfx_passthru; +} + +void xen_igd_gfx_pt_set(bool value, Error **errp) +{ +has_igd_gfx_passthru = value; +} #define XEN_PT_NR_IRQS (256) static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 179775db7b..6e9cec95f3 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -5,6 +5,9 @@ #include "hw/pci/pci.h" #include "xen-host-pci-device.h" +bool xen_igd_gfx_pt_enabled(void); +void xen_igd_gfx_pt_set(bool value, Error **errp); + void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3); #define XEN_PT_ERR(d, _f, _a...) xen_pt_log(d, "%s: Error: "_f, __func__, ##_a) @@ -322,10 +325,9 @@ extern void *pci_assign_dev_load_option_rom(PCIDevice *dev, unsigned int domain, unsigned int bus, unsigned int slot, unsigned int function); -extern bool has_igd_gfx_passthru; static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev) { -return (has_igd_gfx_passthru +return (xen_igd_gfx_pt_enabled() && ((dev->class_code >> 0x8) ==
[PULL 114/115] stubs: move Xen stubs to accel/
Keep them close to the other accelerator-dependent stubs, so as to remove stubs that are not needed by tools. Signed-off-by: Paolo Bonzini --- accel/stubs/Makefile.objs | 1 + stubs/xen-hvm.c => accel/stubs/xen-stub.c | 14 +++--- stubs/Makefile.objs | 2 -- stubs/xen-common.c| 13 - 4 files changed, 8 insertions(+), 22 deletions(-) rename stubs/xen-hvm.c => accel/stubs/xen-stub.c (74%) delete mode 100644 stubs/xen-common.c diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs index 3894caf95d..bbd14e71fb 100644 --- a/accel/stubs/Makefile.objs +++ b/accel/stubs/Makefile.objs @@ -3,3 +3,4 @@ obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o obj-$(call lnot,$(CONFIG_WHPX)) += whpx-stub.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o +obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o diff --git a/stubs/xen-hvm.c b/accel/stubs/xen-stub.c similarity index 74% rename from stubs/xen-hvm.c rename to accel/stubs/xen-stub.c index 6954a5b696..dcca4e678a 100644 --- a/stubs/xen-hvm.c +++ b/accel/stubs/xen-stub.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2010 Citrix Ltd. + * Copyright (C) 2014 Citrix Systems UK Ltd. * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" #include "hw/xen/xen.h" -#include "exec/memory.h" #include "qapi/qapi-commands-misc.h" +void xenstore_store_pv_console_info(int i, Chardev *chr) +{ +} + int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) { return -1; diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index c1e43ac68f..28e48171d1 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -49,7 +49,5 @@ stub-obj-y += target-get-monitor-def.o stub-obj-y += target-monitor-defs.o stub-obj-y += uuid.o stub-obj-y += vm-stop.o -stub-obj-y += xen-common.o -stub-obj-y += xen-hvm.o endif # CONFIG_SOFTMMU || CONFIG_TOOLS diff --git a/stubs/xen-common.c b/stubs/xen-common.c deleted file mode 100644 index f5efcae362..00 --- a/stubs/xen-common.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2014 Citrix Systems UK Ltd. - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "hw/xen/xen.h" - -void xenstore_store_pv_console_info(int i, Chardev *chr) -{ -} -- 2.26.2
[PULL 115/115] target/i386: Remove obsolete TODO file
From: Thomas Huth The last real change to this file is from 2012, so it is very likely that this file is completely out-of-date and ignored today. Let's simply remove it to avoid confusion if someone finds it by accident. Signed-off-by: Thomas Huth Message-Id: <20200611172445.5177-1-th...@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/TODO | 31 --- 1 file changed, 31 deletions(-) delete mode 100644 target/i386/TODO diff --git a/target/i386/TODO b/target/i386/TODO deleted file mode 100644 index a8d69cf87f..00 --- a/target/i386/TODO +++ /dev/null @@ -1,31 +0,0 @@ -Correctness issues: - -- some eflags manipulation incorrectly reset the bit 0x2. -- SVM: test, cpu save/restore, SMM save/restore. -- x86_64: lcall/ljmp intel/amd differences ? -- better code fetch (different exception handling + CS.limit support) -- user/kernel PUSHL/POPL in helper.c -- add missing cpuid tests -- return UD exception if LOCK prefix incorrectly used -- test ldt limit < 7 ? -- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) -- full support of segment limit/rights -- full x87 exception support -- improve x87 bit exactness (use bochs code ?) -- DRx register support -- CR0.AC emulation -- SSE alignment checks - -Optimizations/Features: - -- add SVM nested paging support -- add VMX support -- add AVX support -- add SSE5 support -- fxsave/fxrstor AMD extensions -- improve monitor/mwait support -- faster EFLAGS update: consider SZAP, C, O can be updated separately - with a bit field in CC_OP and more state variables. -- evaluate x87 stack pointer statically -- find a way to avoid translating several time the same TB if CR0.TS - is set or not. -- 2.26.2
[PULL 085/115] sysemu/hvf: Only declare hvf_allowed when HVF is available
From: Philippe Mathieu-Daudé When HVF is not available, the hvf_allowed variable does not exist. Reviewed-by: Edgar E. Iglesias Reviewed-by: Cornelia Huck Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Roman Bolshakov Message-Id: <20200526172427.17460-4-f4...@amsat.org> Signed-off-by: Paolo Bonzini --- include/sysemu/hvf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index d211e808e9..fe95743124 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -18,7 +18,6 @@ #include "exec/memory.h" #include "sysemu/accel.h" -extern bool hvf_allowed; #ifdef CONFIG_HVF #include #include @@ -26,11 +25,12 @@ extern bool hvf_allowed; #include "target/i386/cpu.h" uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg); +extern bool hvf_allowed; #define hvf_enabled() (hvf_allowed) -#else +#else /* !CONFIG_HVF */ #define hvf_enabled() 0 #define hvf_get_supported_cpuid(func, idx, reg) 0 -#endif +#endif /* !CONFIG_HVF */ /* hvf_slot flags */ #define HVF_SLOT_LOG (1 << 0) -- 2.26.2
[PULL 110/115] exec/memory: Remove unused MemoryRegionMmio type
From: Philippe Mathieu-Daudé Since commit 62a0db942dec ('memory: Remove old_mmio accessors') this structure is unused. Remove it. Suggested-by: Peter Maydell Reviewed-by: Peter Maydell Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200601141536.15192-2-f4...@amsat.org> Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 6 -- 1 file changed, 6 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index af8ca7824e..7207025bd4 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -50,12 +50,6 @@ extern bool global_dirty_log; typedef struct MemoryRegionOps MemoryRegionOps; -typedef struct MemoryRegionMmio MemoryRegionMmio; - -struct MemoryRegionMmio { -CPUReadMemoryFunc *read[3]; -CPUWriteMemoryFunc *write[3]; -}; typedef struct IOMMUTLBEntry IOMMUTLBEntry; -- 2.26.2
[PULL 112/115] exec/cpu-common: Move MUSB specific typedefs to 'hw/usb/hcd-musb.h'
From: Philippe Mathieu-Daudé The CPUReadMemoryFunc/CPUWriteMemoryFunc typedefs are legacy remnant from before the conversion to MemoryRegions. Since they are now only used in tusb6010.c and hcd-musb.c, move them to "hw/usb/musb.h" and rename them appropriately. Suggested-by: Peter Maydell Reviewed-by: Peter Maydell Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200601141536.15192-4-f4...@amsat.org> Signed-off-by: Paolo Bonzini --- hw/usb/hcd-musb.c | 4 ++-- include/exec/cpu-common.h | 3 --- include/hw/usb/hcd-musb.h | 9 + 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index 5ab13feb3a..85f5ff5bd4 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -1540,13 +1540,13 @@ static void musb_writew(void *opaque, hwaddr addr, uint32_t value) }; } -CPUReadMemoryFunc * const musb_read[] = { +MUSBReadFunc * const musb_read[] = { musb_readb, musb_readh, musb_readw, }; -CPUWriteMemoryFunc * const musb_write[] = { +MUSBWriteFunc * const musb_write[] = { musb_writeb, musb_writeh, musb_writew, diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index b47e5630e7..d5e285d2b5 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -43,9 +43,6 @@ extern ram_addr_t ram_size; /* memory API */ -typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value); -typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); - void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should not be used by devices. */ ram_addr_t qemu_ram_addr_from_host(void *ptr); diff --git a/include/hw/usb/hcd-musb.h b/include/hw/usb/hcd-musb.h index 26b50132ff..c874b9f292 100644 --- a/include/hw/usb/hcd-musb.h +++ b/include/hw/usb/hcd-musb.h @@ -13,8 +13,6 @@ #ifndef HW_USB_MUSB_H #define HW_USB_MUSB_H -#include "exec/cpu-common.h" - enum musb_irq_source_e { musb_irq_suspend = 0, musb_irq_resume, @@ -32,8 +30,11 @@ enum musb_irq_source_e { musb_irq_max /* total number of interrupts defined */ }; -extern CPUReadMemoryFunc * const musb_read[]; -extern CPUWriteMemoryFunc * const musb_write[]; +/* TODO convert hcd-musb to QOM/qdev and remove MUSBReadFunc/MUSBWriteFunc */ +typedef void MUSBWriteFunc(void *opaque, hwaddr addr, uint32_t value); +typedef uint32_t MUSBReadFunc(void *opaque, hwaddr addr); +extern MUSBReadFunc * const musb_read[]; +extern MUSBWriteFunc * const musb_write[]; typedef struct MUSBState MUSBState; -- 2.26.2
[PULL 080/115] exec: set map length to zero when returning NULL
From: Prasad J Pandit When mapping physical memory into host's virtual address space, 'address_space_map' may return NULL if BounceBuffer is in_use. Set and return '*plen = 0' to avoid later NULL pointer dereference. Reported-by: Alexander Bulekov Fixes: https://bugs.launchpad.net/qemu/+bug/1878259 Suggested-by: Paolo Bonzini Suggested-by: Peter Maydell Signed-off-by: Prasad J Pandit Message-Id: <20200526111743.428367-1-ppan...@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- exec.c| 1 + include/exec/memory.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 9cbde85d8c..778263f1c6 100644 --- a/exec.c +++ b/exec.c @@ -3540,6 +3540,7 @@ void *address_space_map(AddressSpace *as, if (!memory_access_is_direct(mr, is_write)) { if (atomic_xchg(_use, true)) { +*plen = 0; return NULL; } /* Avoid unbounded allocations */ diff --git a/include/exec/memory.h b/include/exec/memory.h index bd7fdd6081..af8ca7824e 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2314,7 +2314,8 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len, /* address_space_map: map a physical memory region into a host virtual address * * May map a subset of the requested range, given by and returned in @plen. - * May return %NULL if resources needed to perform the mapping are exhausted. + * May return %NULL and set *@plen to zero(0), if resources needed to perform + * the mapping are exhausted. * Use only for reads OR writes - not for read-modify-write operations. * Use cpu_register_map_client() to know when retrying the map operation is * likely to succeed. -- 2.26.2
[PULL 081/115] target/i386: fix IEEE x87 floating-point exception raising
From: Joseph Myers Most x87 instruction implementations fail to raise the expected IEEE floating-point exceptions because they do nothing to convert the exception state from the softfloat machinery into the exception flags in the x87 status word. There is special-case handling of division to raise the divide-by-zero exception, but that handling is itself buggy: it raises the exception in inappropriate cases (inf / 0 and nan / 0, which should not raise any exceptions, and 0 / 0, which should raise "invalid" instead). Fix this by converting the floating-point exceptions raised during an operation by the softfloat machinery into exceptions in the x87 status word (passing through the existing fpu_set_exception function for handling related to trapping exceptions). There are special cases where some functions convert to integer internally but exceptions from that conversion are not always correct exceptions for the instruction to raise. There might be scope for some simplification if the softfloat exception state either could always be assumed to be in sync with the state in the status word, or could always be ignored at the start of each instruction and just set to 0 then; I haven't looked into that in detail, and it might run into interactions with the various ways the emulation does not yet handle trapping exceptions properly. I think the approach taken here, of saving the softfloat state, setting exceptions there to 0 and then merging the old exceptions back in after carrying out the operation, is conservatively safe. Signed-off-by: Joseph Myers Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/fpu_helper.c | 126 +++- tests/tcg/i386/test-i386-fp-exceptions.c | 831 +++ 2 files changed, 926 insertions(+), 31 deletions(-) create mode 100644 tests/tcg/i386/test-i386-fp-exceptions.c diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 9c93f385b1..8ef5b463ea 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -161,12 +161,32 @@ static void fpu_set_exception(CPUX86State *env, int mask) } } +static inline uint8_t save_exception_flags(CPUX86State *env) +{ +uint8_t old_flags = get_float_exception_flags(>fp_status); +set_float_exception_flags(0, >fp_status); +return old_flags; +} + +static void merge_exception_flags(CPUX86State *env, uint8_t old_flags) +{ +uint8_t new_flags = get_float_exception_flags(>fp_status); +float_raise(old_flags, >fp_status); +fpu_set_exception(env, + ((new_flags & float_flag_invalid ? FPUS_IE : 0) | + (new_flags & float_flag_divbyzero ? FPUS_ZE : 0) | + (new_flags & float_flag_overflow ? FPUS_OE : 0) | + (new_flags & float_flag_underflow ? FPUS_UE : 0) | + (new_flags & float_flag_inexact ? FPUS_PE : 0) | + (new_flags & float_flag_input_denormal ? FPUS_DE : 0))); +} + static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b) { -if (floatx80_is_zero(b)) { -fpu_set_exception(env, FPUS_ZE); -} -return floatx80_div(a, b, >fp_status); +uint8_t old_flags = save_exception_flags(env); +floatx80 ret = floatx80_div(a, b, >fp_status); +merge_exception_flags(env, old_flags); +return ret; } static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) @@ -183,6 +203,7 @@ static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) void helper_flds_FT0(CPUX86State *env, uint32_t val) { +uint8_t old_flags = save_exception_flags(env); union { float32 f; uint32_t i; @@ -190,10 +211,12 @@ void helper_flds_FT0(CPUX86State *env, uint32_t val) u.i = val; FT0 = float32_to_floatx80(u.f, >fp_status); +merge_exception_flags(env, old_flags); } void helper_fldl_FT0(CPUX86State *env, uint64_t val) { +uint8_t old_flags = save_exception_flags(env); union { float64 f; uint64_t i; @@ -201,6 +224,7 @@ void helper_fldl_FT0(CPUX86State *env, uint64_t val) u.i = val; FT0 = float64_to_floatx80(u.f, >fp_status); +merge_exception_flags(env, old_flags); } void helper_fildl_FT0(CPUX86State *env, int32_t val) @@ -210,6 +234,7 @@ void helper_fildl_FT0(CPUX86State *env, int32_t val) void helper_flds_ST0(CPUX86State *env, uint32_t val) { +uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float32 f; @@ -221,10 +246,12 @@ void helper_flds_ST0(CPUX86State *env, uint32_t val) env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, >fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ +merge_exception_flags(env, old_flags); } void helper_fldl_ST0(CPUX86State *env, uint64_t val) { +uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float64 f; @@ -236,6 +263,7 @@ void
[PULL 107/115] target/i386: sev: Remove redundant handle field
From: David Gibson The user can explicitly specify a handle via the "handle" property wired to SevGuestState::handle. That gets passed to the KVM_SEV_LAUNCH_START ioctl() which may update it, the final value being copied back to both SevGuestState::handle and SEVState::handle. AFAICT, nothing will be looking SEVState::handle before it and SevGuestState::handle have been updated from the ioctl(). So, remove the field and just use SevGuestState::handle directly. Signed-off-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-9-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 4b261beaa7..24e2dea9b8 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -40,7 +40,6 @@ struct SEVState { uint8_t api_minor; uint8_t build_id; uint64_t me_mask; -uint32_t handle; int sev_fd; SevState state; gchar *measurement; @@ -64,13 +63,13 @@ struct SevGuestState { /* configuration parameters */ char *sev_device; uint32_t policy; -uint32_t handle; char *dh_cert_file; char *session_file; uint32_t cbitpos; uint32_t reduced_phys_bits; /* runtime state */ +uint32_t handle; SEVState state; }; @@ -398,7 +397,7 @@ sev_get_info(void) info->build_id = sev_guest->state.build_id; info->policy = sev_guest->policy; info->state = sev_guest->state.state; -info->handle = sev_guest->state.handle; +info->handle = sev_guest->handle; } return info; @@ -517,8 +516,7 @@ sev_launch_start(SevGuestState *sev) start = g_new0(struct kvm_sev_launch_start, 1); -start->handle = object_property_get_int(OBJECT(sev), "handle", -_abort); +start->handle = sev->handle; start->policy = sev->policy; if (sev->session_file) { if (sev_read_file_base64(sev->session_file, , ) < 0) { @@ -544,10 +542,8 @@ sev_launch_start(SevGuestState *sev) goto out; } -object_property_set_int(OBJECT(sev), start->handle, "handle", -_abort); sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE); -s->handle = start->handle; +sev->handle = start->handle; ret = 0; out: -- 2.26.2
[PULL 092/115] i386: hvf: Drop fetch_rip from HVFX86EmulatorState
From: Roman Bolshakov The field is used to print address of instructions that have no parser in decode_invalid(). RIP from VMCS is saved into fetch_rip before decoding starts but it's also saved into env->eip in load_regs(). Therefore env->eip can be used instead of fetch_rip. While at it, correct address printed in decode_invalid(). It prints an address before the unknown instruction. Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-8-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c| 6 -- target/i386/hvf/x86.h| 1 - target/i386/hvf/x86_decode.c | 3 +-- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 45ae55dd27..416a6fae7c 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -767,8 +767,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); -env->hvf_emul->fetch_rip = rip; - decode_instruction(env, ); exec_instruction(env, ); store_regs(cpu); @@ -809,8 +807,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); -env->hvf_emul->fetch_rip = rip; - decode_instruction(env, ); assert(ins_len == decode.len); exec_instruction(env, ); @@ -915,8 +911,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); -env->hvf_emul->fetch_rip = rip; - decode_instruction(env, ); exec_instruction(env, ); store_regs(cpu); diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index e3ab7c5137..411e4b6599 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -293,7 +293,6 @@ typedef struct lazy_flags { /* Definition of hvf_x86_state is here */ struct HVFX86EmulatorState { -uint64_t fetch_rip; struct x86_register regs[16]; struct x86_reg_flags rflags; struct lazy_flags lflags; diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index a590088f54..d881542181 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -29,8 +29,7 @@ static void decode_invalid(CPUX86State *env, struct x86_decode *decode) { -printf("%llx: failed to decode instruction ", env->hvf_emul->fetch_rip - - decode->len); +printf("%llx: failed to decode instruction ", env->eip); for (int i = 0; i < decode->opcode_len; i++) { printf("%x ", decode->opcode[i]); } -- 2.26.2
[PULL 058/115] disas: Let disas::read_memory() handler return EIO on error
From: Philippe Mathieu-Daudé Both cpu_memory_rw_debug() and address_space_read() return an error on failed transaction. Check the returned value, and return EIO in case of error. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- disas.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/disas.c b/disas.c index 45285d3f63..c1397d3933 100644 --- a/disas.c +++ b/disas.c @@ -39,9 +39,11 @@ target_read_memory (bfd_vma memaddr, struct disassemble_info *info) { CPUDebug *s = container_of(info, CPUDebug, info); +int r; -cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); -return 0; +r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); + +return r ? EIO : 0; } /* Print an error message. We can assume that this is in response to @@ -718,10 +720,11 @@ physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, struct disassemble_info *info) { CPUDebug *s = container_of(info, CPUDebug, info); +MemTxResult res; -address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, - myaddr, length); -return 0; +res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, + myaddr, length); +return res == MEMTX_OK ? 0 : EIO; } /* Disassembler for the monitor. */ -- 2.26.2
[PULL 082/115] target/i386: correct fix for pcmpxstrx substring search
From: Joseph Myers This corrects a bug introduced in my previous fix for SSE4.2 pcmpestri / pcmpestrm / pcmpistri / pcmpistrm substring search, commit ae35eea7e4a9f21dd147406dfbcd0c4c6aaf2a60. That commit fixed a bug that showed up in four GCC tests with one libc implementation. The tests in question generate random inputs to the intrinsics and compare results to a C implementation, but they only test 1024 possible random inputs, and when the tests use the cases of those instructions that work with word rather than byte inputs, it's easy to have problematic cases that show up much less frequently than that. Thus, testing with a different libc implementation, and so a different random number generator, showed up a problem with the previous patch. When investigating the previous test failures, I found the description of these instructions in the Intel manuals (starting from computing a 16x16 or 8x8 set of comparison results) confusing and hard to match up with the more optimized implementation in QEMU, and referred to AMD manuals which described the instructions in a different way. Those AMD descriptions are very explicit that the whole of the string being searched for must be found in the other operand, not running off the end of that operand; they say "If the prototype and the SUT are equal in length, the two strings must be identical for the comparison to be TRUE.". However, that statement is incorrect. In my previous commit message, I noted: The operation in this case is a search for a string (argument d to the helper) in another string (argument s to the helper); if a copy of d at a particular position would run off the end of s, the resulting output bit should be 0 whether or not the strings match in the region where they overlap, but the QEMU implementation was wrongly comparing only up to the point where s ends and counting it as a match if an initial segment of d matched a terminal segment of s. Here, "run off the end of s" means that some byte of d would overlap some byte outside of s; thus, if d has zero length, it is considered to match everywhere, including after the end of s. The description "some byte of d would overlap some byte outside of s" is accurate only when understood to refer to overlapping some byte *within the 16-byte operand* but at or after the zero terminator; it is valid to run over the end of s if the end of s is the end of the 16-byte operand. So the fix in the previous patch for the case of d being empty was correct, but the other part of that patch was not correct (as it never allowed partial matches even at the end of the 16-byte operand). Nor was the code before the previous patch correct for the case of d nonempty, as it would always have allowed partial matches at the end of s. Fix with a partial revert of my previous change, combined with inserting a check for the special case of s having maximum length to determine where it is necessary to check for matches. In the added test, test 1 is for the case of empty strings, which failed before my 2017 patch, test 2 is for the bug introduced by my 2017 patch and test 3 deals with the case where a match of an initial segment at the end of the string is not valid when the string ends before the end of the 16-byte operand (that is, the case that would be broken by a simple revert of the non-empty-string part of my 2017 patch). Signed-off-by: Joseph Myers Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h| 4 ++-- tests/tcg/i386/Makefile.target | 3 +++ tests/tcg/i386/test-i386-pcmpistri.c | 33 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/tcg/i386/test-i386-pcmpistri.c diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 01d6017412..14f2b16abd 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -2089,10 +2089,10 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s, res = (2 << upper) - 1; break; } -for (j = valids - validd; j >= 0; j--) { +for (j = valids == upper ? valids : valids - validd; j >= 0; j--) { res <<= 1; v = 1; -for (i = validd; i >= 0; i--) { +for (i = MIN(valids - j, validd); i >= 0; i--) { v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i)); } res |= v; diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 43ee2e181e..de5a3a275f 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -10,6 +10,9 @@ ALL_X86_TESTS=$(I386_SRCS:.c=) SKIP_I386_TESTS=test-i386-ssse3 X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS)) +test-i386-pcmpistri: CFLAGS += -msse4.2 +test-i386-pcmpistri: QEMU_OPTS += -cpu max + # # hello-i386 is a barebones app # diff --git a/tests/tcg/i386/test-i386-pcmpistri.c
[PULL 073/115] replay: implement fair mutex
From: Pavel Dovgalyuk In record/replay icount mode main loop thread and vCPU thread do not perform simultaneously. They take replay mutex to synchronize the actions. Sometimes vCPU thread waits for locking the mutex for very long time, because main loop releases the mutex and takes it back again. Standard qemu mutex do not provide the ordering capabilities. This patch adds a "queue" for replay mutex. Therefore thread ordering becomes more "fair". Threads are executed in the same order as they are trying to take the mutex. Signed-off-by: Pavel Dovgalyuk Message-Id: <158823802979.28101.9340462887738957616.stgit@pasha-ThinkPad-X280> Signed-off-by: Paolo Bonzini --- replay/replay-internal.c | 15 ++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/replay/replay-internal.c b/replay/replay-internal.c index eba8246aae..2e8a3e947a 100644 --- a/replay/replay-internal.c +++ b/replay/replay-internal.c @@ -22,6 +22,9 @@ It also protects replay events queue which stores events to be written or read to the log. */ static QemuMutex lock; +/* Condition and queue for fair ordering of mutex lock requests. */ +static QemuCond mutex_cond; +static unsigned long mutex_head, mutex_tail; /* File for replay writing */ static bool write_error; @@ -197,9 +200,10 @@ static __thread bool replay_locked; void replay_mutex_init(void) { qemu_mutex_init(); +qemu_cond_init(_cond); /* Hold the mutex while we start-up */ -qemu_mutex_lock(); replay_locked = true; +++mutex_tail; } bool replay_mutex_locked(void) @@ -211,10 +215,16 @@ bool replay_mutex_locked(void) void replay_mutex_lock(void) { if (replay_mode != REPLAY_MODE_NONE) { +unsigned long id; g_assert(!qemu_mutex_iothread_locked()); g_assert(!replay_mutex_locked()); qemu_mutex_lock(); +id = mutex_tail++; +while (id != mutex_head) { +qemu_cond_wait(_cond, ); +} replay_locked = true; +qemu_mutex_unlock(); } } @@ -222,7 +232,10 @@ void replay_mutex_unlock(void) { if (replay_mode != REPLAY_MODE_NONE) { g_assert(replay_mutex_locked()); +qemu_mutex_lock(); +++mutex_head; replay_locked = false; +qemu_cond_broadcast(_cond); qemu_mutex_unlock(); } } -- 2.26.2
[PULL 089/115] i386: hvf: Drop unused variable
From: Roman Bolshakov Signed-off-by: Roman Bolshakov Message-Id: <20200528193758.51454-5-r.bolsha...@yadro.com> Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- target/i386/hvf/x86.h | 1 - 1 file changed, 1 deletion(-) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index c95d5b2116..56fcde13c6 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -293,7 +293,6 @@ typedef struct lazy_flags { /* Definition of hvf_x86_state is here */ struct HVFX86EmulatorState { -int interruptable; uint64_t fetch_rip; uint64_t rip; struct x86_register regs[16]; -- 2.26.2
[PULL 100/115] target/i386: sev: Remove unused QSevGuestInfoClass
From: David Gibson This structure is nothing but an empty wrapper around the parent class, which by QOM conventions means we don't need it at all. Signed-off-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200604064219.436242-2-da...@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 1 - target/i386/sev_i386.h | 5 - 2 files changed, 6 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 51cdbe5496..2312510cf2 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -287,7 +287,6 @@ static const TypeInfo qsev_guest_info = { .name = TYPE_QSEV_GUEST_INFO, .instance_size = sizeof(QSevGuestInfo), .instance_finalize = qsev_guest_finalize, -.class_size = sizeof(QSevGuestInfoClass), .class_init = qsev_guest_class_init, .instance_init = qsev_guest_init, .interfaces = (InterfaceInfo[]) { diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index 8ada9d385d..4f193642ac 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -41,7 +41,6 @@ extern char *sev_get_launch_measurement(void); extern SevCapability *sev_get_capabilities(void); typedef struct QSevGuestInfo QSevGuestInfo; -typedef struct QSevGuestInfoClass QSevGuestInfoClass; /** * QSevGuestInfo: @@ -64,10 +63,6 @@ struct QSevGuestInfo { uint32_t reduced_phys_bits; }; -struct QSevGuestInfoClass { -ObjectClass parent_class; -}; - struct SEVState { QSevGuestInfo *sev_info; uint8_t api_major; -- 2.26.2