From 57914ecb069e56ca53fc97a53437bcf684f5cc13 Mon Sep 17 00:00:00 2001 From: Jay Zhou Date: Thu, 4 Jan 2018 13:29:48 +0800 Subject: memory: update comments and fix some typos Signed-off-by: Jay Zhou Message-Id: <1515043788-38300-1-git-send-email-jianjay.zhou@huawei.com> Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/exec/memory.h b/include/exec/memory.h index 07c5d6d597..67e4ee349d 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -324,7 +324,7 @@ FlatView *address_space_to_flatview(AddressSpace *as); * MemoryRegionSection: describes a fragment of a #MemoryRegion * * @mr: the region, or %NULL if empty - * @address_space: the address space the region is mapped in + * @fv: the flat view of the address space the region is mapped in * @offset_within_region: the beginning of the section, relative to @mr's start * @size: the size of the section; will not exceed @mr's boundaries * @offset_within_address_space: the address of the first byte of the section @@ -610,6 +610,7 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr, * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count * @ops: callbacks for write access handling (must not be NULL). + * @opaque: passed to the read and write callbacks of the @ops structure. * @name: Region name, becomes part of RAMBlock name used in migration stream * must be unique within any device * @size: size of the region. @@ -653,11 +654,10 @@ static inline void memory_region_init_reservation(MemoryRegion *mr, * An IOMMU region translates addresses and forwards accesses to a target * memory region. * - * @typename: QOM class name * @_iommu_mr: the #IOMMUMemoryRegion to be initialized * @instance_size: the IOMMUMemoryRegion subclass instance size + * @mrtypename: the type name of the #IOMMUMemoryRegion * @owner: the object that tracks the region's reference count - * @ops: a function that translates addresses into the @target region * @name: used for debugging; not visible to the user or ABI * @size: size of the region. */ @@ -827,8 +827,8 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr) * memory_region_get_iommu_class_nocheck: returns iommu memory region class * if an iommu or NULL if not * - * Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu, - * otherwise NULL. This is fast path avoinding QOM checking, use with caution. + * Returns pointer to IOMMUMemoryRegionClass if a memory region is an iommu, + * otherwise NULL. This is fast path avoiding QOM checking, use with caution. * * @mr: the memory region being queried */ @@ -993,7 +993,8 @@ int memory_region_get_fd(MemoryRegion *mr); * protecting the pointer, such as a reference to the region that includes * the incoming ram_addr_t. * - * @mr: the memory region being queried. + * @ptr: the host pointer to be converted + * @offset: the offset within memory region */ MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset); @@ -1270,7 +1271,7 @@ void memory_region_clear_global_locking(MemoryRegion *mr); * @size: the size of the access to trigger the eventfd * @match_data: whether to match against @data, instead of just @addr * @data: the data to match against the guest write - * @fd: the eventfd to be triggered when @addr, @size, and @data all match. + * @e: event notifier to be triggered when @addr, @size, and @data all match. **/ void memory_region_add_eventfd(MemoryRegion *mr, hwaddr addr, @@ -1290,7 +1291,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, * @size: the size of the access to trigger the eventfd * @match_data: whether to match against @data, instead of just @addr * @data: the data to match against the guest write - * @fd: the eventfd to be triggered when @addr, @size, and @data all match. + * @e: event notifier to be triggered when @addr, @size, and @data all match. */ void memory_region_del_eventfd(MemoryRegion *mr, hwaddr addr, @@ -1526,7 +1527,7 @@ bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr); * will need to request the pointer again. * * @mr: #MemoryRegion associated to the pointer. - * @addr: address within that region + * @offset: offset within the memory region * @size: size of that area. */ void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset, @@ -1595,6 +1596,7 @@ void address_space_destroy(AddressSpace *as); * @addr: address within that address space * @attrs: memory transaction attributes * @buf: buffer with the data transferred + * @len: the number of bytes to read or write * @is_write: indicates the transfer direction */ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, @@ -1612,6 +1614,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, * @addr: address within that address space * @attrs: memory transaction attributes * @buf: buffer with the data transferred + * @len: the number of bytes to write */ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, @@ -1810,7 +1813,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, * called from an RCU critical section, to avoid that the last reference * to the returned region disappears after address_space_translate returns. * - * @as: #AddressSpace to be accessed + * @fv: #FlatView to be accessed * @addr: address within that address space * @xlat: pointer to address within the returned memory region section's * #MemoryRegion. @@ -1868,7 +1871,7 @@ void *address_space_map(AddressSpace *as, hwaddr addr, * the amount of memory that was actually read or written by the caller. * * @as: #AddressSpace used - * @addr: address within that address space + * @buffer: host pointer as returned by address_space_map() * @len: buffer length as returned by address_space_map() * @access_len: amount of data actually transferred * @is_write: indicates the transfer direction @@ -1905,7 +1908,7 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) * or failed (eg unassigned memory, device rejected the transaction, * IOMMU fault). * - * @as: #AddressSpace to be accessed + * @fv: #FlatView to be accessed * @addr: address within that address space * @attrs: memory transaction attributes * @buf: buffer with the data transferred -- cgit v1.2.3-55-g7522 From b850f664a1dbbc1ea27bef12cd251ee5da0bfe05 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 13 Jan 2018 23:04:10 -0300 Subject: qdev: rename typedef qdev_resetfn() -> DeviceReset() following the DeviceRealize and DeviceUnrealize typedefs, this unify a bit the new QOM API. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20180114020412.26160-2-f4bug@amsat.org> Reviewed-by: Laurent Vivier Signed-off-by: Paolo Bonzini --- include/hw/qdev-core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 51473eee7b..85fa26d8a1 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -32,9 +32,9 @@ typedef enum DeviceCategory { typedef int (*qdev_initfn)(DeviceState *dev); typedef int (*qdev_event)(DeviceState *dev); -typedef void (*qdev_resetfn)(DeviceState *dev); typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); +typedef void (*DeviceReset)(DeviceState *dev); typedef void (*BusRealize)(BusState *bus, Error **errp); typedef void (*BusUnrealize)(BusState *bus, Error **errp); @@ -117,7 +117,7 @@ typedef struct DeviceClass { bool hotpluggable; /* callbacks */ - void (*reset)(DeviceState *dev); + DeviceReset reset; DeviceRealize realize; DeviceUnrealize unrealize; -- cgit v1.2.3-55-g7522 From 46795cf2e2f643ace9454822022ba8b1e9c0cf61 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 13 Jan 2018 23:04:11 -0300 Subject: qdev: add helpers to be more explicit when using abstract QOM parent functions QOM API learning curve is quite hard, in particular when devices inherit from abstract parent. To be more explicit about when a device class change the parent hooks, add few helpers hoping a device class_init() will be easier to understand. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20180114020412.26160-3-f4bug@amsat.org> Reviewed-by: Laurent Vivier Signed-off-by: Paolo Bonzini --- hw/core/qdev.c | 24 ++++++++++++++++++++++++ include/hw/qdev-core.h | 10 ++++++++++ 2 files changed, 34 insertions(+) (limited to 'include') diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 2456035d1a..11f8a27a69 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -1075,6 +1075,30 @@ static void device_class_init(ObjectClass *class, void *data) dc->user_creatable = true; } +void device_class_set_parent_reset(DeviceClass *dc, + DeviceReset dev_reset, + DeviceReset *parent_reset) +{ + *parent_reset = dc->reset; + dc->reset = dev_reset; +} + +void device_class_set_parent_realize(DeviceClass *dc, + DeviceRealize dev_realize, + DeviceRealize *parent_realize) +{ + *parent_realize = dc->realize; + dc->realize = dev_realize; +} + +void device_class_set_parent_unrealize(DeviceClass *dc, + DeviceUnrealize dev_unrealize, + DeviceUnrealize *parent_unrealize) +{ + *parent_unrealize = dc->unrealize; + dc->unrealize = dev_unrealize; +} + void device_reset(DeviceState *dev) { DeviceClass *klass = DEVICE_GET_CLASS(dev); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 85fa26d8a1..18c0251b40 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -382,6 +382,16 @@ void qdev_machine_init(void); */ void device_reset(DeviceState *dev); +void device_class_set_parent_reset(DeviceClass *dc, + DeviceReset dev_reset, + DeviceReset *parent_reset); +void device_class_set_parent_realize(DeviceClass *dc, + DeviceRealize dev_realize, + DeviceRealize *parent_realize); +void device_class_set_parent_unrealize(DeviceClass *dc, + DeviceUnrealize dev_unrealize, + DeviceUnrealize *parent_unrealize); + const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev); const char *qdev_fw_name(DeviceState *dev); -- cgit v1.2.3-55-g7522 From 9d70618c6842570226866f9409d7b8c4d6489da6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 21 Nov 2017 15:08:08 +0000 Subject: memory-internal.h: Remove obsolete claim that header is obsolete The memory-internal.h header claims that it is for "obsolete exec.c functions" which "will be removed soon". This statement was added in 2011, six years ago, but the header is still here. (Admittedly none of the prototypes added in commit 67d95c153bef55f6 are still in the header.) It's convenient to have a place to put prototypes for functions which are used internally to the various .c files of the memory system or by the accel/tcg code, which is inevitably fairly closely coupled. So keep the header but update the comments to reflect what we're actually using it for. Signed-off-by: Peter Maydell Message-Id: <1511276888-17834-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Paolo Bonzini --- include/exec/memory-internal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 98d82964cc..4162474fd5 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -1,5 +1,5 @@ /* - * Declarations for obsolete exec.c functions + * Declarations for functions which are internal to the memory subsystem. * * Copyright 2011 Red Hat, Inc. and/or its affiliates * @@ -12,8 +12,9 @@ */ /* - * This header is for use by exec.c and memory.c ONLY. Do not include it. - * The functions declared here will be removed soon. + * This header is for use by exec.c, memory.c and accel/tcg/cputlb.c ONLY, + * for declarations which are shared between the memory subsystem's + * internals and the TCG TLB code. Do not include it from elsewhere. */ #ifndef MEMORY_INTERNAL_H -- cgit v1.2.3-55-g7522 From b1cef6d02f84bd842fb94a6109ad4e2ad873e8e5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Jan 2018 16:19:49 +0000 Subject: Drop remaining bits of ia64 host support We dropped support for ia64 host CPUs in the 2.11 release (removing the TCG backend for it, and advertising the support as being completely removed in the changelog). However there are a few bits and pieces of code still floating about. Remove those, too. We can drop the check in configure for "ia64 or hppa host?" entirely, because we don't support hppa hosts either any more. Signed-off-by: Peter Maydell Message-Id: <1516897189-11035-1-git-send-email-peter.maydell@linaro.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- accel/tcg/user-exec.c | 33 --------------------------------- configure | 5 ----- include/qemu/processor.h | 3 --- include/qemu/timer.h | 9 --------- linux-user/syscall.c | 7 +------ 5 files changed, 1 insertion(+), 56 deletions(-) (limited to 'include') diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index a0a4a1924e..77899584f2 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -503,39 +503,6 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } -#elif defined(__ia64) - -#ifndef __ISR_VALID - /* This ought to be in ... */ -# define __ISR_VALID 1 -#endif - -int cpu_signal_handler(int host_signum, void *pinfo, void *puc) -{ - siginfo_t *info = pinfo; - ucontext_t *uc = puc; - unsigned long ip; - int is_write = 0; - - ip = uc->uc_mcontext.sc_ip; - switch (host_signum) { - case SIGILL: - case SIGFPE: - case SIGSEGV: - case SIGBUS: - case SIGTRAP: - if (info->si_code && (info->si_segvflags & __ISR_VALID)) { - /* ISR.W (write-access) is bit 33: */ - is_write = (info->si_isr >> 33) & 1; - } - break; - - default: - break; - } - return handle_cpu_signal(ip, info, is_write, (sigset_t *)&uc->uc_sigmask); -} - #elif defined(__s390__) int cpu_signal_handler(int host_signum, void *pinfo, diff --git a/configure b/configure index 302fdc92ff..bdbd097c84 100755 --- a/configure +++ b/configure @@ -636,8 +636,6 @@ elif check_define _ARCH_PPC ; then fi elif check_define __mips__ ; then cpu="mips" -elif check_define __ia64__ ; then - cpu="ia64" elif check_define __s390__ ; then if check_define __s390x__ ; then cpu="s390x" @@ -4744,9 +4742,6 @@ if test "$coroutine_pool" = ""; then fi if test "$debug_stack_usage" = "yes"; then - if test "$cpu" = "ia64" -o "$cpu" = "hppa"; then - error_exit "stack usage debugging is not supported for $cpu" - fi if test "$coroutine_pool" = "yes"; then echo "WARN: disabling coroutine pool for stack usage debugging" coroutine_pool=no diff --git a/include/qemu/processor.h b/include/qemu/processor.h index 8b2570283a..8e16c9277d 100644 --- a/include/qemu/processor.h +++ b/include/qemu/processor.h @@ -12,9 +12,6 @@ #if defined(__i386__) || defined(__x86_64__) # define cpu_relax() asm volatile("rep; nop" ::: "memory") -#elif defined(__ia64__) -# define cpu_relax() asm volatile("hint @pause" ::: "memory") - #elif defined(__aarch64__) # define cpu_relax() asm volatile("yield" ::: "memory") diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 1b518bca30..3b5a54b014 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -931,15 +931,6 @@ static inline int64_t cpu_get_host_ticks(void) return val; } -#elif defined(__ia64) - -static inline int64_t cpu_get_host_ticks(void) -{ - int64_t val; - asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory"); - return val; -} - #elif defined(__s390__) static inline int64_t cpu_get_host_ticks(void) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 74378947f0..df1edf0cd3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -36,10 +36,6 @@ #include #include #include -#ifdef __ia64__ -int __clone2(int (*fn)(void *), void *child_stack_base, - size_t stack_size, int flags, void *arg, ...); -#endif #include #include #include @@ -246,8 +242,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_inotify_add_watch __NR_inotify_add_watch #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch -#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \ - defined(__s390x__) +#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__) #define __NR__llseek __NR_lseek #endif -- cgit v1.2.3-55-g7522 From d83414e1fd1941ca8228b5cf6a06697bd1ff7f83 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 16 Jan 2018 16:11:52 +0100 Subject: ucontext: annotate coroutine stack for ASAN It helps ASAN to detect more leaks on coroutine stacks, and to get rid of some extra warnings. Before: tests/test-coroutine -p /basic/lifecycle /basic/lifecycle: ==20781==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases! ==20781==WARNING: ASan is ignoring requested __asan_handle_no_return: stack top: 0x7ffcb184d000; bottom 0x7ff6c4cfd000; size: 0x0005ecb50000 (25446121472) False positive error reports may follow For details see https://github.com/google/sanitizers/issues/189 OK After: tests/test-coroutine -p /basic/lifecycle /basic/lifecycle: ==21110==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases! OK A similar work would need to be done for sigaltstack & windows fibers to have similar coverage. Since ucontext is preferred, I didn't bother checking the other coroutine implementations for now. Update travis to fix the build with ASAN annotations. Signed-off-by: Marc-André Lureau Message-Id: <20180116151152.4040-4-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- .travis.yml | 3 ++- configure | 30 +++++++++++++++++++++++++++++ include/qemu/compiler.h | 4 ++++ util/coroutine-ucontext.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/.travis.yml b/.travis.yml index f583839755..f2291e87a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,12 +13,13 @@ addons: - libattr1-dev - libbrlapi-dev - libcap-ng-dev + - libgcc-6-dev - libgnutls-dev - libgtk-3-dev - libiscsi-dev - liblttng-ust-dev - - libnfs-dev - libncurses5-dev + - libnfs-dev - libnss3-dev - libpixman-1-dev - libpng12-dev diff --git a/configure b/configure index 35147adc8e..529aad5491 100755 --- a/configure +++ b/configure @@ -5213,6 +5213,8 @@ write_c_skeleton have_asan=no have_ubsan=no +have_asan_iface_h=no +have_asan_iface_fiber=no if test "$sanitizers" = "yes" ; then if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" ""; then @@ -5221,12 +5223,29 @@ if test "$sanitizers" = "yes" ; then if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then have_ubsan=yes fi + + if check_include "sanitizer/asan_interface.h" ; then + have_asan_iface_h=yes + fi + + cat > $TMPC << EOF +#include +int main(void) { + __sanitizer_start_switch_fiber(0, 0, 0); + return 0; +} +EOF + if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" "" ; then + have_asan_iface_fiber=yes + fi fi ########################################## # End of CC checks # After here, no more $cc or $ld runs +write_c_skeleton + if test "$gcov" = "yes" ; then CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS" LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS" @@ -5249,6 +5268,13 @@ fi if test "$have_asan" = "yes"; then CFLAGS="-fsanitize=address $CFLAGS" + if test "$have_asan_iface_h" = "no" ; then + echo "ASAN build enabled, but ASAN header missing." \ + "Without code annotation, the report may be inferior." + elif test "$have_asan_iface_fiber" = "no" ; then + echo "ASAN build enabled, but ASAN header is too old." \ + "Without code annotation, the report may be inferior." + fi fi if test "$have_ubsan" = "yes"; then CFLAGS="-fsanitize=undefined $CFLAGS" @@ -6237,6 +6263,10 @@ if test "$valgrind_h" = "yes" ; then echo "CONFIG_VALGRIND_H=y" >> $config_host_mak fi +if test "$have_asan_iface_fiber" = "yes" ; then + echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak +fi + if test "$has_environ" = "yes" ; then echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak fi diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 340e5fdc09..5fcc4f7ec7 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -111,4 +111,8 @@ #define GCC_FMT_ATTR(n, m) #endif +#ifndef __has_feature +#define __has_feature(x) 0 /* compatibility with non-clang compilers */ +#endif + #endif /* COMPILER_H */ diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index 6621f3f692..926d3402e3 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -31,6 +31,13 @@ #include #endif +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) +#ifdef CONFIG_ASAN_IFACE_FIBER +#define CONFIG_ASAN 1 +#include +#endif +#endif + typedef struct { Coroutine base; void *stack; @@ -59,11 +66,37 @@ union cc_arg { int i[2]; }; +static void finish_switch_fiber(void *fake_stack_save) +{ +#ifdef CONFIG_ASAN + const void *bottom_old; + size_t size_old; + + __sanitizer_finish_switch_fiber(fake_stack_save, &bottom_old, &size_old); + + if (!leader.stack) { + leader.stack = (void *)bottom_old; + leader.stack_size = size_old; + } +#endif +} + +static void start_switch_fiber(void **fake_stack_save, + const void *bottom, size_t size) +{ +#ifdef CONFIG_ASAN + __sanitizer_start_switch_fiber(fake_stack_save, bottom, size); +#endif +} + static void coroutine_trampoline(int i0, int i1) { union cc_arg arg; CoroutineUContext *self; Coroutine *co; + void *fake_stack_save = NULL; + + finish_switch_fiber(NULL); arg.i[0] = i0; arg.i[1] = i1; @@ -72,9 +105,13 @@ static void coroutine_trampoline(int i0, int i1) /* Initialize longjmp environment and switch back the caller */ if (!sigsetjmp(self->env, 0)) { + start_switch_fiber(&fake_stack_save, + leader.stack, leader.stack_size); siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); } + finish_switch_fiber(fake_stack_save); + while (true) { co->entry(co->entry_arg); qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE); @@ -87,6 +124,7 @@ Coroutine *qemu_coroutine_new(void) ucontext_t old_uc, uc; sigjmp_buf old_env; union cc_arg arg = {0}; + void *fake_stack_save = NULL; /* The ucontext functions preserve signal masks which incurs a * system call overhead. sigsetjmp(buf, 0)/siglongjmp() does not @@ -122,8 +160,12 @@ Coroutine *qemu_coroutine_new(void) /* swapcontext() in, siglongjmp() back out */ if (!sigsetjmp(old_env, 0)) { + start_switch_fiber(&fake_stack_save, co->stack, co->stack_size); swapcontext(&old_uc, &uc); } + + finish_switch_fiber(fake_stack_save); + return &co->base; } @@ -169,13 +211,19 @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_); CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_); int ret; + void *fake_stack_save = NULL; current = to_; ret = sigsetjmp(from->env, 0); if (ret == 0) { + start_switch_fiber(action == COROUTINE_TERMINATE ? + NULL : &fake_stack_save, to->stack, to->stack_size); siglongjmp(to->env, action); } + + finish_switch_fiber(fake_stack_save); + return ret; } -- cgit v1.2.3-55-g7522 From 0f2956f9159e4aecc9f4de6b8412a1d1ac5a2da0 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Thu, 1 Feb 2018 14:27:51 +0100 Subject: memfd: add error argument, instead of perror() This will allow callers to silence error report when the call is allowed to failed. Signed-off-by: Marc-André Lureau Message-Id: <20180201132757.23063-2-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/virtio/vhost.c | 8 +++++++- include/qemu/memfd.h | 5 +++-- util/memfd.c | 57 +++++++++++++++++++++++++++------------------------- 3 files changed, 40 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index d16c0c813d..338e4395b7 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -330,6 +330,7 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) static struct vhost_log *vhost_log_alloc(uint64_t size, bool share) { + Error *err = NULL; struct vhost_log *log; uint64_t logsize = size * sizeof(*(log->log)); int fd = -1; @@ -338,7 +339,12 @@ static struct vhost_log *vhost_log_alloc(uint64_t size, bool share) if (share) { log->log = qemu_memfd_alloc("vhost-log", logsize, F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL, - &fd); + &fd, &err); + if (err) { + error_report_err(err); + g_free(log); + return NULL; + } memset(log->log, 0, logsize); } else { log->log = g_malloc0(logsize); diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index 41c24d807c..b9d09873b5 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -16,9 +16,10 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif -int qemu_memfd_create(const char *name, size_t size, unsigned int seals); +int qemu_memfd_create(const char *name, size_t size, unsigned int seals, + Error **errp); void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, - int *fd); + int *fd, Error **errp); void qemu_memfd_free(void *ptr, size_t size, int fd); bool qemu_memfd_check(void); diff --git a/util/memfd.c b/util/memfd.c index dce61f9d21..8d27307137 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -27,6 +27,7 @@ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qemu/memfd.h" #if defined CONFIG_LINUX && !defined CONFIG_MEMFD @@ -51,11 +52,11 @@ static int memfd_create(const char *name, unsigned int flags) #define MFD_ALLOW_SEALING 0x0002U #endif -int qemu_memfd_create(const char *name, size_t size, unsigned int seals) +int qemu_memfd_create(const char *name, size_t size, + unsigned int seals, Error **errp) { - int mfd = -1; - #ifdef CONFIG_LINUX + int mfd = -1; unsigned int flags = MFD_CLOEXEC; if (seals) { @@ -64,23 +65,26 @@ int qemu_memfd_create(const char *name, size_t size, unsigned int seals) mfd = memfd_create(name, flags); if (mfd < 0) { - return -1; + goto err; } if (ftruncate(mfd, size) == -1) { - perror("ftruncate"); - close(mfd); - return -1; + goto err; } if (seals && fcntl(mfd, F_ADD_SEALS, seals) == -1) { - perror("fcntl"); - close(mfd); - return -1; + goto err; } -#endif return mfd; + +err: + if (mfd >= 0) { + close(mfd); + } +#endif + error_setg_errno(errp, errno, "failed to create memfd"); + return -1; } /* @@ -90,14 +94,14 @@ int qemu_memfd_create(const char *name, size_t size, unsigned int seals) * sealing. */ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, - int *fd) + int *fd, Error **errp) { void *ptr; - int mfd = qemu_memfd_create(name, size, seals); + int mfd = qemu_memfd_create(name, size, seals, NULL); /* some systems have memfd without sealing */ if (mfd == -1) { - mfd = qemu_memfd_create(name, size, 0); + mfd = qemu_memfd_create(name, size, 0, NULL); } if (mfd == -1) { @@ -109,27 +113,26 @@ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, unlink(fname); g_free(fname); - if (mfd == -1) { - perror("mkstemp"); - return NULL; - } - - if (ftruncate(mfd, size) == -1) { - perror("ftruncate"); - close(mfd); - return NULL; + if (mfd == -1 || + ftruncate(mfd, size) == -1) { + goto err; } } ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0); if (ptr == MAP_FAILED) { - perror("mmap"); - close(mfd); - return NULL; + goto err; } *fd = mfd; return ptr; + +err: + error_setg_errno(errp, errno, "failed to allocate shared memory"); + if (mfd >= 0) { + close(mfd); + } + return NULL; } void qemu_memfd_free(void *ptr, size_t size, int fd) @@ -157,7 +160,7 @@ bool qemu_memfd_check(void) int fd; void *ptr; - ptr = qemu_memfd_alloc("test", 4096, 0, &fd); + ptr = qemu_memfd_alloc("test", 4096, 0, &fd, NULL); memfd_check = ptr ? MEMFD_OK : MEMFD_KO; qemu_memfd_free(ptr, 4096, fd); } -- cgit v1.2.3-55-g7522 From c5b2a9e0782c54402b3e06afd14b4c1de9efba8f Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Thu, 1 Feb 2018 14:27:52 +0100 Subject: memfd: add hugetlb support Linux commit 749df87bd7bee5a79cef073f5d032ddb2b211de8 (v4.14-rc1) added a new flag MFD_HUGETLB to memfd_create() that specify the file to be created resides in the hugetlbfs filesystem. This is the generic hugetlbfs filesystem not associated with any specific mount point. hugetlbfs does not support sealing operations in v4.14, therefore specifying MFD_ALLOW_SEALING with MFD_HUGETLB will result in EINVAL. However, I added sealing support in "[PATCH v3 0/9] memfd: add sealing to hugetlb-backed memory" series, queued in -mm tree for v4.16. Signed-off-by: Marc-André Lureau Message-Id: <20180201132757.23063-3-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/memfd.h | 4 ++-- util/memfd.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index b9d09873b5..1d3ecc7458 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -16,8 +16,8 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif -int qemu_memfd_create(const char *name, size_t size, unsigned int seals, - Error **errp); +int qemu_memfd_create(const char *name, size_t size, bool hugetlb, + unsigned int seals, Error **errp); void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp); void qemu_memfd_free(void *ptr, size_t size, int fd); diff --git a/util/memfd.c b/util/memfd.c index 8d27307137..7594af7089 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -52,7 +52,11 @@ static int memfd_create(const char *name, unsigned int flags) #define MFD_ALLOW_SEALING 0x0002U #endif -int qemu_memfd_create(const char *name, size_t size, +#ifndef MFD_HUGETLB +#define MFD_HUGETLB 0x0004U +#endif + +int qemu_memfd_create(const char *name, size_t size, bool hugetlb, unsigned int seals, Error **errp) { #ifdef CONFIG_LINUX @@ -62,6 +66,9 @@ int qemu_memfd_create(const char *name, size_t size, if (seals) { flags |= MFD_ALLOW_SEALING; } + if (hugetlb) { + flags |= MFD_HUGETLB; + } mfd = memfd_create(name, flags); if (mfd < 0) { @@ -97,11 +104,11 @@ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp) { void *ptr; - int mfd = qemu_memfd_create(name, size, seals, NULL); + int mfd = qemu_memfd_create(name, size, false, seals, NULL); /* some systems have memfd without sealing */ if (mfd == -1) { - mfd = qemu_memfd_create(name, size, 0, NULL); + mfd = qemu_memfd_create(name, size, false, 0, NULL); } if (mfd == -1) { -- cgit v1.2.3-55-g7522 From 2ef8c0c99be7ee5b9dbceaae41b8890e7c81240f Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Thu, 1 Feb 2018 14:27:53 +0100 Subject: memfd: add hugetlbsize argument Learn to specificy hugetlb size as qemu_memfd_create() argument. Signed-off-by: Marc-André Lureau Message-Id: <20180201132757.23063-4-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/memfd.h | 2 +- util/memfd.c | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index 1d3ecc7458..de10198ed6 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -17,7 +17,7 @@ #endif int qemu_memfd_create(const char *name, size_t size, bool hugetlb, - unsigned int seals, Error **errp); + uint64_t hugetlbsize, unsigned int seals, Error **errp); void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp); void qemu_memfd_free(void *ptr, size_t size, int fd); diff --git a/util/memfd.c b/util/memfd.c index 7594af7089..07d579ea7d 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -29,6 +29,7 @@ #include "qapi/error.h" #include "qemu/memfd.h" +#include "qemu/host-utils.h" #if defined CONFIG_LINUX && !defined CONFIG_MEMFD #include @@ -56,9 +57,22 @@ static int memfd_create(const char *name, unsigned int flags) #define MFD_HUGETLB 0x0004U #endif +#ifndef MFD_HUGE_SHIFT +#define MFD_HUGE_SHIFT 26 +#endif + int qemu_memfd_create(const char *name, size_t size, bool hugetlb, - unsigned int seals, Error **errp) + uint64_t hugetlbsize, unsigned int seals, Error **errp) { + int htsize = hugetlbsize ? ctz64(hugetlbsize) : 0; + + if (htsize && 1 << htsize != hugetlbsize) { + error_setg(errp, "Hugepage size must be a power of 2"); + return -1; + } + + htsize = htsize << MFD_HUGE_SHIFT; + #ifdef CONFIG_LINUX int mfd = -1; unsigned int flags = MFD_CLOEXEC; @@ -68,8 +82,8 @@ int qemu_memfd_create(const char *name, size_t size, bool hugetlb, } if (hugetlb) { flags |= MFD_HUGETLB; + flags |= htsize; } - mfd = memfd_create(name, flags); if (mfd < 0) { goto err; @@ -104,11 +118,11 @@ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp) { void *ptr; - int mfd = qemu_memfd_create(name, size, false, seals, NULL); + int mfd = qemu_memfd_create(name, size, false, 0, seals, NULL); /* some systems have memfd without sealing */ if (mfd == -1) { - mfd = qemu_memfd_create(name, size, false, 0, NULL); + mfd = qemu_memfd_create(name, size, false, 0, 0, NULL); } if (mfd == -1) { -- cgit v1.2.3-55-g7522 From 29b22c79bcacce7839209c7344948e8c305fa2d3 Mon Sep 17 00:00:00 2001 From: Justin Terry (VM) Date: Mon, 22 Jan 2018 13:07:47 -0800 Subject: Add the WHPX vcpu API Adds support for the Windows Hypervisor Platform accelerator (WHPX) stubs and introduces the whpx.h sysemu API for managing the vcpu scheduling and management. Signed-off-by: Justin Terry (VM) Message-Id: <1516655269-1785-3-git-send-email-juterry@microsoft.com> Signed-off-by: Paolo Bonzini --- accel/stubs/Makefile.objs | 9 +++++---- accel/stubs/whpx-stub.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ include/sysemu/whpx.h | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 accel/stubs/whpx-stub.c create mode 100644 include/sysemu/whpx.h (limited to 'include') diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs index 779343b0c0..3894caf95d 100644 --- a/accel/stubs/Makefile.objs +++ b/accel/stubs/Makefile.objs @@ -1,4 +1,5 @@ -obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o -obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o +obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o +obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o +obj-$(call lnot,$(CONFIG_WHPX)) += whpx-stub.o +obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o diff --git a/accel/stubs/whpx-stub.c b/accel/stubs/whpx-stub.c new file mode 100644 index 0000000000..5fb049c281 --- /dev/null +++ b/accel/stubs/whpx-stub.c @@ -0,0 +1,48 @@ +/* + * QEMU Windows Hypervisor Platform accelerator (WHPX) stub + * + * Copyright Microsoft Corp. 2017 + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "sysemu/whpx.h" + +int whpx_init_vcpu(CPUState *cpu) +{ + return -1; +} + +int whpx_vcpu_exec(CPUState *cpu) +{ + return -1; +} + +void whpx_destroy_vcpu(CPUState *cpu) +{ +} + +void whpx_vcpu_kick(CPUState *cpu) +{ +} + +void whpx_cpu_synchronize_state(CPUState *cpu) +{ +} + +void whpx_cpu_synchronize_post_reset(CPUState *cpu) +{ +} + +void whpx_cpu_synchronize_post_init(CPUState *cpu) +{ +} + +void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu) +{ +} diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h new file mode 100644 index 0000000000..89592ae4fa --- /dev/null +++ b/include/sysemu/whpx.h @@ -0,0 +1,40 @@ +/* + * QEMU Windows Hypervisor Platform accelerator (WHPX) support + * + * Copyright Microsoft, Corp. 2017 + * + * Authors: + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_WHPX_H +#define QEMU_WHPX_H + +#include "config-host.h" +#include "qemu-common.h" + +int whpx_init_vcpu(CPUState *cpu); +int whpx_vcpu_exec(CPUState *cpu); +void whpx_destroy_vcpu(CPUState *cpu); +void whpx_vcpu_kick(CPUState *cpu); + + +void whpx_cpu_synchronize_state(CPUState *cpu); +void whpx_cpu_synchronize_post_reset(CPUState *cpu); +void whpx_cpu_synchronize_post_init(CPUState *cpu); +void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu); + +#ifdef CONFIG_WHPX + +int whpx_enabled(void); + +#else /* CONFIG_WHPX */ + +#define whpx_enabled() (0) + +#endif /* CONFIG_WHPX */ + +#endif /* QEMU_WHPX_H */ -- cgit v1.2.3-55-g7522 From 19306806ae30b7fb5fe61a9130c6995402acad00 Mon Sep 17 00:00:00 2001 From: Justin Terry (VM) Date: Mon, 22 Jan 2018 13:07:49 -0800 Subject: Add the WHPX acceleration enlightenments Implements the WHPX accelerator cpu enlightenments to actually use the whpx-all accelerator on Windows platforms. Signed-off-by: Justin Terry (VM) Message-Id: <1516655269-1785-5-git-send-email-juterry@microsoft.com> [Register/unregister VCPU thread with RCU. - Paolo] Signed-off-by: Paolo Bonzini --- cpus.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++- include/sysemu/hw_accel.h | 13 +++++++++ target/i386/helper.c | 2 +- 3 files changed, 82 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/cpus.c b/cpus.c index 8d8bb7c6d3..6825fe10c6 100644 --- a/cpus.c +++ b/cpus.c @@ -38,6 +38,7 @@ #include "sysemu/kvm.h" #include "sysemu/hax.h" #include "sysemu/hvf.h" +#include "sysemu/whpx.h" #include "qmp-commands.h" #include "exec/exec-all.h" @@ -1545,6 +1546,49 @@ static void *qemu_hvf_cpu_thread_fn(void *arg) return NULL; } +static void *qemu_whpx_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id = qemu_get_thread_id(); + current_cpu = cpu; + + r = whpx_init_vcpu(cpu); + if (r < 0) { + fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r)); + exit(1); + } + + /* signal CPU creation */ + cpu->created = true; + qemu_cond_signal(&qemu_cpu_cond); + + do { + if (cpu_can_run(cpu)) { + r = whpx_vcpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + while (cpu_thread_is_idle(cpu)) { + qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); + } + qemu_wait_io_event_common(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + whpx_destroy_vcpu(cpu); + cpu->created = false; + qemu_cond_signal(&qemu_cpu_cond); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + #ifdef _WIN32 static void CALLBACK dummy_apc_func(ULONG_PTR unused) { @@ -1635,7 +1679,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu) } #else /* _WIN32 */ if (!qemu_cpu_is_self(cpu)) { - if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { + if (whpx_enabled()) { + whpx_vcpu_kick(cpu); + } else if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n", __func__, GetLastError()); exit(1); @@ -1877,6 +1923,25 @@ static void qemu_hvf_start_vcpu(CPUState *cpu) } } +static void qemu_whpx_start_vcpu(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, qemu_whpx_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +#ifdef _WIN32 + cpu->hThread = qemu_thread_get_handle(cpu->thread); +#endif + while (!cpu->created) { + qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + } +} + static void qemu_dummy_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1915,6 +1980,8 @@ void qemu_init_vcpu(CPUState *cpu) qemu_hvf_start_vcpu(cpu); } else if (tcg_enabled()) { qemu_tcg_init_vcpu(cpu); + } else if (whpx_enabled()) { + qemu_whpx_start_vcpu(cpu); } else { qemu_dummy_start_vcpu(cpu); } diff --git a/include/sysemu/hw_accel.h b/include/sysemu/hw_accel.h index 469ffda460..d2ddfb5ad0 100644 --- a/include/sysemu/hw_accel.h +++ b/include/sysemu/hw_accel.h @@ -14,6 +14,7 @@ #include "qom/cpu.h" #include "sysemu/hax.h" #include "sysemu/kvm.h" +#include "sysemu/whpx.h" static inline void cpu_synchronize_state(CPUState *cpu) { @@ -23,6 +24,9 @@ static inline void cpu_synchronize_state(CPUState *cpu) if (hax_enabled()) { hax_cpu_synchronize_state(cpu); } + if (whpx_enabled()) { + whpx_cpu_synchronize_state(cpu); + } } static inline void cpu_synchronize_post_reset(CPUState *cpu) @@ -33,6 +37,9 @@ static inline void cpu_synchronize_post_reset(CPUState *cpu) if (hax_enabled()) { hax_cpu_synchronize_post_reset(cpu); } + if (whpx_enabled()) { + whpx_cpu_synchronize_post_reset(cpu); + } } static inline void cpu_synchronize_post_init(CPUState *cpu) @@ -43,6 +50,9 @@ static inline void cpu_synchronize_post_init(CPUState *cpu) if (hax_enabled()) { hax_cpu_synchronize_post_init(cpu); } + if (whpx_enabled()) { + whpx_cpu_synchronize_post_init(cpu); + } } static inline void cpu_synchronize_pre_loadvm(CPUState *cpu) @@ -53,6 +63,9 @@ static inline void cpu_synchronize_pre_loadvm(CPUState *cpu) if (hax_enabled()) { hax_cpu_synchronize_pre_loadvm(cpu); } + if (whpx_enabled()) { + whpx_cpu_synchronize_pre_loadvm(cpu); + } } #endif /* QEMU_HW_ACCEL_H */ diff --git a/target/i386/helper.c b/target/i386/helper.c index f63eb3d3f4..9fba146b7f 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -986,7 +986,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access) X86CPU *cpu = x86_env_get_cpu(env); CPUState *cs = CPU(cpu); - if (kvm_enabled()) { + if (kvm_enabled() || whpx_enabled()) { env->tpr_access_type = access; cpu_interrupt(cs, CPU_INTERRUPT_TPR); -- cgit v1.2.3-55-g7522