From 3b8c1761f0e1523622e008836d01a6544b1c21ab Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 25 Jul 2016 14:47:12 +0200 Subject: qtail: clean up direct access to tqe_prev field instead of accessing tqe_prev field dircetly outside of queue.h use macros to check if element is in list and make sure that afer element is removed from list tqe_prev field could be used to do the same check. Signed-off-by: Igor Mammedov Message-Id: <1469450832-84343-1-git-send-email-imammedo@redhat.com> Signed-off-by: Paolo Bonzini --- include/qemu/queue.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/qemu/queue.h b/include/qemu/queue.h index c2b6c8149d..342073fb4d 100644 --- a/include/qemu/queue.h +++ b/include/qemu/queue.h @@ -407,6 +407,7 @@ struct { \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + (elm)->field.tqe_prev = NULL; \ } while (/*CONSTCOND*/0) #define QTAILQ_FOREACH(var, head, field) \ @@ -430,6 +431,7 @@ struct { \ #define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define QTAILQ_FIRST(head) ((head)->tqh_first) #define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_prev != NULL) #define QTAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) -- cgit v1.2.3-55-g7522 From 6d21e4208f382dd8ca1f7995a6dd9ea7ca281163 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 19 Jul 2016 08:36:18 +0200 Subject: tcg: Prepare TB invalidation for lockless TB lookup When invalidating a translation block, set an invalid flag into the TranslationBlock structure first. It is also necessary to check whether the target TB is still valid after acquiring 'tb_lock' but before calling tb_add_jump() since TB lookup is to be performed out of 'tb_lock' in future. Note that we don't have to check 'last_tb'; an already invalidated TB will not be executed anyway and it is thus safe to patch it. Suggested-by: Sergey Fedorov Signed-off-by: Paolo Bonzini --- cpu-exec.c | 5 +++-- include/exec/exec-all.h | 2 ++ translate-all.c | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/cpu-exec.c b/cpu-exec.c index 877ff8ed70..cdaab1dbcd 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -241,7 +241,8 @@ static bool tb_cmp(const void *p, const void *d) if (tb->pc == desc->pc && tb->page_addr[0] == desc->phys_page1 && tb->cs_base == desc->cs_base && - tb->flags == desc->flags) { + tb->flags == desc->flags && + !atomic_read(&tb->invalid)) { /* check next page if needed */ if (tb->page_addr[1] == -1) { return true; @@ -352,7 +353,7 @@ static inline TranslationBlock *tb_find_fast(CPUState *cpu, /* Check if translation buffer has been flushed */ if (cpu->tb_flushed) { cpu->tb_flushed = false; - } else { + } else if (!tb->invalid) { tb_add_jump(last_tb, tb_exit, tb); } } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index d008296c1b..a0e87be88f 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -225,6 +225,8 @@ struct TranslationBlock { #define CF_USE_ICOUNT 0x20000 #define CF_IGNORE_ICOUNT 0x40000 /* Do not generate icount code */ + uint16_t invalid; + void *tc_ptr; /* pointer to the translated code */ uint8_t *tc_search; /* pointer to search data */ /* original tb when cflags has CF_NOCACHE */ diff --git a/translate-all.c b/translate-all.c index e753a50640..5a5499ffb6 100644 --- a/translate-all.c +++ b/translate-all.c @@ -773,6 +773,7 @@ static TranslationBlock *tb_alloc(target_ulong pc) tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++]; tb->pc = pc; tb->cflags = 0; + tb->invalid = false; return tb; } @@ -994,6 +995,8 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) uint32_t h; tb_page_addr_t phys_pc; + atomic_set(&tb->invalid, true); + /* remove the TB from the hash list */ phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); h = tb_hash_func(phys_pc, tb->pc, tb->flags); -- cgit v1.2.3-55-g7522 From 490ab15a4948f9150fae781fc421becce9221b32 Mon Sep 17 00:00:00 2001 From: Cao jin Date: Fri, 29 Jul 2016 19:05:36 +0800 Subject: timer: update comments The comments is outdated. The patch has following changes: 1. tense correction. 2. all clock time value is returned in nanoseconds, so, they are same in precision. 3. virtual clock doesn't use cpu cycles. Cc: Paolo Bonzini Cc: Peter Maydell Signed-off-by: Cao jin Message-Id: <1469790338-28990-2-git-send-email-caoj.fnst@cn.fujitsu.com> Signed-off-by: Paolo Bonzini --- include/qemu/timer.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 309f3d09e9..34650b2039 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -22,23 +22,20 @@ * @QEMU_CLOCK_REALTIME: Real time clock * * The real time clock should be used only for stuff which does not - * change the virtual machine state, as it is run even if the virtual - * machine is stopped. The real time clock has a frequency of 1000 - * Hz. + * change the virtual machine state, as it runs even if the virtual + * machine is stopped. * * @QEMU_CLOCK_VIRTUAL: virtual clock * - * The virtual clock is only run during the emulation. It is stopped - * when the virtual machine is stopped. Virtual timers use a high - * precision clock, usually cpu cycles (use ticks_per_sec). + * The virtual clock only runs during the emulation. It stops + * when the virtual machine is stopped. * * @QEMU_CLOCK_HOST: host clock * - * The host clock should be use for device models that emulate accurate + * The host clock should be used for device models that emulate accurate * real time sources. It will continue to run when the virtual machine * is suspended, and it will reflect system time changes the host may - * undergo (e.g. due to NTP). The host clock has the same precision as - * the virtual clock. + * undergo (e.g. due to NTP). * * @QEMU_CLOCK_VIRTUAL_RT: realtime clock used for icount warp * @@ -76,10 +73,6 @@ struct QEMUTimer { extern QEMUTimerListGroup main_loop_tlg; -/* - * QEMUClockType - */ - /* * qemu_clock_get_ns; * @type: the clock type -- cgit v1.2.3-55-g7522 From c2cd627ddb13f62557aaf66305edb03cc3d9612d Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 12 Sep 2016 14:34:56 +0800 Subject: kvm-all: drop kvm_setup_guest_memory kvm_setup_guest_memory only does "madvise to QEMU_MADV_DONTFORK" and is only called by ram_block_add, which actually is duplicate code. Bonus: add simple comment for kvm_has_sync_mmu to make life easier. Suggested-by: Paolo Bonzini Signed-off-by: Cao jin Message-Id: <1473662096-32598-1-git-send-email-caoj.fnst@cn.fujitsu.com> Signed-off-by: Paolo Bonzini --- exec.c | 4 +--- include/sysemu/kvm.h | 1 - kvm-all.c | 15 +-------------- kvm-stub.c | 4 ---- 4 files changed, 2 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/exec.c b/exec.c index ce3fb9ec8e..c81d5ab981 100644 --- a/exec.c +++ b/exec.c @@ -1621,10 +1621,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) if (new_block->host) { qemu_ram_setup_dump(new_block->host, new_block->max_length); qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE); + /* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */ qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK); - if (kvm_enabled()) { - kvm_setup_guest_memory(new_block->host, new_block->max_length); - } } } diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index c9c243631e..4938f65c7a 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -221,7 +221,6 @@ int kvm_destroy_vcpu(CPUState *cpu); #ifdef NEED_CPU_H #include "cpu.h" -void kvm_setup_guest_memory(void *start, size_t size); void kvm_flush_coalesced_mmio_buffer(void); int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, diff --git a/kvm-all.c b/kvm-all.c index ebf35b0c5b..8a4382eed8 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -2148,6 +2148,7 @@ void kvm_device_access(int fd, int group, uint64_t attr, } } +/* Return 1 on success, 0 on failure */ int kvm_has_sync_mmu(void) { return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU); @@ -2190,20 +2191,6 @@ int kvm_has_intx_set_mask(void) return kvm_state->intx_set_mask; } -void kvm_setup_guest_memory(void *start, size_t size) -{ - if (!kvm_has_sync_mmu()) { - int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK); - - if (ret) { - perror("qemu_madvise"); - fprintf(stderr, - "Need MADV_DONTFORK in absence of synchronous KVM MMU\n"); - exit(1); - } - } -} - #ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc) diff --git a/kvm-stub.c b/kvm-stub.c index 64e23f6be0..322712764f 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -73,10 +73,6 @@ int kvm_has_many_ioeventfds(void) return 0; } -void kvm_setup_guest_memory(void *start, size_t size) -{ -} - int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) { return -ENOSYS; -- cgit v1.2.3-55-g7522 From 705ac1ca539ba05ab52c3290ccb45f9e47aa7c5e Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Wed, 24 Aug 2016 16:44:23 -0400 Subject: atomics: Remove redundant barrier()'s Remove the redundant barrier() after the fence as agreed in previous discussion here: https://lists.gnu.org/archive/html/qemu-devel/2016-04/msg00489.html Signed-off-by: Pranith Kumar Message-Id: <20160824204424.14041-3-bobby.prani@gmail.com> Signed-off-by: Paolo Bonzini --- include/qemu/atomic.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 43b06458f1..8348eccadb 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -72,16 +72,16 @@ * Add one here, and similarly in smp_rmb() and smp_read_barrier_depends(). */ -#define smp_mb() ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); barrier(); }) -#define smp_wmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); barrier(); }) -#define smp_rmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); barrier(); }) +#define smp_mb() ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); }) +#define smp_wmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); }) +#define smp_rmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); }) /* Most compilers currently treat consume and acquire the same, but really * no processors except Alpha need a barrier here. Leave it in if * using Thread Sanitizer to avoid warnings, otherwise optimize it away. */ #if defined(__SANITIZE_THREAD__) -#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); barrier(); }) +#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); }) #elsif defined(__alpha__) #define smp_read_barrier_depends() asm volatile("mb":::"memory") #else -- cgit v1.2.3-55-g7522 From 89943de17c4e276f2c47f05b4604e8816a6a636c Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Mon, 29 Aug 2016 13:17:01 -0400 Subject: atomics: Use __atomic_*_n() variant primitives Use the __atomic_*_n() primitives which take the value as argument. It is not necessary to store the value locally before calling the primitive, hence saving us a stack store and load. Signed-off-by: Pranith Kumar Message-Id: <20160829171701.14025-1-bobby.prani@gmail.com> Signed-off-by: Paolo Bonzini --- include/qemu/atomic.h | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 8348eccadb..0cce246ea9 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -96,15 +96,12 @@ #define atomic_read(ptr) \ ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof_strip_qual(*ptr) _val; \ - __atomic_load(ptr, &_val, __ATOMIC_RELAXED); \ - _val; \ + __atomic_load_n(ptr, __ATOMIC_RELAXED); \ }) #define atomic_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof(*ptr) _val = (i); \ - __atomic_store(ptr, &_val, __ATOMIC_RELAXED); \ + __atomic_store_n(ptr, i, __ATOMIC_RELAXED); \ } while(0) /* See above: most compilers currently treat consume and acquire the @@ -129,8 +126,7 @@ #define atomic_rcu_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof(*ptr) _val = (i); \ - __atomic_store(ptr, &_val, __ATOMIC_RELEASE); \ + __atomic_store_n(ptr, i, __ATOMIC_RELEASE); \ } while(0) /* atomic_mb_read/set semantics map Java volatile variables. They are @@ -153,9 +149,8 @@ #define atomic_mb_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof(*ptr) _val = (i); \ smp_wmb(); \ - __atomic_store(ptr, &_val, __ATOMIC_RELAXED); \ + __atomic_store_n(ptr, i, __ATOMIC_RELAXED); \ smp_mb(); \ } while(0) #else @@ -169,8 +164,7 @@ #define atomic_mb_set(ptr, i) do { \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof(*ptr) _val = (i); \ - __atomic_store(ptr, &_val, __ATOMIC_SEQ_CST); \ + __atomic_store_n(ptr, i, __ATOMIC_SEQ_CST); \ } while(0) #endif @@ -179,17 +173,15 @@ #define atomic_xchg(ptr, i) ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof_strip_qual(*ptr) _new = (i), _old; \ - __atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \ - _old; \ + __atomic_exchange_n(ptr, i, __ATOMIC_SEQ_CST); \ }) /* Returns the eventual value, failed or not */ #define atomic_cmpxchg(ptr, old, new) \ ({ \ QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \ - typeof_strip_qual(*ptr) _old = (old), _new = (new); \ - __atomic_compare_exchange(ptr, &_old, &_new, false, \ + typeof_strip_qual(*ptr) _old = (old); \ + __atomic_compare_exchange_n(ptr, &_old, new, false, \ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ _old; \ }) -- cgit v1.2.3-55-g7522 From 78d6a05d2f69cbfa6e95f0a4a24a2c934969913b Mon Sep 17 00:00:00 2001 From: Dr. David Alan Gilbert Date: Mon, 12 Sep 2016 18:18:35 +0100 Subject: x86/lapic: Load LAPIC state at post_load Load the LAPIC state during post_load (rather than when the CPU starts). This allows an interrupt to be delivered from the ioapic to the lapic prior to cpu loading, in particular the RTC that starts ticking as soon as we load it's state. Fixes a case where Windows hangs after migration due to RTC interrupts disappearing. Signed-off-by: Dr. David Alan Gilbert Suggested-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- hw/i386/kvm/apic.c | 27 +++++++++++++++++++++++++-- include/sysemu/kvm.h | 1 - target-i386/kvm.c | 17 ----------------- 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 2bd0de82b4..5d140b9341 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -28,9 +28,8 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic, return *((uint32_t *)(kapic->regs + (reg_id << 4))); } -void kvm_put_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic) +static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic) { - APICCommonState *s = APIC_COMMON(dev); int i; memset(kapic, 0, sizeof(*kapic)); @@ -125,6 +124,27 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) } } +static void kvm_apic_put(void *data) +{ + APICCommonState *s = data; + struct kvm_lapic_state kapic; + int ret; + + kvm_put_apic_state(s, &kapic); + + ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic); + if (ret < 0) { + fprintf(stderr, "KVM_SET_LAPIC failed: %s\n", strerror(ret)); + abort(); + } +} + +static void kvm_apic_post_load(APICCommonState *s) +{ + fprintf(stderr, "%s: Yeh\n", __func__); + run_on_cpu(CPU(s->cpu), kvm_apic_put, s); +} + static void do_inject_external_nmi(void *data) { APICCommonState *s = data; @@ -178,6 +198,8 @@ static void kvm_apic_reset(APICCommonState *s) { /* Not used by KVM, which uses the CPU mp_state instead. */ s->wait_for_sipi = 0; + + run_on_cpu(CPU(s->cpu), kvm_apic_put, s); } static void kvm_apic_realize(DeviceState *dev, Error **errp) @@ -206,6 +228,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data) k->set_base = kvm_apic_set_base; k->set_tpr = kvm_apic_set_tpr; k->get_tpr = kvm_apic_get_tpr; + k->post_load = kvm_apic_post_load; k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting; k->vapic_base_update = kvm_apic_vapic_base_update; k->external_nmi = kvm_apic_external_nmi; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 4938f65c7a..f2a7b3b8fe 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -371,7 +371,6 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin); -void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); struct kvm_guest_debug; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index d1a25c5465..f1ad805665 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2416,19 +2416,6 @@ static int kvm_get_apic(X86CPU *cpu) return 0; } -static int kvm_put_apic(X86CPU *cpu) -{ - DeviceState *apic = cpu->apic_state; - struct kvm_lapic_state kapic; - - if (apic && kvm_irqchip_in_kernel()) { - kvm_put_apic_state(apic, &kapic); - - return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic); - } - return 0; -} - static int kvm_put_vcpu_events(X86CPU *cpu, int level) { CPUState *cs = CPU(cpu); @@ -2670,10 +2657,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) if (ret < 0) { return ret; } - ret = kvm_put_apic(x86_cpu); - if (ret < 0) { - return ret; - } } ret = kvm_put_tscdeadline_msr(x86_cpu); -- cgit v1.2.3-55-g7522 From 2286459d3ac19eb0697503282ce7830907d055ea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 13 Sep 2016 18:42:38 +0200 Subject: ppc: do not redefine CPUPPCState Just include the file that is supposed to bring it in. Signed-off-by: Paolo Bonzini --- include/hw/ppc/fdt.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/hw/ppc/fdt.h b/include/hw/ppc/fdt.h index 2c68d1616f..0cabb6af04 100644 --- a/include/hw/ppc/fdt.h +++ b/include/hw/ppc/fdt.h @@ -11,8 +11,7 @@ #define PPC_FDT_H #include "qemu/error-report.h" - -typedef struct CPUPPCState CPUPPCState; +#include "target-ppc/cpu-qom.h" #define _FDT(exp) \ do { \ -- cgit v1.2.3-55-g7522 From a1febc4950f2c6232c002f401d7cd409f6fa6a88 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Aug 2016 11:46:14 -0700 Subject: cutils: Export only buffer_is_zero Since the two users don't make use of the returned offset, beyond ensuring that the entire buffer is zero, consider the can_use_buffer_find_nonzero_offset and buffer_find_nonzero_offset functions internal. Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Richard Henderson Message-Id: <1472496380-19706-4-git-send-email-rth@twiddle.net> Signed-off-by: Paolo Bonzini --- include/qemu/cutils.h | 2 -- migration/ram.c | 2 +- migration/rdma.c | 5 +---- util/bufferiszero.c | 8 ++++---- 4 files changed, 6 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index 3e4ea236f0..ca58577565 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -168,8 +168,6 @@ int64_t qemu_strtosz_suffix_unit(const char *nptr, char **end, /* used to print char* safely */ #define STR_OR_NULL(str) ((str) ? (str) : "null") -bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len); -size_t buffer_find_nonzero_offset(const void *buf, size_t len); bool buffer_is_zero(const void *buf, size_t len); /* diff --git a/migration/ram.c b/migration/ram.c index a3d70c4c62..a6e1c63a08 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -73,7 +73,7 @@ static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE]; static inline bool is_zero_range(uint8_t *p, uint64_t size) { - return buffer_find_nonzero_offset(p, size) == size; + return buffer_is_zero(p, size); } /* struct contains XBZRLE cache and a static page diff --git a/migration/rdma.c b/migration/rdma.c index 5110ec828d..88bdb64457 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1934,10 +1934,7 @@ retry: * memset() + madvise() the entire chunk without RDMA. */ - if (can_use_buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, - length) - && buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, - length) == length) { + if (buffer_is_zero((void *)(uintptr_t)sge.addr, length)) { RDMACompress comp = { .offset = current_addr, .value = 0, diff --git a/util/bufferiszero.c b/util/bufferiszero.c index 067d08f1ca..0cf8b6e7e4 100644 --- a/util/bufferiszero.c +++ b/util/bufferiszero.c @@ -192,9 +192,9 @@ static bool avx2_support(void) return b & bit_AVX2; } -bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) \ +static bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) \ __attribute__ ((ifunc("can_use_buffer_find_nonzero_offset_ifunc"))); -size_t buffer_find_nonzero_offset(const void *buf, size_t len) \ +static size_t buffer_find_nonzero_offset(const void *buf, size_t len) \ __attribute__ ((ifunc("buffer_find_nonzero_offset_ifunc"))); static void *buffer_find_nonzero_offset_ifunc(void) @@ -215,12 +215,12 @@ static void *can_use_buffer_find_nonzero_offset_ifunc(void) } #pragma GCC pop_options #else -bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) +static bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) { return can_use_buffer_find_nonzero_offset_inner(buf, len); } -size_t buffer_find_nonzero_offset(const void *buf, size_t len) +static size_t buffer_find_nonzero_offset(const void *buf, size_t len) { return buffer_find_nonzero_offset_inner(buf, len); } -- cgit v1.2.3-55-g7522 From efad6682452ec85a898609c885c2721ea12585db Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Aug 2016 11:46:16 -0700 Subject: cutils: Add test for buffer_is_zero Signed-off-by: Richard Henderson Message-Id: <1472496380-19706-6-git-send-email-rth@twiddle.net> Signed-off-by: Paolo Bonzini --- include/qemu/cutils.h | 1 + tests/Makefile.include | 3 ++ tests/test-bufferiszero.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++ util/bufferiszero.c | 20 ++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 tests/test-bufferiszero.c (limited to 'include') diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index ca58577565..8033929139 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -169,6 +169,7 @@ int64_t qemu_strtosz_suffix_unit(const char *nptr, char **end, #define STR_OR_NULL(str) ((str) ? (str) : "null") bool buffer_is_zero(const void *buf, size_t len); +bool test_buffer_is_zero_next_accel(void); /* * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) diff --git a/tests/Makefile.include b/tests/Makefile.include index e3a3266370..bde274d31e 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -112,6 +112,8 @@ check-unit-y += tests/test-crypto-xts$(EXESUF) check-unit-y += tests/test-crypto-block$(EXESUF) gcov-files-test-logging-y = tests/test-logging.c check-unit-y += tests/test-logging$(EXESUF) +check-unit-y += tests/test-bufferiszero$(EXESUF) +gcov-files-check-bufferiszero-y = util/bufferiszero.c check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh @@ -484,6 +486,7 @@ tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y) tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y) tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y) tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) +tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y) tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\ diff --git a/tests/test-bufferiszero.c b/tests/test-bufferiszero.c new file mode 100644 index 0000000000..42d194cadf --- /dev/null +++ b/tests/test-bufferiszero.c @@ -0,0 +1,78 @@ +/* + * QEMU buffer_is_zero test + * + * Copyright (c) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" + +static char buffer[8 * 1024 * 1024]; + +static void test_1(void) +{ + size_t s, a, o; + + /* Basic positive test. */ + g_assert(buffer_is_zero(buffer, sizeof(buffer))); + + /* Basic negative test. */ + buffer[sizeof(buffer) - 1] = 1; + g_assert(!buffer_is_zero(buffer, sizeof(buffer))); + buffer[sizeof(buffer) - 1] = 0; + + /* Positive tests for size and alignment. */ + for (a = 1; a <= 64; a++) { + for (s = 1; s < 1024; s++) { + buffer[a - 1] = 1; + buffer[a + s] = 1; + g_assert(buffer_is_zero(buffer + a, s)); + buffer[a - 1] = 0; + buffer[a + s] = 0; + } + } + + /* Negative tests for size, alignment, and the offset of the marker. */ + for (a = 1; a <= 64; a++) { + for (s = 1; s < 1024; s++) { + for (o = 0; o < s; ++o) { + buffer[a + o] = 1; + g_assert(!buffer_is_zero(buffer + a, s)); + buffer[a + o] = 0; + } + } + } +} + +static void test_2(void) +{ + if (g_test_perf()) { + test_1(); + } else { + do { + test_1(); + } while (test_buffer_is_zero_next_accel()); + } +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/cutils/bufferiszero", test_2); + + return g_test_run(); +} diff --git a/util/bufferiszero.c b/util/bufferiszero.c index a3a842f9fd..4af3caa1b6 100644 --- a/util/bufferiszero.c +++ b/util/bufferiszero.c @@ -162,6 +162,19 @@ static void __attribute__((constructor)) init_cpuid_cache(void) cpuid_cache = cache; } +#define HAVE_NEXT_ACCEL +bool test_buffer_is_zero_next_accel(void) +{ + /* If no bits set, we just tested buffer_zero_int, and there + are no more acceleration options to test. */ + if (cpuid_cache == 0) { + return false; + } + /* Disable the accelerator we used before and select a new one. */ + cpuid_cache &= cpuid_cache - 1; + return true; +} + static bool select_accel_fn(const void *buf, size_t len) { uintptr_t ibuf = (uintptr_t)buf; @@ -180,6 +193,13 @@ static bool select_accel_fn(const void *buf, size_t len) #define select_accel_fn buffer_zero_int #endif +#ifndef HAVE_NEXT_ACCEL +bool test_buffer_is_zero_next_accel(void) +{ + return false; +} +#endif + /* * Checks if a buffer is all zeroes */ -- cgit v1.2.3-55-g7522