[Qemu-devel] [Bug 1708442] Re: Crash(assert) during reading image from http url through qemu-nbd

2017-08-15 Thread Andrey Smetanin
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

2017-08-03 Thread Andrey Smetanin
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

2017-08-03 Thread Andrey Smetanin
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

2017-08-03 Thread Andrey Smetanin
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

2017-08-03 Thread Andrey Smetanin
** 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

2017-08-03 Thread Andrey Smetanin
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

2016-02-24 Thread Andrey Smetanin
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

2016-02-24 Thread Andrey Smetanin
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

2016-02-12 Thread Andrey Smetanin



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

2016-02-11 Thread Andrey Smetanin
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

2016-02-11 Thread Andrey Smetanin
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

2016-02-11 Thread Andrey Smetanin
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

2016-02-11 Thread Andrey Smetanin
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

2016-02-11 Thread Andrey Smetanin
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

2016-02-11 Thread Andrey Smetanin
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

2016-02-02 Thread Andrey Smetanin

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

2016-01-22 Thread Andrey Smetanin



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

2016-01-22 Thread Andrey Smetanin



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

2016-01-22 Thread Andrey Smetanin



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

2016-01-22 Thread Andrey Smetanin



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

2016-01-22 Thread Andrey Smetanin



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

2016-01-22 Thread Andrey Smetanin



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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-21 Thread Andrey Smetanin
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

2016-01-20 Thread Andrey Smetanin



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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin

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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-12 Thread Andrey Smetanin
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

2016-01-11 Thread Andrey Smetanin

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()

2016-01-07 Thread Andrey Smetanin



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

2016-01-06 Thread Andrey Smetanin



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

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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()

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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

2015-12-28 Thread Andrey Smetanin
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

2015-12-24 Thread Andrey Smetanin
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

2015-12-24 Thread Andrey Smetanin
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

2015-12-24 Thread Andrey Smetanin



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

2015-12-24 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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()

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-23 Thread Andrey Smetanin
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

2015-12-21 Thread Andrey Smetanin



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

2015-12-21 Thread Andrey Smetanin



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 Bonzini  wrote:

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

2015-12-14 Thread Andrey Smetanin
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

2015-12-14 Thread Andrey Smetanin



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

2015-12-14 Thread Andrey Smetanin



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

2015-12-08 Thread Andrey Smetanin
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

2015-12-08 Thread Andrey Smetanin
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

2015-12-08 Thread Andrey Smetanin
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

2015-12-08 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-30 Thread Andrey Smetanin
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

2015-11-27 Thread Andrey Smetanin



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

2015-11-27 Thread Andrey Smetanin



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

2015-11-27 Thread Andrey Smetanin



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

2015-11-27 Thread Andrey Smetanin



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

2015-11-26 Thread Andrey Smetanin



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

2015-11-26 Thread Andrey Smetanin



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

2015-11-26 Thread Andrey Smetanin



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

2015-11-26 Thread Andrey Smetanin
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

2015-11-26 Thread Andrey Smetanin
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

2015-11-26 Thread Andrey Smetanin
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

2015-11-26 Thread Andrey Smetanin
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

2015-11-26 Thread Andrey Smetanin
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

2015-11-26 Thread Andrey Smetanin
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

2015-11-25 Thread Andrey Smetanin
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

2015-11-25 Thread Andrey Smetanin
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




  1   2   >