[Qemu-devel] [Bug 1708442] Re: Crash(assert) during reading image from http url through qemu-nbd
ping -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1708442 Title: Crash(assert) during reading image from http url through qemu-nbd Status in QEMU: New Bug description: Description: During reading image from nbd device mounted by qemu-nbd server with url backend I/O error happens "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some investigation I found that qemu-nbd server aborts in aio_co_enter() assert in util/async.c:468. Steps to reproduce: 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- report.tar.gz) or try directly 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 2) try read whole nbd device while error "blk_update_request: I/O error, dev nbd0, sector 42117" appears in dmesg Versions: 1) qemu built from sources(/configure --target-list=x86_64-softmmu --disable-user --enable-curl --enable-linux-aio --enable-virtfs --enable-debug --disable-pie , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): qemu-nbd -v qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) 2) libcurl(built from sources, top commit 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): curl -V curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 Backtrace: (gdb) bt #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #1 0x7f713142802a in __GI_abort () at abort.c:89 #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", file=file@entry=0x54c871 "util/async.c", line=line@entry=468, function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at util/async.c:468 #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, opaque=0xf1cb90) at block/curl.c:275 #7 0x7f713242ac24 in Curl_client_chop_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #8 0x7f713242ae03 in Curl_client_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #9 0x7f713244e1cf in readwrite_data () from /usr/lib/x86_64-linux-gnu/libcurl.so #10 0x7f713244eb6f in Curl_readwrite () from /usr/lib/x86_64-linux-gnu/libcurl.so #11 0x7f713245c1bb in multi_runsingle () from /usr/lib/x86_64-linux-gnu/libcurl.so #12 0x7f713245d819 in multi_socket () from /usr/lib/x86_64-linux-gnu/libcurl.so #13 0x7f713245e067 in curl_multi_socket_action () from /usr/lib/x86_64-linux-gnu/libcurl.so #14 0x00497555 in curl_setup_preadv (bs=0xf16820, acb=0x7f712d379860) at block/curl.c:918 #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 #16 0x0047730f in bdrv_driver_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:836 #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, qiov=0x7f712d379b40, flags=0) at block/io.c:1086 #18 0x00478109 in bdrv_co_preadv (child=0xf1be20, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:1180 #19 0x00437498 in qcow2_co_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/qcow2.c:1812 #20 0x0047730f in bdrv_driver_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:836 #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, qiov=0x7f712d379e80, flags=0) at block/io.c:1086 #22 0x00478109 in bdrv_co_preadv (child=0xf1c0d0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:1180 #23 0x004645ad in blk_co_preadv (blk=0xf1be90, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/block-backend.c:991 #24 0x004646fa in blk_read_entry (opaque=0x7f712d379ea0) at block/block-backend.c:1038 #25 0x0046481c in blk_prw (blk=0xf1be90, offset=21563904, ---Type to continue, or q to quit--- buf=0xf7f000 "2,NV\241t!\ti\312\vp\364\017Kl*\354\021\a\177\021\260\b\027\212\347\027\004\322\nG\340b\\\306pG\332\313\060\341;\002\360\063L\240\027T
[Qemu-devel] [Bug 1708442] Re: Crash(assert) during reading image from http url through qemu-nbd
I've attached patch which resolves bug, but actually it's just workaround and may be not unsafe, because it's just ignore assert. ** Patch added: "workaround patch" https://bugs.launchpad.net/qemu/+bug/1708442/+attachment/4926546/+files/0001-util-async-ignore-self-co-enter-instead-of-assert.patch -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1708442 Title: Crash(assert) during reading image from http url through qemu-nbd Status in QEMU: New Bug description: Description: During reading image from nbd device mounted by qemu-nbd server with url backend I/O error happens "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some investigation I found that qemu-nbd server aborts in aio_co_enter() assert in util/async.c:468. Steps to reproduce: 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- report.tar.gz) or try directly 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 2) try read whole nbd device while error "blk_update_request: I/O error, dev nbd0, sector 42117" appears in dmesg Versions: 1) qemu built from sources(/configure --target-list=x86_64-softmmu --disable-user --enable-curl --enable-linux-aio --enable-virtfs --enable-debug --disable-pie , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): qemu-nbd -v qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) 2) libcurl(built from sources, top commit 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): curl -V curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 Backtrace: (gdb) bt #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #1 0x7f713142802a in __GI_abort () at abort.c:89 #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", file=file@entry=0x54c871 "util/async.c", line=line@entry=468, function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at util/async.c:468 #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, opaque=0xf1cb90) at block/curl.c:275 #7 0x7f713242ac24 in Curl_client_chop_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #8 0x7f713242ae03 in Curl_client_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #9 0x7f713244e1cf in readwrite_data () from /usr/lib/x86_64-linux-gnu/libcurl.so #10 0x7f713244eb6f in Curl_readwrite () from /usr/lib/x86_64-linux-gnu/libcurl.so #11 0x7f713245c1bb in multi_runsingle () from /usr/lib/x86_64-linux-gnu/libcurl.so #12 0x7f713245d819 in multi_socket () from /usr/lib/x86_64-linux-gnu/libcurl.so #13 0x7f713245e067 in curl_multi_socket_action () from /usr/lib/x86_64-linux-gnu/libcurl.so #14 0x00497555 in curl_setup_preadv (bs=0xf16820, acb=0x7f712d379860) at block/curl.c:918 #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 #16 0x0047730f in bdrv_driver_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:836 #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, qiov=0x7f712d379b40, flags=0) at block/io.c:1086 #18 0x00478109 in bdrv_co_preadv (child=0xf1be20, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:1180 #19 0x00437498 in qcow2_co_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/qcow2.c:1812 #20 0x0047730f in bdrv_driver_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:836 #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, qiov=0x7f712d379e80, flags=0) at block/io.c:1086 #22 0x00478109 in bdrv_co_preadv (child=0xf1c0d0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:1180 #23 0x004645ad in blk_co_preadv (blk=0xf1be90, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/block-backend.c:991 #24 0x004646fa in blk_read_entry (opaque=0x7f712d379ea0) at block/block-backend.c:1038 #25 0x0046481c in blk_prw (blk=0xf1be90, offset=21563904, ---Type to continue, or q to quit--- buf=0xf7f000
[Qemu-devel] [Bug 1708442] Re: Crash(assert) during reading image from http url through qemu-nbd
I've build qemu-nbd-bug.go into binary qemu-nbd-bug (go build qemu-nbd-bug.go), so to reproduce bug anyone may try: 0) ensure image.img exists in current folder. image.img may be copied from "Qemu-nbd core dump and script to reproduce " attachment. 1) sudo ./qemu-nbd-bug 2) wait while binary aborting(panicking) 3) check dmesg for error like "blk_update_request: I/O error, dev nbd0, sector 42117" 4) check qemu-nbd core dump (since it's aborting due to assert in aio_co_enter(), util/async.c:468). ** Attachment added: "qemu-nbd-bug" https://bugs.launchpad.net/qemu/+bug/1708442/+attachment/4926543/+files/qemu-nbd-bug -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1708442 Title: Crash(assert) during reading image from http url through qemu-nbd Status in QEMU: New Bug description: Description: During reading image from nbd device mounted by qemu-nbd server with url backend I/O error happens "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some investigation I found that qemu-nbd server aborts in aio_co_enter() assert in util/async.c:468. Steps to reproduce: 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- report.tar.gz) or try directly 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 2) try read whole nbd device while error "blk_update_request: I/O error, dev nbd0, sector 42117" appears in dmesg Versions: 1) qemu built from sources(/configure --target-list=x86_64-softmmu --disable-user --enable-curl --enable-linux-aio --enable-virtfs --enable-debug --disable-pie , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): qemu-nbd -v qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) 2) libcurl(built from sources, top commit 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): curl -V curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 Backtrace: (gdb) bt #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #1 0x7f713142802a in __GI_abort () at abort.c:89 #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", file=file@entry=0x54c871 "util/async.c", line=line@entry=468, function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at util/async.c:468 #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, opaque=0xf1cb90) at block/curl.c:275 #7 0x7f713242ac24 in Curl_client_chop_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #8 0x7f713242ae03 in Curl_client_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #9 0x7f713244e1cf in readwrite_data () from /usr/lib/x86_64-linux-gnu/libcurl.so #10 0x7f713244eb6f in Curl_readwrite () from /usr/lib/x86_64-linux-gnu/libcurl.so #11 0x7f713245c1bb in multi_runsingle () from /usr/lib/x86_64-linux-gnu/libcurl.so #12 0x7f713245d819 in multi_socket () from /usr/lib/x86_64-linux-gnu/libcurl.so #13 0x7f713245e067 in curl_multi_socket_action () from /usr/lib/x86_64-linux-gnu/libcurl.so #14 0x00497555 in curl_setup_preadv (bs=0xf16820, acb=0x7f712d379860) at block/curl.c:918 #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 #16 0x0047730f in bdrv_driver_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:836 #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, qiov=0x7f712d379b40, flags=0) at block/io.c:1086 #18 0x00478109 in bdrv_co_preadv (child=0xf1be20, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:1180 #19 0x00437498 in qcow2_co_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/qcow2.c:1812 #20 0x0047730f in bdrv_driver_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:836 #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, qiov=0x7f712d379e80, flags=0) at block/io.c:1086 #22 0x00478109 in bdrv_co_preadv (child=0xf1c0d0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:1180 #23 0x004645ad in blk_co_preadv (blk=0xf1be90,
Re: [Qemu-devel] [Bug 1708442] [NEW] Crash(assert) during reading image from http url through qemu-nbd
03.08.2017, 17:01, "Eric Blake" <1708...@bugs.launchpad.net>: > On 08/03/2017 07:12 AM, Andrey Smetanin wrote: >> Public bug reported: >> >> Description: >> During reading image from nbd device mounted by qemu-nbd server with url >> backend I/O error happens >> "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some >> investigation I found that qemu-nbd server aborts in aio_co_enter() assert >> in util/async.c:468. > > Based on the backtrace, this looks to be a bug in the block/curl.c > driver, rather than the nbd/ or block/nbd.c code. If I'm right, it > should be possible to reproduce the crash using qemu-io directly on the > curl path, rather than adding the extra layer of an nbd client reading > through qemu-nbd (then again, having the qemu-nbd layer may be what is > allowing multiple parallel requests to hit the curl driver at once, > while qemu-io is not quite as easy to provoke into performing > complicated access patterns). > >> Steps to reproduce: >> >> 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- >> report.tar.gz) >> >> or try directly >> >> 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 >> json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 > > Presumably, you've got something serving the file at port 9666? Yes, you are right. I'm using qemu-nbd-bug.go(see qemu-nbd-bug-report.tar.gz) script which does it. > >> 2) try read whole nbd device while error in dmesg appears x >> >> Versions: >> >> 1) qemu built from sources(/configure --target-list=x86_64-softmmu >> --disable-user --enable-curl --enable-linux-aio --enable-virtfs >> --enable-debug --disable-pie >> , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): >> >> qemu-nbd -v >> qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) >> >> 2) libcurl(built from sources, top commit >> 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): >> >> curl -V >> curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 >> >> Backtrace: >> (gdb) bt >> #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at >> ../sysdeps/unix/sysv/linux/raise.c:54 >> #1 0x7f713142802a in __GI_abort () at abort.c:89 >> #2 0x7f713141ebd7 in __assert_fail_base (fmt=, >> assertion=assertion@entry=0x54c924 "self != co", >> file=file@entry=0x54c871 "util/async.c", line=line@entry=468, >> function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> >> "aio_co_enter") at assert.c:92 >> #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != >> co", file=0x54c871 "util/async.c", line=468, >> function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at >> assert.c:101 >> #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at >> util/async.c:468 >> #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 >> #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, >> opaque=0xf1cb90) at block/curl.c:275 >> #7 0x7f713242ac24 in Curl_client_chop_write () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #8 0x7f713242ae03 in Curl_client_write () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #9 0x7f713244e1cf in readwrite_data () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #10 0x7f713244eb6f in Curl_readwrite () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #11 0x7f713245c1bb in multi_runsingle () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #12 0x7f713245d819 in multi_socket () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #13 0x7f713245e067 in curl_multi_socket_action () from >> /usr/lib/x86_64-linux-gnu/libcurl.so >> #14 0x00497555 in curl_setup_preadv (bs=0xf16820, >> acb=0x7f712d379860) at block/curl.c:918 >> #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, >> bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 > > The backtrace is definitely pointing at curl as being the problem. > > -- > Eric Blake, Principal Software Engineer > Red Hat, Inc. +1-919-301-3266 > Virtualization: qemu.org | libvirt.org > > -- > You received this bug notification because you are subscribed to the bug > report. > https://bugs.launchpad.net/bugs/1708442 > > Title: > Crash(assert) during reading image from http url through qemu-nbd > > Statu
[Qemu-devel] [Bug 1708442] Re: Crash(assert) during reading image from http url through qemu-nbd
** Description changed: Description: During reading image from nbd device mounted by qemu-nbd server with url backend I/O error happens "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some investigation I found that qemu-nbd server aborts in aio_co_enter() assert in util/async.c:468. - Steps to reproduce: 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- report.tar.gz) or try directly 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 - 2) try read whole nbd device while error in dmesg appears x + 2) try read whole nbd device while error "blk_update_request: I/O error, dev nbd0, sector 42117" appears in dmesg Versions: 1) qemu built from sources(/configure --target-list=x86_64-softmmu --disable-user --enable-curl --enable-linux-aio --enable-virtfs --enable-debug --disable-pie , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): qemu-nbd -v qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) 2) libcurl(built from sources, top commit 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): curl -V curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 - Backtrace: (gdb) bt #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #1 0x7f713142802a in __GI_abort () at abort.c:89 - #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", - file=file@entry=0x54c871 "util/async.c", line=line@entry=468, - function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 - #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, - function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 + #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", + file=file@entry=0x54c871 "util/async.c", line=line@entry=468, + function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 + #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, + function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at util/async.c:468 #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, opaque=0xf1cb90) at block/curl.c:275 #7 0x7f713242ac24 in Curl_client_chop_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #8 0x7f713242ae03 in Curl_client_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #9 0x7f713244e1cf in readwrite_data () from /usr/lib/x86_64-linux-gnu/libcurl.so #10 0x7f713244eb6f in Curl_readwrite () from /usr/lib/x86_64-linux-gnu/libcurl.so #11 0x7f713245c1bb in multi_runsingle () from /usr/lib/x86_64-linux-gnu/libcurl.so #12 0x7f713245d819 in multi_socket () from /usr/lib/x86_64-linux-gnu/libcurl.so #13 0x7f713245e067 in curl_multi_socket_action () from /usr/lib/x86_64-linux-gnu/libcurl.so #14 0x00497555 in curl_setup_preadv (bs=0xf16820, acb=0x7f712d379860) at block/curl.c:918 #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 #16 0x0047730f in bdrv_driver_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:836 - #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, - qiov=0x7f712d379b40, flags=0) at block/io.c:1086 + #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, + qiov=0x7f712d379b40, flags=0) at block/io.c:1086 #18 0x00478109 in bdrv_co_preadv (child=0xf1be20, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:1180 #19 0x00437498 in qcow2_co_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) - at block/qcow2.c:1812 + at block/qcow2.c:1812 #20 0x0047730f in bdrv_driver_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) - at block/io.c:836 - #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, - qiov=0x7f712d379e80, flags=0) at block/io.c:1086 + at block/io.c:836 + #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, + qiov=0x7f712d379e80, flags=0) at block/io.c:1086 #22 0x00478109 in bdrv_co_preadv (child=0xf1c0d0, offset=21563904, bytes=512,
[Qemu-devel] [Bug 1708442] [NEW] Crash(assert) during reading image from http url through qemu-nbd
Public bug reported: Description: During reading image from nbd device mounted by qemu-nbd server with url backend I/O error happens "blk_update_request: I/O error, dev nbd0, sector 42117" dmesg. After some investigation I found that qemu-nbd server aborts in aio_co_enter() assert in util/async.c:468. Steps to reproduce: 1) sudo go run qemu-nbd-bug-report/qemu-nbd-bug.go (see qemu-nbd-bug- report.tar.gz) or try directly 1) qemu-nbd -c /dev/nbd0 -r -v --aio=native -f qcow2 json:{"file.driver":"http","file.url":"http://localhost:9666/image","file.readahead":3276800 2) try read whole nbd device while error in dmesg appears x Versions: 1) qemu built from sources(/configure --target-list=x86_64-softmmu --disable-user --enable-curl --enable-linux-aio --enable-virtfs --enable-debug --disable-pie , top commit 5619c179057e24195ff19c8fe6d6a6cbcb16ed28): qemu-nbd -v qemu-nbd 2.9.90 (v2.10.0-rc0-67-g5619c17) 2) libcurl(built from sources, top commit 1767adf4399bb3be29121435e1bb1cc2bc05f7bf): curl -V curl 7.55.0-DEV (Linux) libcurl/7.55.0-DEV OpenSSL/1.0.2g zlib/1.2.8 Backtrace: (gdb) bt #0 0x7f7131426428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #1 0x7f713142802a in __GI_abort () at abort.c:89 #2 0x7f713141ebd7 in __assert_fail_base (fmt=, assertion=assertion@entry=0x54c924 "self != co", file=file@entry=0x54c871 "util/async.c", line=line@entry=468, function=function@entry=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:92 #3 0x7f713141ec82 in __GI___assert_fail (assertion=0x54c924 "self != co", file=0x54c871 "util/async.c", line=468, function=0x54c980 <__PRETTY_FUNCTION__.24766> "aio_co_enter") at assert.c:101 #4 0x004fe6a2 in aio_co_enter (ctx=0xf0ddb0, co=0xf14650) at util/async.c:468 #5 0x004fe637 in aio_co_wake (co=0xf14650) at util/async.c:456 #6 0x00495c8a in curl_read_cb (ptr=0xf566d9, size=1, nmemb=16135, opaque=0xf1cb90) at block/curl.c:275 #7 0x7f713242ac24 in Curl_client_chop_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #8 0x7f713242ae03 in Curl_client_write () from /usr/lib/x86_64-linux-gnu/libcurl.so #9 0x7f713244e1cf in readwrite_data () from /usr/lib/x86_64-linux-gnu/libcurl.so #10 0x7f713244eb6f in Curl_readwrite () from /usr/lib/x86_64-linux-gnu/libcurl.so #11 0x7f713245c1bb in multi_runsingle () from /usr/lib/x86_64-linux-gnu/libcurl.so #12 0x7f713245d819 in multi_socket () from /usr/lib/x86_64-linux-gnu/libcurl.so #13 0x7f713245e067 in curl_multi_socket_action () from /usr/lib/x86_64-linux-gnu/libcurl.so #14 0x00497555 in curl_setup_preadv (bs=0xf16820, acb=0x7f712d379860) at block/curl.c:918 #15 0x004975fb in curl_co_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/curl.c:935 #16 0x0047730f in bdrv_driver_preadv (bs=0xf16820, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:836 #17 0x00477c1f in bdrv_aligned_preadv (child=0xf1be20, req=0x7f712d379a60, offset=6556160, bytes=512, align=1, qiov=0x7f712d379b40, flags=0) at block/io.c:1086 #18 0x00478109 in bdrv_co_preadv (child=0xf1be20, offset=6556160, bytes=512, qiov=0x7f712d379b40, flags=0) at block/io.c:1180 #19 0x00437498 in qcow2_co_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/qcow2.c:1812 #20 0x0047730f in bdrv_driver_preadv (bs=0xf0fdc0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:836 #21 0x00477c1f in bdrv_aligned_preadv (child=0xf1c0d0, req=0x7f712d379d30, offset=21563904, bytes=512, align=1, qiov=0x7f712d379e80, flags=0) at block/io.c:1086 #22 0x00478109 in bdrv_co_preadv (child=0xf1c0d0, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/io.c:1180 #23 0x004645ad in blk_co_preadv (blk=0xf1be90, offset=21563904, bytes=512, qiov=0x7f712d379e80, flags=0) at block/block-backend.c:991 #24 0x004646fa in blk_read_entry (opaque=0x7f712d379ea0) at block/block-backend.c:1038 #25 0x0046481c in blk_prw (blk=0xf1be90, offset=21563904, ---Type to continue, or q to quit--- buf=0xf7f000 "2,NV\241t!\ti\312\vp\364\017Kl*\354\021\a\177\021\260\b\027\212\347\027\004\322\nG\340b\\\306pG\332\313\060\341;\002\360\063L\240\027T \211\341\305\022АE\230\356DǮ}\211\bx\016\a\b\313\350\316\064.\017\372\032-R\376z\261\263\350|cQ<\016S_L\340A\221\366~L#\001+\271\204\065~\327\023\027I\211\343\361\276zT$4\336\273ˏ\353ʪ\234\016_Z|TMk\"\370\002\363~\334\332.\a\375\265mӌ{/%\304֎\374sFI\356\302\375F\340\332\324\021\202\232>\026\261\233\303tv\023\304\006\243\037\062BϏ\b\324rs\360'"..., bytes=512, co_entry=0x4646aa , flags=0) at block/block-backend.c:1074 #26 0x00464f81 in blk_pread (blk=0xf1be90, offset=21563904, buf=0xf7f000, count=512) at block/block-backend.c:1227 #27
[Qemu-devel] [PATCH v3 1/2] headers: KVM Hyper-V VMBus hypercalls defines and exit
This patch brings in the necessary changes from the corresponding kernel patchset. It's included only for completeness; ideally these changes should arrive via the standard kernel header pull. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org --- include/standard-headers/asm-x86/hyperv.h | 4 +++- linux-headers/linux/kvm.h | 6 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h index acb119d..47b38fb 100644 --- a/include/standard-headers/asm-x86/hyperv.h +++ b/include/standard-headers/asm-x86/hyperv.h @@ -226,7 +226,9 @@ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) /* Declare the various hypercall operations. */ -#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 +#define HVCALL_POST_MESSAGE0x005c +#define HVCALL_SIGNAL_EVENT0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 4e20262..08e652e 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -157,6 +157,7 @@ struct kvm_s390_skeys { struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 +#define KVM_EXIT_HYPERV_HCALL 2 __u32 type; union { struct { @@ -165,6 +166,11 @@ struct kvm_hyperv_exit { __u64 evt_page; __u64 msg_page; } synic; + struct { + __u64 input; + __u64 result; + __u64 params[2]; + } hcall; } u; }; -- 2.4.3
[Qemu-devel] [PATCH v3 2/2] target-i386/kvm: Hyper-V VMBus hypercalls blank handlers
Add Hyper-V VMBus hypercalls blank handlers which just returns error code - HV_STATUS_INVALID_HYPERCALL_CODE. Changes v3: * use HVCALL_* defines Changes v2: * use KVM_EXIT_HYPERV exit type Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org --- target-i386/hyperv.c | 12 1 file changed, 12 insertions(+) diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c index 6b519c3..c4d6a9b 100644 --- a/target-i386/hyperv.c +++ b/target-i386/hyperv.c @@ -44,6 +44,18 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) return -1; } return 0; +case KVM_EXIT_HYPERV_HCALL: { +uint16_t code; + +code = exit->u.hcall.input & 0x; +switch (code) { +case HVCALL_POST_MESSAGE: +case HVCALL_SIGNAL_EVENT: +default: +exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE; +return 0; +} +} default: return -1; } -- 2.4.3
Re: [Qemu-devel] [PATCH v3 2/5] drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header
On 02/12/2016 12:46 AM, Paolo Bonzini wrote: On 11/02/2016 14:44, Andrey Smetanin wrote: VMBus hypercall codes inside Hyper-V UAPI header will be used by QEMU to implement VMBus host devices support. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: K. Y. Srinivasan <k...@microsoft.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 ++ drivers/hv/connection.c| 2 +- drivers/hv/hv.c| 2 +- drivers/hv/hyperv_vmbus.h | 6 -- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 0c50fab..bc1c8a9 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -227,6 +227,8 @@ /* Declare the various hypercall operations. */ #define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HV_X64_HCALL_POST_MESSAGE 0x005c +#define HV_X64_HCALL_SIGNAL_EVENT 0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index fa86b2c..84700c6 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -485,5 +485,5 @@ void vmbus_set_event(struct vmbus_channel *channel) (child_relid >> 5)); } - hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL); + hv_do_hypercall(HV_X64_HCALL_SIGNAL_EVENT, channel->sig_event, NULL); What tree does this apply to? next-20160211 Paolo } diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ccb335f..48388dc 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -337,7 +337,7 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); + status = hv_do_hypercall(HV_X64_HCALL_POST_MESSAGE, aligned_msg, NULL); put_cpu(); return status & 0x; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index b9ea7f5..1dabaa4 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -256,12 +256,6 @@ struct hv_monitor_page { u8 rsvdz4[1984]; }; -/* Declare the various hypercall operations. */ -enum hv_call_code { - HVCALL_POST_MESSAGE = 0x005c, - HVCALL_SIGNAL_EVENT = 0x005d, -}; - /* Definition of the hv_post_message hypercall input structure. */ struct hv_input_post_message { union hv_connection_id connectionid;
[Qemu-devel] [PATCH v3 2/5] drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header
VMBus hypercall codes inside Hyper-V UAPI header will be used by QEMU to implement VMBus host devices support. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: K. Y. Srinivasan <k...@microsoft.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 ++ drivers/hv/connection.c| 2 +- drivers/hv/hv.c| 2 +- drivers/hv/hyperv_vmbus.h | 6 -- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 0c50fab..bc1c8a9 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -227,6 +227,8 @@ /* Declare the various hypercall operations. */ #define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 +#define HV_X64_HCALL_POST_MESSAGE 0x005c +#define HV_X64_HCALL_SIGNAL_EVENT 0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index fa86b2c..84700c6 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -485,5 +485,5 @@ void vmbus_set_event(struct vmbus_channel *channel) (child_relid >> 5)); } - hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL); + hv_do_hypercall(HV_X64_HCALL_SIGNAL_EVENT, channel->sig_event, NULL); } diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ccb335f..48388dc 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -337,7 +337,7 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); + status = hv_do_hypercall(HV_X64_HCALL_POST_MESSAGE, aligned_msg, NULL); put_cpu(); return status & 0x; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index b9ea7f5..1dabaa4 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -256,12 +256,6 @@ struct hv_monitor_page { u8 rsvdz4[1984]; }; -/* Declare the various hypercall operations. */ -enum hv_call_code { - HVCALL_POST_MESSAGE = 0x005c, - HVCALL_SIGNAL_EVENT = 0x005d, -}; - /* Definition of the hv_post_message hypercall input structure. */ struct hv_input_post_message { union hv_connection_id connectionid; -- 2.4.3
[Qemu-devel] [PATCH v3 4/5] kvm/x86: Reject Hyper-V hypercall continuation
Currently we do not support Hyper-V hypercall continuation so reject it. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 0e7c90f..e1daa8b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1083,6 +1083,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); + /* Hypercall continuation is not supported yet */ + if (rep_cnt || rep_idx) { + res = HV_STATUS_INVALID_HYPERCALL_CODE; + goto set_result; + } + switch (code) { case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); @@ -1092,6 +1098,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) break; } +set_result: ret = res | (((u64)rep_done & 0xfff) << 32); if (longmode) { kvm_register_write(vcpu, VCPU_REGS_RAX, ret); -- 2.4.3
[Qemu-devel] [PATCH v3 0/5] KVM: Hyper-V VMBus hypercalls
The patch implements userspace exit 'KVM_EXIT_HYPERV' for Hyper-V VMBus hypercalls(postmsg, signalevent) to handle these hypercalls by QEMU. Changes v3: * use vcpu->arch.complete_userspace_io to setup hypercall result * rebase for 'next-20160211' Changes v2: * use KVM_EXIT_HYPERV for hypercalls Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): kvm/x86: Rename Hyper-V long spin wait hypercall drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header kvm/x86: Pass return code of kvm_emulate_hypercall kvm/x86: Reject Hyper-V hypercall continuation kvm/x86: Hyper-V VMBus hypercall userspace exit Documentation/virtual/kvm/api.txt | 6 + arch/x86/include/uapi/asm/hyperv.h | 4 ++- arch/x86/kvm/hyperv.c | 50 +++--- arch/x86/kvm/svm.c | 3 +-- arch/x86/kvm/vmx.c | 3 +-- drivers/hv/connection.c| 2 +- drivers/hv/hv.c| 2 +- drivers/hv/hyperv_vmbus.h | 6 - include/uapi/linux/kvm.h | 6 + 9 files changed, 60 insertions(+), 22 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v3 1/5] kvm/x86: Rename Hyper-V long spin wait hypercall
Rename HV_X64_HV_NOTIFY_LONG_SPIN_WAIT by HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT. So the name better reflects hypercall codes accessory. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 +- arch/x86/kvm/hyperv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 7956412..0c50fab 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -226,7 +226,7 @@ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) /* Declare the various hypercall operations. */ -#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index c58ba67..f1a42e1 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1084,7 +1084,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); switch (code) { - case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT: + case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; default: -- 2.4.3
[Qemu-devel] [PATCH v3 5/5] kvm/x86: Hyper-V VMBus hypercall userspace exit
The patch implements KVM_EXIT_HYPERV userspace exit functionality for Hyper-V VMBus hypercalls: HV_X64_HCALL_POST_MESSAGE, HV_X64_HCALL_SIGNAL_EVENT. Changes v3: * use vcpu->arch.complete_userspace_io to setup hypercall result Changes v2: * use KVM_EXIT_HYPERV for hypercalls Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- Documentation/virtual/kvm/api.txt | 6 ++ arch/x86/kvm/hyperv.c | 39 --- include/uapi/linux/kvm.h | 6 ++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 07e4cdf..4a661e5 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -3339,6 +3339,7 @@ EOI was received. struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 +#define KVM_EXIT_HYPERV_HCALL 2 __u32 type; union { struct { @@ -3347,6 +3348,11 @@ EOI was received. __u64 evt_page; __u64 msg_page; } synic; + struct { + __u64 input; + __u64 result; + __u64 params[2]; + } hcall; } u; }; /* KVM_EXIT_HYPERV */ diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index e1daa8b..f8d97ee 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1043,6 +1043,27 @@ bool kvm_hv_hypercall_enabled(struct kvm *kvm) return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE; } +static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) +{ + bool longmode; + + longmode = is_64_bit_mode(vcpu); + if (longmode) + kvm_register_write(vcpu, VCPU_REGS_RAX, result); + else { + kvm_register_write(vcpu, VCPU_REGS_RDX, result >> 32); + kvm_register_write(vcpu, VCPU_REGS_RAX, result & 0x); + } +} + +static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + + kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result); + return 1; +} + int kvm_hv_hypercall(struct kvm_vcpu *vcpu) { u64 param, ingpa, outgpa, ret; @@ -1093,6 +1114,16 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; + case HV_X64_HCALL_POST_MESSAGE: + case HV_X64_HCALL_SIGNAL_EVENT: + vcpu->run->exit_reason = KVM_EXIT_HYPERV; + vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL; + vcpu->run->hyperv.u.hcall.input = param; + vcpu->run->hyperv.u.hcall.params[0] = ingpa; + vcpu->run->hyperv.u.hcall.params[1] = outgpa; + vcpu->arch.complete_userspace_io = + kvm_hv_hypercall_complete_userspace; + return 0; default: res = HV_STATUS_INVALID_HYPERCALL_CODE; break; @@ -1100,12 +1131,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) set_result: ret = res | (((u64)rep_done & 0xfff) << 32); - if (longmode) { - kvm_register_write(vcpu, VCPU_REGS_RAX, ret); - } else { - kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32); - kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0x); - } - + kvm_hv_hypercall_set_result(vcpu, ret); return 1; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a2fe0ac..82581b6 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -157,6 +157,7 @@ struct kvm_s390_skeys { struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 +#define KVM_EXIT_HYPERV_HCALL 2 __u32 type; union { struct { @@ -165,6 +166,11 @@ struct kvm_hyperv_exit { __u64 evt_page; __u64 msg_page; } synic; + struct { + __u64 input; + __u64 result; + __u64 params[2]; + } hcall; } u; }; -- 2.4.3
[Qemu-devel] [PATCH v3 3/5] kvm/x86: Pass return code of kvm_emulate_hypercall
Pass the return code from kvm_emulate_hypercall on to the caller, in order to allow it to indicate to the userspace that the hypercall has to be handled there. Also adjust all the existing code paths to return 1 to make sure the hypercall isn't passed to the userspace without setting kvm_run appropriately. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/svm.c| 3 +-- arch/x86/kvm/vmx.c| 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index f1a42e1..0e7c90f 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1055,7 +1055,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) */ if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) { kvm_queue_exception(vcpu, UD_VECTOR); - return 0; + return 1; } longmode = is_64_bit_mode(vcpu); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c13a64b..9507038 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1858,8 +1858,7 @@ static int halt_interception(struct vcpu_svm *svm) static int vmmcall_interception(struct vcpu_svm *svm) { svm->next_rip = kvm_rip_read(>vcpu) + 3; - kvm_emulate_hypercall(>vcpu); - return 1; + return kvm_emulate_hypercall(>vcpu); } static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 164eb9e..2edca5d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5747,8 +5747,7 @@ static int handle_halt(struct kvm_vcpu *vcpu) static int handle_vmcall(struct kvm_vcpu *vcpu) { - kvm_emulate_hypercall(vcpu); - return 1; + return kvm_emulate_hypercall(vcpu); } static int handle_invd(struct kvm_vcpu *vcpu) -- 2.4.3
Re: [Qemu-devel] [PATCH v2 0/5] KVM: Hyper-V VMBus hypercalls
ping On 01/21/2016 05:01 PM, Andrey Smetanin wrote: The patch implements userspace exit 'KVM_EXIT_HYPERV' for Hyper-V VMBus hypercalls(postmsg, signalevent) to handle these hypercalls by QEMU. Changes v2: * use KVM_EXIT_HYPERV for hypercalls Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): kvm/x86: Rename Hyper-V long spin wait hypercall drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header kvm/x86: Pass return code of kvm_emulate_hypercall kvm/x86: Reject Hyper-V hypercall continuation kvm/x86: Hyper-V VMBus hypercall userspace exit Documentation/virtual/kvm/api.txt | 6 ++ arch/x86/include/uapi/asm/hyperv.h | 4 +++- arch/x86/kvm/hyperv.c | 40 +- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/svm.c | 3 +-- arch/x86/kvm/vmx.c | 3 +-- arch/x86/kvm/x86.c | 5 + drivers/hv/hv.c| 4 ++-- drivers/hv/hyperv_vmbus.h | 6 -- include/uapi/linux/kvm.h | 6 ++ 10 files changed, 56 insertions(+), 22 deletions(-)
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 01:08 PM, Paolo Bonzini wrote: On 24/12/2015 10:33, Andrey Smetanin wrote: Lately tsc page was implemented but filled with empty values. This patch setup tsc page scale and offset based on vcpu tsc, tsc_khz and HV_X64_MSR_TIME_REF_COUNT value. The valid tsc page drops HV_X64_MSR_TIME_REF_COUNT msr reads count to zero which potentially improves performance. The patch applies on top of 'kvm: Make vcpu->requests as 64 bit bitmap' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Actually there are some more issues: - unless KVM can use a master clock, it is incorrect to set up the TSC page this way; the sequence needs to be 0x in that case 0x is not an invalid value for tsc page, see https://lkml.org/lkml/2015/11/2/655 - writing the TSC page must be done while all VCPUs are stopped, because the TSC page doesn't provide the possibility for the guest to retry in the middle of an update (like seqcount in Linux doess) I think Windows guest gives tsc page address at boot time and protects against other vcpu's tsc page access. In the end, the TSC page is actually pretty similar to the kvmclock master clock and it makes sense to build it on the master clock too. I'll post a patch next week. Paolo --- arch/x86/kvm/hyperv.c| 117 +-- arch/x86/kvm/hyperv.h| 2 + arch/x86/kvm/x86.c | 12 + include/linux/kvm_host.h | 1 + 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d50675a..504fdc7 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -753,6 +753,105 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, return 0; } +static u64 calc_tsc_page_scale(u32 tsc_khz) +{ + /* +* reftime (in 100ns) = tsc * tsc_scale / 2^64 + tsc_offset +* so reftime_delta = (tsc_delta * tsc_scale) / 2^64 +* so tsc_scale = (2^64 * reftime_delta)/tsc_delta +* so tsc_scale = (2^64 * 10 * 10^6) / tsc_hz = (2^64 * 1) / tsc_khz +* so tsc_scale = (2^63 * 2 * 1) / tsc_khz +*/ + return mul_u64_u32_div(1ULL << 63, 2 * 1, tsc_khz); +} + +static int write_tsc_page(struct kvm *kvm, u64 gfn, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_write_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + mark_page_dirty(kvm, gfn); + return 0; +} + +static int read_tsc_page(struct kvm *kvm, u64 gfn, +PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_read_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + return 0; +} + +static u64 calc_tsc_page_time(struct kvm_vcpu *vcpu, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + return mul_u64_u64_shr(tsc, tsc_ref->tsc_scale, 64) + + tsc_ref->tsc_offset; +} + +static int setup_blank_tsc_page(struct kvm_vcpu *vcpu, u64 gfn) +{ + HV_REFERENCE_TSC_PAGE tsc_ref; + + memset(_ref, 0, sizeof(tsc_ref)); + return write_tsc_page(vcpu->kvm, gfn, _ref); +} + +int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_hv *hv = >arch.hyperv; + HV_REFERENCE_TSC_PAGE tsc_ref; + u32 tsc_khz; + int r; + u64 gfn, ref_time, tsc_scale, tsc_offset, tsc; + + if (WARN_ON_ONCE(!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))) + return -EINVAL; + + gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT; + vcpu_debug(vcpu, "tsc page gfn 0x%llx\n", gfn); + + tsc_khz = vcpu->arch.virtual_tsc_khz; + if (!tsc_khz) { + vcpu_unimpl(vcpu, "no tsc khz\n"); + return setup_blank_tsc_page(vcpu, gfn); + } + + r = read_tsc_page(kvm, gfn, _ref); + if (r) { + vcpu_err(vcpu, "can't access tsc page gfn 0x%llx\n", gfn); + return r; + } + + tsc_scale = calc_tsc_page_scale(tsc_khz); + ref_time = get_time_ref_counter(kvm); + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + /* tsc_offset = reftime - tsc * tsc_scale / 2^64 */ + tsc_offset = ref_time - mul_u64_u64_shr(tsc, tsc_scale, 64); + vcpu_debug(vcpu, "tsc khz %u tsc %llu scale %llu offset %llu\n", + tsc_khz, tsc, tsc_scale, tsc_offset); + + tsc_ref.tsc_sequence++; + if (tsc_ref.tsc_sequence == 0) + tsc_ref.tsc_sequence = 1; + + tsc_ref
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 02:02 PM, Paolo Bonzini wrote: On 22/01/2016 11:15, Andrey Smetanin wrote: - unless KVM can use a master clock, it is incorrect to set up the TSC page this way; the sequence needs to be 0x in that case 0x is not an invalid value for tsc page, see https://lkml.org/lkml/2015/11/2/655 oh, I see now. - writing the TSC page must be done while all VCPUs are stopped, because the TSC page doesn't provide the possibility for the guest to retry in the middle of an update (like seqcount in Linux doess) I think Windows guest gives tsc page address at boot time and protects against other vcpu's tsc page access. Sometimes the TSC is detected to be unstable and Linux switches to another clocksource. At least in that case you can get a write to the TSC page while the guest is running. I can't understand how write is possible. Linux Hyper-V driver hv_vmbus.ko does the following inside hv_init() drivers/hv/hv.c(line 256): wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64); clocksource_register_hz(_cs_tsc, NSEC_PER_SEC/100); So page is setup only once before registration clock source. In that case it would be enough to write a zero to tsc_sequence, which _can_ be done atomically while the guest is running. However, KVM already has a mechanism to stop all VCPUs (KVM_REQ_MASTERCLOCK_UPDATE) so we might as well use it. Paolo
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 02:02 PM, Paolo Bonzini wrote: On 22/01/2016 11:15, Andrey Smetanin wrote: - unless KVM can use a master clock, it is incorrect to set up the TSC page this way; the sequence needs to be 0x in that case 0x is not an invalid value for tsc page, see https://lkml.org/lkml/2015/11/2/655 oh, I see now. - writing the TSC page must be done while all VCPUs are stopped, because the TSC page doesn't provide the possibility for the guest to retry in the middle of an update (like seqcount in Linux doess) I think Windows guest gives tsc page address at boot time and protects against other vcpu's tsc page access. Sometimes the TSC is detected to be unstable and Linux switches to another clocksource. At least in that case you can get a write to the TSC page while the guest is running. Sorry, now I got it, you mean host TSC is unstable and we should mark guest tsc page invalid. Now I understand please ignore my prev. message. In that case it would be enough to write a zero to tsc_sequence, which _can_ be done atomically while the guest is running. However, KVM already has a mechanism to stop all VCPUs (KVM_REQ_MASTERCLOCK_UPDATE) so we might as well use it. Paolo
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 02:53 PM, Paolo Bonzini wrote: On 22/01/2016 12:31, Andrey Smetanin wrote: Sometimes the TSC is detected to be unstable and Linux switches to another clocksource. At least in that case you can get a write to the TSC page while the guest is running. Sorry, now I got it, you mean host TSC is unstable and we should mark guest tsc page invalid. Now I understand please ignore my prev. message. No problem. Anyhow yes, this is what I meant: a host write to the TSC page, not a guest write to the TSC page MSR. Usually it happens only at migration time to update the sequence---which I believe your patch wasn't doing either. QEMU saves address of page inside ->msr_hv_tsc, so at restore QEMU sets corresponding MSR and KVM setup's tsc page again. So migration should able to work. But if we tie TSC page updates to kvm_gen_update_masterclock, we get that for free when the migration destination calls the KVM_SET_CLOCK ioctl. Paolo
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 01:08 PM, Paolo Bonzini wrote: On 24/12/2015 10:33, Andrey Smetanin wrote: Lately tsc page was implemented but filled with empty values. This patch setup tsc page scale and offset based on vcpu tsc, tsc_khz and HV_X64_MSR_TIME_REF_COUNT value. The valid tsc page drops HV_X64_MSR_TIME_REF_COUNT msr reads count to zero which potentially improves performance. The patch applies on top of 'kvm: Make vcpu->requests as 64 bit bitmap' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Actually there are some more issues: - unless KVM can use a master clock, it is incorrect to set up the TSC page this way; the sequence needs to be 0x in that case - writing the TSC page must be done while all VCPUs are stopped, because the TSC page doesn't provide the possibility for the guest to retry in the middle of an update (like seqcount in Linux doess) In the end, the TSC page is actually pretty similar to the kvmclock master clock and it makes sense to build it on the master clock too. I'll post a patch next week. We(@virtuozzo.com) will be very thankful to you for the patch which integrates Hyper-V tsc page with kvm clock. We even may do work by yourself, but our priority now is Hyper-V VMBus initialization (which is not in dependency on Hyper-V tsc page). What is really helpful for us now - patches '[PATCH v2 0/5] KVM: Hyper-V VMBus hypercalls'. Paolo --- arch/x86/kvm/hyperv.c| 117 +-- arch/x86/kvm/hyperv.h| 2 + arch/x86/kvm/x86.c | 12 + include/linux/kvm_host.h | 1 + 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d50675a..504fdc7 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -753,6 +753,105 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, return 0; } +static u64 calc_tsc_page_scale(u32 tsc_khz) +{ + /* +* reftime (in 100ns) = tsc * tsc_scale / 2^64 + tsc_offset +* so reftime_delta = (tsc_delta * tsc_scale) / 2^64 +* so tsc_scale = (2^64 * reftime_delta)/tsc_delta +* so tsc_scale = (2^64 * 10 * 10^6) / tsc_hz = (2^64 * 1) / tsc_khz +* so tsc_scale = (2^63 * 2 * 1) / tsc_khz +*/ + return mul_u64_u32_div(1ULL << 63, 2 * 1, tsc_khz); +} + +static int write_tsc_page(struct kvm *kvm, u64 gfn, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_write_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + mark_page_dirty(kvm, gfn); + return 0; +} + +static int read_tsc_page(struct kvm *kvm, u64 gfn, +PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_read_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + return 0; +} + +static u64 calc_tsc_page_time(struct kvm_vcpu *vcpu, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + return mul_u64_u64_shr(tsc, tsc_ref->tsc_scale, 64) + + tsc_ref->tsc_offset; +} + +static int setup_blank_tsc_page(struct kvm_vcpu *vcpu, u64 gfn) +{ + HV_REFERENCE_TSC_PAGE tsc_ref; + + memset(_ref, 0, sizeof(tsc_ref)); + return write_tsc_page(vcpu->kvm, gfn, _ref); +} + +int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_hv *hv = >arch.hyperv; + HV_REFERENCE_TSC_PAGE tsc_ref; + u32 tsc_khz; + int r; + u64 gfn, ref_time, tsc_scale, tsc_offset, tsc; + + if (WARN_ON_ONCE(!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))) + return -EINVAL; + + gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT; + vcpu_debug(vcpu, "tsc page gfn 0x%llx\n", gfn); + + tsc_khz = vcpu->arch.virtual_tsc_khz; + if (!tsc_khz) { + vcpu_unimpl(vcpu, "no tsc khz\n"); + return setup_blank_tsc_page(vcpu, gfn); + } + + r = read_tsc_page(kvm, gfn, _ref); + if (r) { + vcpu_err(vcpu, "can't access tsc page gfn 0x%llx\n", gfn); + return r; + } + + tsc_scale = calc_tsc_page_scale(tsc_khz); + ref_time = get_time_ref_counter(kvm); + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + /* tsc_offset = reftime - tsc * tsc_scale / 2^64 */ + tsc_offset = ref_time - mul_u64_u64_shr(tsc, tsc_scale, 64); + vcpu_debug(vcpu, "tsc khz %u tsc %llu scale %llu offset %llu\n", +
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/22/2016 04:21 PM, Paolo Bonzini wrote: On 22/01/2016 14:13, Andrey Smetanin wrote: We(@virtuozzo.com) will be very thankful to you for the patch which integrates Hyper-V tsc page with kvm clock. We even may do work by yourself, but our priority now is Hyper-V VMBus initialization (which is not in dependency on Hyper-V tsc page). What is really helpful for us now - patches '[PATCH v2 0/5] KVM: Hyper-V VMBus hypercalls'. Yes, I want to merge that very soon as well. Great, thanks! Paolo
[Qemu-devel] [PATCH v2 3/5] kvm/x86: Pass return code of kvm_emulate_hypercall
Pass the return code from kvm_emulate_hypercall on to the caller, in order to allow it to indicate to the userspace that the hypercall has to be handled there. Also adjust all the existing code paths to return 1 to make sure the hypercall isn't passed to the userspace without setting kvm_run appropriately. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/svm.c| 3 +-- arch/x86/kvm/vmx.c| 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index f1a42e1..0e7c90f 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1055,7 +1055,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) */ if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) { kvm_queue_exception(vcpu, UD_VECTOR); - return 0; + return 1; } longmode = is_64_bit_mode(vcpu); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c13a64b..9507038 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1858,8 +1858,7 @@ static int halt_interception(struct vcpu_svm *svm) static int vmmcall_interception(struct vcpu_svm *svm) { svm->next_rip = kvm_rip_read(>vcpu) + 3; - kvm_emulate_hypercall(>vcpu); - return 1; + return kvm_emulate_hypercall(>vcpu); } static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 04d61d4..82879aa 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5747,8 +5747,7 @@ static int handle_halt(struct kvm_vcpu *vcpu) static int handle_vmcall(struct kvm_vcpu *vcpu) { - kvm_emulate_hypercall(vcpu); - return 1; + return kvm_emulate_hypercall(vcpu); } static int handle_invd(struct kvm_vcpu *vcpu) -- 2.4.3
[Qemu-devel] [PATCH v2 1/5] kvm/x86: Rename Hyper-V long spin wait hypercall
Rename HV_X64_HV_NOTIFY_LONG_SPIN_WAIT by HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT. So the name better reflects hypercall codes accessory. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 +- arch/x86/kvm/hyperv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 7956412..0c50fab 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -226,7 +226,7 @@ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) /* Declare the various hypercall operations. */ -#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index c58ba67..f1a42e1 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1084,7 +1084,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); switch (code) { - case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT: + case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; default: -- 2.4.3
[Qemu-devel] [PATCH v2 0/5] KVM: Hyper-V VMBus hypercalls
The patch implements userspace exit 'KVM_EXIT_HYPERV' for Hyper-V VMBus hypercalls(postmsg, signalevent) to handle these hypercalls by QEMU. Changes v2: * use KVM_EXIT_HYPERV for hypercalls Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): kvm/x86: Rename Hyper-V long spin wait hypercall drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header kvm/x86: Pass return code of kvm_emulate_hypercall kvm/x86: Reject Hyper-V hypercall continuation kvm/x86: Hyper-V VMBus hypercall userspace exit Documentation/virtual/kvm/api.txt | 6 ++ arch/x86/include/uapi/asm/hyperv.h | 4 +++- arch/x86/kvm/hyperv.c | 40 +- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/svm.c | 3 +-- arch/x86/kvm/vmx.c | 3 +-- arch/x86/kvm/x86.c | 5 + drivers/hv/hv.c| 4 ++-- drivers/hv/hyperv_vmbus.h | 6 -- include/uapi/linux/kvm.h | 6 ++ 10 files changed, 56 insertions(+), 22 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v2 4/5] kvm/x86: Reject Hyper-V hypercall continuation
Currently we do not support Hyper-V hypercall continuation so reject it. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 0e7c90f..e1daa8b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1083,6 +1083,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); + /* Hypercall continuation is not supported yet */ + if (rep_cnt || rep_idx) { + res = HV_STATUS_INVALID_HYPERCALL_CODE; + goto set_result; + } + switch (code) { case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); @@ -1092,6 +1098,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) break; } +set_result: ret = res | (((u64)rep_done & 0xfff) << 32); if (longmode) { kvm_register_write(vcpu, VCPU_REGS_RAX, ret); -- 2.4.3
[Qemu-devel] [PATCH v2] target-i386/kvm: Hyper-V VMBus hypercalls blank handlers
Add Hyper-V VMBus hypercalls blank handlers which just returns error code - HV_STATUS_INVALID_HYPERCALL_CODE. Changes v2: * use KVM_EXIT_HYPERV exit type Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org --- target-i386/hyperv.c | 12 1 file changed, 12 insertions(+) diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c index e79b173..d3f3059 100644 --- a/target-i386/hyperv.c +++ b/target-i386/hyperv.c @@ -43,6 +43,18 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) return -1; } return 0; +case KVM_EXIT_HYPERV_HCALL: { +uint16_t code; + +code = exit->u.hcall.input & 0x; +switch (code) { +case HV_X64_HCALL_POST_MESSAGE: +case HV_X64_HCALL_SIGNAL_EVENT: +default: +exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE; +return 0; +} +} default: return -1; } -- 2.4.3
[Qemu-devel] [PATCH v2 5/5] kvm/x86: Hyper-V VMBus hypercall userspace exit
The patch implements KVM_EXIT_HYPERV userspace exit functionality for Hyper-V VMBus hypercalls: HV_X64_HCALL_POST_MESSAGE, HV_X64_HCALL_SIGNAL_EVENT. Changes v2: * use KVM_EXIT_HYPERV for hypercalls Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- Documentation/virtual/kvm/api.txt | 6 ++ arch/x86/kvm/hyperv.c | 29 ++--- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/x86.c| 5 + include/uapi/linux/kvm.h | 6 ++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 053f613..1bf1a07 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -3339,6 +3339,7 @@ EOI was received. struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 +#define KVM_EXIT_HYPERV_HCALL 2 __u32 type; union { struct { @@ -3347,6 +3348,11 @@ EOI was received. __u64 evt_page; __u64 msg_page; } synic; + struct { + __u64 input; + __u64 result; + __u64 params[2]; + } hcall; } u; }; /* KVM_EXIT_HYPERV */ diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index e1daa8b..26ae973 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1093,6 +1093,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; + case HV_X64_HCALL_POST_MESSAGE: + case HV_X64_HCALL_SIGNAL_EVENT: + vcpu->run->exit_reason = KVM_EXIT_HYPERV; + vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL; + vcpu->run->hyperv.u.hcall.input = param; + vcpu->run->hyperv.u.hcall.params[0] = ingpa; + vcpu->run->hyperv.u.hcall.params[1] = outgpa; + return 0; default: res = HV_STATUS_INVALID_HYPERCALL_CODE; break; @@ -1100,12 +1108,19 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) set_result: ret = res | (((u64)rep_done & 0xfff) << 32); - if (longmode) { - kvm_register_write(vcpu, VCPU_REGS_RAX, ret); - } else { - kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32); - kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0x); - } - + kvm_hv_hypercall_set_result(vcpu, ret); return 1; } + +void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) +{ + bool longmode; + + longmode = is_64_bit_mode(vcpu); + if (longmode) + kvm_register_write(vcpu, VCPU_REGS_RAX, result); + else { + kvm_register_write(vcpu, VCPU_REGS_RDX, result >> 32); + kvm_register_write(vcpu, VCPU_REGS_RAX, result & 0x); + } +} diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index 60eccd4..64a4a3b 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -52,6 +52,7 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); bool kvm_hv_hypercall_enabled(struct kvm *kvm); int kvm_hv_hypercall(struct kvm_vcpu *vcpu); +void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result); void kvm_hv_irq_routing_update(struct kvm *kvm); int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vcpu_id, u32 sint); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f53f5b1..e5c842b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6891,6 +6891,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } else WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed); + if (unlikely(kvm_run->exit_reason == KVM_EXIT_HYPERV) && + kvm_run->hyperv.type == KVM_EXIT_HYPERV_HCALL) + kvm_hv_hypercall_set_result(vcpu, + kvm_run->hyperv.u.hcall.result); + r = vcpu_run(vcpu); out: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 9da9051..c5519a9 100644 --- a/include/uap
[Qemu-devel] [PATCH v2 2/5] drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header
VMBus hypercall codes inside Hyper-V UAPI header will be used by QEMU to implement VMBus host devices support. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: K. Y. Srinivasan <k...@microsoft.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 ++ drivers/hv/hv.c| 4 ++-- drivers/hv/hyperv_vmbus.h | 6 -- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 0c50fab..bc1c8a9 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -227,6 +227,8 @@ /* Declare the various hypercall operations. */ #define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 +#define HV_X64_HCALL_POST_MESSAGE 0x005c +#define HV_X64_HCALL_SIGNAL_EVENT 0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 11bca51..5ce2dec 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -331,7 +331,7 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); + status = hv_do_hypercall(HV_X64_HCALL_POST_MESSAGE, aligned_msg, NULL); put_cpu(); return status & 0x; @@ -348,7 +348,7 @@ int hv_signal_event(void *con_id) { u64 status; - status = hv_do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL); + status = hv_do_hypercall(HV_X64_HCALL_SIGNAL_EVENT, con_id, NULL); return status & 0x; } diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 4ebc796..2f8c0f4 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -256,12 +256,6 @@ struct hv_monitor_page { u8 rsvdz4[1984]; }; -/* Declare the various hypercall operations. */ -enum hv_call_code { - HVCALL_POST_MESSAGE = 0x005c, - HVCALL_SIGNAL_EVENT = 0x005d, -}; - /* Definition of the hv_post_message hypercall input structure. */ struct hv_input_post_message { union hv_connection_id connectionid; -- 2.4.3
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/20/2016 05:05 PM, Paolo Bonzini wrote: On 19/01/2016 08:48, Denis V. Lunev wrote: diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6877b4d7e..93c9e25 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -145,6 +145,7 @@ static inline bool is_error_page(struct page *page) #define KVM_REQ_HV_RESET 29 #define KVM_REQ_HV_EXIT 30 #define KVM_REQ_HV_STIMER 31 +#define KVM_REQ_HV_TSC_PAGE 32 #define KVM_REQ_MAX 64 ping Applied with this change: diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d7716c6e2752..047c275717d3 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -842,7 +842,7 @@ int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) tsc_khz, tsc, tsc_scale, tsc_offset); tsc_ref.tsc_sequence++; - if (tsc_ref.tsc_sequence == 0) + if (tsc_ref.tsc_sequence == 0x tsc_ref.tsc_sequence == 0) "(tsc_ref.tsc_sequence == 0x || tsc_ref.tsc_sequence == 0)" ? tsc_ref.tsc_sequence = 1; tsc_ref.tsc_scale = tsc_scale; and renumbering KVM_REQ_HV_TSC_PAGE from 32 to 31. Paolo
[Qemu-devel] [PATCH v1 2/5] drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header
VMBus hypercall codes inside Hyper-V UAPI header will be used by QEMU to implement VMBus host devices support. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 ++ drivers/hv/hv.c| 5 +++-- drivers/hv/hyperv_vmbus.h | 6 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 0c50fab..bc1c8a9 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -227,6 +227,8 @@ /* Declare the various hypercall operations. */ #define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 +#define HV_X64_HCALL_POST_MESSAGE 0x005c +#define HV_X64_HCALL_SIGNAL_EVENT 0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 6341be8..56437d5 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -329,7 +329,7 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL) + status = do_hypercall(HV_X64_HCALL_POST_MESSAGE, aligned_msg, NULL) & 0x; put_cpu(); @@ -347,7 +347,8 @@ u16 hv_signal_event(void *con_id) { u16 status; - status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0x); + status = (do_hypercall(HV_X64_HCALL_SIGNAL_EVENT, con_id, NULL) + & 0x); return status; } diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 678663e..36cad1f 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -251,12 +251,6 @@ struct hv_monitor_page { u8 rsvdz4[1984]; }; -/* Declare the various hypercall operations. */ -enum hv_call_code { - HVCALL_POST_MESSAGE = 0x005c, - HVCALL_SIGNAL_EVENT = 0x005d, -}; - /* Definition of the hv_post_message hypercall input structure. */ struct hv_input_post_message { union hv_connection_id connectionid; -- 2.4.3
[Qemu-devel] [PATCH v1 0/5] KVM: Hyper-V VMBus hypercalls
The patch implements userspace exit 'KVM_EXIT_HYPERV_HCALL' for Hyper-V VMBus hypercalls(postmsg, signalevent) to handle these hypercalls by QEMU. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): kvm/x86: Rename Hyper-V long spin wait hypercall drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header kvm/x86: Pass return code of kvm_emulate_hypercall kvm/x86: Hyper-V VMBus hypercall userspace exit kvm/x86: Reject Hyper-V hypercall continuation Documentation/virtual/kvm/api.txt | 8 arch/x86/include/uapi/asm/hyperv.h | 4 +++- arch/x86/kvm/hyperv.c | 39 +- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/svm.c | 3 +-- arch/x86/kvm/vmx.c | 3 +-- arch/x86/kvm/x86.c | 3 +++ drivers/hv/hv.c| 5 +++-- drivers/hv/hyperv_vmbus.h | 6 -- include/uapi/linux/kvm.h | 7 +++ 10 files changed, 57 insertions(+), 22 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v1 4/5] kvm/x86: Hyper-V VMBus hypercall userspace exit
The patch implements KVM_EXIT_HV_HCALL functionality for Hyper-V VMBus hypercalls: HV_X64_HCALL_POST_MESSAGE, HV_X64_HCALL_SIGNAL_EVENT. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- Documentation/virtual/kvm/api.txt | 8 arch/x86/kvm/hyperv.c | 28 +--- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/x86.c| 3 +++ include/uapi/linux/kvm.h | 7 +++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 053f613..23d4b9d 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -3359,6 +3359,14 @@ Hyper-V SynIC state change. Notification is used to remap SynIC event/message pages and to enable/disable SynIC messages/events processing in userspace. + /* KVM_EXIT_HYPERV_HCALL */ + struct { + __u64 input; + __u64 params[2]; + __u64 result; + } hv_hcall; +Indicates that the VCPU exits into userspace to process some guest +Hyper-V hypercalls. /* Fix the size of the union. */ char padding[256]; }; diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 0e7c90f..76c9ec4 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1087,18 +1087,32 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; + case HV_X64_HCALL_POST_MESSAGE: + case HV_X64_HCALL_SIGNAL_EVENT: + vcpu->run->exit_reason = KVM_EXIT_HYPERV_HCALL; + vcpu->run->hv_hcall.input = param; + vcpu->run->hv_hcall.params[0] = ingpa; + vcpu->run->hv_hcall.params[1] = outgpa; + return 0; default: res = HV_STATUS_INVALID_HYPERCALL_CODE; break; } ret = res | (((u64)rep_done & 0xfff) << 32); - if (longmode) { - kvm_register_write(vcpu, VCPU_REGS_RAX, ret); - } else { - kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32); - kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0x); - } - + kvm_hv_hypercall_set_result(vcpu, ret); return 1; } + +void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) +{ + bool longmode; + + longmode = is_64_bit_mode(vcpu); + if (longmode) + kvm_register_write(vcpu, VCPU_REGS_RAX, result); + else { + kvm_register_write(vcpu, VCPU_REGS_RDX, result >> 32); + kvm_register_write(vcpu, VCPU_REGS_RAX, result & 0x); + } +} diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index 60eccd4..64a4a3b 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -52,6 +52,7 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); bool kvm_hv_hypercall_enabled(struct kvm *kvm); int kvm_hv_hypercall(struct kvm_vcpu *vcpu); +void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result); void kvm_hv_irq_routing_update(struct kvm *kvm); int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vcpu_id, u32 sint); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fad1d09..6ad3599 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6886,6 +6886,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } else WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed); + if (unlikely(kvm_run->exit_reason == KVM_EXIT_HYPERV_HCALL)) + kvm_hv_hypercall_set_result(vcpu, kvm_run->hv_hcall.result); + r = vcpu_run(vcpu); out: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 9da9051..a62c4fb 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -199,6 +199,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_S390_STSI25 #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 +#define KVM_EXIT_HYPERV_HCALL 28 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -355,6 +356,12 @@ struct kvm_run { } eoi; /* KVM_EXIT_HYPERV */ struct kvm_hyperv_exit hyperv; + /* KVM_EXIT_HYPERV_HCALL */ + struct { +
[Qemu-devel] [PATCH v1 2/2] target-i386/kvm: Hyper-V VMBus hypercalls blank handlers
Add Hyper-V VMBus hypercalls blank handlers which just returns error code - HV_STATUS_INVALID_HYPERCALL_CODE. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org --- target-i386/hyperv.c | 14 ++ target-i386/hyperv.h | 2 ++ target-i386/kvm.c| 3 +++ 3 files changed, 19 insertions(+) diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c index e79b173..bd09506 100644 --- a/target-i386/hyperv.c +++ b/target-i386/hyperv.c @@ -125,3 +125,17 @@ int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route) { return event_notifier_set(_route->sint_set_notifier); } + +int kvm_hv_handle_hypercall(X86CPU *cpu, struct kvm_run *run) +{ +uint16_t code; + +code = run->hv_hcall.input & 0x; +switch (code) { +case HV_X64_HCALL_POST_MESSAGE: +case HV_X64_HCALL_SIGNAL_EVENT: +default: +run->hv_hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE; +return 0; +} +} diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h index b26201f..9515b6e 100644 --- a/target-i386/hyperv.h +++ b/target-i386/hyperv.h @@ -39,4 +39,6 @@ void kvm_hv_sint_route_destroy(HvSintRoute *sint_route); int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route); +int kvm_hv_handle_hypercall(X86CPU *cpu, struct kvm_run *run); + #endif diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ab65a6e..adb1d64 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -3026,6 +3026,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ioapic_eoi_broadcast(run->eoi.vector); ret = 0; break; +case KVM_EXIT_HYPERV_HCALL: +ret = kvm_hv_handle_hypercall(cpu, run); +break; default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); ret = -1; -- 2.4.3
[Qemu-devel] [PATCH v1] KVM-UNIT-TESTS:x86/hyperv: Hyper-V hypercalls test
This is a simple test which performs the following: * setup hypecall page * do some hypercalls and output their results Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- config/config-x86-common.mak | 4 ++ lib/x86/vm.h | 2 + x86/hyperv.c | 95 ++ x86/hyperv.h | 28 + x86/hyperv_hypercall.c | 99 x86/unittests.cfg| 5 +++ 6 files changed, 233 insertions(+) create mode 100644 x86/hyperv_hypercall.c diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak index 72b95e3..11714d6 100644 --- a/config/config-x86-common.mak +++ b/config/config-x86-common.mak @@ -38,6 +38,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ + $(TEST_DIR)/hyperv_hypercall.flat \ ifdef API tests-common += api/api-sample @@ -119,6 +120,9 @@ $(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ $(TEST_DIR)/hyperv_stimer.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ $(TEST_DIR)/hyperv_stimer.o +$(TEST_DIR)/hyperv_hypercall.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ + $(TEST_DIR)/hyperv_hypercall.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d lib/x86/.*.d diff --git a/lib/x86/vm.h b/lib/x86/vm.h index 28794d7..085e29f 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -4,6 +4,8 @@ #include "processor.h" #define PAGE_SIZE 4096ul +#define PAGE_SHIFT 12 + #ifdef __x86_64__ #define LARGE_PAGE_SIZE (512 * PAGE_SIZE) #else diff --git a/x86/hyperv.c b/x86/hyperv.c index 824773d..1d3ab23 100644 --- a/x86/hyperv.c +++ b/x86/hyperv.c @@ -1,4 +1,5 @@ #include "hyperv.h" +#include "vm.h" static void synic_ctl(u8 ctl, u8 vcpu_id, u8 sint) { @@ -22,3 +23,97 @@ void synic_sint_destroy(int vcpu, int sint) wrmsr(HV_X64_MSR_SINT0 + sint, 0xFF|HV_SYNIC_SINT_MASKED); synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, vcpu, sint); } + +static void *hv_hypercall_page; + +static inline u64 generate_guest_id(u8 d_info1, u32 kernel_version, +u16 d_info2) +{ +u64 guest_id = 0; + +guest_id = (((u64)HV_LINUX_VENDOR_ID) << 48); +guest_id |= (((u64)(d_info1)) << 48); +guest_id |= (((u64)(kernel_version)) << 16); +guest_id |= ((u64)(d_info2)); + +return guest_id; +} + +int hv_hypercall_init(void) +{ +void *page; +u64 val; + +wrmsr(HV_X64_MSR_GUEST_OS_ID, generate_guest_id(0, 263168, 0)); +page = alloc_page(); +if (!page) { +return -1; +} + +wrmsr(HV_X64_MSR_HYPERCALL, + ((virt_to_phys(page) >> PAGE_SHIFT) << + HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) | + HV_X64_MSR_HYPERCALL_ENABLE); + +val = rdmsr(HV_X64_MSR_HYPERCALL); +if (!(val & HV_X64_MSR_HYPERCALL_ENABLE)) { +goto err; +} + +hv_hypercall_page = page; +return 0; +err: +free_page(page); +return -1; +} + +void hv_hypercall_deinit(void) +{ +wrmsr(HV_X64_MSR_HYPERCALL, 0); +free_page(hv_hypercall_page); +wrmsr(HV_X64_MSR_GUEST_OS_ID, 0); +hv_hypercall_page = NULL; +} + +u64 hv_hypercall(u64 control, void *input, void *output) +{ +u64 input_address = (input) ? virt_to_phys(input) : 0; +u64 output_address = (output) ? virt_to_phys(output) : 0; +#ifdef __x86_64__ +u64 hv_status = 0; + +if (!hv_hypercall_page) { +return (u64)-1; +} + +__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); +__asm__ __volatile__("call *%3" : "=a" (hv_status) : + "c" (control), "d" (input_address), + "m" (hv_hypercall_page)); + +return hv_status; + +#else + +u32 control_hi = control >> 32; +u32 control_lo = control & 0x; +u32 hv_status_hi = 1; +u32 hv_status_lo = 1; +u32 input_address_hi = input_address >> 32; +u32 input_address_lo = input_address & 0x; +u32 output_address_hi = output_address >> 32; +u32 output_address_lo = output_address & 0x; + +if (!hv_hypercall_page) { +return (u64)-1; +} + +__asm__ __volatile__ ("
Re: [Qemu-devel] [PATCH v1 0/5] KVM: Hyper-V VMBus hypercalls
Paolo, Could you please force these patches applied during current merge window. We need them very, because they are last patches for KVM which are required to start development of Hyper-V VMBus devices in QEMU side. P.S.: We have created our public repo (based on current kvm/queue) to fetch our latest changes in KVM code to support Hyper-V VMBus: https://src.openvz.org/projects/UP/repos/kvm_hyperv/commits?until=refs%2Fheads%2Fvmbus_hypercall Thanks, Andrey On 01/12/2016 01:50 PM, Andrey Smetanin wrote: The patch implements userspace exit 'KVM_EXIT_HYPERV_HCALL' for Hyper-V VMBus hypercalls(postmsg, signalevent) to handle these hypercalls by QEMU. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): kvm/x86: Rename Hyper-V long spin wait hypercall drivers/hv: Move VMBus hypercall codes into Hyper-V UAPI header kvm/x86: Pass return code of kvm_emulate_hypercall kvm/x86: Hyper-V VMBus hypercall userspace exit kvm/x86: Reject Hyper-V hypercall continuation Documentation/virtual/kvm/api.txt | 8 arch/x86/include/uapi/asm/hyperv.h | 4 +++- arch/x86/kvm/hyperv.c | 39 +- arch/x86/kvm/hyperv.h | 1 + arch/x86/kvm/svm.c | 3 +-- arch/x86/kvm/vmx.c | 3 +-- arch/x86/kvm/x86.c | 3 +++ drivers/hv/hv.c| 5 +++-- drivers/hv/hyperv_vmbus.h | 6 -- include/uapi/linux/kvm.h | 7 +++ 10 files changed, 57 insertions(+), 22 deletions(-)
[Qemu-devel] [PATCH v1 5/5] kvm/x86: Reject Hyper-V hypercall continuation
Currently we do not support Hyper-V hypercall continuation so reject it. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 76c9ec4..bc4884e 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1083,6 +1083,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); + /* Hypercall continuation is not supported yet */ + if (rep_cnt || rep_idx) { + res = HV_STATUS_INVALID_HYPERCALL_CODE; + goto set_result; + } + switch (code) { case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); @@ -1099,6 +1105,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) break; } +set_result: ret = res | (((u64)rep_done & 0xfff) << 32); kvm_hv_hypercall_set_result(vcpu, ret); return 1; -- 2.4.3
[Qemu-devel] [PATCH v1 1/5] kvm/x86: Rename Hyper-V long spin wait hypercall
Rename HV_X64_HV_NOTIFY_LONG_SPIN_WAIT by HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT. So the name better reflects hypercall codes accessory. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 +- arch/x86/kvm/hyperv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 7956412..0c50fab 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -226,7 +226,7 @@ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) /* Declare the various hypercall operations. */ -#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index c58ba67..f1a42e1 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1084,7 +1084,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa); switch (code) { - case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT: + case HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT: kvm_vcpu_on_spin(vcpu); break; default: -- 2.4.3
[Qemu-devel] [PATCH v1 3/5] kvm/x86: Pass return code of kvm_emulate_hypercall
Pass the return code from kvm_emulate_hypercall on to the caller, in order to allow it to indicate to the userspace that the hypercall has to be handled there. Also adjust all the existing code paths to return 1 to make sure the hypercall isn't passed to the userspace without setting kvm_run appropriately. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Joerg Roedel <j...@8bytes.org> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/svm.c| 3 +-- arch/x86/kvm/vmx.c| 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index f1a42e1..0e7c90f 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1055,7 +1055,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) */ if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) { kvm_queue_exception(vcpu, UD_VECTOR); - return 0; + return 1; } longmode = is_64_bit_mode(vcpu); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index af34215..5fd8a5b 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1858,8 +1858,7 @@ static int halt_interception(struct vcpu_svm *svm) static int vmmcall_interception(struct vcpu_svm *svm) { svm->next_rip = kvm_rip_read(>vcpu) + 3; - kvm_emulate_hypercall(>vcpu); - return 1; + return kvm_emulate_hypercall(>vcpu); } static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 62d958a..762c18e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5747,8 +5747,7 @@ static int handle_halt(struct kvm_vcpu *vcpu) static int handle_vmcall(struct kvm_vcpu *vcpu) { - kvm_emulate_hypercall(vcpu); - return 1; + return kvm_emulate_hypercall(vcpu); } static int handle_invd(struct kvm_vcpu *vcpu) -- 2.4.3
[Qemu-devel] [PATCH v1 0/2] QEMU: Hyper-V VMBus hypercalls blank handlers
The patches adds blank handlers for Hyper-V VMBus hypercalls routed by KVM_EXIT_HYPERV_HCALL KVM exit. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org Andrey Smetanin (2): headers: Hyper-V VMBus hypercall codes and exit target-i386/kvm: Hyper-V VMBus hypercalls blank handlers include/standard-headers/asm-x86/hyperv.h | 4 +++- linux-headers/linux/kvm.h | 7 +++ target-i386/hyperv.c | 14 ++ target-i386/hyperv.h | 2 ++ target-i386/kvm.c | 3 +++ 5 files changed, 29 insertions(+), 1 deletion(-) -- 2.4.3
[Qemu-devel] [PATCH v1 1/2] headers: Hyper-V VMBus hypercall codes and exit
This patch just for completeness, this changes should be received by scripts/update-linux-headers.sh Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> CC: "Andreas Färber" <afaer...@suse.de> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: k...@vger.kernel.org --- include/standard-headers/asm-x86/hyperv.h | 4 +++- linux-headers/linux/kvm.h | 7 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h index acb119d..27b445e 100644 --- a/include/standard-headers/asm-x86/hyperv.h +++ b/include/standard-headers/asm-x86/hyperv.h @@ -226,7 +226,9 @@ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) /* Declare the various hypercall operations. */ -#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT0x0008 +#define HV_X64_HCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 +#define HV_X64_HCALL_POST_MESSAGE 0x005c +#define HV_X64_HCALL_SIGNAL_EVENT 0x005d #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x0001 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12 diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 4e20262..32879ba 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -199,6 +199,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_S390_STSI25 #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 +#define KVM_EXIT_HYPERV_HCALL 28 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -355,6 +356,12 @@ struct kvm_run { } eoi; /* KVM_EXIT_HYPERV */ struct kvm_hyperv_exit hyperv; + /* KVM_EXIT_HYPERV_HCALL */ + struct { + __u64 input; + __u64 params[2]; + __u64 result; + } hv_hcall; /* Fix the size of the union. */ char padding[256]; }; -- 2.4.3
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
ping On 12/24/2015 12:33 PM, Andrey Smetanin wrote: Lately tsc page was implemented but filled with empty values. This patch setup tsc page scale and offset based on vcpu tsc, tsc_khz and HV_X64_MSR_TIME_REF_COUNT value. The valid tsc page drops HV_X64_MSR_TIME_REF_COUNT msr reads count to zero which potentially improves performance. The patch applies on top of 'kvm: Make vcpu->requests as 64 bit bitmap' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c| 117 +-- arch/x86/kvm/hyperv.h| 2 + arch/x86/kvm/x86.c | 12 + include/linux/kvm_host.h | 1 + 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d50675a..504fdc7 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -753,6 +753,105 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, return 0; } +static u64 calc_tsc_page_scale(u32 tsc_khz) +{ + /* +* reftime (in 100ns) = tsc * tsc_scale / 2^64 + tsc_offset +* so reftime_delta = (tsc_delta * tsc_scale) / 2^64 +* so tsc_scale = (2^64 * reftime_delta)/tsc_delta +* so tsc_scale = (2^64 * 10 * 10^6) / tsc_hz = (2^64 * 1) / tsc_khz +* so tsc_scale = (2^63 * 2 * 1) / tsc_khz +*/ + return mul_u64_u32_div(1ULL << 63, 2 * 1, tsc_khz); +} + +static int write_tsc_page(struct kvm *kvm, u64 gfn, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_write_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + mark_page_dirty(kvm, gfn); + return 0; +} + +static int read_tsc_page(struct kvm *kvm, u64 gfn, +PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_read_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + return 0; +} + +static u64 calc_tsc_page_time(struct kvm_vcpu *vcpu, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + return mul_u64_u64_shr(tsc, tsc_ref->tsc_scale, 64) + + tsc_ref->tsc_offset; +} + +static int setup_blank_tsc_page(struct kvm_vcpu *vcpu, u64 gfn) +{ + HV_REFERENCE_TSC_PAGE tsc_ref; + + memset(_ref, 0, sizeof(tsc_ref)); + return write_tsc_page(vcpu->kvm, gfn, _ref); +} + +int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_hv *hv = >arch.hyperv; + HV_REFERENCE_TSC_PAGE tsc_ref; + u32 tsc_khz; + int r; + u64 gfn, ref_time, tsc_scale, tsc_offset, tsc; + + if (WARN_ON_ONCE(!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))) + return -EINVAL; + + gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT; + vcpu_debug(vcpu, "tsc page gfn 0x%llx\n", gfn); + + tsc_khz = vcpu->arch.virtual_tsc_khz; + if (!tsc_khz) { + vcpu_unimpl(vcpu, "no tsc khz\n"); + return setup_blank_tsc_page(vcpu, gfn); + } + + r = read_tsc_page(kvm, gfn, _ref); + if (r) { + vcpu_err(vcpu, "can't access tsc page gfn 0x%llx\n", gfn); + return r; + } + + tsc_scale = calc_tsc_page_scale(tsc_khz); + ref_time = get_time_ref_counter(kvm); + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + /* tsc_offset = reftime - tsc * tsc_scale / 2^64 */ + tsc_offset = ref_time - mul_u64_u64_shr(tsc, tsc_scale, 64); + vcpu_debug(vcpu, "tsc khz %u tsc %llu scale %llu offset %llu\n", + tsc_khz, tsc, tsc_scale, tsc_offset); + + tsc_ref.tsc_sequence++; + if (tsc_ref.tsc_sequence == 0) + tsc_ref.tsc_sequence = 1; + + tsc_ref.tsc_scale = tsc_scale; + tsc_ref.tsc_offset = tsc_offset; + + vcpu_debug(vcpu, "tsc page calibration time %llu vs. reftime %llu\n", + calc_tsc_page_time(vcpu, _ref), + get_time_ref_counter(kvm)); + + return write_tsc_page(kvm, gfn, _ref); +} + static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) { @@ -790,23 +889,11 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, mark_page_dirty(kvm, gfn); break; } - case HV_X64_MSR_REFERENCE_TSC: { - u64 gfn; - HV_REFERENCE_TSC_PAGE tsc_ref; - - memset(_ref, 0, sizeof(tsc_ref)); + case HV_
Re: [Qemu-devel] [PATCH v1 2/6] kvm/x86: Hyper-V unify stimer_start() and stimer_restart()
On 01/07/2016 07:32 PM, Paolo Bonzini wrote: On 23/12/2015 12:28, Andrey Smetanin wrote: This will be used in future to start Hyper-V SynIC timer in several places by one logic in one function. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 37 - 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index ec3a900..8623aa6 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -408,6 +408,7 @@ static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); stimer->msg_pending = false; + stimer->exp_time = 0; } static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) @@ -420,24 +421,6 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) return HRTIMER_NORESTART; } -static void stimer_restart(struct kvm_vcpu_hv_stimer *stimer) -{ - u64 time_now; - ktime_t ktime_now; - u64 remainder; - - time_now = get_time_ref_counter(stimer_to_vcpu(stimer)->kvm); - ktime_now = ktime_get(); - - div64_u64_rem(time_now - stimer->exp_time, stimer->count, ); - stimer->exp_time = time_now + (stimer->count - remainder); - - hrtimer_start(>timer, - ktime_add_ns(ktime_now, - 100 * (stimer->exp_time - time_now)), - HRTIMER_MODE_ABS); -} - static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) { u64 time_now; @@ -450,9 +433,21 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) if (stimer->count == 0) return -EINVAL; - stimer->exp_time = time_now + stimer->count; + if (stimer->exp_time) { + if (time_now >= stimer->exp_time) { Just for my education, is it possible to have this function called with stimer->exp_time != 0 && time_now < stimer->exp_time? I think it's possible, assume the following situation: GUEST HOST periodic timer setup & startstart timer timer expiration send timer expiration message guest is busy and . do not processing timer timer expiration message for longer than timer try to send timer expiration message period since message slot is still occupied . by guest set slot->msg_pending = 1 guest wake and now processed timer message, since slot->msg_pending = 1 do wrmsr(HV_X64_MSR_EOM) handle HV_X64_MSR_EOM kvm_hv_notify_acked_sint() schedule KVM_REQ_HV_STIMER kvm_hv_process_stimers() exp_time != 0 && now < exp_time timer expiration In this case we just start hrtimer again with the same(previous) target exp_time, so I do not see any side effects. Paolo + u64 remainder; + + div64_u64_rem(time_now - stimer->exp_time, + stimer->count, ); + stimer->exp_time = + time_now + (stimer->count - remainder); + } + } else + stimer->exp_time = time_now + stimer->count; + hrtimer_start(>timer, - ktime_add_ns(ktime_now, 100 * stimer->count), + ktime_add_ns(ktime_now, + 100 * (stimer->exp_time - time_now)), HRTIMER_MODE_ABS); return 0; } @@ -580,7 +575,7 @@ static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) if (!(stimer->config & HV_STIMER_PERIODIC)) stimer->config |= ~HV_STIMER_ENABLE; else - stimer_restart(stimer); + stimer_start(stimer); } void kvm_hv_process_stimers(struct kvm_vcpu *vcpu)
Re: [Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
On 01/06/2016 12:48 AM, Peter Hornyack wrote: On Thu, Dec 24, 2015 at 1:33 AM, Andrey Smetanin <asmeta...@virtuozzo.com> wrote: Lately tsc page was implemented but filled with empty values. This patch setup tsc page scale and offset based on vcpu tsc, tsc_khz and HV_X64_MSR_TIME_REF_COUNT value. The valid tsc page drops HV_X64_MSR_TIME_REF_COUNT msr reads count to zero which potentially improves performance. The patch applies on top of 'kvm: Make vcpu->requests as 64 bit bitmap' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Reviewed-by: Peter Hornyack <peterhorny...@google.com> --- arch/x86/kvm/hyperv.c| 117 +-- arch/x86/kvm/hyperv.h| 2 + arch/x86/kvm/x86.c | 12 + include/linux/kvm_host.h | 1 + 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d50675a..504fdc7 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -753,6 +753,105 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, return 0; } +static u64 calc_tsc_page_scale(u32 tsc_khz) +{ + /* +* reftime (in 100ns) = tsc * tsc_scale / 2^64 + tsc_offset +* so reftime_delta = (tsc_delta * tsc_scale) / 2^64 +* so tsc_scale = (2^64 * reftime_delta)/tsc_delta +* so tsc_scale = (2^64 * 10 * 10^6) / tsc_hz = (2^64 * 1) / tsc_khz +* so tsc_scale = (2^63 * 2 * 1) / tsc_khz +*/ + return mul_u64_u32_div(1ULL << 63, 2 * 1, tsc_khz); +} + +static int write_tsc_page(struct kvm *kvm, u64 gfn, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_write_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + mark_page_dirty(kvm, gfn); + return 0; +} + +static int read_tsc_page(struct kvm *kvm, u64 gfn, +PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_read_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + return 0; +} + +static u64 calc_tsc_page_time(struct kvm_vcpu *vcpu, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + return mul_u64_u64_shr(tsc, tsc_ref->tsc_scale, 64) + + tsc_ref->tsc_offset; +} + +static int setup_blank_tsc_page(struct kvm_vcpu *vcpu, u64 gfn) +{ + HV_REFERENCE_TSC_PAGE tsc_ref; + + memset(_ref, 0, sizeof(tsc_ref)); + return write_tsc_page(vcpu->kvm, gfn, _ref); +} + +int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_hv *hv = >arch.hyperv; + HV_REFERENCE_TSC_PAGE tsc_ref; + u32 tsc_khz; + int r; + u64 gfn, ref_time, tsc_scale, tsc_offset, tsc; + + if (WARN_ON_ONCE(!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))) + return -EINVAL; + + gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT; + vcpu_debug(vcpu, "tsc page gfn 0x%llx\n", gfn); + + tsc_khz = vcpu->arch.virtual_tsc_khz; + if (!tsc_khz) { + vcpu_unimpl(vcpu, "no tsc khz\n"); + return setup_blank_tsc_page(vcpu, gfn); + } + + r = read_tsc_page(kvm, gfn, _ref); + if (r) { + vcpu_err(vcpu, "can't access tsc page gfn 0x%llx\n", gfn); + return r; + } + + tsc_scale = calc_tsc_page_scale(tsc_khz); + ref_time = get_time_ref_counter(kvm); + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + /* tsc_offset = reftime - tsc * tsc_scale / 2^64 */ + tsc_offset = ref_time - mul_u64_u64_shr(tsc, tsc_scale, 64); + vcpu_debug(vcpu, "tsc khz %u tsc %llu scale %llu offset %llu\n", + tsc_khz, tsc, tsc_scale, tsc_offset); + + tsc_ref.tsc_sequence++; + if (tsc_ref.tsc_sequence == 0) Also avoid tsc_sequence == 0x here. In the Hyper-V TLFS 4.0 (Win2012 R2) 0x is the special sequence number to disable the reference TSC page. we already discussed with Microsoft that documentation contains wrong sequence number - 0x (instead of 0). please take a look into details here: https://lkml.org/lkml/2015/11/2/655 + tsc_ref.tsc_sequence = 1; + + tsc_ref.tsc_scale = tsc_scale; + tsc_ref.tsc_offset = tsc_offset; + + vcpu_debug(vcpu, "tsc page calibration time %llu vs. reftime %llu\n", + calc_tsc_page_time(vcpu, _ref), + get_time_ref_counter(kvm)); + + return write_tsc_page
[Qemu-devel] [PATCH v2 1/7] kvm/x86: Hyper-V timers fix incorrect logical operation
Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index f34f666..e4ef13a 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -583,7 +583,7 @@ static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) { stimer_send_msg(stimer); if (!(stimer->config & HV_STIMER_PERIODIC)) - stimer->config |= ~HV_STIMER_ENABLE; + stimer->config &= ~HV_STIMER_ENABLE; else stimer_restart(stimer); } -- 2.4.3
[Qemu-devel] [PATCH v2 6/7] kvm/x86: Skip SynIC vector check for QEMU side
QEMU zero-inits Hyper-V SynIC vectors. We should allow that, and don't reject zero values if set by the host. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index abfb920..ddae13e 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -72,12 +72,13 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic, return false; } -static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, u64 data) +static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, + u64 data, bool host) { int vector; vector = data & HV_SYNIC_SINT_VECTOR_MASK; - if (vector < 16) + if (vector < 16 && !host) return 1; /* * Guest may configure multiple SINTs to use the same vector, so @@ -247,7 +248,7 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic, break; } case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15: - ret = synic_set_sint(synic, msr - HV_X64_MSR_SINT0, data); + ret = synic_set_sint(synic, msr - HV_X64_MSR_SINT0, data, host); break; default: ret = 1; -- 2.4.3
[Qemu-devel] [PATCH v2 2/7] kvm/x86: Drop stimer_stop() function
The function stimer_stop() is called in one place so remove the function and replace it's call by function content. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index e4ef13a..6b2ed93 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -400,16 +400,11 @@ static void stimer_mark_expired(struct kvm_vcpu_hv_stimer *stimer, kvm_vcpu_kick(vcpu); } -static void stimer_stop(struct kvm_vcpu_hv_stimer *stimer) -{ - hrtimer_cancel(>timer); -} - static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); - stimer_stop(stimer); + hrtimer_cancel(>timer); clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); stimer->msg_pending = false; -- 2.4.3
[Qemu-devel] [PATCH v2 7/7] kvm/x86: Update SynIC timers on guest entry only
Consolidate updating the Hyper-V SynIC timers in a single place: on guest entry in processing KVM_REQ_HV_STIMER request. This simplifies the overall logic, and makes sure the most current state of msrs and guest clock is used for arming the timers (to achieve that, KVM_REQ_HV_STIMER has to be processed after KVM_REQ_CLOCK_UPDATE). Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 38 +++--- arch/x86/kvm/x86.c| 6 ++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index ddae13e..101c2e4 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -389,7 +389,7 @@ static u64 get_time_ref_counter(struct kvm *kvm) return div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); } -static void stimer_mark_expired(struct kvm_vcpu_hv_stimer *stimer, +static void stimer_mark_pending(struct kvm_vcpu_hv_stimer *stimer, bool vcpu_kick) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); @@ -417,7 +417,7 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) struct kvm_vcpu_hv_stimer *stimer; stimer = container_of(timer, struct kvm_vcpu_hv_stimer, timer); - stimer_mark_expired(stimer, true); + stimer_mark_pending(stimer, true); return HRTIMER_NORESTART; } @@ -462,7 +462,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) * "If a one shot is enabled and the specified count is in * the past, it will expire immediately." */ - stimer_mark_expired(stimer, false); + stimer_mark_pending(stimer, false); return 0; } @@ -475,30 +475,24 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, bool host) { + stimer_cleanup(stimer); if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) config &= ~HV_STIMER_ENABLE; stimer->config = config; - stimer_cleanup(stimer); - if (stimer->config & HV_STIMER_ENABLE) - if (stimer_start(stimer)) - return 1; + stimer_mark_pending(stimer, false); return 0; } static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count, bool host) { - stimer->count = count; - stimer_cleanup(stimer); + stimer->count = count; if (stimer->count == 0) stimer->config &= ~HV_STIMER_ENABLE; - else if (stimer->config & HV_STIMER_AUTOENABLE) { + else if (stimer->config & HV_STIMER_AUTOENABLE) stimer->config |= HV_STIMER_ENABLE; - if (stimer_start(stimer)) - return 1; - } - + stimer_mark_pending(stimer, false); return 0; } @@ -582,18 +576,24 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) { struct kvm_vcpu_hv *hv_vcpu = vcpu_to_hv_vcpu(vcpu); struct kvm_vcpu_hv_stimer *stimer; - u64 time_now; + u64 time_now, exp_time; int i; for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) if (test_and_clear_bit(i, hv_vcpu->stimer_pending_bitmap)) { stimer = _vcpu->stimer[i]; if (stimer->config & HV_STIMER_ENABLE) { - time_now = get_time_ref_counter(vcpu->kvm); - if (time_now >= stimer->exp_time) - stimer_expiration(stimer); + exp_time = stimer->exp_time; + + if (exp_time) { + time_now = + get_time_ref_counter(vcpu->kvm); + if (time_now >= exp_time) + stimer_expiration(stimer); + } - if (stimer->config & HV_STIMER_ENABLE) + if ((stimer->config & HV_STIMER_ENABLE) && + stimer->count) stimer_start(stimer); else stimer_cleanup(stimer); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e231
[Qemu-devel] [PATCH v2 5/7] kvm/x86: Hyper-V fix SynIC timer disabling condition
Hypervisor Function Specification(HFS) doesn't require to disable SynIC timer at timer config write if timer->count = 0. So drop this check, this allow to load timers MSR's during migration restore, because config are set before count in QEMU side. Also fix condition according to HFS doc(15.3.1): "It is not permitted to set the SINTx field to zero for an enabled timer. If attempted, the timer will be marked disabled (that is, bit 0 cleared) immediately." Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 5f85c12..abfb920 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -474,7 +474,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, bool host) { - if (stimer->count == 0 || HV_STIMER_SINT(config) == 0) + if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) config &= ~HV_STIMER_ENABLE; stimer->config = config; stimer_cleanup(stimer); -- 2.4.3
[Qemu-devel] [PATCH v2 3/7] kvm/x86: Hyper-V unify stimer_start() and stimer_restart()
This will be used in future to start Hyper-V SynIC timer in several places by one logic in one function. Changes v2: * drop stimer->count == 0 check inside stimer_start() * comment stimer_start() assumptions Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 43 --- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 6b2ed93..0dd7d17 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -408,6 +408,7 @@ static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); stimer->msg_pending = false; + stimer->exp_time = 0; } static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) @@ -420,24 +421,11 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) return HRTIMER_NORESTART; } -static void stimer_restart(struct kvm_vcpu_hv_stimer *stimer) -{ - u64 time_now; - ktime_t ktime_now; - u64 remainder; - - time_now = get_time_ref_counter(stimer_to_vcpu(stimer)->kvm); - ktime_now = ktime_get(); - - div64_u64_rem(time_now - stimer->exp_time, stimer->count, ); - stimer->exp_time = time_now + (stimer->count - remainder); - - hrtimer_start(>timer, - ktime_add_ns(ktime_now, - 100 * (stimer->exp_time - time_now)), - HRTIMER_MODE_ABS); -} - +/* + * stimer_start() assumptions: + * a) stimer->count is not equal to 0 + * b) stimer->config has HV_STIMER_ENABLE flag + */ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) { u64 time_now; @@ -447,12 +435,21 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) ktime_now = ktime_get(); if (stimer->config & HV_STIMER_PERIODIC) { - if (stimer->count == 0) - return -EINVAL; + if (stimer->exp_time) { + if (time_now >= stimer->exp_time) { + u64 remainder; + + div64_u64_rem(time_now - stimer->exp_time, + stimer->count, ); + stimer->exp_time = + time_now + (stimer->count - remainder); + } + } else + stimer->exp_time = time_now + stimer->count; - stimer->exp_time = time_now + stimer->count; hrtimer_start(>timer, - ktime_add_ns(ktime_now, 100 * stimer->count), + ktime_add_ns(ktime_now, + 100 * (stimer->exp_time - time_now)), HRTIMER_MODE_ABS); return 0; } @@ -580,7 +577,7 @@ static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) if (!(stimer->config & HV_STIMER_PERIODIC)) stimer->config &= ~HV_STIMER_ENABLE; else - stimer_restart(stimer); + stimer_start(stimer); } void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) -- 2.4.3
[Qemu-devel] [PATCH v2 0/7] KVM: Hyper-V SynIC timers migration fixes
During testing of Windows 2012R2 guest migration with Hyper-V SynIC timers enabled we found several bugs which lead to restoring guest in a hung state. This patch series provides several fixes to make the migration of guest with Hyper-V SynIC timers enabled succeed. The series applies on top of 'kvm/x86: Remove Hyper-V SynIC timer stopping' previously sent. Changes v2: * fix incorrect logical operation for one-shot timers * drop stimer->count == 0 inside stimer_start() * comment stimer_start() assumtions Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (7): kvm/x86: Hyper-V timers fix incorrect logical operation kvm/x86: Drop stimer_stop() function kvm/x86: Hyper-V unify stimer_start() and stimer_restart() kvm/x86: Reorg stimer_expiration() to better control timer restart kvm/x86: Hyper-V fix SynIC timer disabling condition kvm/x86: Skip SynIC vector check for QEMU side kvm/x86: Update SynIC timers on guest entry only arch/x86/kvm/hyperv.c | 119 -- arch/x86/kvm/x86.c| 6 +++ 2 files changed, 63 insertions(+), 62 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v2 4/7] kvm/x86: Reorg stimer_expiration() to better control timer restart
Split stimer_expiration() into two parts - timer expiration message sending and timer restart/cleanup based on timer state(config). This also fixes a bug where a one-shot timer message whose delivery failed once would get lost for good. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 26 ++ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 0dd7d17..5f85c12 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -554,30 +554,27 @@ static int synic_deliver_msg(struct kvm_vcpu_hv_synic *synic, u32 sint, return r; } -static void stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) +static int stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); struct hv_message *msg = >msg; struct hv_timer_message_payload *payload = (struct hv_timer_message_payload *)>u.payload; - int r; - stimer->msg_pending = true; payload->expiration_time = stimer->exp_time; payload->delivery_time = get_time_ref_counter(vcpu->kvm); - r = synic_deliver_msg(vcpu_to_synic(vcpu), - HV_STIMER_SINT(stimer->config), msg); - if (!r) - stimer->msg_pending = false; + return synic_deliver_msg(vcpu_to_synic(vcpu), +HV_STIMER_SINT(stimer->config), msg); } static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) { - stimer_send_msg(stimer); - if (!(stimer->config & HV_STIMER_PERIODIC)) - stimer->config &= ~HV_STIMER_ENABLE; - else - stimer_start(stimer); + stimer->msg_pending = true; + if (!stimer_send_msg(stimer)) { + stimer->msg_pending = false; + if (!(stimer->config & HV_STIMER_PERIODIC)) + stimer->config &= ~HV_STIMER_ENABLE; + } } void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) @@ -594,6 +591,11 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) time_now = get_time_ref_counter(vcpu->kvm); if (time_now >= stimer->exp_time) stimer_expiration(stimer); + + if (stimer->config & HV_STIMER_ENABLE) + stimer_start(stimer); + else + stimer_cleanup(stimer); } } } -- 2.4.3
[Qemu-devel] [PATCH v1] kvm/x86: Hyper-V tsc page setup
Lately tsc page was implemented but filled with empty values. This patch setup tsc page scale and offset based on vcpu tsc, tsc_khz and HV_X64_MSR_TIME_REF_COUNT value. The valid tsc page drops HV_X64_MSR_TIME_REF_COUNT msr reads count to zero which potentially improves performance. The patch applies on top of 'kvm: Make vcpu->requests as 64 bit bitmap' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c| 117 +-- arch/x86/kvm/hyperv.h| 2 + arch/x86/kvm/x86.c | 12 + include/linux/kvm_host.h | 1 + 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d50675a..504fdc7 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -753,6 +753,105 @@ static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu, return 0; } +static u64 calc_tsc_page_scale(u32 tsc_khz) +{ + /* +* reftime (in 100ns) = tsc * tsc_scale / 2^64 + tsc_offset +* so reftime_delta = (tsc_delta * tsc_scale) / 2^64 +* so tsc_scale = (2^64 * reftime_delta)/tsc_delta +* so tsc_scale = (2^64 * 10 * 10^6) / tsc_hz = (2^64 * 1) / tsc_khz +* so tsc_scale = (2^63 * 2 * 1) / tsc_khz +*/ + return mul_u64_u32_div(1ULL << 63, 2 * 1, tsc_khz); +} + +static int write_tsc_page(struct kvm *kvm, u64 gfn, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_write_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + mark_page_dirty(kvm, gfn); + return 0; +} + +static int read_tsc_page(struct kvm *kvm, u64 gfn, +PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + if (kvm_read_guest(kvm, gfn_to_gpa(gfn), + tsc_ref, sizeof(*tsc_ref))) + return 1; + return 0; +} + +static u64 calc_tsc_page_time(struct kvm_vcpu *vcpu, + PHV_REFERENCE_TSC_PAGE tsc_ref) +{ + + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + return mul_u64_u64_shr(tsc, tsc_ref->tsc_scale, 64) + + tsc_ref->tsc_offset; +} + +static int setup_blank_tsc_page(struct kvm_vcpu *vcpu, u64 gfn) +{ + HV_REFERENCE_TSC_PAGE tsc_ref; + + memset(_ref, 0, sizeof(tsc_ref)); + return write_tsc_page(vcpu->kvm, gfn, _ref); +} + +int kvm_hv_setup_tsc_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_hv *hv = >arch.hyperv; + HV_REFERENCE_TSC_PAGE tsc_ref; + u32 tsc_khz; + int r; + u64 gfn, ref_time, tsc_scale, tsc_offset, tsc; + + if (WARN_ON_ONCE(!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))) + return -EINVAL; + + gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT; + vcpu_debug(vcpu, "tsc page gfn 0x%llx\n", gfn); + + tsc_khz = vcpu->arch.virtual_tsc_khz; + if (!tsc_khz) { + vcpu_unimpl(vcpu, "no tsc khz\n"); + return setup_blank_tsc_page(vcpu, gfn); + } + + r = read_tsc_page(kvm, gfn, _ref); + if (r) { + vcpu_err(vcpu, "can't access tsc page gfn 0x%llx\n", gfn); + return r; + } + + tsc_scale = calc_tsc_page_scale(tsc_khz); + ref_time = get_time_ref_counter(kvm); + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + /* tsc_offset = reftime - tsc * tsc_scale / 2^64 */ + tsc_offset = ref_time - mul_u64_u64_shr(tsc, tsc_scale, 64); + vcpu_debug(vcpu, "tsc khz %u tsc %llu scale %llu offset %llu\n", + tsc_khz, tsc, tsc_scale, tsc_offset); + + tsc_ref.tsc_sequence++; + if (tsc_ref.tsc_sequence == 0) + tsc_ref.tsc_sequence = 1; + + tsc_ref.tsc_scale = tsc_scale; + tsc_ref.tsc_offset = tsc_offset; + + vcpu_debug(vcpu, "tsc page calibration time %llu vs. reftime %llu\n", + calc_tsc_page_time(vcpu, _ref), + get_time_ref_counter(kvm)); + + return write_tsc_page(kvm, gfn, _ref); +} + static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) { @@ -790,23 +889,11 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, mark_page_dirty(kvm, gfn); break; } - case HV_X64_MSR_REFERENCE_TSC: { - u64 gfn; - HV_REFERENCE_TSC_PAGE tsc_ref; - - memset(_ref, 0, sizeof(tsc_ref)); + case HV_X64_MSR_REFERENCE_TSC: hv->hv_tsc_page =
[Qemu-devel] [PATCH v1] kvm: Make vcpu->requests as 64 bit bitmap
Currently on x86 arch we has already 32 requests defined so the newer request bits can't be placed inside vcpu->requests(unsigned long) inside x86 32 bit system. But we are going to add a new request in x86 arch for Hyper-V tsc page support. To solve the problem the patch replaces vcpu->requests by bitmap with 64 bit length and uses bitmap API. The patch consists of: * announce kvm_vcpu_has_requests() to check whether vcpu has requests * announce kvm_vcpu_requests() to get vcpu requests pointer * announce kvm_clear_request() to clear particular vcpu request * replace if (vcpu->requests) by if (kvm_vcpu_has_requests(vcpu)) * replace clear_bit(req, vcpu->requests) by kvm_clear_request(req, vcpu) Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: James Hogan <james.ho...@imgtec.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Paul Burton <paul.bur...@imgtec.com> CC: Ralf Baechle <r...@linux-mips.org> CC: Alexander Graf <ag...@suse.com> CC: Christian Borntraeger <borntrae...@de.ibm.com> CC: Cornelia Huck <cornelia.h...@de.ibm.com> CC: linux-m...@linux-mips.org CC: kvm-...@vger.kernel.org CC: linux-s...@vger.kernel.org CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/mips/kvm/emulate.c | 4 +--- arch/powerpc/kvm/book3s_pr.c | 2 +- arch/powerpc/kvm/book3s_pr_papr.c | 2 +- arch/powerpc/kvm/booke.c | 6 +++--- arch/powerpc/kvm/powerpc.c| 6 +++--- arch/powerpc/kvm/trace.h | 2 +- arch/s390/kvm/kvm-s390.c | 4 ++-- arch/x86/kvm/vmx.c| 2 +- arch/x86/kvm/x86.c| 14 +++--- include/linux/kvm_host.h | 27 ++- 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 41b1b09..14aebe8 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -774,10 +774,8 @@ enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu) * We we are runnable, then definitely go off to user space to * check if any I/O interrupts are pending. */ - if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) { - clear_bit(KVM_REQ_UNHALT, >requests); + if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; - } } return EMULATE_DONE; diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 64891b0..e975279 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -349,7 +349,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) if (msr & MSR_POW) { if (!vcpu->arch.pending_exceptions) { kvm_vcpu_block(vcpu); - clear_bit(KVM_REQ_UNHALT, >requests); + kvm_clear_request(KVM_REQ_UNHALT, vcpu)); vcpu->stat.halt_wakeup++; /* Unset POW bit after we woke up */ diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c index f2c75a1..60cf393 100644 --- a/arch/powerpc/kvm/book3s_pr_papr.c +++ b/arch/powerpc/kvm/book3s_pr_papr.c @@ -309,7 +309,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) case H_CEDE: kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE); kvm_vcpu_block(vcpu); - clear_bit(KVM_REQ_UNHALT, >requests); + kvm_clear_request(KVM_REQ_UNHALT, vcpu); vcpu->stat.halt_wakeup++; return EMULATE_DONE; case H_LOGICAL_CI_LOAD: diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index fd58751..6bed382 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -574,7 +574,7 @@ static void arm_next_watchdog(struct kvm_vcpu *vcpu) * userspace, so clear the KVM_REQ_WATCHDOG request. */ if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS)) - clear_bit(KVM_REQ_WATCHDOG, >requests); + kvm_clear_request(KVM_REQ_WATCHDOG, vcpu); spin_lock_irqsave(>arch.wdt_lock, flags); nr_jiffies = watchdog_next_timeout(vcpu); @@ -677,7 +677,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) kvmppc_core_check_exceptions(vcpu); - if (vcpu->requests) { + if (kvm_vcpu_has_requests(vcpu)) { /* Exception delivery raised request; start over */ return 1; } @@ -685,7 +685,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) if (vcpu->arch.shared->msr &am
Re: [Qemu-devel] [PATCH v1] kvm: Make vcpu->requests as 64 bit bitmap
On 12/24/2015 02:14 PM, Roman Kagan wrote: On Thu, Dec 24, 2015 at 12:30:26PM +0300, Andrey Smetanin wrote: Currently on x86 arch we has already 32 requests defined so the newer request bits can't be placed inside vcpu->requests(unsigned long) inside x86 32 bit system. But we are going to add a new request in x86 arch for Hyper-V tsc page support. To solve the problem the patch replaces vcpu->requests by bitmap with 64 bit length and uses bitmap API. The patch consists of: * announce kvm_vcpu_has_requests() to check whether vcpu has requests * announce kvm_vcpu_requests() to get vcpu requests pointer I think that if abstracting out the implementation of the request container is what you're after, you'd better not define this function; accesses to the request map should be through your accessor functions. Good idea! I'll rework this patch and will send V2. * announce kvm_clear_request() to clear particular vcpu request * replace if (vcpu->requests) by if (kvm_vcpu_has_requests(vcpu)) * replace clear_bit(req, vcpu->requests) by kvm_clear_request(req, vcpu) Apparently one accessor is missing: test the presence of a request without clearing it from the bitmap (because kvm_check_request() clears it). agree diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index 2e0e67e..4015b88 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h @@ -109,7 +109,7 @@ TRACE_EVENT(kvm_check_requests, TP_fast_assign( __entry->cpu_nr = vcpu->vcpu_id; - __entry->requests= vcpu->requests; + __entry->requests= (__u32)kvm_vcpu_requests(vcpu)[0]; ), This doesn't make sense, to expose only subset of the requests. BTW I don't see this event in Linus tree, nor in linux-next, I found it here: arch/powerpc/kvm/powerpc.c:104: trace_kvm_check_requests(vcpu); >so I'm not quite sure why it's formed this way; I guess the interesting part is the request number and the return value (i.e. whether it's set), not the whole bitmap. No, the code actually dumps part of first 32 bit of bitmap: TP_printk("vcpu=%x requests=%x", __entry->cpu_nr, __entry->requests) So, for this corner case we can make __entry->requests as unsigned long variable and make the API helper to get first unsigned long from vcpu->requests bitmap. Next print part of bitmap this way: TP_printk("vcpu=0x%x requests=0x%lx", __entry->cpu_nr, __entry->requests) (as unsigned long). POWERPC guys what do you think about such approach? Or could we even drop trace_kvm_check_requests() at all. Does trace_kvm_check_requests() still useful for you? --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5957,7 +5957,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) if (intr_window_requested && vmx_interrupt_allowed(vcpu)) return handle_interrupt_window(>vcpu); - if (test_bit(KVM_REQ_EVENT, >requests)) + if (test_bit(KVM_REQ_EVENT, kvm_vcpu_requests(vcpu))) Here you'd rather want that function to test for the request without clearing it. agree, i'll provide such function. --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2117,7 +2117,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (ka->boot_vcpu_runs_old_kvmclock != tmp) set_bit(KVM_REQ_MASTERCLOCK_UPDATE, - >requests); + kvm_vcpu_requests(vcpu)); This should have been kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu); agree @@ -8048,7 +8048,7 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) if (atomic_read(>arch.nmi_queued)) return true; - if (test_bit(KVM_REQ_SMI, >requests)) + if (test_bit(KVM_REQ_SMI, kvm_vcpu_requests(vcpu))) Again the test-only accessor is due here. agree --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -146,6 +146,8 @@ static inline bool is_error_page(struct page *page) #define KVM_REQ_HV_EXIT 30 #define KVM_REQ_HV_STIMER 31 +#define KVM_REQ_MAX 64 + #define KVM_USERSPACE_IRQ_SOURCE_ID 0 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 @@ -233,7 +235,7 @@ struct kvm_vcpu { int vcpu_id; int srcu_idx; int mode; - unsigned long requests; + DECLARE_BITMAP(requests, KVM_REQ_MAX); unsigned long guest_debug; int pre_pcpu; @@ -286,6 +288,16 @@ struct kvm_vcpu { struct kvm_vcpu_arch arch; }; +static inline bool kvm_vcpu_has_requests(struct kvm_vcpu *vcpu) +{ + return !bitmap_empty(vcpu->requests, KVM_REQ_MAX); +} + +static inline ulong *kvm_vcpu_requests(struct kvm_vcpu *vcpu) +{ + return (ulong *
[Qemu-devel] [PATCH v2] kvm: Make vcpu->requests as 64 bit bitmap
Currently on x86 arch we has already 32 requests defined so the newer request bits can't be placed inside vcpu->requests(unsigned long) inside x86 32 bit system. But we are going to add a new request in x86 arch for Hyper-V tsc page support. To solve the problem the patch replaces vcpu->requests by bitmap with 64 bit length and uses bitmap API. The patch consists of: * announce kvm_has_requests() to check whether vcpu has requests * announce kvm_clear_request() to clear particular vcpu request * announce kvm_test_request() to test particular vcpu request * replace if (vcpu->requests) by if (kvm_has_requests(vcpu)) * replace clear_bit(req, vcpu->requests) by kvm_clear_request(req, vcpu) Changes v2: * hide internals of vcpu requests bitmap by interface usage in all places * replace test_bit(req, vcpu->requests) by kvm_test_request() * POWERPC: trace vcpu requests bitmap by __bitmask, __assign_bitmap, __get_bitmask Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: James Hogan <james.ho...@imgtec.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Gleb Natapov <g...@kernel.org> CC: James Hogan <james.ho...@imgtec.com> CC: Paul Burton <paul.bur...@imgtec.com> CC: Ralf Baechle <r...@linux-mips.org> CC: Alexander Graf <ag...@suse.com> CC: Christian Borntraeger <borntrae...@de.ibm.com> CC: Cornelia Huck <cornelia.h...@de.ibm.com> CC: linux-m...@linux-mips.org CC: kvm-...@vger.kernel.org CC: linux-s...@vger.kernel.org CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/mips/kvm/emulate.c | 4 +--- arch/powerpc/kvm/book3s_pr.c | 2 +- arch/powerpc/kvm/book3s_pr_papr.c | 2 +- arch/powerpc/kvm/booke.c | 6 +++--- arch/powerpc/kvm/powerpc.c| 6 +++--- arch/powerpc/kvm/trace.h | 9 + arch/s390/kvm/kvm-s390.c | 4 ++-- arch/x86/kvm/vmx.c| 2 +- arch/x86/kvm/x86.c| 16 include/linux/kvm_host.h | 38 +- 10 files changed, 50 insertions(+), 39 deletions(-) diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 41b1b09..14aebe8 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -774,10 +774,8 @@ enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu) * We we are runnable, then definitely go off to user space to * check if any I/O interrupts are pending. */ - if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) { - clear_bit(KVM_REQ_UNHALT, >requests); + if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; - } } return EMULATE_DONE; diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 64891b0..e975279 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -349,7 +349,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) if (msr & MSR_POW) { if (!vcpu->arch.pending_exceptions) { kvm_vcpu_block(vcpu); - clear_bit(KVM_REQ_UNHALT, >requests); + kvm_clear_request(KVM_REQ_UNHALT, vcpu)); vcpu->stat.halt_wakeup++; /* Unset POW bit after we woke up */ diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c index f2c75a1..60cf393 100644 --- a/arch/powerpc/kvm/book3s_pr_papr.c +++ b/arch/powerpc/kvm/book3s_pr_papr.c @@ -309,7 +309,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) case H_CEDE: kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE); kvm_vcpu_block(vcpu); - clear_bit(KVM_REQ_UNHALT, >requests); + kvm_clear_request(KVM_REQ_UNHALT, vcpu); vcpu->stat.halt_wakeup++; return EMULATE_DONE; case H_LOGICAL_CI_LOAD: diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index fd58751..b2e8643 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -574,7 +574,7 @@ static void arm_next_watchdog(struct kvm_vcpu *vcpu) * userspace, so clear the KVM_REQ_WATCHDOG request. */ if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS)) - clear_bit(KVM_REQ_WATCHDOG, >requests); + kvm_clear_request(KVM_REQ_WATCHDOG, vcpu); spin_lock_irqsave(>arch.wdt_lock, flags); nr_jiffies = watchdog_next_timeout(vcpu); @@ -677,7 +677,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) kvmppc_core_check_exceptions(vcpu); - if (vcpu->requests) { + if (kvm_has_requests(vcpu)
[Qemu-devel] [PATCH v1 1/6] kvm/x86: Drop stimer_stop() function
The function stimer_stop() is called in one place so remove the function and replace it's call by function content. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index f34f666..ec3a900 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -400,16 +400,11 @@ static void stimer_mark_expired(struct kvm_vcpu_hv_stimer *stimer, kvm_vcpu_kick(vcpu); } -static void stimer_stop(struct kvm_vcpu_hv_stimer *stimer) -{ - hrtimer_cancel(>timer); -} - static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); - stimer_stop(stimer); + hrtimer_cancel(>timer); clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); stimer->msg_pending = false; -- 2.4.3
[Qemu-devel] [PATCH v1 2/6] kvm/x86: Hyper-V unify stimer_start() and stimer_restart()
This will be used in future to start Hyper-V SynIC timer in several places by one logic in one function. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 37 - 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index ec3a900..8623aa6 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -408,6 +408,7 @@ static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); stimer->msg_pending = false; + stimer->exp_time = 0; } static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) @@ -420,24 +421,6 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) return HRTIMER_NORESTART; } -static void stimer_restart(struct kvm_vcpu_hv_stimer *stimer) -{ - u64 time_now; - ktime_t ktime_now; - u64 remainder; - - time_now = get_time_ref_counter(stimer_to_vcpu(stimer)->kvm); - ktime_now = ktime_get(); - - div64_u64_rem(time_now - stimer->exp_time, stimer->count, ); - stimer->exp_time = time_now + (stimer->count - remainder); - - hrtimer_start(>timer, - ktime_add_ns(ktime_now, - 100 * (stimer->exp_time - time_now)), - HRTIMER_MODE_ABS); -} - static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) { u64 time_now; @@ -450,9 +433,21 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) if (stimer->count == 0) return -EINVAL; - stimer->exp_time = time_now + stimer->count; + if (stimer->exp_time) { + if (time_now >= stimer->exp_time) { + u64 remainder; + + div64_u64_rem(time_now - stimer->exp_time, + stimer->count, ); + stimer->exp_time = + time_now + (stimer->count - remainder); + } + } else + stimer->exp_time = time_now + stimer->count; + hrtimer_start(>timer, - ktime_add_ns(ktime_now, 100 * stimer->count), + ktime_add_ns(ktime_now, + 100 * (stimer->exp_time - time_now)), HRTIMER_MODE_ABS); return 0; } @@ -580,7 +575,7 @@ static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) if (!(stimer->config & HV_STIMER_PERIODIC)) stimer->config |= ~HV_STIMER_ENABLE; else - stimer_restart(stimer); + stimer_start(stimer); } void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) -- 2.4.3
[Qemu-devel] [PATCH v1 3/6] kvm/x86: Reorg stimer_expiration() to better control timer restart
Split stimer_expiration() into two parts - timer expiration message sending and timer restart/cleanup based on timer state(config). This also fixes a bug where a one-shot timer message whose delivery failed once would get lost for good. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 26 ++ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 8623aa6..ce17529 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -552,30 +552,27 @@ static int synic_deliver_msg(struct kvm_vcpu_hv_synic *synic, u32 sint, return r; } -static void stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) +static int stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); struct hv_message *msg = >msg; struct hv_timer_message_payload *payload = (struct hv_timer_message_payload *)>u.payload; - int r; - stimer->msg_pending = true; payload->expiration_time = stimer->exp_time; payload->delivery_time = get_time_ref_counter(vcpu->kvm); - r = synic_deliver_msg(vcpu_to_synic(vcpu), - HV_STIMER_SINT(stimer->config), msg); - if (!r) - stimer->msg_pending = false; + return synic_deliver_msg(vcpu_to_synic(vcpu), +HV_STIMER_SINT(stimer->config), msg); } static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) { - stimer_send_msg(stimer); - if (!(stimer->config & HV_STIMER_PERIODIC)) - stimer->config |= ~HV_STIMER_ENABLE; - else - stimer_start(stimer); + stimer->msg_pending = true; + if (!stimer_send_msg(stimer)) { + stimer->msg_pending = false; + if (!(stimer->config & HV_STIMER_PERIODIC)) + stimer->config |= ~HV_STIMER_ENABLE; + } } void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) @@ -592,6 +589,11 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) time_now = get_time_ref_counter(vcpu->kvm); if (time_now >= stimer->exp_time) stimer_expiration(stimer); + + if (stimer->config & HV_STIMER_ENABLE) + stimer_start(stimer); + else + stimer_cleanup(stimer); } } } -- 2.4.3
[Qemu-devel] [PATCH v1 6/6] kvm/x86: Update SynIC timers on guest entry only
Consolidate updating the Hyper-V SynIC timers in a single place: on guest entry in processing KVM_REQ_HV_STIMER request. This simplifies the overall logic, and makes sure the most current state of msrs and guest clock is used for arming the timers (to achieve that, KVM_REQ_HV_STIMER has to be processed after KVM_REQ_CLOCK_UPDATE). Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 35 +-- arch/x86/kvm/x86.c| 6 ++ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index d7e6651..7857329 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -389,7 +389,7 @@ static u64 get_time_ref_counter(struct kvm *kvm) return div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); } -static void stimer_mark_expired(struct kvm_vcpu_hv_stimer *stimer, +static void stimer_mark_pending(struct kvm_vcpu_hv_stimer *stimer, bool vcpu_kick) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); @@ -417,7 +417,7 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) struct kvm_vcpu_hv_stimer *stimer; stimer = container_of(timer, struct kvm_vcpu_hv_stimer, timer); - stimer_mark_expired(stimer, true); + stimer_mark_pending(stimer, true); return HRTIMER_NORESTART; } @@ -460,7 +460,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) * "If a one shot is enabled and the specified count is in * the past, it will expire immediately." */ - stimer_mark_expired(stimer, false); + stimer_mark_pending(stimer, false); return 0; } @@ -473,30 +473,24 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, bool host) { + stimer_cleanup(stimer); if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) config &= ~HV_STIMER_ENABLE; stimer->config = config; - stimer_cleanup(stimer); - if (stimer->config & HV_STIMER_ENABLE) - if (stimer_start(stimer)) - return 1; + stimer_mark_pending(stimer, false); return 0; } static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count, bool host) { - stimer->count = count; - stimer_cleanup(stimer); + stimer->count = count; if (stimer->count == 0) stimer->config &= ~HV_STIMER_ENABLE; - else if (stimer->config & HV_STIMER_AUTOENABLE) { + else if (stimer->config & HV_STIMER_AUTOENABLE) stimer->config |= HV_STIMER_ENABLE; - if (stimer_start(stimer)) - return 1; - } - + stimer_mark_pending(stimer, false); return 0; } @@ -580,16 +574,21 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) { struct kvm_vcpu_hv *hv_vcpu = vcpu_to_hv_vcpu(vcpu); struct kvm_vcpu_hv_stimer *stimer; - u64 time_now; + u64 time_now, exp_time; int i; for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) if (test_and_clear_bit(i, hv_vcpu->stimer_pending_bitmap)) { stimer = _vcpu->stimer[i]; if (stimer->config & HV_STIMER_ENABLE) { - time_now = get_time_ref_counter(vcpu->kvm); - if (time_now >= stimer->exp_time) - stimer_expiration(stimer); + exp_time = stimer->exp_time; + + if (exp_time) { + time_now = + get_time_ref_counter(vcpu->kvm); + if (time_now >= exp_time) + stimer_expiration(stimer); + } if (stimer->config & HV_STIMER_ENABLE) stimer_start(stimer); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b6102c1..795c14c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6492,6 +6492,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) r = 0; goto out; } + + /* +
[Qemu-devel] [PATCH v1 0/6] KVM: Hyper-V SynIC timers migration fixes
During testing of Windows 2012R2 guest migration with Hyper-V SynIC timers enabled we found several bugs which lead to restoring guest in a hung state. This patch series provides several fixes to make the migration of guest with Hyper-V SynIC timers enabled succeed. The series applies on top of 'kvm/x86: Remove Hyper-V SynIC timer stopping' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (6): kvm/x86: Drop stimer_stop() function kvm/x86: Hyper-V unify stimer_start() and stimer_restart() kvm/x86: Reorg stimer_expiration() to better control timer restart kvm/x86: Hyper-V fix SynIC timer disabling condition kvm/x86: Skip SynIC vector check for QEMU side kvm/x86: Update SynIC timers on guest entry only arch/x86/kvm/hyperv.c | 112 +++--- arch/x86/kvm/x86.c| 6 +++ 2 files changed, 58 insertions(+), 60 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v1 4/6] kvm/x86: Hyper-V fix SynIC timer disabling condition
Hypervisor Function Specification(HFS) doesn't require to disable SynIC timer at timer config write if timer->count = 0. So drop this check, this allow to load timers MSR's during migration restore, because config are set before count in QEMU side. Also fix condition according to HFS doc(15.3.1): "It is not permitted to set the SINTx field to zero for an enabled timer. If attempted, the timer will be marked disabled (that is, bit 0 cleared) immediately." Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index ce17529..b203ce3 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -472,7 +472,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, bool host) { - if (stimer->count == 0 || HV_STIMER_SINT(config) == 0) + if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) config &= ~HV_STIMER_ENABLE; stimer->config = config; stimer_cleanup(stimer); -- 2.4.3
[Qemu-devel] [PATCH v1 5/6] kvm/x86: Skip SynIC vector check for QEMU side
QEMU zero-inits Hyper-V SynIC vectors. We should allow that, and don't reject zero values if set by the host. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index b203ce3..d7e6651 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -72,12 +72,13 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic, return false; } -static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, u64 data) +static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, + u64 data, bool host) { int vector; vector = data & HV_SYNIC_SINT_VECTOR_MASK; - if (vector < 16) + if (vector < 16 && !host) return 1; /* * Guest may configure multiple SINTs to use the same vector, so @@ -247,7 +248,7 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic, break; } case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15: - ret = synic_set_sint(synic, msr - HV_X64_MSR_SINT0, data); + ret = synic_set_sint(synic, msr - HV_X64_MSR_SINT0, data, host); break; default: ret = 1; -- 2.4.3
[Qemu-devel] [PATCH v1 2/2] kvm/x86: Hyper-V SynIC timers tracepoints
Trace the following Hyper SynIC timers events: * periodic timer start * one-shot timer start * timer callback * timer expiration and message delivery result * timer config setup * timer count setup * timer cleanup Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 27 +++- arch/x86/kvm/trace.h | 170 ++ 2 files changed, 196 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index e69a823..d50675a 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -405,6 +405,9 @@ static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer) { struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); + trace_kvm_hv_stimer_cleanup(stimer_to_vcpu(stimer)->vcpu_id, + stimer->index); + hrtimer_cancel(>timer); clear_bit(stimer->index, vcpu_to_hv_vcpu(vcpu)->stimer_pending_bitmap); @@ -417,6 +420,8 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) struct kvm_vcpu_hv_stimer *stimer; stimer = container_of(timer, struct kvm_vcpu_hv_stimer, timer); + trace_kvm_hv_stimer_callback(stimer_to_vcpu(stimer)->vcpu_id, +stimer->index); stimer_mark_pending(stimer, true); return HRTIMER_NORESTART; @@ -446,6 +451,11 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) } else stimer->exp_time = time_now + stimer->count; + trace_kvm_hv_stimer_start_periodic( + stimer_to_vcpu(stimer)->vcpu_id, + stimer->index, + time_now, stimer->exp_time); + hrtimer_start(>timer, ktime_add_ns(ktime_now, 100 * (stimer->exp_time - time_now)), @@ -464,6 +474,10 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) return 0; } + trace_kvm_hv_stimer_start_one_shot(stimer_to_vcpu(stimer)->vcpu_id, + stimer->index, + time_now, stimer->count); + hrtimer_start(>timer, ktime_add_ns(ktime_now, 100 * (stimer->count - time_now)), HRTIMER_MODE_ABS); @@ -473,6 +487,9 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, bool host) { + trace_kvm_hv_stimer_set_config(stimer_to_vcpu(stimer)->vcpu_id, + stimer->index, config, host); + stimer_cleanup(stimer); if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) config &= ~HV_STIMER_ENABLE; @@ -484,6 +501,9 @@ static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count, bool host) { + trace_kvm_hv_stimer_set_count(stimer_to_vcpu(stimer)->vcpu_id, + stimer->index, count, host); + stimer_cleanup(stimer); stimer->count = count; if (stimer->count == 0) @@ -562,8 +582,13 @@ static int stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) { + int r; + stimer->msg_pending = true; - if (!stimer_send_msg(stimer)) { + r = stimer_send_msg(stimer); + trace_kvm_hv_stimer_expiration(stimer_to_vcpu(stimer)->vcpu_id, + stimer->index, r); + if (!r) { stimer->msg_pending = false; if (!(stimer->config & HV_STIMER_PERIODIC)) stimer->config |= ~HV_STIMER_ENABLE; diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 5be9c13..41010d8 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -1118,6 +1118,176 @@ TRACE_EVENT(kvm_hv_synic_set_msr, __entry->vcpu_id, __entry->msr, __entry->data, __entry->host) ); +/* + * Tracepoint for stimer_set_config. + */ +TRACE_EVENT(kvm_hv_stimer_set_config, + TP_PROTO(int vcpu_id, int timer_index, u64 config, bool host), + TP_ARGS(vcpu_id, timer_index, config, host), + + TP_STRUCT__entry( + __field(int, vcpu_id) + __field(int, timer_index) + __field(u64, con
[Qemu-devel] [PATCH v1 0/2] KVM: Hyper-V SynIC tracepoints
The patches adds tracepoints inside Hyper-V SynIC and SynIC timers code. The series applies on top of 'kvm/x86: Update SynIC timers on guest entry only' previously sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (2): kvm/x86: Hyper-V SynIC tracepoints kvm/x86: Hyper-V SynIC timers tracepoints arch/x86/kvm/hyperv.c | 37 +-- arch/x86/kvm/trace.h | 263 ++ 2 files changed, 294 insertions(+), 6 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v1 1/2] kvm/x86: Hyper-V SynIC tracepoints
Trace the following Hyper SynIC events: * set msr * set sint irq * ack sint * sint irq eoi Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 10 +++--- arch/x86/kvm/trace.h | 93 +++ 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 7857329..e69a823 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -152,7 +152,7 @@ static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint) struct kvm_vcpu_hv_stimer *stimer; int gsi, idx, stimers_pending; - vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint); + trace_kvm_hv_notify_acked_sint(vcpu->vcpu_id, sint); if (synic->msg_page & HV_SYNIC_SIMP_ENABLE) synic_clear_sint_msg_pending(synic, sint); @@ -202,8 +202,8 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic, if (!synic->active) return 1; - vcpu_debug(vcpu, "Hyper-V SynIC set msr 0x%x 0x%llx host %d\n", - msr, data, host); + trace_kvm_hv_synic_set_msr(vcpu->vcpu_id, msr, data, host); + ret = 0; switch (msr) { case HV_X64_MSR_SCONTROL: @@ -312,7 +312,7 @@ int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint) irq.level = 1; ret = kvm_irq_delivery_to_apic(vcpu->kvm, NULL, , NULL); - vcpu_debug(vcpu, "Hyper-V SynIC set irq ret %d\n", ret); + trace_kvm_hv_synic_set_irq(vcpu->vcpu_id, sint, irq.vector, ret); return ret; } @@ -332,7 +332,7 @@ void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector) struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu); int i; - vcpu_debug(vcpu, "Hyper-V SynIC send eoi vec %d\n", vector); + trace_kvm_hv_synic_send_eoi(vcpu->vcpu_id, vector); for (i = 0; i < ARRAY_SIZE(synic->sint); i++) if (synic_get_sint_vector(synic_read_sint(synic, i)) == vector) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 1203025..5be9c13 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -1025,6 +1025,99 @@ TRACE_EVENT(kvm_pi_irte_update, __entry->pi_desc_addr) ); +/* + * Tracepoint for kvm_hv_notify_acked_sint. + */ +TRACE_EVENT(kvm_hv_notify_acked_sint, + TP_PROTO(int vcpu_id, u32 sint), + TP_ARGS(vcpu_id, sint), + + TP_STRUCT__entry( + __field(int, vcpu_id) + __field(u32, sint) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->sint = sint; + ), + + TP_printk("vcpu_id %d sint %u", __entry->vcpu_id, __entry->sint) +); + +/* + * Tracepoint for synic_set_irq. + */ +TRACE_EVENT(kvm_hv_synic_set_irq, + TP_PROTO(int vcpu_id, u32 sint, int vector, int ret), + TP_ARGS(vcpu_id, sint, vector, ret), + + TP_STRUCT__entry( + __field(int, vcpu_id) + __field(u32, sint) + __field(int, vector) + __field(int, ret) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->sint = sint; + __entry->vector = vector; + __entry->ret = ret; + ), + + TP_printk("vcpu_id %d sint %u vector %d ret %d", + __entry->vcpu_id, __entry->sint, __entry->vector, + __entry->ret) +); + +/* + * Tracepoint for kvm_hv_synic_send_eoi. + */ +TRACE_EVENT(kvm_hv_synic_send_eoi, + TP_PROTO(int vcpu_id, int vector), + TP_ARGS(vcpu_id, vector), + + TP_STRUCT__entry( + __field(int, vcpu_id) + __field(u32, sint) + __field(int, vector) + __field(int, ret) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->vector = vector; + ), + + TP_printk("vcpu_id %d vector %d", __entry->vcpu_id, __entry->vector) +); + +/* + * Tracepoint for synic_set_msr. + */ +TRACE_EVENT(kvm_hv_synic_set_msr, + TP_PROTO(int vcpu_id, u32 msr, u64 data, bool host), + TP_ARGS(vcpu_id, msr, data, host), + + TP_STRUCT__entry( + __field(int, vcpu_id) + __field(u32, msr) + __field(u64, data) + __field(bool, host) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->msr = msr; + __entry->data = data; + __entry->host = host + ), + + TP_printk("vcpu_id %d msr 0x%x data 0x%llx host %d", + __entry->vcpu_id, __entry->msr, __entry->data, __entry->host) +); + #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH -- 2.4.3
Re: [Qemu-devel] [PATCH v4 5/5] kvm/x86: Hyper-V kvm exit
On 12/21/2015 04:28 PM, Pavel Fedin wrote: Hello! Yes, we can use KVM_EXIT_REG_IO/MSR_IO for Hyper-V SynIC MSRS's changes and can even use only one MSR value . So union inside struct kvm_hyperv_exit is excessive. But we still need Vcpu exit to handle VMBus hypercalls by QEMU to emulate VMBus devices inside QEMU. And currently we are going to extend struct kvm_hyperv_exit to store Hyper-V VMBus hypercall parameters. Hm... Hypercalls, you say? We already have KVM_EXIT_HYPERCALL. Documentation says it's currently unused. Is it a leftover from ia64 KVM? Could we reuse it for the purpose? but could we replace Hyper-V VMBus hypercall and it's parameters by KVM_EXIT_REG_IO/MSR_IO too? It depends. Can i read about these hypercalls somewhere? Is there any documentation? I don't know about a documentation, but you can look at the code of Hyper-V hypercall handling inside KVM: https://github.com/torvalds/linux/blob/master/arch/x86/kvm/hyperv.c#L346 The code simply decodes hypercall parameters from vcpu registers then handle hypercall code in switch and encode return code inside vcpu registers. Probably encode and decode of hypercall parameters/return code can be done in QEMU so we need only some exit with parameter that this is Hyper-V hypercall and probably KVM_EXIT_HYPERCALL is good for it. But KVM_EXIT_HYPERCALL is not used inside KVM/QEMU so requires implementation. Kind regards, Pavel Fedin Expert Engineer Samsung Electronics Research center Russia
Re: [Qemu-devel] [PATCH v4 5/5] kvm/x86: Hyper-V kvm exit
On 12/18/2015 09:39 PM, Roman Kagan wrote: On Fri, Dec 18, 2015 at 10:10:11AM -0800, Peter Hornyack wrote: On Fri, Dec 18, 2015 at 8:01 AM, Paolo Bonziniwrote: On 18/12/2015 16:19, Pavel Fedin wrote: As far as i understand this code, KVM_EXIT_HYPERV is called when one of three MSRs are accessed. But, shouldn't we have implemented instead something more generic, like KVM_EXIT_REG_IO, which would work similar to KVM_EXIT_PIO or KVM_EXIT_MMIO, but carry register code and value? Yes, we considered that. There were actually patches for this as well. However, in this case the register is still emulated in the kernel, and userspace just gets informed of the new value. On brief inspection of Andrey's patch (I have not been following closely) it looks like the kvm_hyperv_exit struct that's returned to userspace contains more data (control, evt_page, and msg_page fields) than simply the value of the MSR, so would the desired SynIC exit fit into a general-purpose exit for MSR emulation? Frankly I'm struggling trying to recall why we implemented it this way. Actually all three fields are the values of respective MSRs and I don't see any necessity to pass all three at the same time when any of them gets updated. The patch for QEMU adds an exit handler which processes the fields individually, so I have a strong suspicion that union was meant here rather than struct. I hope Andrey will help to shed some light on that when he's back in the office on Monday; meanwhile I think this peculiarity can be ignored. Hello! We have implemented Hyper-V related Vcpu exit not only for Hyper-V SynIC MSR's changes but also to provide future interface to transfer guest VMBus hypercalls parameters into QEMU. Yes, we can use KVM_EXIT_REG_IO/MSR_IO for Hyper-V SynIC MSRS's changes and can even use only one MSR value . So union inside struct kvm_hyperv_exit is excessive. But we still need Vcpu exit to handle VMBus hypercalls by QEMU to emulate VMBus devices inside QEMU. And currently we are going to extend struct kvm_hyperv_exit to store Hyper-V VMBus hypercall parameters. SynIC MSR's changes could be replaced by KVM_EXIT_REG_IO/MSR_IO but could we replace Hyper-V VMBus hypercall and it's parameters by KVM_EXIT_REG_IO/MSR_IO too? Roman.
[Qemu-devel] [PATCH v1] kvm/x86: Remove Hyper-V SynIC timer stopping
It's possible that guest send us Hyper-V EOM at the middle of Hyper-V SynIC timer running, so we start processing of Hyper-V SynIC timers in vcpu context and stop the Hyper-V SynIC timer uncoditionally and lose time expiration which Windows 2012R2 guest expects. The patch fixes such situation by not stopping Hyper-V SynIC timer at all, because it's safe to restart it without stop in vcpu context and timer callback always returns HRTIMER_NORESTART. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 8ff8829..f34f666 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -598,7 +598,6 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) if (test_and_clear_bit(i, hv_vcpu->stimer_pending_bitmap)) { stimer = _vcpu->stimer[i]; - stimer_stop(stimer); if (stimer->config & HV_STIMER_ENABLE) { time_now = get_time_ref_counter(vcpu->kvm); if (time_now >= stimer->exp_time) -- 2.4.3
Re: [Qemu-devel] [PATCH v1] kvm/x86: Remove Hyper-V SynIC timer stopping
On 12/14/2015 07:09 PM, Paolo Bonzini wrote: On 14/12/2015 16:33, Andrey Smetanin wrote: It's possible that guest send us Hyper-V EOM at the middle of Hyper-V SynIC timer running, so we start processing of Hyper-V SynIC timers in vcpu context and stop the Hyper-V SynIC timer uncoditionally and lose time expiration which Windows 2012R2 guest expects. The patch fixes such situation by not stopping Hyper-V SynIC timer at all, because it's safe to restart it without stop in vcpu context and timer callback always returns HRTIMER_NORESTART. Can you summarize with a "picture" what is the bad race? hostguest start periodic stimer start periodic timer timer expires after 15ms send expiration message into guest restart periodic timer doing something timer expires again after 15 ms msg slot is still not cleared so setup ->msg_pending restart periodic timer doing something process timer msg and clear slot so ->msg_pending was set: send EOM into host received EOM queued call of kvm_hv_process_stimers() by KVM_REQ_HV_STIMER kvm_hv_process_stimers(): ... stimer_stop() if (time_now >= stimer->exp_time) stimer_expiration(stimer); But time_now < stimer->exp_time, so stimer_expiration is not called in this case and timer is not restarted. so guest lose timer. The patch seems safe, but I'd like to have a better understanding of what goes wrong. Paolo
Re: [Qemu-devel] [PATCH v1] kvm/x86: Remove Hyper-V SynIC timer stopping
On 12/14/2015 07:09 PM, Paolo Bonzini wrote: On 14/12/2015 16:33, Andrey Smetanin wrote: It's possible that guest send us Hyper-V EOM at the middle of Hyper-V SynIC timer running, so we start processing of Hyper-V SynIC timers in vcpu context and stop the Hyper-V SynIC timer uncoditionally and lose time expiration which Windows 2012R2 guest expects. The patch fixes such situation by not stopping Hyper-V SynIC timer at all, because it's safe to restart it without stop in vcpu context and timer callback always returns HRTIMER_NORESTART. Can you summarize with a "picture" what is the bad race? Currently I see that guest starts periodic timer and doesn't clear message slot after timer expires, so timer expires again and trying to deliver expiration message but message slot is still busy so we set ->msg_pending flag for guest to receive EOM. timer restarts again and while it's not expired guest notifies us with EOM, in this case we schedule timer processing in vcpu context by KVM_REQ_HV_STIMER, kvm_hv_process_stimers() is called in vcpu context and stops the timer before it expires, so timer is disabled forever but guest expects it's periodic expiration(15ms). I do not understand why Windows doesn't clear message slot for a long time, it's likely need to be analyzed with debugger(and need more research). But we can go out from such situation by such fix. The patch seems safe, but I'd like to have a better understanding of what goes wrong. Paolo
[Qemu-devel] [PATCH v2 1/3] lib/x86: Make free_page() available to call
This will be used to release allocated pages by Hyper-V SynIC timers test. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- lib/x86/vm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/x86/vm.h b/lib/x86/vm.h index bd73840..28794d7 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -33,6 +33,7 @@ unsigned long *install_pte(unsigned long *cr3, unsigned long *pt_page); void *alloc_page(); +void free_page(void *page); unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, void *virt); -- 2.4.3
[Qemu-devel] [PATCH v2 0/3] KVM-UNIT-TESTS: Hyper-V SynIC timers test
The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Changes v2: * Share generic Hyper-V tests code * Hyper-V SynIC timers test fixes to improve readability and output Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (3): lib/x86: Make free_page() available to call x86/hyperv: Move Hyper-V generic code into hyperv.h/hyperv.c x86: Hyper-V SynIC timers test config/config-x86-common.mak | 8 +- lib/x86/msr.h| 23 --- lib/x86/vm.h | 1 + x86/hyperv.c | 24 +++ x86/hyperv.h | 183 + x86/hyperv_stimer.c | 376 +++ x86/hyperv_synic.c | 42 + x86/unittests.cfg| 5 + 8 files changed, 603 insertions(+), 59 deletions(-) create mode 100644 x86/hyperv.c create mode 100644 x86/hyperv.h create mode 100644 x86/hyperv_stimer.c -- 2.4.3
[Qemu-devel] [PATCH v2 2/3] x86/hyperv: Move Hyper-V generic code into hyperv.h/hyperv.c
This code will be used as shared between hyperv_synic and hyperv_stimer tests. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- config/config-x86-common.mak | 3 ++- lib/x86/msr.h| 23 -- x86/hyperv.c | 24 ++ x86/hyperv.h | 58 x86/hyperv_synic.c | 42 ++-- 5 files changed, 92 insertions(+), 58 deletions(-) create mode 100644 x86/hyperv.c create mode 100644 x86/hyperv.h diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak index f64874d..156be1c 100644 --- a/config/config-x86-common.mak +++ b/config/config-x86-common.mak @@ -113,7 +113,8 @@ $(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.o $(TEST_DIR)/memory.elf: $(cstart.o) $(TEST_DIR)/memory.o -$(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv_synic.o +$(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ + $(TEST_DIR)/hyperv_synic.o arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 54da420..281255a 100644 --- a/lib/x86/msr.h +++ b/lib/x86/msr.h @@ -408,27 +408,4 @@ #define MSR_VM_IGNNE0xc0010115 #define MSR_VM_HSAVE_PA 0xc0010117 -/* Define synthetic interrupt controller model specific registers. */ -#define HV_X64_MSR_SCONTROL 0x4080 -#define HV_X64_MSR_SVERSION 0x4081 -#define HV_X64_MSR_SIEFP0x4082 -#define HV_X64_MSR_SIMP 0x4083 -#define HV_X64_MSR_EOM 0x4084 -#define HV_X64_MSR_SINT00x4090 -#define HV_X64_MSR_SINT10x4091 -#define HV_X64_MSR_SINT20x4092 -#define HV_X64_MSR_SINT30x4093 -#define HV_X64_MSR_SINT40x4094 -#define HV_X64_MSR_SINT50x4095 -#define HV_X64_MSR_SINT60x4096 -#define HV_X64_MSR_SINT70x4097 -#define HV_X64_MSR_SINT80x4098 -#define HV_X64_MSR_SINT90x4099 -#define HV_X64_MSR_SINT10 0x409A -#define HV_X64_MSR_SINT11 0x409B -#define HV_X64_MSR_SINT12 0x409C -#define HV_X64_MSR_SINT13 0x409D -#define HV_X64_MSR_SINT14 0x409E -#define HV_X64_MSR_SINT15 0x409F - #endif /* _ASM_X86_MSR_INDEX_H */ diff --git a/x86/hyperv.c b/x86/hyperv.c new file mode 100644 index 000..824773d --- /dev/null +++ b/x86/hyperv.c @@ -0,0 +1,24 @@ +#include "hyperv.h" + +static void synic_ctl(u8 ctl, u8 vcpu_id, u8 sint) +{ +outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000); +} + +void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi) +{ +wrmsr(HV_X64_MSR_SINT0 + sint, + (u64)vec | ((auto_eoi) ? HV_SYNIC_SINT_AUTO_EOI : 0)); +synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, vcpu, sint); +} + +void synic_sint_set(int vcpu, int sint) +{ +synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint); +} + +void synic_sint_destroy(int vcpu, int sint) +{ +wrmsr(HV_X64_MSR_SINT0 + sint, 0xFF|HV_SYNIC_SINT_MASKED); +synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, vcpu, sint); +} diff --git a/x86/hyperv.h b/x86/hyperv.h new file mode 100644 index 000..0dd1d0d --- /dev/null +++ b/x86/hyperv.h @@ -0,0 +1,58 @@ +#ifndef __HYPERV_H +#define __HYPERV_H + +#include "libcflat.h" +#include "processor.h" +#include "io.h" + +#define HYPERV_CPUID_FEATURES 0x4003 + +#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) + +/* Define synthetic interrupt controller model specific registers. */ +#define HV_X64_MSR_SCONTROL 0x4080 +#define HV_X64_MSR_SVERSION 0x4081 +#define HV_X64_MSR_SIEFP0x4082 +#define HV_X64_MSR_SIMP 0x4083 +#define HV_X64_MSR_EOM 0x4084 +#define HV_X64_MSR_SINT00x4090 +#define HV_X64_MSR_SINT10x4091 +#define HV_X64_MSR_SINT20x4092 +#define HV_X64_MSR_SINT30x4093 +#define HV_X64_MSR_SINT40x4094 +#define HV_X64_MSR_SINT50x4095 +#define HV_X64_MSR_SINT60x40
[Qemu-devel] [PATCH v2 3/3] x86: Hyper-V SynIC timers test
The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Changes v2: * reorg code to use generic hyperv.h * split timer test into test cases with separate callbacks * removed unnecessary irq_enable() calls * moved sint's create/destoy into test prepare/cleanup callbacks * defined used sint's numbers and vectors Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- config/config-x86-common.mak | 5 +- x86/hyperv.h | 125 ++ x86/hyperv_stimer.c | 376 +++ x86/unittests.cfg| 5 + 4 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 x86/hyperv_stimer.c diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak index 156be1c..72b95e3 100644 --- a/config/config-x86-common.mak +++ b/config/config-x86-common.mak @@ -37,7 +37,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ - $(TEST_DIR)/hyperv_synic.flat + $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ ifdef API tests-common += api/api-sample @@ -116,6 +116,9 @@ $(TEST_DIR)/memory.elf: $(cstart.o) $(TEST_DIR)/memory.o $(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ $(TEST_DIR)/hyperv_synic.o +$(TEST_DIR)/hyperv_stimer.elf: $(cstart.o) $(TEST_DIR)/hyperv.o \ + $(TEST_DIR)/hyperv_stimer.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d lib/x86/.*.d diff --git a/x86/hyperv.h b/x86/hyperv.h index 0dd1d0d..faf931b 100644 --- a/x86/hyperv.h +++ b/x86/hyperv.h @@ -7,7 +7,11 @@ #define HYPERV_CPUID_FEATURES 0x4003 +#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1) #define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) +#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3) + +#define HV_X64_MSR_TIME_REF_COUNT 0x4020 /* Define synthetic interrupt controller model specific registers. */ #define HV_X64_MSR_SCONTROL 0x4080 @@ -32,6 +36,19 @@ #define HV_X64_MSR_SINT14 0x409E #define HV_X64_MSR_SINT15 0x409F +/* + * Synthetic Timer MSRs. Four timers per vcpu. + */ + +#define HV_X64_MSR_STIMER0_CONFIG 0x40B0 +#define HV_X64_MSR_STIMER0_COUNT0x40B1 +#define HV_X64_MSR_STIMER1_CONFIG 0x40B2 +#define HV_X64_MSR_STIMER1_COUNT0x40B3 +#define HV_X64_MSR_STIMER2_CONFIG 0x40B4 +#define HV_X64_MSR_STIMER2_COUNT0x40B5 +#define HV_X64_MSR_STIMER3_CONFIG 0x40B6 +#define HV_X64_MSR_STIMER3_COUNT0x40B7 + #define HV_SYNIC_CONTROL_ENABLE (1ULL << 0) #define HV_SYNIC_SIMP_ENABLE(1ULL << 0) #define HV_SYNIC_SIEFP_ENABLE (1ULL << 0) @@ -40,6 +57,104 @@ #define HV_SYNIC_SINT_VECTOR_MASK (0xFF) #define HV_SYNIC_SINT_COUNT 16 +#define HV_STIMER_ENABLE(1ULL << 0) +#define HV_STIMER_PERIODIC (1ULL << 1) +#define HV_STIMER_LAZY (1ULL << 2) +#define HV_STIMER_AUTOENABLE(1ULL << 3) +#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F) + +#define HV_SYNIC_STIMER_COUNT (4) + +/* Define synthetic interrupt controller message constants. */ +#define HV_MESSAGE_SIZE (256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +enum hv_message_type { +HVMSG_NONE = 0x, + +/* Memory access messages. */ +HVMSG_UNMAPPED_GPA = 0x8000, +HVMSG_GPA_INTERCEPT = 0x8001, + +/* Timer notification messages. */ +HVMSG_TIMER_EXPIRED = 0x8010, + +/* Error messages. */ +HVMSG_INVALID_VP_REGISTER_VALUE = 0x8020, +HVMSG_UNRECOVERABLE_EXCEPTION = 0x8021, +HVMSG_UNSUPPORTED_FEATURE = 0x8022, + +/* Trace buffer complete messages. */ +
[Qemu-devel] [PATCH v2 0/9] KVM: Hyper-V SynIC timers
Per Hyper-V specification (and as required by Hyper-V-aware guests), SynIC provides 4 per-vCPU timers. Each timer is programmed via a pair of MSRs, and signals expiration by delivering a special format message to the configured SynIC message slot and triggering the corresponding synthetic interrupt. Note: as implemented by this patch, all periodic timers are "lazy" (i.e. if the vCPU wasn't scheduled for more than the timer period the timer events are lost), regardless of the corresponding configuration MSR. If deemed necessary, the "catch up" mode (the timer period is shortened until the timer catches up) will be implemented later. The Hyper-V SynIC timers support is required to load winhv.sys inside Windows guest on which guest VMBus devices depends on. This patches depends on Hyper-V SynIC patches previosly sent. Changes v2: * Hyper-V headers patches split and fixes * Use remainder to calculate peridic timer expiration time Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (9): drivers/hv: Replace enum hv_message_type by u32 drivers/hv: Move HV_SYNIC_STIMER_COUNT into Hyper-V UAPI x86 header drivers/hv: Move struct hv_message into UAPI Hyper-V x86 header drivers/hv: Move struct hv_timer_message_payload into UAPI Hyper-V x86 header kvm/x86: Rearrange func's declarations inside Hyper-V header kvm/x86: Added Hyper-V vcpu_to_hv_vcpu()/hv_vcpu_to_vcpu() helpers kvm/x86: Hyper-V internal helper to read MSR HV_X64_MSR_TIME_REF_COUNT kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack kvm/x86: Hyper-V SynIC timers arch/x86/include/asm/kvm_host.h| 13 ++ arch/x86/include/uapi/asm/hyperv.h | 90 ++ arch/x86/kvm/hyperv.c | 360 - arch/x86/kvm/hyperv.h | 54 -- arch/x86/kvm/x86.c | 9 + drivers/hv/hv.c| 4 +- drivers/hv/hyperv_vmbus.h | 92 +- include/linux/kvm_host.h | 3 + 8 files changed, 516 insertions(+), 109 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v2 5/9] kvm/x86: Rearrange func's declarations inside Hyper-V header
This rearrangement places functions declarations together according to their functionality, so future additions will be simplier. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.h | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index 315af4b..9483d49 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -24,14 +24,6 @@ #ifndef __ARCH_X86_KVM_HYPERV_H__ #define __ARCH_X86_KVM_HYPERV_H__ -int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); -int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); -bool kvm_hv_hypercall_enabled(struct kvm *kvm); -int kvm_hv_hypercall(struct kvm_vcpu *vcpu); - -int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vcpu_id, u32 sint); -void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector); - static inline struct kvm_vcpu_hv_synic *vcpu_to_synic(struct kvm_vcpu *vcpu) { return >arch.hyperv.synic; @@ -46,10 +38,18 @@ static inline struct kvm_vcpu *synic_to_vcpu(struct kvm_vcpu_hv_synic *synic) arch = container_of(hv, struct kvm_vcpu_arch, hyperv); return container_of(arch, struct kvm_vcpu, arch); } -void kvm_hv_irq_routing_update(struct kvm *kvm); -void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); +int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); +int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); + +bool kvm_hv_hypercall_enabled(struct kvm *kvm); +int kvm_hv_hypercall(struct kvm_vcpu *vcpu); +void kvm_hv_irq_routing_update(struct kvm *kvm); +int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vcpu_id, u32 sint); +void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector); int kvm_hv_activate_synic(struct kvm_vcpu *vcpu); +void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); + #endif -- 2.4.3
[Qemu-devel] [PATCH v2 7/9] kvm/x86: Hyper-V internal helper to read MSR HV_X64_MSR_TIME_REF_COUNT
This helper will be used also in Hyper-V SynIC timers implementation. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 41869a9..9958926 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -335,6 +335,11 @@ static void synic_init(struct kvm_vcpu_hv_synic *synic) } } +static u64 get_time_ref_counter(struct kvm *kvm) +{ + return div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); +} + void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) { synic_init(vcpu_to_synic(vcpu)); @@ -576,11 +581,9 @@ static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case HV_X64_MSR_HYPERCALL: data = hv->hv_hypercall; break; - case HV_X64_MSR_TIME_REF_COUNT: { - data = -div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); + case HV_X64_MSR_TIME_REF_COUNT: + data = get_time_ref_counter(kvm); break; - } case HV_X64_MSR_REFERENCE_TSC: data = hv->hv_tsc_page; break; -- 2.4.3
[Qemu-devel] [PATCH v2 4/9] drivers/hv: Move struct hv_timer_message_payload into UAPI Hyper-V x86 header
This struct is required for Hyper-V SynIC timers implementation inside KVM and for upcoming Hyper-V VMBus support by userspace(QEMU). So place it into Hyper-V UAPI header. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 8 drivers/hv/hyperv_vmbus.h | 9 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 76e503d..42278f8 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -345,4 +345,12 @@ struct hv_message_page { struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; }; +/* Define timer message payload structure. */ +struct hv_timer_message_payload { + __u32 timer_index; + __u32 reserved; + __u64 expiration_time; /* When the timer expired */ + __u64 delivery_time;/* When the message was delivered */ +}; + #endif diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 3f3756b..db60080 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -136,15 +136,6 @@ union hv_timer_config { }; }; - -/* Define timer message payload structure. */ -struct hv_timer_message_payload { - u32 timer_index; - u32 reserved; - u64 expiration_time;/* When the timer expired */ - u64 delivery_time; /* When the message was delivered */ -}; - /* Define the number of message buffers associated with each port. */ #define HV_PORT_MESSAGE_BUFFER_COUNT (16) -- 2.4.3
[Qemu-devel] [PATCH v2 9/9] kvm/x86: Hyper-V SynIC timers
Per Hyper-V specification (and as required by Hyper-V-aware guests), SynIC provides 4 per-vCPU timers. Each timer is programmed via a pair of MSRs, and signals expiration by delivering a special format message to the configured SynIC message slot and triggering the corresponding synthetic interrupt. Note: as implemented by this patch, all periodic timers are "lazy" (i.e. if the vCPU wasn't scheduled for more than the timer period the timer events are lost), regardless of the corresponding configuration MSR. If deemed necessary, the "catch up" mode (the timer period is shortened until the timer catches up) will be implemented later. Changes v2: * Use remainder to calculate periodic timer expiration time Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/asm/kvm_host.h| 13 ++ arch/x86/include/uapi/asm/hyperv.h | 6 + arch/x86/kvm/hyperv.c | 318 - arch/x86/kvm/hyperv.h | 24 +++ arch/x86/kvm/x86.c | 9 ++ include/linux/kvm_host.h | 1 + 6 files changed, 368 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 8140077..a7c8987 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -379,6 +379,17 @@ struct kvm_mtrr { struct list_head head; }; +/* Hyper-V SynIC timer */ +struct kvm_vcpu_hv_stimer { + struct hrtimer timer; + int index; + u64 config; + u64 count; + u64 exp_time; + struct hv_message msg; + bool msg_pending; +}; + /* Hyper-V synthetic interrupt controller (SynIC)*/ struct kvm_vcpu_hv_synic { u64 version; @@ -398,6 +409,8 @@ struct kvm_vcpu_hv { s64 runtime_offset; struct kvm_vcpu_hv_synic synic; struct kvm_hyperv_exit exit; + struct kvm_vcpu_hv_stimer stimer[HV_SYNIC_STIMER_COUNT]; + DECLARE_BITMAP(stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT); }; struct kvm_vcpu_arch { diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 42278f8..71fce3f 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -353,4 +353,10 @@ struct hv_timer_message_payload { __u64 delivery_time;/* When the message was delivered */ }; +#define HV_STIMER_ENABLE (1ULL << 0) +#define HV_STIMER_PERIODIC (1ULL << 1) +#define HV_STIMER_LAZY (1ULL << 2) +#define HV_STIMER_AUTOENABLE (1ULL << 3) +#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F) + #endif diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 6412b6b..8ff8829 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -147,15 +147,32 @@ static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint) { struct kvm *kvm = vcpu->kvm; struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu); - int gsi, idx; + struct kvm_vcpu_hv *hv_vcpu = vcpu_to_hv_vcpu(vcpu); + struct kvm_vcpu_hv_stimer *stimer; + int gsi, idx, stimers_pending; vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint); if (synic->msg_page & HV_SYNIC_SIMP_ENABLE) synic_clear_sint_msg_pending(synic, sint); + /* Try to deliver pending Hyper-V SynIC timers messages */ + stimers_pending = 0; + for (idx = 0; idx < ARRAY_SIZE(hv_vcpu->stimer); idx++) { + stimer = _vcpu->stimer[idx]; + if (stimer->msg_pending && + (stimer->config & HV_STIMER_ENABLE) && + HV_STIMER_SINT(stimer->config) == sint) { + set_bit(stimer->index, + hv_vcpu->stimer_pending_bitmap); + stimers_pending++; + } + } + if (stimers_pending) + kvm_make_request(KVM_REQ_HV_STIMER, vcpu); + idx = srcu_read_lock(>irq_srcu); - gsi = atomic_read(_to_synic(vcpu)->sint_to_gsi[sint]); + gsi = atomic_read(>sint_to_gsi[sint]); if (gsi != -1) kvm_notify_acked_gsi(kvm, gsi); srcu_read_unlock(>irq_srcu, idx); @@ -371,9 +388,268 @@ static u64 get_time_ref_counter(struct kvm *kvm) return div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); } +static void stimer_mark_expired(struct kv
[Qemu-devel] [PATCH v2 2/9] drivers/hv: Move HV_SYNIC_STIMER_COUNT into Hyper-V UAPI x86 header
This constant is required for Hyper-V SynIC timers MSR's support by userspace(QEMU). Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: K. Y. Srinivasan <k...@microsoft.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 2 ++ drivers/hv/hyperv_vmbus.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 040d408..07981f0 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -269,4 +269,6 @@ typedef struct _HV_REFERENCE_TSC_PAGE { #define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17) #define HV_SYNIC_SINT_VECTOR_MASK (0xFF) +#define HV_SYNIC_STIMER_COUNT (4) + #endif diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index e46e18c..f214e37 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -100,8 +100,6 @@ enum hv_cpuid_function { #define HVMSG_X64_APIC_EOI 0x80010004 #define HVMSG_X64_LEGACY_FP_ERROR 0x80010005 -#define HV_SYNIC_STIMER_COUNT (4) - /* Define invalid partition identifier. */ #define HV_PARTITION_ID_INVALID((u64)0x0) -- 2.4.3
[Qemu-devel] [PATCH v2 6/9] kvm/x86: Added Hyper-V vcpu_to_hv_vcpu()/hv_vcpu_to_vcpu() helpers
Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.h | 20 ++-- 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index 9483d49..d5d8217 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -24,21 +24,29 @@ #ifndef __ARCH_X86_KVM_HYPERV_H__ #define __ARCH_X86_KVM_HYPERV_H__ -static inline struct kvm_vcpu_hv_synic *vcpu_to_synic(struct kvm_vcpu *vcpu) +static inline struct kvm_vcpu_hv *vcpu_to_hv_vcpu(struct kvm_vcpu *vcpu) { - return >arch.hyperv.synic; + return >arch.hyperv; } -static inline struct kvm_vcpu *synic_to_vcpu(struct kvm_vcpu_hv_synic *synic) +static inline struct kvm_vcpu *hv_vcpu_to_vcpu(struct kvm_vcpu_hv *hv_vcpu) { - struct kvm_vcpu_hv *hv; struct kvm_vcpu_arch *arch; - hv = container_of(synic, struct kvm_vcpu_hv, synic); - arch = container_of(hv, struct kvm_vcpu_arch, hyperv); + arch = container_of(hv_vcpu, struct kvm_vcpu_arch, hyperv); return container_of(arch, struct kvm_vcpu, arch); } +static inline struct kvm_vcpu_hv_synic *vcpu_to_synic(struct kvm_vcpu *vcpu) +{ + return >arch.hyperv.synic; +} + +static inline struct kvm_vcpu *synic_to_vcpu(struct kvm_vcpu_hv_synic *synic) +{ + return hv_vcpu_to_vcpu(container_of(synic, struct kvm_vcpu_hv, synic)); +} + int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); -- 2.4.3
[Qemu-devel] [PATCH v2 3/9] drivers/hv: Move struct hv_message into UAPI Hyper-V x86 header
This struct is required for Hyper-V SynIC timers implementation inside KVM and for upcoming Hyper-V VMBus support by userspace(QEMU). So place it into Hyper-V UAPI header. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Acked-by: K. Y. Srinivasan <k...@microsoft.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 74 ++ drivers/hv/hyperv_vmbus.h | 73 - 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 07981f0..76e503d 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -271,4 +271,78 @@ typedef struct _HV_REFERENCE_TSC_PAGE { #define HV_SYNIC_STIMER_COUNT (4) +/* Define synthetic interrupt controller message constants. */ +#define HV_MESSAGE_SIZE(256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +#define HVMSG_NONE 0x + +/* Memory access messages. */ +#define HVMSG_UNMAPPED_GPA 0x8000 +#define HVMSG_GPA_INTERCEPT0x8001 + +/* Timer notification messages. */ +#define HVMSG_TIMER_EXPIRED0x8010 + +/* Error messages. */ +#define HVMSG_INVALID_VP_REGISTER_VALUE0x8020 +#define HVMSG_UNRECOVERABLE_EXCEPTION 0x8021 +#define HVMSG_UNSUPPORTED_FEATURE 0x8022 + +/* Trace buffer complete messages. */ +#define HVMSG_EVENTLOG_BUFFERCOMPLETE 0x8040 + +/* Platform-specific processor intercept messages. */ +#define HVMSG_X64_IOPORT_INTERCEPT 0x8001 +#define HVMSG_X64_MSR_INTERCEPT0x80010001 +#define HVMSG_X64_CPUID_INTERCEPT 0x80010002 +#define HVMSG_X64_EXCEPTION_INTERCEPT 0x80010003 +#define HVMSG_X64_APIC_EOI 0x80010004 +#define HVMSG_X64_LEGACY_FP_ERROR 0x80010005 + +/* Define synthetic interrupt controller message flags. */ +union hv_message_flags { + __u8 asu8; + struct { + __u8 msg_pending:1; + __u8 reserved:7; + }; +}; + +/* Define port identifier type. */ +union hv_port_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } u; +}; + +/* Define synthetic interrupt controller message header. */ +struct hv_message_header { + __u32 message_type; + __u8 payload_size; + union hv_message_flags message_flags; + __u8 reserved[2]; + union { + __u64 sender; + union hv_port_id port; + }; +}; + +/* Define synthetic interrupt controller message format. */ +struct hv_message { + struct hv_message_header header; + union { + __u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; + } u; +}; + +/* Define the synthetic interrupt message page layout. */ +struct hv_message_page { + struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; +}; + #endif diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index f214e37..3f3756b 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -63,10 +63,6 @@ enum hv_cpuid_function { /* Define version of the synthetic interrupt controller. */ #define HV_SYNIC_VERSION (1) -/* Define synthetic interrupt controller message constants. */ -#define HV_MESSAGE_SIZE(256) -#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) -#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) #define HV_ANY_VP (0x) /* Define synthetic interrupt controller flag constants. */ @@ -74,44 +70,9 @@ enum hv_cpuid_function { #define HV_EVENT_FLAGS_BYTE_COUNT (256) #define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(u32)) -/* Define hypervisor message types. */ -#define HVMSG_NONE 0x - -/* Memory access messages. */ -#define HVMSG_UNMAPPED_GPA 0x8000 -#define HVMSG_GPA_INTERCEPT0x8001 - -/* Timer notification messages. */ -#define HVMSG_TIMER_EXPIRED0x8010 - -/* Error messages. */ -#define HVMSG_INVALID_VP_REGISTER_VALUE0x8020 -#define HVMSG_UNRECOVERABLE_EXCEPTION 0x8021 -#define HVMSG_UNSUPPORTED_FEATURE 0x8022 - -/* Trace buffer complete messages. */ -#define HVMSG_EVENTLOG_BUFFERCOMPLETE 0x8040 - -/* Platform-specific processor intercept messages. */ -#define HVMSG_X64_IOPORT_INTERCEPT 0x800100
[Qemu-devel] [PATCH v2 1/9] drivers/hv: replace enum hv_message_type by u32
enum hv_message_type inside struct hv_message, hv_post_message is not size portable. Replace enum by u32. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- drivers/hv/hv.c | 4 ++-- drivers/hv/hyperv_vmbus.h | 48 +++ 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 6341be8..dde7e1c 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -310,8 +310,8 @@ void hv_cleanup(void) * This involves a hypercall. */ int hv_post_message(union hv_connection_id connection_id, - enum hv_message_type message_type, - void *payload, size_t payload_size) + u32 message_type, + void *payload, size_t payload_size) { struct hv_input_post_message *aligned_msg; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 3782636..e46e18c 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -75,32 +75,30 @@ enum hv_cpuid_function { #define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(u32)) /* Define hypervisor message types. */ -enum hv_message_type { - HVMSG_NONE = 0x, +#define HVMSG_NONE 0x - /* Memory access messages. */ - HVMSG_UNMAPPED_GPA = 0x8000, - HVMSG_GPA_INTERCEPT = 0x8001, +/* Memory access messages. */ +#define HVMSG_UNMAPPED_GPA 0x8000 +#define HVMSG_GPA_INTERCEPT0x8001 - /* Timer notification messages. */ - HVMSG_TIMER_EXPIRED = 0x8010, +/* Timer notification messages. */ +#define HVMSG_TIMER_EXPIRED0x8010 - /* Error messages. */ - HVMSG_INVALID_VP_REGISTER_VALUE = 0x8020, - HVMSG_UNRECOVERABLE_EXCEPTION = 0x8021, - HVMSG_UNSUPPORTED_FEATURE = 0x8022, +/* Error messages. */ +#define HVMSG_INVALID_VP_REGISTER_VALUE0x8020 +#define HVMSG_UNRECOVERABLE_EXCEPTION 0x8021 +#define HVMSG_UNSUPPORTED_FEATURE 0x8022 - /* Trace buffer complete messages. */ - HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x8040, +/* Trace buffer complete messages. */ +#define HVMSG_EVENTLOG_BUFFERCOMPLETE 0x8040 - /* Platform-specific processor intercept messages. */ - HVMSG_X64_IOPORT_INTERCEPT = 0x8001, - HVMSG_X64_MSR_INTERCEPT = 0x80010001, - HVMSG_X64_CPUID_INTERCEPT = 0x80010002, - HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, - HVMSG_X64_APIC_EOI = 0x80010004, - HVMSG_X64_LEGACY_FP_ERROR = 0x80010005 -}; +/* Platform-specific processor intercept messages. */ +#define HVMSG_X64_IOPORT_INTERCEPT 0x8001 +#define HVMSG_X64_MSR_INTERCEPT0x80010001 +#define HVMSG_X64_CPUID_INTERCEPT 0x80010002 +#define HVMSG_X64_EXCEPTION_INTERCEPT 0x80010003 +#define HVMSG_X64_APIC_EOI 0x80010004 +#define HVMSG_X64_LEGACY_FP_ERROR 0x80010005 #define HV_SYNIC_STIMER_COUNT (4) @@ -174,7 +172,7 @@ union hv_message_flags { /* Define synthetic interrupt controller message header. */ struct hv_message_header { - enum hv_message_type message_type; + u32 message_type; u8 payload_size; union hv_message_flags message_flags; u8 reserved[2]; @@ -347,7 +345,7 @@ enum hv_call_code { struct hv_input_post_message { union hv_connection_id connectionid; u32 reserved; - enum hv_message_type message_type; + u32 message_type; u32 payload_size; u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; }; @@ -579,8 +577,8 @@ extern int hv_init(void); extern void hv_cleanup(void); extern int hv_post_message(union hv_connection_id connection_id, -enum hv_message_type message_type, -void *payload, size_t payload_size); + u32 message_type, + void *payload, size_t payload_size); extern u16 hv_signal_event(void *con_id); -- 2.4.3
[Qemu-devel] [PATCH v2 8/9] kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack
The SynIC message protocol mandates that the message slot is claimed by atomically setting message type to something other than HVMSG_NONE. If another message is to be delivered while the slot is still busy, message pending flag is asserted to indicate to the guest that the hypervisor wants to be notified when the slot is released. To make sure the protocol works regardless of where the message sources are (kernel or userspace), clear the pending flag on SINT ACK notification, and let the message sources compete for the slot again. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c| 31 +++ include/linux/kvm_host.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 9958926..6412b6b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -27,6 +27,7 @@ #include "hyperv.h" #include +#include #include #include @@ -116,13 +117,43 @@ static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vcpu_id) return (synic->active) ? synic : NULL; } +static void synic_clear_sint_msg_pending(struct kvm_vcpu_hv_synic *synic, + u32 sint) +{ + struct kvm_vcpu *vcpu = synic_to_vcpu(synic); + struct page *page; + gpa_t gpa; + struct hv_message *msg; + struct hv_message_page *msg_page; + + gpa = synic->msg_page & PAGE_MASK; + page = kvm_vcpu_gfn_to_page(vcpu, gpa >> PAGE_SHIFT); + if (is_error_page(page)) { + vcpu_err(vcpu, "Hyper-V SynIC can't get msg page, gpa 0x%llx\n", +gpa); + return; + } + msg_page = kmap_atomic(page); + + msg = _page->sint_message[sint]; + msg->header.message_flags.msg_pending = 0; + + kunmap_atomic(msg_page); + kvm_release_page_dirty(page); + kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT); +} + static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint) { struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu); int gsi, idx; vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint); + if (synic->msg_page & HV_SYNIC_SIMP_ENABLE) + synic_clear_sint_msg_pending(synic, sint); + idx = srcu_read_lock(>irq_srcu); gsi = atomic_read(_to_synic(vcpu)->sint_to_gsi[sint]); if (gsi != -1) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2911919..9b64c8c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -450,6 +450,8 @@ struct kvm { #define vcpu_debug(vcpu, fmt, ...) \ kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) +#define vcpu_err(vcpu, fmt, ...) \ + kvm_err("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) { -- 2.4.3
Re: [Qemu-devel] [PATCH v1 2/7] drivers/hv: Move struct hv_message into UAPI Hyper-V x86 header
On 11/27/2015 12:34 PM, Paolo Bonzini wrote: On 25/11/2015 16:20, Andrey Smetanin wrote: This struct is required for Hyper-V SynIC timers implementation inside KVM and for upcoming Hyper-V VMBus support by userspace(QEMU). So place it into Hyper-V UAPI header. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/include/uapi/asm/hyperv.h | 91 ++ drivers/hv/hyperv_vmbus.h | 91 -- 2 files changed, 91 insertions(+), 91 deletions(-) diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index 07981f0..e86d77e 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -271,4 +271,95 @@ typedef struct _HV_REFERENCE_TSC_PAGE { #define HV_SYNIC_STIMER_COUNT (4) +/* Define synthetic interrupt controller message constants. */ +#define HV_MESSAGE_SIZE(256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +enum hv_message_type { + HVMSG_NONE = 0x, + + /* Memory access messages. */ + HVMSG_UNMAPPED_GPA = 0x8000, + HVMSG_GPA_INTERCEPT = 0x8001, + + /* Timer notification messages. */ + HVMSG_TIMER_EXPIRED = 0x8010, + + /* Error messages. */ + HVMSG_INVALID_VP_REGISTER_VALUE = 0x8020, + HVMSG_UNRECOVERABLE_EXCEPTION = 0x8021, + HVMSG_UNSUPPORTED_FEATURE = 0x8022, + + /* Trace buffer complete messages. */ + HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x8040, + + /* Platform-specific processor intercept messages. */ + HVMSG_X64_IOPORT_INTERCEPT = 0x8001, + HVMSG_X64_MSR_INTERCEPT = 0x80010001, + HVMSG_X64_CPUID_INTERCEPT = 0x80010002, + HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, + HVMSG_X64_APIC_EOI = 0x80010004, + HVMSG_X64_LEGACY_FP_ERROR = 0x80010005 +}; + +/* Define synthetic interrupt controller message flags. */ +union hv_message_flags { + __u8 asu8; + struct { + __u8 msg_pending:1; + __u8 reserved:7; + }; +}; + +/* Define port identifier type. */ +union hv_port_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } u; +}; + +/* Define port type. */ +enum hv_port_type { + HVPORT_MSG = 1, + HVPORT_EVENT= 2, + HVPORT_MONITOR = 3 +}; + +/* Define synthetic interrupt controller message header. */ +struct hv_message_header { + enum hv_message_type message_type; Do not declare this as an enum, declare it as __u32 to make the size portable. It can be a patch on top. Ok, I'll prepare such patch. KY, can you ack these two patches? Paolo + __u8 payload_size; + union hv_message_flags message_flags; + __u8 reserved[2]; + union { + __u64 sender; + union hv_port_id port; + }; +}; + +/* Define timer message payload structure. */ +struct hv_timer_message_payload { + __u32 timer_index; + __u32 reserved; + __u64 expiration_time; /* When the timer expired */ + __u64 delivery_time;/* When the message was delivered */ +}; + +/* Define synthetic interrupt controller message format. */ +struct hv_message { + struct hv_message_header header; + union { + __u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; + } u; +}; + +/* Define the synthetic interrupt message page layout. */ +struct hv_message_page { + struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; +}; + #endif diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 46e23d1..d22230c 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -63,10 +63,6 @@ enum hv_cpuid_function { /* Define version of the synthetic interrupt controller. */ #define HV_SYNIC_VERSION (1) -/* Define synthetic interrupt controller message constants. */ -#define HV_MESSAGE_SIZE(256) -#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) -#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) #define HV_ANY_VP (0x) /* Define synthetic interrupt controller flag constants. */ @@ -74,53 +70,9 @@ enum hv_cpuid_function { #define HV_EVENT_FLAGS_BYTE_COUNT
Re: [Qemu-devel] [PATCH v1 0/5] KVM-UNIT-TESTS: Hyper-V SynIC timers test
On 11/27/2015 02:17 PM, Paolo Bonzini wrote: On 26/11/2015 17:29, Andrey Smetanin wrote: The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): lib/x86: Added Hyper-V MSR's availability bits into msr.h lib/x86: Added HV_X64_MSR_TIME_REF_COUNT value into msr.h lib/x86: Added Hyper-V SynIC timers MSR's values lib/x86: Make free_page() available to call x86: Hyper-V SynIC timers test In addition to my comments on 5/5, can you make instead a hyperv.h file with all that you need in the two testcases? Yes, I'll do it. Thanks! Paolo config/config-x86-common.mak | 4 +- lib/x86/msr.h| 19 ++ lib/x86/vm.h | 1 + x86/hyperv_stimer.c | 500 +++ x86/hyperv_synic.c | 2 +- x86/unittests.cfg| 5 + 6 files changed, 529 insertions(+), 2 deletions(-) create mode 100644 x86/hyperv_stimer.c
Re: [Qemu-devel] [PATCH v1 7/7] kvm/x86: Hyper-V SynIC timers
On 11/27/2015 01:49 PM, Paolo Bonzini wrote: On 27/11/2015 09:12, Roman Kagan wrote: + n = div64_u64(time_now - stimer->exp_time, stimer->count) + 1; + stimer->exp_time += n * stimer->count; This is actually just a reminder calculation so I'd rather do it directly with div64_u64_rem(). It took me a while to understand why it was a remained. :) Expanding Andrey's formula you get exp_time = exp_time + count + (time_now - exp_time) / count * count the remainder, (time_now - exp_time) % count would be time_now - exp_time - (time_now - exp_time) / count * count so -((time_now - exp_time) % count) is exp_time - time_now + (time_now - exp_time) / count * count so Andrey's expression is exp_time = time_now + (count - (time_now - exp_time) % count) Yeah, that looks nice. I'll redo this way. Paolo
Re: [Qemu-devel] [PATCH v1 5/5] x86: Hyper-V SynIC timers test
On 11/27/2015 02:17 PM, Paolo Bonzini wrote: The test logic is good, but the glue can be improved a bit so that the output is more useful if it breaks. Thanks for comments below. I'll redo this patch. On 26/11/2015 17:29, Andrey Smetanin wrote: The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- config/config-x86-common.mak | 4 +- x86/hyperv_stimer.c | 500 +++ x86/unittests.cfg| 5 + 3 files changed, 508 insertions(+), 1 deletion(-) create mode 100644 x86/hyperv_stimer.c diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak index f64874d..a75be87 100644 --- a/config/config-x86-common.mak +++ b/config/config-x86-common.mak @@ -37,7 +37,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ - $(TEST_DIR)/hyperv_synic.flat + $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ ifdef API tests-common += api/api-sample @@ -115,6 +115,8 @@ $(TEST_DIR)/memory.elf: $(cstart.o) $(TEST_DIR)/memory.o $(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv_synic.o +$(TEST_DIR)/hyperv_stimer.elf: $(cstart.o) $(TEST_DIR)/hyperv_stimer.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d lib/x86/.*.d diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c new file mode 100644 index 000..e9186ca --- /dev/null +++ b/x86/hyperv_stimer.c @@ -0,0 +1,500 @@ +#include "libcflat.h" +#include "processor.h" +#include "msr.h" +#include "isr.h" +#include "vm.h" +#include "apic.h" +#include "desc.h" +#include "io.h" +#include "smp.h" +#include "atomic.h" + +#define MAX_CPUS 4 +#define HYPERV_CPUID_FEATURES 0x4003 + +#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0) +#define HV_SYNIC_SIMP_ENABLE(1ULL << 0) +#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0) +#define HV_SYNIC_SINT_MASKED(1ULL << 16) +#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17) +#define HV_SYNIC_SINT_VECTOR_MASK (0xFF) +#define HV_SYNIC_SINT_COUNT 16 + +#define HV_STIMER_ENABLE(1ULL << 0) +#define HV_STIMER_PERIODIC (1ULL << 1) +#define HV_STIMER_LAZY (1ULL << 2) +#define HV_STIMER_AUTOENABLE(1ULL << 3) +#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F) + +#define HV_SYNIC_STIMER_COUNT (4) + +/* Define synthetic interrupt controller message constants. */ +#define HV_MESSAGE_SIZE (256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +enum hv_message_type { +HVMSG_NONE = 0x, + +/* Memory access messages. */ +HVMSG_UNMAPPED_GPA = 0x8000, +HVMSG_GPA_INTERCEPT = 0x8001, + +/* Timer notification messages. */ +HVMSG_TIMER_EXPIRED = 0x8010, + +/* Error messages. */ +HVMSG_INVALID_VP_REGISTER_VALUE = 0x8020, +HVMSG_UNRECOVERABLE_EXCEPTION = 0x8021, +HVMSG_UNSUPPORTED_FEATURE = 0x8022, + +/* Trace buffer complete messages. */ +HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x8040, + +/* Platform-specific processor intercept messages. */ +HVMSG_X64_IOPORT_INTERCEPT = 0x8001, +HVMSG_X64_MSR_INTERCEPT = 0x80010001, +HVMSG_X64_CPUID_INTERCEPT = 0x80010002, +HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, +HVMSG_X64_APIC_EOI = 0x80010004, +HVMSG_X64_LEGACY_FP_ERROR = 0x80010005 +}; + +/* Define synthetic interrupt controller message flags. */ +union hv_message_flags { +uint8_t asu8; +struct { +uint8_t msg_pending:1; +uint8_t reserved:7; +}; +}; + +union hv_port_id { +uint32_t asu32; +struct { +
Re: [Qemu-devel] [PATCH v1 0/7] KVM: Hyper-V SynIC timers
On 11/26/2015 08:28 AM, Wanpeng Li wrote: 2015-11-25 23:20 GMT+08:00 Andrey Smetanin <asmeta...@virtuozzo.com>: Per Hyper-V specification (and as required by Hyper-V-aware guests), SynIC provides 4 per-vCPU timers. Each timer is programmed via a pair of MSRs, and signals expiration by delivering a special format message to the configured SynIC message slot and triggering the corresponding synthetic interrupt. Could you post a link for this specification? Official link: http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx and there is a pdf variant(my own docx -> pdf conversion): https://www.dropbox.com/s/ehxictr5wgnedq7/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.pdf?dl=0 Regards, Wanpeng Li
Re: [Qemu-devel] [PATCH v1 6/7] kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack
On 11/25/2015 08:14 PM, Paolo Bonzini wrote: On 25/11/2015 17:55, Andrey Smetanin wrote: +gpa = synic->msg_page & PAGE_MASK; +page = kvm_vcpu_gfn_to_page(vcpu, gpa >> PAGE_SHIFT); +if (is_error_page(page)) { +vcpu_err(vcpu, "Hyper-V SynIC can't get msg page, gpa 0x%llx\n", + gpa); +return; +} +msg_page = kmap_atomic(page); But the message page is not being pinned, is it? Actually I don't know anything about pinning. Is it pinning against page swapping ? Yes. Unless the page is pinned, kmap_atomic can fail. kmap_atomic() can't fail for a valid page struct. Does kvm_vcpu_gfn_to_page() can provide invalid page(swapped page) struct which may pass is_error_page(page) check but can leads to incorrect behavior inside kmap_atomic()? However, I don't think that kvm_hv_notify_acked_sint is called from atomic context. It is only called from apic_set_eoi. Could you just use kvm_vcpu_write_guest_page? In this case I can use kvm_vcpu_write_guest_page(), but in the 'PATCH v1 7/7' I do the same page mapping method to sync_cmpxchg() at guest message page address to exclusively acquire message page slot(see synic_deliver_msg()). So we need some method to map and access atomically memory of guest page in KVM. Does any method to pin and map guest page in kernel exists? Or should we use mlock() for this page in QEMU part ? By the way, do you need to do this also in kvm_get_apic_interrupt, for auto EOI interrupts? No we don't need this because in case of auto EOI interrupts, if ->msg_pending was set, host will receive HV_X64_MSR_EOM write request which calls kvm_hv_notify_acked_sint(). Thanks, Paolo Could you please clarify and provide an API to use in this case ?
Re: [Qemu-devel] [PATCH v1 6/7] kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack
On 11/26/2015 05:43 PM, Paolo Bonzini wrote: On 26/11/2015 10:06, Andrey Smetanin wrote: On 11/25/2015 08:14 PM, Paolo Bonzini wrote: On 25/11/2015 17:55, Andrey Smetanin wrote: +gpa = synic->msg_page & PAGE_MASK; +page = kvm_vcpu_gfn_to_page(vcpu, gpa >> PAGE_SHIFT); +if (is_error_page(page)) { +vcpu_err(vcpu, "Hyper-V SynIC can't get msg page, gpa 0x%llx\n", + gpa); +return; +} +msg_page = kmap_atomic(page); But the message page is not being pinned, is it? Actually I don't know anything about pinning. Is it pinning against page swapping ? Yes. Unless the page is pinned, kmap_atomic can fail. kmap_atomic() can't fail for a valid page struct. Does kvm_vcpu_gfn_to_page() can provide invalid page(swapped page) struct which may pass is_error_page(page) check but can leads to incorrect behavior inside kmap_atomic()? No, you're right. Nevermind, I was confused because I thought you needed kmap_atomic rather than kmap. Here using kmap_atomic is just an optimization, so it's okay. (If you needed kmap_atomic, the problem would have been that kvm_vcpu_gfn_to_page() can sleep). In patch 7/7 you're also not in atomic context, so kvm_vcpu_gfn_to_page is okay. Shouldn't have reviewed the patch when tired. :) Then the patches look good, I think. With a testcase I can try them out and hopefully merge them for Linux 4.5 / QEMU 2.6. Thank you! We already have a working Hyper-V SynIC timers kvm-unit-tests test case. We are going to send appropriate patches seria into kvm-unit-tests git. But kvm-unit-tests master now broken: > make objcopy -O elf32-i386 x86/memory.elf x86/memory.flat make: *** No rule to make target 'x86/pku.o', needed by 'x86/pku.elf'. Stop. The problem is in latest commit 3da70799dd3cf1169c4668b4a3fd6f598528b8b9. The commit adds 'pku' test case building, but not added any pku.c implementation file. [root@asm-pc kvm-unit-tests]# ls -al x86/pku.c ls: cannot access x86/pku.c: No such file or directory Could you please fix it ? Paolo
[Qemu-devel] [PATCH v1 1/5] lib/x86: Added Hyper-V MSR's availability bits into msr.h
Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- lib/x86/msr.h | 4 x86/hyperv_synic.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 54da420..89ed718 100644 --- a/lib/x86/msr.h +++ b/lib/x86/msr.h @@ -408,6 +408,10 @@ #define MSR_VM_IGNNE0xc0010115 #define MSR_VM_HSAVE_PA 0xc0010117 +#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1) +#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) +#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3) + /* Define synthetic interrupt controller model specific registers. */ #define HV_X64_MSR_SCONTROL 0x4080 #define HV_X64_MSR_SVERSION 0x4081 diff --git a/x86/hyperv_synic.c b/x86/hyperv_synic.c index 18d1295..eb141c1 100644 --- a/x86/hyperv_synic.c +++ b/x86/hyperv_synic.c @@ -11,7 +11,7 @@ #define MAX_CPUS 4 #define HYPERV_CPUID_FEATURES 0x4003 -#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) + #define HV_SYNIC_CONTROL_ENABLE (1ULL << 0) #define HV_SYNIC_SIMP_ENABLE(1ULL << 0) #define HV_SYNIC_SIEFP_ENABLE (1ULL << 0) -- 2.4.3
[Qemu-devel] [PATCH v1 3/5] lib/x86: Added Hyper-V SynIC timers MSR's values
Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- lib/x86/msr.h | 13 + 1 file changed, 13 insertions(+) diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 4ac9c71..d3f4198 100644 --- a/lib/x86/msr.h +++ b/lib/x86/msr.h @@ -437,4 +437,17 @@ #define HV_X64_MSR_SINT14 0x409E #define HV_X64_MSR_SINT15 0x409F +/* + * Synthetic Timer MSRs. Four timers per vcpu. + */ + +#define HV_X64_MSR_STIMER0_CONFIG 0x40B0 +#define HV_X64_MSR_STIMER0_COUNT0x40B1 +#define HV_X64_MSR_STIMER1_CONFIG 0x40B2 +#define HV_X64_MSR_STIMER1_COUNT0x40B3 +#define HV_X64_MSR_STIMER2_CONFIG 0x40B4 +#define HV_X64_MSR_STIMER2_COUNT0x40B5 +#define HV_X64_MSR_STIMER3_CONFIG 0x40B6 +#define HV_X64_MSR_STIMER3_COUNT0x40B7 + #endif /* _ASM_X86_MSR_INDEX_H */ -- 2.4.3
[Qemu-devel] [PATCH v1 0/5] KVM-UNIT-TESTS: Hyper-V SynIC timers test
The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (5): lib/x86: Added Hyper-V MSR's availability bits into msr.h lib/x86: Added HV_X64_MSR_TIME_REF_COUNT value into msr.h lib/x86: Added Hyper-V SynIC timers MSR's values lib/x86: Make free_page() available to call x86: Hyper-V SynIC timers test config/config-x86-common.mak | 4 +- lib/x86/msr.h| 19 ++ lib/x86/vm.h | 1 + x86/hyperv_stimer.c | 500 +++ x86/hyperv_synic.c | 2 +- x86/unittests.cfg| 5 + 6 files changed, 529 insertions(+), 2 deletions(-) create mode 100644 x86/hyperv_stimer.c -- 2.4.3
[Qemu-devel] [PATCH v1 2/5] lib/x86: Added HV_X64_MSR_TIME_REF_COUNT value into msr.h
Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- lib/x86/msr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 89ed718..4ac9c71 100644 --- a/lib/x86/msr.h +++ b/lib/x86/msr.h @@ -412,6 +412,8 @@ #define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) #define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3) +#define HV_X64_MSR_TIME_REF_COUNT 0x4020 + /* Define synthetic interrupt controller model specific registers. */ #define HV_X64_MSR_SCONTROL 0x4080 #define HV_X64_MSR_SVERSION 0x4081 -- 2.4.3
[Qemu-devel] [PATCH v1 5/5] x86: Hyper-V SynIC timers test
The test checks Hyper-V SynIC timers functionality. The test runs on every vCPU and performs start/stop of periodic/one-shot timers (with period=1ms) and checks validity of received expiration messages in appropriate ISR's. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- config/config-x86-common.mak | 4 +- x86/hyperv_stimer.c | 500 +++ x86/unittests.cfg| 5 + 3 files changed, 508 insertions(+), 1 deletion(-) create mode 100644 x86/hyperv_stimer.c diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak index f64874d..a75be87 100644 --- a/config/config-x86-common.mak +++ b/config/config-x86-common.mak @@ -37,7 +37,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ - $(TEST_DIR)/hyperv_synic.flat + $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ ifdef API tests-common += api/api-sample @@ -115,6 +115,8 @@ $(TEST_DIR)/memory.elf: $(cstart.o) $(TEST_DIR)/memory.o $(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv_synic.o +$(TEST_DIR)/hyperv_stimer.elf: $(cstart.o) $(TEST_DIR)/hyperv_stimer.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d lib/x86/.*.d diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c new file mode 100644 index 000..e9186ca --- /dev/null +++ b/x86/hyperv_stimer.c @@ -0,0 +1,500 @@ +#include "libcflat.h" +#include "processor.h" +#include "msr.h" +#include "isr.h" +#include "vm.h" +#include "apic.h" +#include "desc.h" +#include "io.h" +#include "smp.h" +#include "atomic.h" + +#define MAX_CPUS 4 +#define HYPERV_CPUID_FEATURES 0x4003 + +#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0) +#define HV_SYNIC_SIMP_ENABLE(1ULL << 0) +#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0) +#define HV_SYNIC_SINT_MASKED(1ULL << 16) +#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17) +#define HV_SYNIC_SINT_VECTOR_MASK (0xFF) +#define HV_SYNIC_SINT_COUNT 16 + +#define HV_STIMER_ENABLE(1ULL << 0) +#define HV_STIMER_PERIODIC (1ULL << 1) +#define HV_STIMER_LAZY (1ULL << 2) +#define HV_STIMER_AUTOENABLE(1ULL << 3) +#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F) + +#define HV_SYNIC_STIMER_COUNT (4) + +/* Define synthetic interrupt controller message constants. */ +#define HV_MESSAGE_SIZE (256) +#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) +#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) + +/* Define hypervisor message types. */ +enum hv_message_type { +HVMSG_NONE = 0x, + +/* Memory access messages. */ +HVMSG_UNMAPPED_GPA = 0x8000, +HVMSG_GPA_INTERCEPT = 0x8001, + +/* Timer notification messages. */ +HVMSG_TIMER_EXPIRED = 0x8010, + +/* Error messages. */ +HVMSG_INVALID_VP_REGISTER_VALUE = 0x8020, +HVMSG_UNRECOVERABLE_EXCEPTION = 0x8021, +HVMSG_UNSUPPORTED_FEATURE = 0x8022, + +/* Trace buffer complete messages. */ +HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x8040, + +/* Platform-specific processor intercept messages. */ +HVMSG_X64_IOPORT_INTERCEPT = 0x8001, +HVMSG_X64_MSR_INTERCEPT = 0x80010001, +HVMSG_X64_CPUID_INTERCEPT = 0x80010002, +HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003, +HVMSG_X64_APIC_EOI = 0x80010004, +HVMSG_X64_LEGACY_FP_ERROR = 0x80010005 +}; + +/* Define synthetic interrupt controller message flags. */ +union hv_message_flags { +uint8_t asu8; +struct { +uint8_t msg_pending:1; +uint8_t reserved:7; +}; +}; + +union hv_port_id { +uint32_t asu32; +struct { +uint32_t id:24; +uint32_t reserved:8; +} u; +}; + +/* Define port type. */ +enum hv_port_type { +HVPORT_MSG = 1, +HVPORT_EVENT= 2, +HVPORT_MONITOR = 3 +}; + +/* Define synthetic interr
[Qemu-devel] [PATCH v1 4/5] lib/x86: Make free_page() available to call
This will be used to release allocated pages by Hyper-V SynIC timers test. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> Reviewed-by: Roman Kagan <rka...@virtuozzo.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- lib/x86/vm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/x86/vm.h b/lib/x86/vm.h index bd73840..28794d7 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -33,6 +33,7 @@ unsigned long *install_pte(unsigned long *cr3, unsigned long *pt_page); void *alloc_page(); +void free_page(void *page); unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, void *virt); -- 2.4.3
[Qemu-devel] [PATCH v1 0/7] KVM: Hyper-V SynIC timers
Per Hyper-V specification (and as required by Hyper-V-aware guests), SynIC provides 4 per-vCPU timers. Each timer is programmed via a pair of MSRs, and signals expiration by delivering a special format message to the configured SynIC message slot and triggering the corresponding synthetic interrupt. Note: as implemented by this patch, all periodic timers are "lazy" (i.e. if the vCPU wasn't scheduled for more than the timer period the timer events are lost), regardless of the corresponding configuration MSR. If deemed necessary, the "catch up" mode (the timer period is shortened until the timer catches up) will be implemented later. The Hyper-V SynIC timers support is required to load winhv.sys inside Windows guest on which guest VMBus devices depends on. This patches depends on Hyper-V SynIC patches previosly sent. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org Andrey Smetanin (7): drivers/hv: Move HV_SYNIC_STIMER_COUNT into Hyper-V UAPI x86 header drivers/hv: Move struct hv_message into UAPI Hyper-V x86 header kvm/x86: Rearrange func's declarations inside Hyper-V header kvm/x86: Added Hyper-V vcpu_to_hv_vcpu()/hv_vcpu_to_vcpu() helpers kvm/x86: Hyper-V internal helper to read MSR HV_X64_MSR_TIME_REF_COUNT kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack kvm/x86: Hyper-V SynIC timers arch/x86/include/asm/kvm_host.h| 13 ++ arch/x86/include/uapi/asm/hyperv.h | 99 ++ arch/x86/kvm/hyperv.c | 367 - arch/x86/kvm/hyperv.h | 54 -- arch/x86/kvm/x86.c | 9 + drivers/hv/hyperv_vmbus.h | 93 -- include/linux/kvm_host.h | 3 + 7 files changed, 527 insertions(+), 111 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH v1 6/7] kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack
The SynIC message protocol mandates that the message slot is claimed by atomically setting message type to something other than HVMSG_NONE. If another message is to be delivered while the slot is still busy, message pending flag is asserted to indicate to the guest that the hypervisor wants to be notified when the slot is released. To make sure the protocol works regardless of where the message sources are (kernel or userspace), clear the pending flag on SINT ACK notification, and let the message sources compete for the slot again. Signed-off-by: Andrey Smetanin <asmeta...@virtuozzo.com> CC: Gleb Natapov <g...@kernel.org> CC: Paolo Bonzini <pbonz...@redhat.com> CC: "K. Y. Srinivasan" <k...@microsoft.com> CC: Haiyang Zhang <haiya...@microsoft.com> CC: Vitaly Kuznetsov <vkuzn...@redhat.com> CC: Roman Kagan <rka...@virtuozzo.com> CC: Denis V. Lunev <d...@openvz.org> CC: qemu-devel@nongnu.org --- arch/x86/kvm/hyperv.c| 31 +++ include/linux/kvm_host.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 9958926..6412b6b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -27,6 +27,7 @@ #include "hyperv.h" #include +#include #include #include @@ -116,13 +117,43 @@ static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vcpu_id) return (synic->active) ? synic : NULL; } +static void synic_clear_sint_msg_pending(struct kvm_vcpu_hv_synic *synic, + u32 sint) +{ + struct kvm_vcpu *vcpu = synic_to_vcpu(synic); + struct page *page; + gpa_t gpa; + struct hv_message *msg; + struct hv_message_page *msg_page; + + gpa = synic->msg_page & PAGE_MASK; + page = kvm_vcpu_gfn_to_page(vcpu, gpa >> PAGE_SHIFT); + if (is_error_page(page)) { + vcpu_err(vcpu, "Hyper-V SynIC can't get msg page, gpa 0x%llx\n", +gpa); + return; + } + msg_page = kmap_atomic(page); + + msg = _page->sint_message[sint]; + msg->header.message_flags.msg_pending = 0; + + kunmap_atomic(msg_page); + kvm_release_page_dirty(page); + kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT); +} + static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint) { struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu); int gsi, idx; vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint); + if (synic->msg_page & HV_SYNIC_SIMP_ENABLE) + synic_clear_sint_msg_pending(synic, sint); + idx = srcu_read_lock(>irq_srcu); gsi = atomic_read(_to_synic(vcpu)->sint_to_gsi[sint]); if (gsi != -1) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2911919..9b64c8c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -450,6 +450,8 @@ struct kvm { #define vcpu_debug(vcpu, fmt, ...) \ kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) +#define vcpu_err(vcpu, fmt, ...) \ + kvm_err("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) { -- 2.4.3