diff options
95 files changed, 2966 insertions, 1880 deletions
diff --git a/.editorconfig b/.editorconfig index b2022e391a..1582883393 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,10 @@ -# http://editorconfig.org +# EditorConfig is a file format and collection of text editor plugins +# for maintaining consistent coding styles between different editors +# and IDEs. Most popular editors support this either natively or via +# plugin. +# +# Check https://editorconfig.org for details. + root = true [*] @@ -6,10 +12,23 @@ end_of_line = lf insert_final_newline = true charset = utf-8 +[*.mak] +indent_style = tab +indent_size = 8 +file_type_emacs = makefile + [Makefile*] indent_style = tab indent_size = 8 +file_type_emacs = makefile [*.{c,h}] indent_style = space indent_size = 4 + +[*.{vert,frag}] +file_type_emacs = glsl + +[*.json] +indent_style = space +file_type_emacs = python diff --git a/.travis.yml b/.travis.yml index 95be6ec59f..aa49c7b114 100644 --- a/.travis.yml +++ b/.travis.yml @@ -117,6 +117,14 @@ matrix: - env: CONFIG="--target-list=x86_64-softmmu" python: - "3.6" + # Acceptance (Functional) tests + - env: CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu" + TEST_CMD="make AVOCADO_SHOW=app check-acceptance" + addons: + apt: + packages: + - python3-pip + - python3.4-venv # Using newer GCC with sanitizers - addons: apt: diff --git a/MAINTAINERS b/MAINTAINERS index 10983bd52d..85f19f569f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1798,7 +1798,7 @@ F: docs/devel/tracing.txt T: git git://github.com/stefanha/qemu.git tracing TPM -M: Stefan Berger <stefanb@linux.vnet.ibm.com> +M: Stefan Berger <stefanb@linux.ibm.com> S: Maintained F: tpm.c F: stubs/tpm.c @@ -2030,7 +2030,6 @@ Sheepdog M: Liu Yuan <namei.unix@gmail.com> M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org -L: sheepdog@lists.wpkg.org S: Supported F: block/sheepdog.c T: git git://github.com/codyprime/qemu-kvm-jtc.git block diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index af57aca5e4..af6bd8ccf9 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -78,7 +78,10 @@ void tlb_init(CPUState *cpu) { CPUArchState *env = cpu->env_ptr; - qemu_spin_init(&env->tlb_lock); + qemu_spin_init(&env->tlb_c.lock); + + /* Ensure that cpu_reset performs a full flush. */ + env->tlb_c.dirty = ALL_MMUIDX_BITS; } /* flush_all_helper: run fn across all cpus @@ -100,139 +103,89 @@ static void flush_all_helper(CPUState *src, run_on_cpu_func fn, } } -size_t tlb_flush_count(void) +void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide) { CPUState *cpu; - size_t count = 0; + size_t full = 0, part = 0, elide = 0; CPU_FOREACH(cpu) { CPUArchState *env = cpu->env_ptr; - count += atomic_read(&env->tlb_flush_count); - } - return count; -} - -/* This is OK because CPU architectures generally permit an - * implementation to drop entries from the TLB at any time, so - * flushing more entries than required is only an efficiency issue, - * not a correctness issue. - */ -static void tlb_flush_nocheck(CPUState *cpu) -{ - CPUArchState *env = cpu->env_ptr; - - /* The QOM tests will trigger tlb_flushes without setting up TCG - * so we bug out here in that case. - */ - if (!tcg_enabled()) { - return; + full += atomic_read(&env->tlb_c.full_flush_count); + part += atomic_read(&env->tlb_c.part_flush_count); + elide += atomic_read(&env->tlb_c.elide_flush_count); } - - assert_cpu_is_self(cpu); - atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1); - tlb_debug("(count: %zu)\n", tlb_flush_count()); - - /* - * tlb_table/tlb_v_table updates from any thread must hold tlb_lock. - * However, updates from the owner thread (as is the case here; see the - * above assert_cpu_is_self) do not need atomic_set because all reads - * that do not hold the lock are performed by the same owner thread. - */ - qemu_spin_lock(&env->tlb_lock); - memset(env->tlb_table, -1, sizeof(env->tlb_table)); - memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table)); - qemu_spin_unlock(&env->tlb_lock); - - cpu_tb_jmp_cache_clear(cpu); - - env->vtlb_index = 0; - env->tlb_flush_addr = -1; - env->tlb_flush_mask = 0; - - atomic_mb_set(&cpu->pending_tlb_flush, 0); -} - -static void tlb_flush_global_async_work(CPUState *cpu, run_on_cpu_data data) -{ - tlb_flush_nocheck(cpu); + *pfull = full; + *ppart = part; + *pelide = elide; } -void tlb_flush(CPUState *cpu) +static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx) { - if (cpu->created && !qemu_cpu_is_self(cpu)) { - if (atomic_mb_read(&cpu->pending_tlb_flush) != ALL_MMUIDX_BITS) { - atomic_mb_set(&cpu->pending_tlb_flush, ALL_MMUIDX_BITS); - async_run_on_cpu(cpu, tlb_flush_global_async_work, - RUN_ON_CPU_NULL); - } - } else { - tlb_flush_nocheck(cpu); - } -} - -void tlb_flush_all_cpus(CPUState *src_cpu) -{ - const run_on_cpu_func fn = tlb_flush_global_async_work; - flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL); - fn(src_cpu, RUN_ON_CPU_NULL); -} - -void tlb_flush_all_cpus_synced(CPUState *src_cpu) -{ - const run_on_cpu_func fn = tlb_flush_global_async_work; - flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL); - async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_NULL); + memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0])); + memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0])); + env->tlb_d[mmu_idx].large_page_addr = -1; + env->tlb_d[mmu_idx].large_page_mask = -1; + env->tlb_d[mmu_idx].vindex = 0; } static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) { CPUArchState *env = cpu->env_ptr; - unsigned long mmu_idx_bitmask = data.host_int; - int mmu_idx; + uint16_t asked = data.host_int; + uint16_t all_dirty, work, to_clean; assert_cpu_is_self(cpu); - tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask); + tlb_debug("mmu_idx:0x%04" PRIx16 "\n", asked); - qemu_spin_lock(&env->tlb_lock); - for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { + qemu_spin_lock(&env->tlb_c.lock); - if (test_bit(mmu_idx, &mmu_idx_bitmask)) { - tlb_debug("%d\n", mmu_idx); + all_dirty = env->tlb_c.dirty; + to_clean = asked & all_dirty; + all_dirty &= ~to_clean; + env->tlb_c.dirty = all_dirty; - memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0])); - memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0])); - } + for (work = to_clean; work != 0; work &= work - 1) { + int mmu_idx = ctz32(work); + tlb_flush_one_mmuidx_locked(env, mmu_idx); } - qemu_spin_unlock(&env->tlb_lock); + + qemu_spin_unlock(&env->tlb_c.lock); cpu_tb_jmp_cache_clear(cpu); - tlb_debug("done\n"); + if (to_clean == ALL_MMUIDX_BITS) { + atomic_set(&env->tlb_c.full_flush_count, + env->tlb_c.full_flush_count + 1); + } else { + atomic_set(&env->tlb_c.part_flush_count, + env->tlb_c.part_flush_count + ctpop16(to_clean)); + if (to_clean != asked) { + atomic_set(&env->tlb_c.elide_flush_count, + env->tlb_c.elide_flush_count + + ctpop16(asked & ~to_clean)); + } + } } void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap) { tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap); - if (!qemu_cpu_is_self(cpu)) { - uint16_t pending_flushes = idxmap; - pending_flushes &= ~atomic_mb_read(&cpu->pending_tlb_flush); - - if (pending_flushes) { - tlb_debug("reduced mmu_idx: 0x%" PRIx16 "\n", pending_flushes); - - atomic_or(&cpu->pending_tlb_flush, pending_flushes); - async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work, - RUN_ON_CPU_HOST_INT(pending_flushes)); - } + if (cpu->created && !qemu_cpu_is_self(cpu)) { + async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work, + RUN_ON_CPU_HOST_INT(idxmap)); } else { - tlb_flush_by_mmuidx_async_work(cpu, - RUN_ON_CPU_HOST_INT(idxmap)); + tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap)); } } +void tlb_flush(CPUState *cpu) +{ + tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS); +} + void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap) { const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work; @@ -243,8 +196,12 @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap) fn(src_cpu, RUN_ON_CPU_HOST_INT(idxmap)); } -void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, - uint16_t idxmap) +void tlb_flush_all_cpus(CPUState *src_cpu) +{ + tlb_flush_by_mmuidx_all_cpus(src_cpu, ALL_MMUIDX_BITS); +} + +void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap) { const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work; @@ -254,6 +211,11 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap)); } +void tlb_flush_all_cpus_synced(CPUState *src_cpu) +{ + tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS); +} + static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry, target_ulong page) { @@ -262,7 +224,7 @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry, tlb_hit_page(tlb_entry->addr_code, page); } -/* Called with tlb_lock held */ +/* Called with tlb_c.lock held */ static inline void tlb_flush_entry_locked(CPUTLBEntry *tlb_entry, target_ulong page) { @@ -271,7 +233,7 @@ static inline void tlb_flush_entry_locked(CPUTLBEntry *tlb_entry, } } -/* Called with tlb_lock held */ +/* Called with tlb_c.lock held */ static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx, target_ulong page) { @@ -283,46 +245,21 @@ static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx, } } -static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data) +static void tlb_flush_page_locked(CPUArchState *env, int midx, + target_ulong page) { - CPUArchState *env = cpu->env_ptr; - target_ulong addr = (target_ulong) data.target_ptr; - int mmu_idx; - - assert_cpu_is_self(cpu); - - tlb_debug("page :" TARGET_FMT_lx "\n", addr); + target_ulong lp_addr = env->tlb_d[midx].large_page_addr; + target_ulong lp_mask = env->tlb_d[midx].large_page_mask; /* Check if we need to flush due to large pages. */ - if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) { - tlb_debug("forcing full flush (" + if ((page & lp_mask) == lp_addr) { + tlb_debug("forcing full flush midx %d (" TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", - env->tlb_flush_addr, env->tlb_flush_mask); - - tlb_flush(cpu); - return; - } - - addr &= TARGET_PAGE_MASK; - qemu_spin_lock(&env->tlb_lock); - for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { - tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr); - tlb_flush_vtlb_page_locked(env, mmu_idx, addr); - } - qemu_spin_unlock(&env->tlb_lock); - - tb_flush_jmp_cache(cpu, addr); -} - -void tlb_flush_page(CPUState *cpu, target_ulong addr) -{ - tlb_debug("page :" TARGET_FMT_lx "\n", addr); - - if (!qemu_cpu_is_self(cpu)) { - async_run_on_cpu(cpu, tlb_flush_page_async_work, - RUN_ON_CPU_TARGET_PTR(addr)); + midx, lp_addr, lp_mask); + tlb_flush_one_mmuidx_locked(env, midx); } else { - tlb_flush_page_async_work(cpu, RUN_ON_CPU_TARGET_PTR(addr)); + tlb_flush_entry_locked(tlb_entry(env, midx, page), page); + tlb_flush_vtlb_page_locked(env, midx, page); } } @@ -342,44 +279,20 @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu, assert_cpu_is_self(cpu); - tlb_debug("flush page addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n", + tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%lx\n", addr, mmu_idx_bitmap); - qemu_spin_lock(&env->tlb_lock); + qemu_spin_lock(&env->tlb_c.lock); for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { if (test_bit(mmu_idx, &mmu_idx_bitmap)) { - tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr); - tlb_flush_vtlb_page_locked(env, mmu_idx, addr); + tlb_flush_page_locked(env, mmu_idx, addr); } } - qemu_spin_unlock(&env->tlb_lock); + qemu_spin_unlock(&env->tlb_c.lock); tb_flush_jmp_cache(cpu, addr); } -static void tlb_check_page_and_flush_by_mmuidx_async_work(CPUState *cpu, - run_on_cpu_data data) -{ - CPUArchState *env = cpu->env_ptr; - target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr; - target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK; - unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS; - - tlb_debug("addr:"TARGET_FMT_lx" mmu_idx: %04lx\n", addr, mmu_idx_bitmap); - - /* Check if we need to flush due to large pages. */ - if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) { - tlb_debug("forced full flush (" - TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", - env->tlb_flush_addr, env->tlb_flush_mask); - - tlb_flush_by_mmuidx_async_work(cpu, - RUN_ON_CPU_HOST_INT(mmu_idx_bitmap)); - } else { - tlb_flush_page_by_mmuidx_async_work(cpu, data); - } -} - void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap) { target_ulong addr_and_mmu_idx; @@ -391,18 +304,23 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap) addr_and_mmu_idx |= idxmap; if (!qemu_cpu_is_self(cpu)) { - async_run_on_cpu(cpu, tlb_check_page_and_flush_by_mmuidx_async_work, + async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_work, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx)); } else { - tlb_check_page_and_flush_by_mmuidx_async_work( + tlb_flush_page_by_mmuidx_async_work( cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx)); } } +void tlb_flush_page(CPUState *cpu, target_ulong addr) +{ + tlb_flush_page_by_mmuidx(cpu, addr, ALL_MMUIDX_BITS); +} + void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr, uint16_t idxmap) { - const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work; + const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work; target_ulong addr_and_mmu_idx; tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap); @@ -415,11 +333,16 @@ void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr, fn(src_cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx)); } +void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr) +{ + tlb_flush_page_by_mmuidx_all_cpus(src, addr, ALL_MMUIDX_BITS); +} + void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu, - target_ulong addr, - uint16_t idxmap) + target_ulong addr, + uint16_t idxmap) { - const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work; + const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work; target_ulong addr_and_mmu_idx; tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap); @@ -432,21 +355,9 @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu, async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx)); } -void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr) +void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr) { - const run_on_cpu_func fn = tlb_flush_page_async_work; - - flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr)); - fn(src, RUN_ON_CPU_TARGET_PTR(addr)); -} - -void tlb_flush_page_all_cpus_synced(CPUState *src, - target_ulong addr) -{ - const run_on_cpu_func fn = tlb_flush_page_async_work; - - flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr)); - async_safe_run_on_cpu(src, fn, RUN_ON_CPU_TARGET_PTR(addr)); + tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS); } /* update the TLBs so that writes to code in the virtual page 'addr' @@ -479,7 +390,7 @@ void tlb_unprotect_code(ram_addr_t ram_addr) * te->addr_write with atomic_set. We don't need to worry about this for * oversized guests as MTTCG is disabled for them. * - * Called with tlb_lock held. + * Called with tlb_c.lock held. */ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry, uintptr_t start, uintptr_t length) @@ -501,7 +412,7 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry, } /* - * Called with tlb_lock held. + * Called with tlb_c.lock held. * Called only from the vCPU context, i.e. the TLB's owner thread. */ static inline void copy_tlb_helper_locked(CPUTLBEntry *d, const CPUTLBEntry *s) @@ -511,7 +422,7 @@ static inline void copy_tlb_helper_locked(CPUTLBEntry *d, const CPUTLBEntry *s) /* This is a cross vCPU call (i.e. another vCPU resetting the flags of * the target vCPU). - * We must take tlb_lock to avoid racing with another vCPU update. The only + * We must take tlb_c.lock to avoid racing with another vCPU update. The only * thing actually updated is the target TLB entry ->addr_write flags. */ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length) @@ -521,7 +432,7 @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length) int mmu_idx; env = cpu->env_ptr; - qemu_spin_lock(&env->tlb_lock); + qemu_spin_lock(&env->tlb_c.lock); for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { unsigned int i; @@ -535,10 +446,10 @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length) length); } } - qemu_spin_unlock(&env->tlb_lock); + qemu_spin_unlock(&env->tlb_c.lock); } -/* Called with tlb_lock held */ +/* Called with tlb_c.lock held */ static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry, target_ulong vaddr) { @@ -557,7 +468,7 @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr) assert_cpu_is_self(cpu); vaddr &= TARGET_PAGE_MASK; - qemu_spin_lock(&env->tlb_lock); + qemu_spin_lock(&env->tlb_c.lock); for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { tlb_set_dirty1_locked(tlb_entry(env, mmu_idx, vaddr), vaddr); } @@ -568,30 +479,31 @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr) tlb_set_dirty1_locked(&env->tlb_v_table[mmu_idx][k], vaddr); } } - qemu_spin_unlock(&env->tlb_lock); + qemu_spin_unlock(&env->tlb_c.lock); } /* Our TLB does not support large pages, so remember the area covered by large pages and trigger a full TLB flush if these are invalidated. */ -static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr, - target_ulong size) +static void tlb_add_large_page(CPUArchState *env, int mmu_idx, + target_ulong vaddr, target_ulong size) { - target_ulong mask = ~(size - 1); + target_ulong lp_addr = env->tlb_d[mmu_idx].large_page_addr; + target_ulong lp_mask = ~(size - 1); - if (env->tlb_flush_addr == (target_ulong)-1) { - env->tlb_flush_addr = vaddr & mask; - env->tlb_flush_mask = mask; - return; - } - /* Extend the existing region to include the new page. - This is a compromise between unnecessary flushes and the cost - of maintaining a full variable size TLB. */ - mask &= env->tlb_flush_mask; - while (((env->tlb_flush_addr ^ vaddr) & mask) != 0) { - mask <<= 1; + if (lp_addr == (target_ulong)-1) { + /* No previous large page. */ + lp_addr = vaddr; + } else { + /* Extend the existing region to include the new page. + This is a compromise between unnecessary flushes and + the cost of maintaining a full variable size TLB. */ + lp_mask &= env->tlb_d[mmu_idx].large_page_mask; + while (((lp_addr ^ vaddr) & lp_mask) != 0) { + lp_mask <<= 1; + } } - env->tlb_flush_addr &= mask; - env->tlb_flush_mask = mask; + env->tlb_d[mmu_idx].large_page_addr = lp_addr & lp_mask; + env->tlb_d[mmu_idx].large_page_mask = lp_mask; } /* Add a new TLB entry. At most one entry for a given virtual address @@ -618,12 +530,10 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, assert_cpu_is_self(cpu); - if (size < TARGET_PAGE_SIZE) { + if (size <= TARGET_PAGE_SIZE) { sz = TARGET_PAGE_SIZE; } else { - if (size > TARGET_PAGE_SIZE) { - tlb_add_large_page(env, vaddr, size); - } + tlb_add_large_page(env, mmu_idx, vaddr, size); sz = size; } vaddr_page = vaddr & TARGET_PAGE_MASK; @@ -669,7 +579,10 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, * a longer critical section, but this is not a concern since the TLB lock * is unlikely to be contended. */ - qemu_spin_lock(&env->tlb_lock); + qemu_spin_lock(&env->tlb_c.lock); + + /* Note that the tlb is no longer clean. */ + env->tlb_c.dirty |= 1 << mmu_idx; /* Make sure there's no cached translation for the new page. */ tlb_flush_vtlb_page_locked(env, mmu_idx, vaddr_page); @@ -679,7 +592,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, * different page; otherwise just overwrite the stale data. */ if (!tlb_hit_page_anyprot(te, vaddr_page)) { - unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE; + unsigned vidx = env->tlb_d[mmu_idx].vindex++ % CPU_VTLB_SIZE; CPUTLBEntry *tv = &env->tlb_v_table[mmu_idx][vidx]; /* Evict the old entry into the victim tlb. */ @@ -736,7 +649,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, } copy_tlb_helper_locked(te, &tn); - qemu_spin_unlock(&env->tlb_lock); + qemu_spin_unlock(&env->tlb_c.lock); } /* Add a new TLB entry, but without specifying the memory @@ -917,11 +830,11 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, /* Found entry in victim tlb, swap tlb and iotlb. */ CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index]; - qemu_spin_lock(&env->tlb_lock); + qemu_spin_lock(&env->tlb_c.lock); copy_tlb_helper_locked(&tmptlb, tlb); copy_tlb_helper_locked(tlb, vtlb); copy_tlb_helper_locked(vtlb, &tmptlb); - qemu_spin_unlock(&env->tlb_lock); + qemu_spin_unlock(&env->tlb_c.lock); CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index]; CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx]; diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 356dcd0948..639f0b2728 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2290,7 +2290,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) { struct tb_tree_stats tst = {}; struct qht_stats hst; - size_t nb_tbs; + size_t nb_tbs, flush_full, flush_part, flush_elide; tcg_tb_foreach(tb_tree_stats_iter, &tst); nb_tbs = tst.nb_tbs; @@ -2326,7 +2326,11 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cpu_fprintf(f, "TB flush count %u\n", atomic_read(&tb_ctx.tb_flush_count)); cpu_fprintf(f, "TB invalidate count %zu\n", tcg_tb_phys_invalidate_count()); - cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count()); + + tlb_flush_counts(&flush_full, &flush_part, &flush_elide); + cpu_fprintf(f, "TLB full flushes %zu\n", flush_full); + cpu_fprintf(f, "TLB partial flushes %zu\n", flush_part); + cpu_fprintf(f, "TLB elided flushes %zu\n", flush_elide); tcg_dump_info(f, cpu_fprintf); } diff --git a/chardev/char-socket.c b/chardev/char-socket.c index a75b46d9fe..eaa8e8b68f 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -26,6 +26,7 @@ #include "chardev/char.h" #include "io/channel-socket.h" #include "io/channel-tls.h" +#include "io/channel-websock.h" #include "io/net-listener.h" #include "qemu/error-report.h" #include "qemu/option.h" @@ -68,6 +69,8 @@ typedef struct { GSource *telnet_source; TCPChardevTelnetInit *telnet_init; + bool is_websock; + GSource *reconnect_timer; int64_t reconnect_time; bool connect_err_reported; @@ -389,30 +392,37 @@ static void tcp_chr_free_connection(Chardev *chr) s->connected = 0; } -static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr, - bool is_listen, bool is_telnet) +static const char *qemu_chr_socket_protocol(SocketChardev *s) +{ + if (s->is_telnet) { + return "telnet"; + } + return s->is_websock ? "websocket" : "tcp"; +} + +static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix) { - switch (addr->type) { + switch (s->addr->type) { case SOCKET_ADDRESS_TYPE_INET: return g_strdup_printf("%s%s:%s:%s%s", prefix, - is_telnet ? "telnet" : "tcp", - addr->u.inet.host, - addr->u.inet.port, - is_listen ? ",server" : ""); + qemu_chr_socket_protocol(s), + s->addr->u.inet.host, + s->addr->u.inet.port, + s->is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_TYPE_UNIX: return g_strdup_printf("%sunix:%s%s", prefix, - addr->u.q_unix.path, - is_listen ? ",server" : ""); + s->addr->u.q_unix.path, + s->is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_TYPE_FD: - return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.str, - is_listen ? ",server" : ""); + return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str, + s->is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_TYPE_VSOCK: return g_strdup_printf("%svsock:%s:%s", prefix, - addr->u.vsock.cid, - addr->u.vsock.port); + s->addr->u.vsock.cid, + s->addr->u.vsock.port); default: abort(); } @@ -424,8 +434,7 @@ static void update_disconnected_filename(SocketChardev *s) g_free(chr->filename); if (s->addr) { - chr->filename = SocketAddress_to_str("disconnected:", s->addr, - s->is_listen, s->is_telnet); + chr->filename = qemu_chr_socket_address(s, "disconnected:"); } else { chr->filename = g_strdup("disconnected:socket"); } @@ -514,10 +523,12 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) return size; } -static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len, - struct sockaddr_storage *ps, socklen_t ps_len, - bool is_listen, bool is_telnet) +static char *qemu_chr_compute_filename(SocketChardev *s) { + struct sockaddr_storage *ss = &s->sioc->localAddr; + struct sockaddr_storage *ps = &s->sioc->remoteAddr; + socklen_t ss_len = s->sioc->localAddrLen; + socklen_t ps_len = s->sioc->remoteAddrLen; char shost[NI_MAXHOST], sserv[NI_MAXSERV]; char phost[NI_MAXHOST], pserv[NI_MAXSERV]; const char *left = "", *right = ""; @@ -527,7 +538,7 @@ static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len, case AF_UNIX: return g_strdup_printf("unix:%s%s", ((struct sockaddr_un *)(ss))->sun_path, - is_listen ? ",server" : ""); + s->is_listen ? ",server" : ""); #endif case AF_INET6: left = "["; @@ -539,9 +550,9 @@ static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len, getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost), pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV); return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s", - is_telnet ? "telnet" : "tcp", + qemu_chr_socket_protocol(s), left, shost, right, sserv, - is_listen ? ",server" : "", + s->is_listen ? ",server" : "", left, phost, right, pserv); default: @@ -576,10 +587,7 @@ static void tcp_chr_connect(void *opaque) SocketChardev *s = SOCKET_CHARDEV(opaque); g_free(chr->filename); - chr->filename = sockaddr_to_str( - &s->sioc->localAddr, s->sioc->localAddrLen, - &s->sioc->remoteAddr, s->sioc->remoteAddrLen, - s->is_listen, s->is_telnet); + chr->filename = qemu_chr_compute_filename(s); s->connected = 1; update_ioc_handlers(s); @@ -709,6 +717,41 @@ cont: } +static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data) +{ + Chardev *chr = user_data; + SocketChardev *s = user_data; + + if (qio_task_propagate_error(task, NULL)) { + tcp_chr_disconnect(chr); + } else { + if (s->do_telnetopt) { + tcp_chr_telnet_init(chr); + } else { + tcp_chr_connect(chr); + } + } +} + + +static void tcp_chr_websock_init(Chardev *chr) +{ + SocketChardev *s = SOCKET_CHARDEV(chr); + QIOChannelWebsock *wioc = NULL; + gchar *name; + + wioc = qio_channel_websock_new_server(s->ioc); + + name = g_strdup_printf("chardev-websocket-server-%s", chr->label); + qio_channel_set_name(QIO_CHANNEL(wioc), name); + g_free(name); + object_unref(OBJECT(s->ioc)); + s->ioc = QIO_CHANNEL(wioc); + + qio_channel_websock_handshake(wioc, tcp_chr_websock_handshake, chr, NULL); +} + + static void tcp_chr_tls_handshake(QIOTask *task, gpointer user_data) { @@ -718,7 +761,9 @@ static void tcp_chr_tls_handshake(QIOTask *task, if (qio_task_propagate_error(task, NULL)) { tcp_chr_disconnect(chr); } else { - if (s->do_telnetopt) { + if (s->is_websock) { + tcp_chr_websock_init(chr); + } else if (s->do_telnetopt) { tcp_chr_telnet_init(chr); } else { tcp_chr_connect(chr); @@ -804,12 +849,12 @@ static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc) if (s->tls_creds) { tcp_chr_tls_init(chr); + } else if (s->is_websock) { + tcp_chr_websock_init(chr); + } else if (s->do_telnetopt) { + tcp_chr_telnet_init(chr); } else { - if (s->do_telnetopt) { - tcp_chr_telnet_init(chr); - } else { - tcp_chr_connect(chr); - } + tcp_chr_connect(chr); } return 0; @@ -954,13 +999,20 @@ static void qmp_chardev_open_socket(Chardev *chr, bool is_telnet = sock->has_telnet ? sock->telnet : false; bool is_tn3270 = sock->has_tn3270 ? sock->tn3270 : false; bool is_waitconnect = sock->has_wait ? sock->wait : false; + bool is_websock = sock->has_websocket ? sock->websocket : false; int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0; QIOChannelSocket *sioc = NULL; SocketAddress *addr; + if (!is_listen && is_websock) { + error_setg(errp, "%s", "Websocket client is not implemented"); + goto error; + } + s->is_listen = is_listen; s->is_telnet = is_telnet; s->is_tn3270 = is_tn3270; + s->is_websock = is_websock; s->do_nodelay = do_nodelay; if (sock->tls_creds) { Object *creds; @@ -997,6 +1049,10 @@ static void qmp_chardev_open_socket(Chardev *chr, s->addr = addr = socket_address_flatten(sock->addr); + if (sock->has_reconnect && addr->type == SOCKET_ADDRESS_TYPE_FD) { + error_setg(errp, "'reconnect' option is incompatible with 'fd'"); + goto error; + } qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */ if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) { @@ -1067,6 +1123,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true); bool is_telnet = qemu_opt_get_bool(opts, "telnet", false); bool is_tn3270 = qemu_opt_get_bool(opts, "tn3270", false); + bool is_websock = qemu_opt_get_bool(opts, "websocket", false); bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true); int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0); const char *path = qemu_opt_get(opts, "path"); @@ -1115,9 +1172,11 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, sock->telnet = is_telnet; sock->has_tn3270 = true; sock->tn3270 = is_tn3270; + sock->has_websocket = true; + sock->websocket = is_websock; sock->has_wait = true; sock->wait = is_waitconnect; - sock->has_reconnect = true; + sock->has_reconnect = qemu_opt_find(opts, "reconnect"); sock->reconnect = reconnect; sock->tls_creds = g_strdup(tls_creds); diff --git a/chardev/char.c b/chardev/char.c index 7f07a1bfbd..79b05fb7b7 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -409,7 +409,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, } if (strstart(filename, "tcp:", &p) || strstart(filename, "telnet:", &p) || - strstart(filename, "tn3270:", &p)) { + strstart(filename, "tn3270:", &p) || + strstart(filename, "websocket:", &p)) { if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { host[0] = 0; if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) @@ -429,6 +430,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, qemu_opt_set(opts, "telnet", "on", &error_abort); } else if (strstart(filename, "tn3270:", &p)) { qemu_opt_set(opts, "tn3270", "on", &error_abort); + } else if (strstart(filename, "websocket:", &p)) { + qemu_opt_set(opts, "websocket", "on", &error_abort); } return opts; } @@ -861,6 +864,9 @@ QemuOptsList qemu_chardev_opts = { .name = "tls-creds", .type = QEMU_OPT_STRING, },{ + .name = "websocket", + .type = QEMU_OPT_BOOL, + },{ .name = "width", .type = QEMU_OPT_NUMBER, },{ @@ -474,6 +474,7 @@ libxml2="" docker="no" debug_mutex="no" libpmem="" +libudev="no" # cross compilers defaults, can be overridden with --cross-cc-ARCH cross_cc_aarch64="aarch64-linux-gnu-gcc" @@ -870,6 +871,7 @@ Linux) vhost_vsock="yes" QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES" supported_os="yes" + libudev="yes" ;; esac @@ -5609,6 +5611,17 @@ if test "$libnfs" != "no" ; then fi fi +########################################## +# Do we have libudev +if test "$libudev" != "no" ; then + if $pkg_config libudev && test "$static" != "yes"; then + libudev="yes" + libudev_libs=$($pkg_config --libs libudev) + else + libudev="no" + fi +fi + # Now we've finished running tests it's OK to add -Werror to the compiler flags if test "$werror" = "yes"; then QEMU_CFLAGS="-Werror $QEMU_CFLAGS" @@ -6033,6 +6046,7 @@ echo "VxHS block device $vxhs" echo "capstone $capstone" echo "docker $docker" echo "libpmem support $libpmem" +echo "libudev $libudev" if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -6128,7 +6142,7 @@ if test "$mingw32" = "yes" ; then echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak fi if test "$guest_agent_ntddscsi" = "yes" ; then - echo "CONFIG_QGA_NTDDDISK=y" >> $config_host_mak + echo "CONFIG_QGA_NTDDSCSI=y" >> $config_host_mak fi if test "$guest_agent_msi" = "yes"; then echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak @@ -6868,6 +6882,11 @@ if test "$docker" != "no"; then echo "HAVE_USER_DOCKER=y" >> $config_host_mak fi +if test "$libudev" != "no"; then + echo "CONFIG_LIBUDEV=y" >> $config_host_mak + echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak +fi + # use included Linux headers if test "$linux" = "yes" ; then mkdir -p linux-headers @@ -7105,6 +7124,7 @@ case "$target_name" in ;; xtensa|xtensaeb) TARGET_ARCH=xtensa + bflt="yes" mttcg="yes" target_compiler=$cross_cc_xtensa ;; diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt index 6302469d0e..e2686bb338 100644 --- a/docs/COLO-FT.txt +++ b/docs/COLO-FT.txt @@ -173,7 +173,7 @@ Secondary: { 'execute': 'nbd-server-start', 'arguments': {'addr': {'type': 'inet', 'data': {'host': 'xx.xx.xx.xx', 'port': '8889'} } } } -{'execute': 'nbd-server-add', 'arguments': {'device': 'secondeary-disk0', 'writable': true } } +{'execute': 'nbd-server-add', 'arguments': {'device': 'secondary-disk0', 'writable': true } } Note: a. The qmp command nbd-server-start and nbd-server-add must be run diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index a227754f86..18e2c0868a 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -545,10 +545,39 @@ Tests based on ``avocado_qemu.Test`` can easily: - http://avocado-framework.readthedocs.io/en/latest/api/test/avocado.html#avocado.Test - http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html -Installation ------------- +Running tests +------------- + +You can run the acceptance tests simply by executing: + +.. code:: + + make check-acceptance + +This involves the automatic creation of Python virtual environment +within the build tree (at ``tests/venv``) which will have all the +right dependencies, and will save tests results also within the +build tree (at ``tests/results``). -To install Avocado and its dependencies, run: +Note: the build environment must be using a Python 3 stack, and have +the ``venv`` and ``pip`` packages installed. If necessary, make sure +``configure`` is called with ``--python=`` and that those modules are +available. On Debian and Ubuntu based systems, depending on the +specific version, they may be on packages named ``python3-venv`` and +``python3-pip``. + +The scripts installed inside the virtual environment may be used +without an "activation". For instance, the Avocado test runner +may be invoked by running: + + .. code:: + + tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/acceptance/ + +Manual Installation +------------------- + +To manually install Avocado and its dependencies, run: .. code:: @@ -689,11 +718,15 @@ The exact QEMU binary to be used on QEMUMachine. Uninstalling Avocado -------------------- -If you've followed the installation instructions above, you can easily -uninstall Avocado. Start by listing the packages you have installed:: +If you've followed the manual installation instructions above, you can +easily uninstall Avocado. Start by listing the packages you have +installed:: pip list --user And remove any package you want with:: pip uninstall <package_name> + +If you've used ``make check-acceptance``, the Python virtual environment where +Avocado is installed will be cleaned up as part of ``make check-clean``. diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt index 0e9bbebe1d..1af82bba86 100644 --- a/docs/specs/tpm.txt +++ b/docs/specs/tpm.txt @@ -20,6 +20,21 @@ QEMU files related to TPM TIS interface: - hw/tpm/tpm_tis.h +QEMU also implements a TPM CRB interface following the Trusted Computing +Group's specification "TCG PC Client Platform TPM Profile (PTP) +Specification", Family "2.0", Level 00 Revision 01.03 v22, May 22, 2017. +This specification, or a later version of it, can be accessed from the +following URL: + +https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ + +The CRB interface makes a memory mapped IO region in the area 0xfed40000 - +0xfed40fff (1 locality) available to the guest operating system. + +QEMU files related to TPM CRB interface: + - hw/tpm/tpm_crb.c + + = ACPI Interface = The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT and passes diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 10bc20dbec..70f4b10284 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -166,6 +166,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number, trace_tpm_emulator_set_locality(locty_number); + memset(&loc, 0, sizeof(loc)); loc.u.req.loc = locty_number; if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc, sizeof(loc), sizeof(loc)) < 0) { diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 4ff62f32bf..6a60f94a41 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -141,18 +141,53 @@ typedef struct CPUIOTLBEntry { MemTxAttrs attrs; } CPUIOTLBEntry; +typedef struct CPUTLBDesc { + /* + * Describe a region covering all of the large pages allocated + * into the tlb. When any page within this region is flushed, + * we must flush the entire tlb. The region is matched if + * (addr & large_page_mask) == large_page_addr. + */ + target_ulong large_page_addr; + target_ulong large_page_mask; + /* The next index to use in the tlb victim table. */ + size_t vindex; +} CPUTLBDesc; + +/* + * Data elements that are shared between all MMU modes. + */ +typedef struct CPUTLBCommon { + /* Serialize updates to tlb_table and tlb_v_table, and others as noted. */ + QemuSpin lock; + /* + * Within dirty, for each bit N, modifications have been made to + * mmu_idx N since the last time that mmu_idx was flushed. + * Protected by tlb_c.lock. + */ + uint16_t dirty; + /* + * Statistics. These are not lock protected, but are read and + * written atomically. This allows the monitor to print a snapshot + * of the stats without interfering with the cpu. + */ + size_t full_flush_count; + size_t part_flush_count; + size_t elide_flush_count; +} CPUTLBCommon; + +/* + * The meaning of each of the MMU modes is defined in the target code. + * Note that NB_MMU_MODES is not yet defined; we can only reference it + * within preprocessor defines that will be expanded later. + */ #define CPU_COMMON_TLB \ - /* The meaning of the MMU modes is defined in the target code. */ \ - /* tlb_lock serializes updates to tlb_table and tlb_v_table */ \ - QemuSpin tlb_lock; \ + CPUTLBCommon tlb_c; \ + CPUTLBDesc tlb_d[NB_MMU_MODES]; \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \ CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ - CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \ - size_t tlb_flush_count; \ - target_ulong tlb_flush_addr; \ - target_ulong tlb_flush_mask; \ - target_ulong vtlb_index; \ + CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; #else diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h index c91db211bc..5373188be3 100644 --- a/include/exec/cputlb.h +++ b/include/exec/cputlb.h @@ -23,6 +23,6 @@ /* cputlb.c */ void tlb_protect_code(ram_addr_t ram_addr); void tlb_unprotect_code(ram_addr_t ram_addr); -size_t tlb_flush_count(void); +void tlb_flush_counts(size_t *full, size_t *part, size_t *elide); #endif #endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index dfe6746692..136fe497b6 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -300,7 +300,15 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = TYPE_X86_CPU,\ .property = "x-hv-synic-kvm-only",\ .value = "on",\ - } + },{\ + .driver = "Skylake-Server" "-" TYPE_X86_CPU,\ + .property = "pku",\ + .value = "off",\ + },{\ + .driver = "Skylake-Server-IBRS" "-" TYPE_X86_CPU,\ + .property = "pku",\ + .value = "off",\ + }, #define PC_COMPAT_2_12 \ HW_COMPAT_2_12 \ diff --git a/include/qom/cpu.h b/include/qom/cpu.h index def0c64308..1396f53e5b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -429,12 +429,6 @@ struct CPUState { struct hax_vcpu_state *hax_vcpu; - /* The pending_tlb_flush flag is set and cleared atomically to - * avoid potential races. The aim of the flag is to avoid - * unnecessary flushes. - */ - uint16_t pending_tlb_flush; - int hvf_fd; /* track IOMMUs whose translations we've cached in the TCG TLB */ diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 0b64b8e067..97d8d9d0d5 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -463,6 +463,8 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); +uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); + void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); diff --git a/io/channel-websock.c b/io/channel-websock.c index e6608b969d..dc43dc6bb9 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -163,6 +163,7 @@ qio_channel_websock_handshake_send_res(QIOChannelWebsock *ioc, responselen = strlen(response); buffer_reserve(&ioc->encoutput, responselen); buffer_append(&ioc->encoutput, response, responselen); + g_free(response); va_end(vargs); } diff --git a/linux-user/flatload.c b/linux-user/flatload.c index 10c529910f..0122ab3afe 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -37,7 +37,7 @@ #include "qemu.h" #include "flat.h" -#include "target_flat.h" +#include <target_flat.h> //#define DEBUG @@ -771,10 +771,10 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) /* Enforce final stack alignment of 16 bytes. This is sufficient for all current targets, and excess alignment is harmless. */ stack_len = bprm->envc + bprm->argc + 2; - stack_len += 3; /* argc, arvg, argp */ + stack_len += flat_argvp_envp_on_stack() ? 2 : 0; /* arvg, argp */ + stack_len += 1; /* argc */ stack_len *= sizeof(abi_ulong); - if ((sp + stack_len) & 15) - sp -= 16 - ((sp + stack_len) & 15); + sp -= (sp - stack_len) & 15; sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, flat_argvp_envp_on_stack()); diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c index b4d3d8af3d..30c3332af4 100644 --- a/linux-user/m68k/cpu_loop.c +++ b/linux-user/m68k/cpu_loop.c @@ -55,7 +55,6 @@ void cpu_loop(CPUM68KState *env) break; case EXCP_LINEA: case EXCP_LINEF: - case EXCP_UNSUPPORTED: do_sigill: info.si_signo = TARGET_SIGILL; info.si_errno = 0; diff --git a/linux-user/xtensa/target_flat.h b/linux-user/xtensa/target_flat.h new file mode 100644 index 0000000000..732adddb0d --- /dev/null +++ b/linux-user/xtensa/target_flat.h @@ -0,0 +1,10 @@ +/* If your arch needs to do custom stuff, create your own target_flat.h + * header file in linux-user/<your arch>/ + */ +#define flat_argvp_envp_on_stack() 0 +#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) +#define flat_old_ram_flag(flag) (flag) +#define flat_get_relocate_addr(relval) (relval) +#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp) +#define flat_set_persistent(relval, persistent) (*persistent) +#define flat_put_addr_at_rp(rp, addr, relval) put_user_ual(addr, rp) diff --git a/migration/migration.c b/migration/migration.c index 8b36e7f184..b261c1e4ce 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -742,7 +742,7 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) * Return true if we're already in the middle of a migration * (i.e. any of the active or setup states) */ -static bool migration_is_setup_or_active(int state) +bool migration_is_setup_or_active(int state) { switch (state) { case MIGRATION_STATUS_ACTIVE: diff --git a/migration/migration.h b/migration/migration.h index f7813f8261..e413d4d8b6 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -241,6 +241,8 @@ void migrate_fd_error(MigrationState *s, const Error *error); void migrate_fd_connect(MigrationState *s, Error *error_in); +bool migration_is_setup_or_active(int state); + void migrate_init(MigrationState *s); bool migration_is_blocked(Error **errp); /* True if outgoing migration has entered postcopy phase */ diff --git a/migration/savevm.c b/migration/savevm.c index 9992af4db4..ef707b8c43 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1327,21 +1327,25 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) MigrationState *ms = migrate_get_current(); MigrationStatus status; - migrate_init(ms); - - ms->to_dst_file = f; + if (migration_is_setup_or_active(ms->state) || + ms->state == MIGRATION_STATUS_CANCELLING || + ms->state == MIGRATION_STATUS_COLO) { + error_setg(errp, QERR_MIGRATION_ACTIVE); + return -EINVAL; + } if (migration_is_blocked(errp)) { - ret = -EINVAL; - goto done; + return -EINVAL; } if (migrate_use_block()) { error_setg(errp, "Block migration and snapshots are incompatible"); - ret = -EINVAL; - goto done; + return -EINVAL; } + migrate_init(ms); + ms->to_dst_file = f; + qemu_mutex_unlock_iothread(); qemu_savevm_state_header(f); qemu_savevm_state_setup(f); @@ -1363,7 +1367,6 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) error_setg_errno(errp, -ret, "Error while writing VM state"); } -done: if (ret != 0) { status = MIGRATION_STATUS_FAILED; } else { diff --git a/qapi/char.json b/qapi/char.json index b7b2a05766..79bac598a0 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -251,6 +251,8 @@ # sockets (default: false) # @tn3270: enable tn3270 protocol on server # sockets (default: false) (Since: 2.10) +# @websocket: enable websocket protocol on server +# sockets (default: false) (Since: 3.1) # @reconnect: For a client socket, if a socket is disconnected, # then attempt a reconnect after the given number of seconds. # Setting this to zero disables this function. (default: 0) @@ -265,6 +267,7 @@ '*nodelay' : 'bool', '*telnet' : 'bool', '*tn3270' : 'bool', + '*websocket' : 'bool', '*reconnect' : 'int' }, 'base': 'ChardevCommon' } diff --git a/qapi/migration.json b/qapi/migration.json index 0928f4b727..38d4c41d88 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1317,7 +1317,7 @@ # # @reason: describes the reason for the COLO exit. # -# Since: 3.0 +# Since: 3.1 ## { 'struct': 'COLOStatus', 'data': { 'mode': 'COLOMode', 'reason': 'COLOExitReason' } } @@ -1334,7 +1334,7 @@ # -> { "execute": "query-colo-status" } # <- { "return": { "mode": "primary", "active": true, "reason": "request" } } # -# Since: 3.0 +# Since: 3.1 ## { 'command': 'query-colo-status', 'returns': 'COLOStatus' } diff --git a/qemu-options.hx b/qemu-options.hx index 08f8516a9a..38c7a978c1 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2414,9 +2414,9 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev help\n" "-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4][,ipv6][,nodelay][,reconnect=seconds]\n" - " [,server][,nowait][,telnet][,reconnect=seconds][,mux=on|off]\n" + " [,server][,nowait][,telnet][,websocket][,reconnect=seconds][,mux=on|off]\n" " [,logfile=PATH][,logappend=on|off][,tls-creds=ID] (tcp)\n" - "-chardev socket,id=id,path=path[,server][,nowait][,telnet][,reconnect=seconds]\n" + "-chardev socket,id=id,path=path[,server][,nowait][,telnet][,websocket][,reconnect=seconds]\n" " [,mux=on|off][,logfile=PATH][,logappend=on|off] (unix)\n" "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n" " [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n" @@ -2544,7 +2544,7 @@ The available backends are: A void device. This device will not emit any data, and will drop any data it receives. The null backend does not take any options. -@item -chardev socket,id=@var{id}[,@var{TCP options} or @var{unix options}][,server][,nowait][,telnet][,reconnect=@var{seconds}][,tls-creds=@var{id}] +@item -chardev socket,id=@var{id}[,@var{TCP options} or @var{unix options}][,server][,nowait][,telnet][,websocket][,reconnect=@var{seconds}][,tls-creds=@var{id}] Create a two-way stream socket, which can be either a TCP or a unix socket. A unix socket will be created if @option{path} is specified. Behaviour is @@ -2558,6 +2558,9 @@ connect to a listening socket. @option{telnet} specifies that traffic on the socket should interpret telnet escape sequences. +@option{websocket} specifies that the socket uses WebSocket protocol for +communication. + @option{reconnect} sets the timeout for reconnecting on non-server sockets when the remote end goes away. qemu will delay this many seconds and then attempt to reconnect. Zero disables reconnecting, and is the default. @@ -3106,6 +3109,10 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break sequence. Typically in unix telnet you do it with Control-] and then type "send break" followed by pressing the enter key. +@item websocket:@var{host}:@var{port},server[,nowait][,nodelay] +The WebSocket protocol is used instead of raw tcp socket. The port acts as +a WebSocket server. Client mode is not supported. + @item unix:@var{path}[,server][,nowait][,reconnect=@var{seconds}] A unix domain socket is used instead of a tcp socket. The option works the same as if you had specified @code{-serial tcp} except the unix domain socket diff --git a/qga/Makefile.objs b/qga/Makefile.objs index ed08c5917c..80e6bb3c2e 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -1,3 +1,4 @@ +commands-posix.o-libs := $(LIBUDEV_LIBS) qga-obj-y = commands.o guest-agent-command-state.o main.o qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o diff --git a/qga/channel-win32.c b/qga/channel-win32.c index b3597a8a0f..c86f4388db 100644 --- a/qga/channel-win32.c +++ b/qga/channel-win32.c @@ -302,7 +302,8 @@ static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); if (c->handle == INVALID_HANDLE_VALUE) { - g_critical("error opening path %s", newpath); + g_critical("error opening path %s: %s", newpath, + g_win32_error_message(GetLastError())); return false; } diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 37e8a2d791..1877976522 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -48,6 +48,10 @@ extern char **environ; #include <net/if.h> #include <sys/statvfs.h> +#ifdef CONFIG_LIBUDEV +#include <libudev.h> +#endif + #ifdef FIFREEZE #define CONFIG_FSFREEZE #endif @@ -872,6 +876,10 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, GuestDiskAddressList *list = NULL; bool has_ata = false, has_host = false, has_tgt = false; char *p, *q, *driver = NULL; +#ifdef CONFIG_LIBUDEV + struct udev *udev = NULL; + struct udev_device *udevice = NULL; +#endif p = strstr(syspath, "/devices/pci"); if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n", @@ -936,6 +944,26 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, list = g_malloc0(sizeof(*list)); list->value = disk; +#ifdef CONFIG_LIBUDEV + udev = udev_new(); + udevice = udev_device_new_from_syspath(udev, syspath); + if (udev == NULL || udevice == NULL) { + g_debug("failed to query udev"); + } else { + const char *devnode, *serial; + devnode = udev_device_get_devnode(udevice); + if (devnode != NULL) { + disk->dev = g_strdup(devnode); + disk->has_dev = true; + } + serial = udev_device_get_property_value(udevice, "ID_SERIAL"); + if (serial != NULL && *serial != 0) { + disk->serial = g_strdup(serial); + disk->has_serial = true; + } + } +#endif + if (strcmp(driver, "ata_piix") == 0) { /* a host per ide bus, target*:0:<unit>:0 */ if (!has_host || !has_tgt) { @@ -995,14 +1023,19 @@ static void build_guest_fsinfo_for_real_device(char const *syspath, list->next = fs->disk; fs->disk = list; - g_free(driver); - return; + goto out; cleanup: if (list) { qapi_free_GuestDiskAddressList(list); } +out: g_free(driver); +#ifdef CONFIG_LIBUDEV + udev_unref(udev); + udev_device_unref(udevice); +#endif + return; } static void build_guest_fsinfo_for_device(char const *devpath, @@ -2035,61 +2068,56 @@ static long sysconf_exact(int name, const char *name_str, Error **errp) * Written members remain unmodified on error. */ static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, - Error **errp) + char *dirpath, Error **errp) { - char *dirpath; + int fd; + int res; int dirfd; + static const char fn[] = "online"; - dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", - vcpu->logical_id); dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); if (dirfd == -1) { error_setg_errno(errp, errno, "open(\"%s\")", dirpath); - } else { - static const char fn[] = "online"; - int fd; - int res; - - fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); - if (fd == -1) { - if (errno != ENOENT) { - error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); - } else if (sys2vcpu) { - vcpu->online = true; - vcpu->can_offline = false; - } else if (!vcpu->online) { - error_setg(errp, "logical processor #%" PRId64 " can't be " - "offlined", vcpu->logical_id); - } /* otherwise pretend successful re-onlining */ - } else { - unsigned char status; - - res = pread(fd, &status, 1, 0); - if (res == -1) { - error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); - } else if (res == 0) { - error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, - fn); - } else if (sys2vcpu) { - vcpu->online = (status != '0'); - vcpu->can_offline = true; - } else if (vcpu->online != (status != '0')) { - status = '0' + vcpu->online; - if (pwrite(fd, &status, 1, 0) == -1) { - error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, - fn); - } - } /* otherwise pretend successful re-(on|off)-lining */ + return; + } - res = close(fd); - g_assert(res == 0); - } + fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); + if (fd == -1) { + if (errno != ENOENT) { + error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); + } else if (sys2vcpu) { + vcpu->online = true; + vcpu->can_offline = false; + } else if (!vcpu->online) { + error_setg(errp, "logical processor #%" PRId64 " can't be " + "offlined", vcpu->logical_id); + } /* otherwise pretend successful re-onlining */ + } else { + unsigned char status; + + res = pread(fd, &status, 1, 0); + if (res == -1) { + error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); + } else if (res == 0) { + error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, + fn); + } else if (sys2vcpu) { + vcpu->online = (status != '0'); + vcpu->can_offline = true; + } else if (vcpu->online != (status != '0')) { + status = '0' + vcpu->online; + if (pwrite(fd, &status, 1, 0) == -1) { + error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, + fn); + } + } /* otherwise pretend successful re-(on|off)-lining */ - res = close(dirfd); + res = close(fd); g_assert(res == 0); } - g_free(dirpath); + res = close(dirfd); + g_assert(res == 0); } GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) @@ -2107,17 +2135,21 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) while (local_err == NULL && current < sc_max) { GuestLogicalProcessor *vcpu; GuestLogicalProcessorList *entry; - - vcpu = g_malloc0(sizeof *vcpu); - vcpu->logical_id = current++; - vcpu->has_can_offline = true; /* lolspeak ftw */ - transfer_vcpu(vcpu, true, &local_err); - - entry = g_malloc0(sizeof *entry); - entry->value = vcpu; - - *link = entry; - link = &entry->next; + int64_t id = current++; + char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", + id); + + if (g_file_test(path, G_FILE_TEST_EXISTS)) { + vcpu = g_malloc0(sizeof *vcpu); + vcpu->logical_id = id; + vcpu->has_can_offline = true; /* lolspeak ftw */ + transfer_vcpu(vcpu, true, path, &local_err); + entry = g_malloc0(sizeof *entry); + entry->value = vcpu; + *link = entry; + link = &entry->next; + } + g_free(path); } if (local_err == NULL) { @@ -2138,7 +2170,11 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) processed = 0; while (vcpus != NULL) { - transfer_vcpu(vcpus->value, false, &local_err); + char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", + vcpus->value->logical_id); + + transfer_vcpu(vcpus->value, false, path, &local_err); + g_free(path); if (local_err != NULL) { break; } diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 98d9735389..ef1d7d48d2 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -89,6 +89,12 @@ static OpenFlags guest_file_open_modes[] = { {"a+b", FILE_GENERIC_APPEND|GENERIC_READ, OPEN_ALWAYS } }; +#define debug_error(msg) do { \ + char *suffix = g_win32_error_message(GetLastError()); \ + g_debug("%s: %s", (msg), suffix); \ + g_free(suffix); \ +} while (0) + static OpenFlags *find_open_flag(const char *mode_str) { int mode; @@ -160,13 +166,15 @@ static void handle_set_nonblocking(HANDLE fh) int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **errp) { - int64_t fd; + int64_t fd = -1; HANDLE fh; HANDLE templ_file = NULL; DWORD share_mode = FILE_SHARE_READ; DWORD flags_and_attr = FILE_ATTRIBUTE_NORMAL; LPSECURITY_ATTRIBUTES sa_attr = NULL; OpenFlags *guest_flags; + GError *gerr = NULL; + wchar_t *w_path = NULL; if (!has_mode) { mode = "r"; @@ -175,16 +183,21 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, guest_flags = find_open_flag(mode); if (guest_flags == NULL) { error_setg(errp, "invalid file open mode"); - return -1; + goto done; } - fh = CreateFile(path, guest_flags->desired_access, share_mode, sa_attr, + w_path = g_utf8_to_utf16(path, -1, NULL, NULL, &gerr); + if (!w_path) { + goto done; + } + + fh = CreateFileW(w_path, guest_flags->desired_access, share_mode, sa_attr, guest_flags->creation_disposition, flags_and_attr, templ_file); if (fh == INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), "failed to open file '%s'", path); - return -1; + goto done; } /* set fd non-blocking to avoid common use cases (like reading from a @@ -196,10 +209,17 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, if (fd < 0) { CloseHandle(fh); error_setg(errp, "failed to add handle to qmp handle table"); - return -1; + goto done; } slog("guest-file-open, handle: % " PRId64, fd); + +done: + if (gerr) { + error_setg(errp, QERR_QGA_COMMAND_FAILED, gerr->message); + g_error_free(gerr); + } + g_free(w_path); return fd; } @@ -465,15 +485,32 @@ static STORAGE_BUS_TYPE win2qemu[] = { static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus) { - if (bus > ARRAY_SIZE(win2qemu) || (int)bus < 0) { + if (bus >= ARRAY_SIZE(win2qemu) || (int)bus < 0) { return GUEST_DISK_BUS_TYPE_UNKNOWN; } return win2qemu[(int)bus]; } +/* XXX: The following function is BROKEN! + * + * It does not work and probably has never worked. When we query for list of + * disks we get cryptic names like "\Device\0000001d" instead of + * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one + * way or the other for comparison is an open question. + * + * When we query volume names (the original version) we are able to match those + * but then the property queries report error "Invalid function". (duh!) + */ + +/* DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +*/ +DEFINE_GUID(GUID_DEVINTERFACE_DISK, + 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, + 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); + static GuestPCIAddress *get_pci_info(char *guid, Error **errp) { @@ -484,23 +521,38 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp) char dev_name[MAX_PATH]; char *buffer = NULL; GuestPCIAddress *pci = NULL; - char *name = g_strdup(&guid[4]); + char *name = NULL; + bool partial_pci = false; + pci = g_malloc0(sizeof(*pci)); + pci->domain = -1; + pci->slot = -1; + pci->function = -1; + pci->bus = -1; + + if (g_str_has_prefix(guid, "\\\\.\\") || + g_str_has_prefix(guid, "\\\\?\\")) { + name = g_strdup(guid + 4); + } else { + name = g_strdup(guid); + } if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) { error_setg_win32(errp, GetLastError(), "failed to get dos device name"); goto out; } - dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0, + dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), "failed to get devices tree"); goto out; } + g_debug("enumerating devices"); dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { - DWORD addr, bus, slot, func, dev, data, size2; + DWORD addr, bus, slot, data, size2; + int func, dev; while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &data, (PBYTE)buffer, size, @@ -522,6 +574,7 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp) if (g_strcmp0(buffer, dev_name)) { continue; } + g_debug("found device %s", dev_name); /* There is no need to allocate buffer in the next functions. The size * is known and ULONG according to @@ -530,21 +583,27 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp) */ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) { - break; + debug_error("failed to get bus"); + bus = -1; + partial_pci = true; } /* The function retrieves the device's address. This value will be * transformed into device function and number */ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) { - break; + debug_error("failed to get address"); + addr = -1; + partial_pci = true; } /* This call returns UINumber of DEVICE_CAPABILITIES structure. * This number is typically a user-perceived slot number. */ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) { - break; + debug_error("failed to get slot"); + slot = -1; + partial_pci = true; } /* SetupApi gives us the same information as driver with @@ -554,13 +613,19 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp) * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF); * SPDRP_ADDRESS is propertyAddress, so we do the same.*/ - func = addr & 0x0000FFFF; - dev = (addr >> 16) & 0x0000FFFF; - pci = g_malloc0(sizeof(*pci)); - pci->domain = dev; - pci->slot = slot; - pci->function = func; - pci->bus = bus; + if (partial_pci) { + pci->domain = -1; + pci->slot = -1; + pci->function = -1; + pci->bus = -1; + } else { + func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF; + dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF; + pci->domain = dev; + pci->slot = (int) slot; + pci->function = func; + pci->bus = (int) bus; + } break; } @@ -572,85 +637,228 @@ out: return pci; } -static int get_disk_bus_type(HANDLE vol_h, Error **errp) +static void get_disk_properties(HANDLE vol_h, GuestDiskAddress *disk, + Error **errp) { STORAGE_PROPERTY_QUERY query; STORAGE_DEVICE_DESCRIPTOR *dev_desc, buf; DWORD received; + ULONG size = sizeof(buf); dev_desc = &buf; - dev_desc->Size = sizeof(buf); query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; if (!DeviceIoControl(vol_h, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(STORAGE_PROPERTY_QUERY), dev_desc, - dev_desc->Size, &received, NULL)) { + size, &received, NULL)) { error_setg_win32(errp, GetLastError(), "failed to get bus type"); - return -1; + return; + } + disk->bus_type = find_bus_type(dev_desc->BusType); + g_debug("bus type %d", disk->bus_type); + + /* Query once more. Now with long enough buffer. */ + size = dev_desc->Size; + dev_desc = g_malloc0(size); + if (!DeviceIoControl(vol_h, IOCTL_STORAGE_QUERY_PROPERTY, &query, + sizeof(STORAGE_PROPERTY_QUERY), dev_desc, + size, &received, NULL)) { + error_setg_win32(errp, GetLastError(), "failed to get serial number"); + g_debug("failed to get serial number"); + goto out_free; } + if (dev_desc->SerialNumberOffset > 0) { + const char *serial; + size_t len; - return dev_desc->BusType; + if (dev_desc->SerialNumberOffset >= received) { + error_setg(errp, "failed to get serial number: offset outside the buffer"); + g_debug("serial number offset outside the buffer"); + goto out_free; + } + serial = (char *)dev_desc + dev_desc->SerialNumberOffset; + len = received - dev_desc->SerialNumberOffset; + g_debug("serial number \"%s\"", serial); + if (*serial != 0) { + disk->serial = g_strndup(serial, len); + disk->has_serial = true; + } + } +out_free: + g_free(dev_desc); + + return; } -/* VSS provider works with volumes, thus there is no difference if - * the volume consist of spanned disks. Info about the first disk in the - * volume is returned for the spanned disk group (LVM) */ -static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) +static void get_single_disk_info(GuestDiskAddress *disk, Error **errp) { - GuestDiskAddressList *list = NULL; - GuestDiskAddress *disk; SCSI_ADDRESS addr, *scsi_ad; DWORD len; - int bus; - HANDLE vol_h; + HANDLE disk_h; + Error *local_err = NULL; scsi_ad = &addr; - char *name = g_strndup(guid, strlen(guid)-1); - vol_h = CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + g_debug("getting disk info for: %s", disk->dev); + disk_h = CreateFile(disk->dev, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (vol_h == INVALID_HANDLE_VALUE) { - error_setg_win32(errp, GetLastError(), "failed to open volume"); - goto out_free; + if (disk_h == INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to open disk"); + return; } - bus = get_disk_bus_type(vol_h, errp); - if (bus < 0) { - goto out_close; + get_disk_properties(disk_h, disk, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto err_close; } - disk = g_malloc0(sizeof(*disk)); - disk->bus_type = find_bus_type(bus); - if (bus == BusTypeScsi || bus == BusTypeAta || bus == BusTypeRAID + g_debug("bus type %d", disk->bus_type); + /* always set pci_controller as required by schema. get_pci_info() should + * report -1 values for non-PCI buses rather than fail. fail the command + * if that doesn't hold since that suggests some other unexpected + * breakage + */ + disk->pci_controller = get_pci_info(disk->dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto err_close; + } + if (disk->bus_type == GUEST_DISK_BUS_TYPE_SCSI + || disk->bus_type == GUEST_DISK_BUS_TYPE_IDE + || disk->bus_type == GUEST_DISK_BUS_TYPE_RAID #if (_WIN32_WINNT >= 0x0600) /* This bus type is not supported before Windows Server 2003 SP1 */ - || bus == BusTypeSas + || disk->bus_type == GUEST_DISK_BUS_TYPE_SAS #endif ) { /* We are able to use the same ioctls for different bus types * according to Microsoft docs * https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */ - if (DeviceIoControl(vol_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad, + g_debug("getting pci-controller info"); + if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad, sizeof(SCSI_ADDRESS), &len, NULL)) { disk->unit = addr.Lun; disk->target = addr.TargetId; disk->bus = addr.PathId; - disk->pci_controller = get_pci_info(name, errp); } /* We do not set error in this case, because we still have enough * information about volume. */ - } else { - disk->pci_controller = NULL; } - list = g_malloc0(sizeof(*list)); - list->value = disk; - list->next = NULL; -out_close: - CloseHandle(vol_h); -out_free: +err_close: + CloseHandle(disk_h); + return; +} + +/* VSS provider works with volumes, thus there is no difference if + * the volume consist of spanned disks. Info about the first disk in the + * volume is returned for the spanned disk group (LVM) */ +static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) +{ + Error *local_err = NULL; + GuestDiskAddressList *list = NULL, *cur_item = NULL; + GuestDiskAddress *disk = NULL; + int i; + HANDLE vol_h; + DWORD size; + PVOLUME_DISK_EXTENTS extents = NULL; + + /* strip final backslash */ + char *name = g_strdup(guid); + if (g_str_has_suffix(name, "\\")) { + name[strlen(name) - 1] = 0; + } + + g_debug("opening %s", name); + vol_h = CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + 0, NULL); + if (vol_h == INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to open volume"); + goto out; + } + + /* Get list of extents */ + g_debug("getting disk extents"); + size = sizeof(VOLUME_DISK_EXTENTS); + extents = g_malloc0(size); + if (!DeviceIoControl(vol_h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, + 0, extents, size, NULL, NULL)) { + DWORD last_err = GetLastError(); + if (last_err == ERROR_MORE_DATA) { + /* Try once more with big enough buffer */ + size = sizeof(VOLUME_DISK_EXTENTS) + + extents->NumberOfDiskExtents*sizeof(DISK_EXTENT); + g_free(extents); + extents = g_malloc0(size); + if (!DeviceIoControl( + vol_h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, + 0, extents, size, NULL, NULL)) { + error_setg_win32(errp, GetLastError(), + "failed to get disk extents"); + return NULL; + } + } else if (last_err == ERROR_INVALID_FUNCTION) { + /* Possibly CD-ROM or a shared drive. Try to pass the volume */ + g_debug("volume not on disk"); + disk = g_malloc0(sizeof(GuestDiskAddress)); + disk->has_dev = true; + disk->dev = g_strdup(name); + get_single_disk_info(disk, &local_err); + if (local_err) { + g_debug("failed to get disk info, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); + goto out; + } + list = g_malloc0(sizeof(*list)); + list->value = disk; + disk = NULL; + list->next = NULL; + goto out; + } else { + error_setg_win32(errp, GetLastError(), + "failed to get disk extents"); + goto out; + } + } + g_debug("Number of extents: %lu", extents->NumberOfDiskExtents); + + /* Go through each extent */ + for (i = 0; i < extents->NumberOfDiskExtents; i++) { + disk = g_malloc0(sizeof(GuestDiskAddress)); + + /* Disk numbers directly correspond to numbers used in UNCs + * + * See documentation for DISK_EXTENT: + * https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-_disk_extent + * + * See also Naming Files, Paths and Namespaces: + * https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#win32-device-namespaces + */ + disk->has_dev = true; + disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu", + extents->Extents[i].DiskNumber); + + get_single_disk_info(disk, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + cur_item = g_malloc0(sizeof(*list)); + cur_item->value = disk; + disk = NULL; + cur_item->next = list; + list = cur_item; + } + + +out: + qapi_free_GuestDiskAddress(disk); + g_free(extents); g_free(name); + return list; } @@ -777,6 +985,13 @@ GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) */ int64_t qmp_guest_fsfreeze_freeze(Error **errp) { + return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); +} + +int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, + strList *mountpoints, + Error **errp) +{ int i; Error *local_err = NULL; @@ -790,7 +1005,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **errp) /* cannot risk guest agent blocking itself on a write in this state */ ga_set_frozen(ga_state); - qga_vss_fsfreeze(&i, true, &local_err); + qga_vss_fsfreeze(&i, true, mountpoints, &local_err); if (local_err) { error_propagate(errp, local_err); goto error; @@ -808,15 +1023,6 @@ error: return 0; } -int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, - strList *mountpoints, - Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); - - return 0; -} - /* * Thaw local file systems using Volume Shadow-copy Service. */ @@ -829,7 +1035,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp) return 0; } - qga_vss_fsfreeze(&i, false, errp); + qga_vss_fsfreeze(&i, false, NULL, errp); ga_unset_frozen(ga_state); return i; @@ -1646,7 +1852,6 @@ GList *ga_command_blacklist_init(GList *blacklist) "guest-set-vcpus", "guest-get-memory-blocks", "guest-set-memory-blocks", "guest-get-memory-block-size", - "guest-fsfreeze-freeze-list", NULL}; char **p = (char **)list_unsupported; diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs index f751a7e9f7..64bf90bd85 100644 --- a/qga/installer/qemu-ga.wxs +++ b/qga/installer/qemu-ga.wxs @@ -78,7 +78,7 @@ Account="LocalSystem" ErrorControl="ignore" Interactive="no" - Arguments="-d" + Arguments="-d --retry-path" > </ServiceInstall> <ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="QEMU-GA" Wait="no" /> diff --git a/qga/main.c b/qga/main.c index c399320d3c..87a0711c14 100644 --- a/qga/main.c +++ b/qga/main.c @@ -34,6 +34,7 @@ #include "qemu/systemd.h" #include "qemu-version.h" #ifdef _WIN32 +#include <dbt.h> #include "qga/service-win32.h" #include "qga/vss-win32.h" #endif @@ -58,6 +59,7 @@ #endif #define QGA_SENTINEL_BYTE 0xFF #define QGA_CONF_DEFAULT CONFIG_QEMU_CONFDIR G_DIR_SEPARATOR_S "qemu-ga.conf" +#define QGA_RETRY_INTERVAL 5 static struct { const char *state_dir; @@ -69,6 +71,8 @@ typedef struct GAPersistentState { int64_t fd_counter; } GAPersistentState; +typedef struct GAConfig GAConfig; + struct GAState { JSONMessageParser parser; GMainLoop *main_loop; @@ -80,6 +84,7 @@ struct GAState { bool logging_enabled; #ifdef _WIN32 GAService service; + HANDLE wakeup_event; #endif bool delimit_response; bool frozen; @@ -94,6 +99,9 @@ struct GAState { #endif gchar *pstate_filepath; GAPersistentState pstate; + GAConfig *config; + int socket_activation; + bool force_exit; }; struct GAState *ga_state; @@ -113,8 +121,11 @@ static const char *ga_freeze_whitelist[] = { #ifdef _WIN32 DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx); +DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data); VOID WINAPI service_main(DWORD argc, TCHAR *argv[]); #endif +static int run_agent(GAState *s); +static void stop_agent(GAState *s, bool requested); static void init_dfl_pathnames(void) @@ -151,7 +162,7 @@ static void quit_handler(int sig) WaitForSingleObject(hEventTimeout, 0); CloseHandle(hEventTimeout); } - qga_vss_fsfreeze(&i, false, &err); + qga_vss_fsfreeze(&i, false, NULL, &err); if (err) { g_debug("Error unfreezing filesystems prior to exiting: %s", error_get_pretty(err)); @@ -163,9 +174,7 @@ static void quit_handler(int sig) } g_debug("received signal num %d, quitting", sig); - if (g_main_loop_is_running(ga_state->main_loop)) { - g_main_loop_quit(ga_state->main_loop); - } + stop_agent(ga_state, true); } #ifndef _WIN32 @@ -250,6 +259,10 @@ QEMU_COPYRIGHT "\n" " to list available RPCs)\n" " -D, --dump-conf dump a qemu-ga config file based on current config\n" " options / command-line parameters to stdout\n" +" -r, --retry-path attempt re-opening path if it's unavailable or closed\n" +" due to an error which may be recoverable in the future\n" +" (virtio-serial driver re-install, serial device hot\n" +" plug/unplug, etc.)\n" " -h, --help display this help and exit\n" "\n" QEMU_HELP_BOTTOM "\n" @@ -609,6 +622,7 @@ static gboolean channel_event_cb(GIOCondition condition, gpointer data) switch (status) { case G_IO_STATUS_ERROR: g_warning("error reading channel"); + stop_agent(s, false); return false; case G_IO_STATUS_NORMAL: buf[count] = 0; @@ -666,6 +680,36 @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path, } #ifdef _WIN32 +DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data) +{ + DWORD ret = NO_ERROR; + PDEV_BROADCAST_HDR broadcast_header = (PDEV_BROADCAST_HDR)data; + + if (broadcast_header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + switch (type) { + /* Device inserted */ + case DBT_DEVICEARRIVAL: + /* Start QEMU-ga's service */ + if (!SetEvent(ga_state->wakeup_event)) { + ret = GetLastError(); + } + break; + /* Device removed */ + case DBT_DEVICEQUERYREMOVE: + case DBT_DEVICEREMOVEPENDING: + case DBT_DEVICEREMOVECOMPLETE: + /* Stop QEMU-ga's service */ + if (!ResetEvent(ga_state->wakeup_event)) { + ret = GetLastError(); + } + break; + default: + ret = ERROR_CALL_NOT_IMPLEMENTED; + } + } + return ret; +} + DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, LPVOID ctx) { @@ -677,9 +721,13 @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: quit_handler(SIGTERM); + SetEvent(ga_state->wakeup_event); service->status.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(service->status_handle, &service->status); break; + case SERVICE_CONTROL_DEVICEEVENT: + handle_serial_device_events(type, data); + break; default: ret = ERROR_CALL_NOT_IMPLEMENTED; @@ -706,10 +754,24 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) service->status.dwServiceSpecificExitCode = NO_ERROR; service->status.dwCheckPoint = 0; service->status.dwWaitHint = 0; + DEV_BROADCAST_DEVICEINTERFACE notification_filter; + ZeroMemory(¬ification_filter, sizeof(notification_filter)); + notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + notification_filter.dbcc_classguid = GUID_VIOSERIAL_PORT; + + service->device_notification_handle = + RegisterDeviceNotification(service->status_handle, + ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); + if (!service->device_notification_handle) { + g_critical("Failed to register device notification handle!\n"); + return; + } SetServiceStatus(service->status_handle, &service->status); - g_main_loop_run(ga_state->main_loop); + run_agent(ga_state); + UnregisterDeviceNotification(service->device_notification_handle); service->status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service->status_handle, &service->status); } @@ -905,7 +967,7 @@ static GList *split_list(const gchar *str, const gchar *delim) return list; } -typedef struct GAConfig { +struct GAConfig { char *channel_path; char *method; char *log_filepath; @@ -922,7 +984,8 @@ typedef struct GAConfig { int daemonize; GLogLevelFlags log_level; int dumpconf; -} GAConfig; + bool retry_path; +}; static void config_load(GAConfig *config) { @@ -971,6 +1034,10 @@ static void config_load(GAConfig *config) /* enable all log levels */ config->log_level = G_LOG_LEVEL_MASK; } + if (g_key_file_has_key(keyfile, "general", "retry-path", NULL)) { + config->retry_path = + g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr); + } if (g_key_file_has_key(keyfile, "general", "blacklist", NULL)) { config->bliststr = g_key_file_get_string(keyfile, "general", "blacklist", &gerr); @@ -1032,6 +1099,8 @@ static void config_dump(GAConfig *config) g_key_file_set_string(keyfile, "general", "statedir", config->state_dir); g_key_file_set_boolean(keyfile, "general", "verbose", config->log_level == G_LOG_LEVEL_MASK); + g_key_file_set_boolean(keyfile, "general", "retry-path", + config->retry_path); tmp = list_join(config->blacklist, ','); g_key_file_set_string(keyfile, "general", "blacklist", tmp); g_free(tmp); @@ -1050,7 +1119,7 @@ static void config_dump(GAConfig *config) static void config_parse(GAConfig *config, int argc, char **argv) { - const char *sopt = "hVvdm:p:l:f:F::b:s:t:D"; + const char *sopt = "hVvdm:p:l:f:F::b:s:t:Dr"; int opt_ind = 0, ch; const struct option lopt[] = { { "help", 0, NULL, 'h' }, @@ -1070,6 +1139,7 @@ static void config_parse(GAConfig *config, int argc, char **argv) { "service", 1, NULL, 's' }, #endif { "statedir", 1, NULL, 't' }, + { "retry-path", 0, NULL, 'r' }, { NULL, 0, NULL, 0 } }; @@ -1114,6 +1184,9 @@ static void config_parse(GAConfig *config, int argc, char **argv) case 'D': config->dumpconf = 1; break; + case 'r': + config->retry_path = true; + break; case 'b': { if (is_help_option(optarg)) { qmp_for_each_command(&ga_commands, ga_print_cmd, NULL); @@ -1211,9 +1284,21 @@ static bool check_is_frozen(GAState *s) return false; } -static int run_agent(GAState *s, GAConfig *config, int socket_activation) +static GAState *initialize_agent(GAConfig *config, int socket_activation) { - ga_state = s; + GAState *s = g_new0(GAState, 1); + + g_assert(ga_state == NULL); + + s->log_level = config->log_level; + s->log_file = stderr; +#ifdef CONFIG_FSFREEZE + s->fsfreeze_hook = config->fsfreeze_hook; +#endif + s->pstate_filepath = g_strdup_printf("%s/qga.state", config->state_dir); + s->state_filepath_isfrozen = g_strdup_printf("%s/qga.state.isfrozen", + config->state_dir); + s->frozen = check_is_frozen(s); g_log_set_default_handler(ga_log, s); g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); @@ -1229,7 +1314,7 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) if (g_mkdir_with_parents(config->state_dir, S_IRWXU) == -1) { g_critical("unable to create (an ancestor of) the state directory" " '%s': %s", config->state_dir, strerror(errno)); - return EXIT_FAILURE; + return NULL; } #endif @@ -1254,7 +1339,7 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) if (!log_file) { g_critical("unable to open specified log file: %s", strerror(errno)); - return EXIT_FAILURE; + return NULL; } s->log_file = log_file; } @@ -1265,7 +1350,7 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) s->pstate_filepath, ga_is_frozen(s))) { g_critical("failed to load persistent state"); - return EXIT_FAILURE; + return NULL; } config->blacklist = ga_command_blacklist_init(config->blacklist); @@ -1286,36 +1371,116 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); - return EXIT_FAILURE; + return NULL; } #endif s->main_loop = g_main_loop_new(NULL, false); - if (!channel_init(ga_state, config->method, config->channel_path, - socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1)) { + s->config = config; + s->socket_activation = socket_activation; + +#ifdef _WIN32 + s->wakeup_event = CreateEvent(NULL, TRUE, FALSE, TEXT("WakeUp")); + if (s->wakeup_event == NULL) { + g_critical("CreateEvent failed"); + return NULL; + } +#endif + + ga_state = s; + return s; +} + +static void cleanup_agent(GAState *s) +{ +#ifdef _WIN32 + CloseHandle(s->wakeup_event); +#endif + if (s->command_state) { + ga_command_state_cleanup_all(s->command_state); + ga_command_state_free(s->command_state); + json_message_parser_destroy(&s->parser); + } + g_free(s->pstate_filepath); + g_free(s->state_filepath_isfrozen); + if (s->main_loop) { + g_main_loop_unref(s->main_loop); + } + g_free(s); + ga_state = NULL; +} + +static int run_agent_once(GAState *s) +{ + if (!channel_init(s, s->config->method, s->config->channel_path, + s->socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1)) { g_critical("failed to initialize guest agent channel"); return EXIT_FAILURE; } -#ifndef _WIN32 + g_main_loop_run(ga_state->main_loop); + + if (s->channel) { + ga_channel_free(s->channel); + } + + return EXIT_SUCCESS; +} + +static void wait_for_channel_availability(GAState *s) +{ + g_warning("waiting for channel path..."); +#ifndef _WIN32 + sleep(QGA_RETRY_INTERVAL); #else - if (config->daemonize) { - SERVICE_TABLE_ENTRY service_table[] = { - { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; - StartServiceCtrlDispatcher(service_table); - } else { - g_main_loop_run(ga_state->main_loop); + DWORD dwWaitResult; + + dwWaitResult = WaitForSingleObject(s->wakeup_event, INFINITE); + + switch (dwWaitResult) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + break; + default: + g_critical("WaitForSingleObject failed"); } #endif +} - return EXIT_SUCCESS; +static int run_agent(GAState *s) +{ + int ret = EXIT_SUCCESS; + + s->force_exit = false; + + do { + ret = run_agent_once(s); + if (s->config->retry_path && !s->force_exit) { + g_warning("agent stopped unexpectedly, restarting..."); + wait_for_channel_availability(s); + } + } while (s->config->retry_path && !s->force_exit); + + return ret; +} + +static void stop_agent(GAState *s, bool requested) +{ + if (!s->force_exit) { + s->force_exit = requested; + } + + if (g_main_loop_is_running(s->main_loop)) { + g_main_loop_quit(s->main_loop); + } } int main(int argc, char **argv) { int ret = EXIT_SUCCESS; - GAState *s = g_new0(GAState, 1); + GAState *s; GAConfig *config = g_new0(GAConfig, 1); int socket_activation; @@ -1383,44 +1548,37 @@ int main(int argc, char **argv) } } - s->log_level = config->log_level; - s->log_file = stderr; -#ifdef CONFIG_FSFREEZE - s->fsfreeze_hook = config->fsfreeze_hook; -#endif - s->pstate_filepath = g_strdup_printf("%s/qga.state", config->state_dir); - s->state_filepath_isfrozen = g_strdup_printf("%s/qga.state.isfrozen", - config->state_dir); - s->frozen = check_is_frozen(s); - if (config->dumpconf) { config_dump(config); goto end; } - ret = run_agent(s, config, socket_activation); - -end: - if (s->command_state) { - ga_command_state_cleanup_all(s->command_state); - ga_command_state_free(s->command_state); - json_message_parser_destroy(&s->parser); + s = initialize_agent(config, socket_activation); + if (!s) { + g_critical("error initializing guest agent"); + goto end; } - if (s->channel) { - ga_channel_free(s->channel); + +#ifdef _WIN32 + if (config->daemonize) { + SERVICE_TABLE_ENTRY service_table[] = { + { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; + StartServiceCtrlDispatcher(service_table); + } else { + ret = run_agent(s); } - g_free(s->pstate_filepath); - g_free(s->state_filepath_isfrozen); +#else + ret = run_agent(s); +#endif + cleanup_agent(s); + +end: if (config->daemonize) { unlink(config->pid_filepath); } config_free(config); - if (s->main_loop) { - g_main_loop_unref(s->main_loop); - } - g_free(s); return ret; } diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index dfbc4a5e32..c6725b3ec8 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -834,13 +834,16 @@ # @bus: bus id # @target: target id # @unit: unit id +# @serial: serial number (since: 3.1) +# @dev: device node (POSIX) or device UNC (Windows) (since: 3.1) # # Since: 2.2 ## { 'struct': 'GuestDiskAddress', 'data': {'pci-controller': 'GuestPCIAddress', 'bus-type': 'GuestDiskBusType', - 'bus': 'int', 'target': 'int', 'unit': 'int'} } + 'bus': 'int', 'target': 'int', 'unit': 'int', + '*serial': 'str', '*dev': 'str'} } ## # @GuestFilesystemInfo: diff --git a/qga/service-win32.h b/qga/service-win32.h index 89e99dfede..7b16d69b57 100644 --- a/qga/service-win32.h +++ b/qga/service-win32.h @@ -20,9 +20,13 @@ #define QGA_SERVICE_NAME "qemu-ga" #define QGA_SERVICE_DESCRIPTION "Enables integration with QEMU machine emulator and virtualizer." +static const GUID GUID_VIOSERIAL_PORT = { 0x6fde7521, 0x1b65, 0x48ae, +{ 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26 } }; + typedef struct GAService { SERVICE_STATUS status; SERVICE_STATUS_HANDLE status_handle; + HDEVNOTIFY device_notification_handle; } GAService; int ga_install_service(const char *path, const char *logfile, diff --git a/qga/vss-win32.c b/qga/vss-win32.c index a541f3ae01..f444a25a70 100644 --- a/qga/vss-win32.c +++ b/qga/vss-win32.c @@ -147,7 +147,8 @@ void ga_uninstall_vss_provider(void) } /* Call VSS requester and freeze/thaw filesystems and applications */ -void qga_vss_fsfreeze(int *nr_volume, bool freeze, Error **errp) +void qga_vss_fsfreeze(int *nr_volume, bool freeze, + strList *mountpoints, Error **errp) { const char *func_name = freeze ? "requester_freeze" : "requester_thaw"; QGAVSSRequesterFunc func; @@ -164,5 +165,5 @@ void qga_vss_fsfreeze(int *nr_volume, bool freeze, Error **errp) return; } - func(nr_volume, &errset); + func(nr_volume, mountpoints, &errset); } diff --git a/qga/vss-win32.h b/qga/vss-win32.h index 4f8e39aa5c..ce2abe5a72 100644 --- a/qga/vss-win32.h +++ b/qga/vss-win32.h @@ -22,6 +22,7 @@ bool vss_initialized(void); int ga_install_vss_provider(void); void ga_uninstall_vss_provider(void); -void qga_vss_fsfreeze(int *nr_volume, bool freeze, Error **errp); +void qga_vss_fsfreeze(int *nr_volume, bool freeze, + strList *mountpints, Error **errp); #endif diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp index 3d9c9716c0..5378c55d23 100644 --- a/qga/vss-win32/requester.cpp +++ b/qga/vss-win32/requester.cpp @@ -234,7 +234,7 @@ out: } } -void requester_freeze(int *num_vols, ErrorSet *errset) +void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset) { COMPointer<IVssAsync> pAsync; HANDLE volume; @@ -246,6 +246,7 @@ void requester_freeze(int *num_vols, ErrorSet *errset) WCHAR short_volume_name[64], *display_name = short_volume_name; DWORD wait_status; int num_fixed_drives = 0, i; + int num_mount_points = 0; if (vss_ctx.pVssbc) { /* already frozen */ *num_vols = 0; @@ -337,39 +338,73 @@ void requester_freeze(int *num_vols, ErrorSet *errset) goto out; } - volume = FindFirstVolumeW(short_volume_name, sizeof(short_volume_name)); - if (volume == INVALID_HANDLE_VALUE) { - err_set(errset, hr, "failed to find first volume"); - goto out; - } - for (;;) { - if (GetDriveTypeW(short_volume_name) == DRIVE_FIXED) { + if (mountpoints) { + PWCHAR volume_name_wchar; + for (volList *list = (volList *)mountpoints; list; list = list->next) { + size_t len = strlen(list->value) + 1; + size_t converted = 0; VSS_ID pid; - hr = vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, + + volume_name_wchar = new wchar_t[len]; + mbstowcs_s(&converted, volume_name_wchar, len, + list->value, _TRUNCATE); + + hr = vss_ctx.pVssbc->AddToSnapshotSet(volume_name_wchar, g_gProviderId, &pid); if (FAILED(hr)) { - WCHAR volume_path_name[PATH_MAX]; - if (GetVolumePathNamesForVolumeNameW( - short_volume_name, volume_path_name, - sizeof(volume_path_name), NULL) && *volume_path_name) { - display_name = volume_path_name; - } err_set(errset, hr, "failed to add %S to snapshot set", - display_name); - FindVolumeClose(volume); + volume_name_wchar); + delete volume_name_wchar; goto out; } - num_fixed_drives++; + num_mount_points++; + + delete volume_name_wchar; } - if (!FindNextVolumeW(volume, short_volume_name, - sizeof(short_volume_name))) { - FindVolumeClose(volume); - break; + + if (num_mount_points == 0) { + /* If there is no valid mount points, just exit. */ + goto out; } } - if (num_fixed_drives == 0) { - goto out; /* If there is no fixed drive, just exit. */ + if (!mountpoints) { + volume = FindFirstVolumeW(short_volume_name, sizeof(short_volume_name)); + if (volume == INVALID_HANDLE_VALUE) { + err_set(errset, hr, "failed to find first volume"); + goto out; + } + + for (;;) { + if (GetDriveTypeW(short_volume_name) == DRIVE_FIXED) { + VSS_ID pid; + hr = vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, + g_gProviderId, &pid); + if (FAILED(hr)) { + WCHAR volume_path_name[PATH_MAX]; + if (GetVolumePathNamesForVolumeNameW( + short_volume_name, volume_path_name, + sizeof(volume_path_name), NULL) && + *volume_path_name) { + display_name = volume_path_name; + } + err_set(errset, hr, "failed to add %S to snapshot set", + display_name); + FindVolumeClose(volume); + goto out; + } + num_fixed_drives++; + } + if (!FindNextVolumeW(volume, short_volume_name, + sizeof(short_volume_name))) { + FindVolumeClose(volume); + break; + } + } + + if (num_fixed_drives == 0) { + goto out; /* If there is no fixed drive, just exit. */ + } } hr = vss_ctx.pVssbc->PrepareForBackup(pAsync.replace()); @@ -435,7 +470,12 @@ void requester_freeze(int *num_vols, ErrorSet *errset) goto out; } - *num_vols = vss_ctx.cFrozenVols = num_fixed_drives; + if (mountpoints) { + *num_vols = vss_ctx.cFrozenVols = num_mount_points; + } else { + *num_vols = vss_ctx.cFrozenVols = num_fixed_drives; + } + return; out: @@ -449,7 +489,7 @@ out1: } -void requester_thaw(int *num_vols, ErrorSet *errset) +void requester_thaw(int *num_vols, void *mountpints, ErrorSet *errset) { COMPointer<IVssAsync> pAsync; diff --git a/qga/vss-win32/requester.h b/qga/vss-win32/requester.h index 2a39d734a2..5a8e8faf0c 100644 --- a/qga/vss-win32/requester.h +++ b/qga/vss-win32/requester.h @@ -34,9 +34,16 @@ typedef struct ErrorSet { STDAPI requester_init(void); STDAPI requester_deinit(void); -typedef void (*QGAVSSRequesterFunc)(int *, ErrorSet *); -void requester_freeze(int *num_vols, ErrorSet *errset); -void requester_thaw(int *num_vols, ErrorSet *errset); +typedef struct volList volList; + +struct volList { + volList *next; + char *value; +}; + +typedef void (*QGAVSSRequesterFunc)(int *, void *, ErrorSet *); +void requester_freeze(int *num_vols, void *volList, ErrorSet *errset); +void requester_thaw(int *num_vols, void *volList, ErrorSet *errset); #ifdef __cplusplus } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3765b0e35e..06ec14e7f7 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1402,6 +1402,10 @@ sub process { $is_patch = 1; } + if ($line =~ /^Author: .*via Qemu-devel.*<qemu-devel\@nongnu.org>/) { + ERROR("Author email address is mangled by the mailing list\n" . $herecurr); + } + #check the patch for a signoff: if ($line =~ /^\s*signed-off-by:/i) { # This is a signoff, if ugly, so do not double report. diff --git a/scripts/decodetree.py b/scripts/decodetree.py index 457cffea90..0bc73b5990 100755 --- a/scripts/decodetree.py +++ b/scripts/decodetree.py @@ -63,13 +63,16 @@ # # *** Argument set syntax: # -# args_def := '&' identifier ( args_elt )+ +# args_def := '&' identifier ( args_elt )+ ( !extern )? # args_elt := identifier # # Each args_elt defines an argument within the argument set. # Each argument set will be rendered as a C structure "arg_$name" # with each of the fields being one of the member arguments. # +# If !extern is specified, the backing structure is assumed to +# have been already declared, typically via a second decoder. +# # Argument set examples: # # ®3 ra rb rc @@ -167,19 +170,20 @@ input_file = '' output_file = None output_fd = None insntype = 'uint32_t' +decode_function = 'decode' re_ident = '[a-zA-Z][a-zA-Z0-9_]*' -def error(lineno, *args): +def error_with_file(file, lineno, *args): """Print an error message from file:line and args and exit.""" global output_file global output_fd if lineno: - r = '{0}:{1}: error:'.format(input_file, lineno) + r = '{0}:{1}: error:'.format(file, lineno) elif input_file: - r = '{0}: error:'.format(input_file) + r = '{0}: error:'.format(file) else: r = 'error:' for a in args: @@ -191,6 +195,8 @@ def error(lineno, *args): os.remove(output_file) exit(1) +def error(lineno, *args): + error_with_file(input_file, lineno, args) def output(*args): global output_fd @@ -298,7 +304,7 @@ class Field: s = 's' else: s = '' - return str(pos) + ':' + s + str(len) + return str(self.pos) + ':' + s + str(self.len) def str_extract(self): if self.sign: @@ -392,8 +398,9 @@ class FunctionField: class Arguments: """Class representing the extracted fields of a format""" - def __init__(self, nm, flds): + def __init__(self, nm, flds, extern): self.name = nm + self.extern = extern self.fields = sorted(flds) def __str__(self): @@ -403,10 +410,11 @@ class Arguments: return 'arg_' + self.name def output_def(self): - output('typedef struct {\n') - for n in self.fields: - output(' int ', n, ';\n') - output('} ', self.struct_name(), ';\n\n') + if not self.extern: + output('typedef struct {\n') + for n in self.fields: + output(' int ', n, ';\n') + output('} ', self.struct_name(), ';\n\n') # end Arguments @@ -414,6 +422,7 @@ class General: """Common code between instruction formats and instruction patterns""" def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds): self.name = name + self.file = input_file self.lineno = lineno self.base = base self.fixedbits = fixb @@ -460,20 +469,19 @@ class Pattern(General): output('typedef ', self.base.base.struct_name(), ' arg_', self.name, ';\n') output(translate_scope, 'bool ', translate_prefix, '_', self.name, - '(DisasContext *ctx, arg_', self.name, - ' *a, ', insntype, ' insn);\n') + '(DisasContext *ctx, arg_', self.name, ' *a);\n') def output_code(self, i, extracted, outerbits, outermask): global translate_prefix ind = str_indent(i) arg = self.base.base.name - output(ind, '/* line ', str(self.lineno), ' */\n') + output(ind, '/* ', self.file, ':', str(self.lineno), ' */\n') if not extracted: output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n') for n, f in self.fields.items(): output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n') output(ind, 'return ', translate_prefix, '_', self.name, - '(ctx, &u.f_', arg, ', insn);\n') + '(ctx, &u.f_', arg, ');\n') # end Pattern @@ -540,7 +548,11 @@ def parse_arguments(lineno, name, toks): global re_ident flds = [] + extern = False for t in toks: + if re_fullmatch('!extern', t): + extern = True + continue if not re_fullmatch(re_ident, t): error(lineno, 'invalid argument set token "{0}"'.format(t)) if t in flds: @@ -549,7 +561,7 @@ def parse_arguments(lineno, name, toks): if name in arguments: error(lineno, 'duplicate argument set', name) - arguments[name] = Arguments(name, flds) + arguments[name] = Arguments(name, flds, extern) # end parse_arguments @@ -573,13 +585,14 @@ def add_field_byname(lineno, flds, new_name, old_name): def infer_argument_set(flds): global arguments + global decode_function for arg in arguments.values(): if eq_fields_for_args(flds, arg.fields): return arg - name = str(len(arguments)) - arg = Arguments(name, flds.keys()) + name = decode_function + str(len(arguments)) + arg = Arguments(name, flds.keys(), False) arguments[name] = arg return arg @@ -587,6 +600,7 @@ def infer_argument_set(flds): def infer_format(arg, fieldmask, flds): global arguments global formats + global decode_function const_flds = {} var_flds = {} @@ -606,7 +620,7 @@ def infer_format(arg, fieldmask, flds): continue return (fmt, const_flds) - name = 'Fmt_' + str(len(formats)) + name = decode_function + '_Fmt_' + str(len(formats)) if not arg: arg = infer_argument_set(flds) @@ -909,8 +923,9 @@ def build_tree(pats, outerbits, outermask): if innermask == 0: pnames = [] for p in pats: - pnames.append(p.name + ':' + str(p.lineno)) - error(pats[0].lineno, 'overlapping patterns:', pnames) + pnames.append(p.name + ':' + p.file + ':' + str(p.lineno)) + error_with_file(pats[0].file, pats[0].lineno, + 'overlapping patterns:', pnames) fullmask = outermask | innermask @@ -971,8 +986,8 @@ def main(): global insnwidth global insntype global insnmask + global decode_function - decode_function = 'decode' decode_scope = 'static ' long_opts = ['decode=', 'translate=', 'output=', 'insnwidth='] @@ -1001,10 +1016,11 @@ def main(): if len(args) < 1: error(0, 'missing input file') - input_file = args[0] - f = open(input_file, 'r') - parse_file(f) - f.close() + for filename in args: + input_file = filename + f = open(filename, 'r') + parse_file(f) + f.close() t = build_tree(patterns, 0, 0) prop_format(t) diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 930200b034..e93a7c0c84 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -72,21 +72,6 @@ ERROR_WHITELIST = [ # devices that don't work out of the box because they require extra options to "-device DEV": # DEVICE | ERROR MESSAGE {'device':'.*-(i386|x86_64)-cpu', 'expected':True}, # CPU socket-id is not set - {'device':'ARM,bitband-memory', 'expected':True}, # source-memory property not set - {'device':'arm.cortex-a9-global-timer', 'expected':True}, # a9_gtimer_realize: num-cpu must be between 1 and 4 - {'device':'arm_mptimer', 'expected':True}, # num-cpu must be between 1 and 4 - {'device':'armv7m', 'expected':True}, # memory property was not set - {'device':'aspeed.scu', 'expected':True}, # Unknown silicon revision: 0x0 - {'device':'aspeed.sdmc', 'expected':True}, # Unknown silicon revision: 0x0 - {'device':'bcm2835-dma', 'expected':True}, # bcm2835_dma_realize: required dma-mr link not found: Property '.dma-mr' not found - {'device':'bcm2835-fb', 'expected':True}, # bcm2835_fb_realize: required vcram-base property not set - {'device':'bcm2835-mbox', 'expected':True}, # bcm2835_mbox_realize: required mbox-mr link not found: Property '.mbox-mr' not found - {'device':'bcm2835-peripherals', 'expected':True}, # bcm2835_peripherals_realize: required ram link not found: Property '.ram' not found - {'device':'bcm2835-property', 'expected':True}, # bcm2835_property_realize: required fb link not found: Property '.fb' not found - {'device':'bcm2835_gpio', 'expected':True}, # bcm2835_gpio_realize: required sdhci link not found: Property '.sdbus-sdhci' not found - {'device':'bcm2836', 'expected':True}, # bcm2836_realize: required ram link not found: Property '.ram' not found - {'device':'cfi.pflash01', 'expected':True}, # attribute "sector-length" not specified or zero. - {'device':'cfi.pflash02', 'expected':True}, # attribute "sector-length" not specified or zero. {'device':'icp', 'expected':True}, # icp_realize: required link 'xics' not found: Property '.xics' not found {'device':'ics', 'expected':True}, # ics_base_realize: required link 'xics' not found: Property '.xics' not found # "-device ide-cd" does work on more recent QEMU versions, so it doesn't have expected=True @@ -108,7 +93,6 @@ ERROR_WHITELIST = [ {'device':'pc-dimm', 'expected':True}, # 'memdev' property is not set {'device':'pci-bridge', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. {'device':'pci-bridge-seat', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. - {'device':'pxa2xx-dma', 'expected':True}, # channels value invalid {'device':'pxb', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. {'device':'scsi-block', 'expected':True}, # drive property not set {'device':'scsi-disk', 'expected':True}, # drive property not set @@ -145,7 +129,6 @@ ERROR_WHITELIST = [ {'device':'virtio-input-host-pci', 'expected':True}, # evdev property is required {'device':'xen-pvdevice', 'expected':True}, # Device ID invalid, it must always be supplied {'device':'vhost-vsock-ccw', 'expected':True}, # guest-cid property must be greater than 2 - {'device':'ALTR.timer', 'expected':True}, # "clock-frequency" property must be provided {'device':'zpci', 'expected':True}, # target must be defined {'device':'pnv-(occ|icp|lpc)', 'expected':True}, # required link 'xics' not found: Property '.xics' not found {'device':'powernv-cpu-.*', 'expected':True}, # pnv_core_realize: required link 'xics' not found: Property '.xics' not found diff --git a/scripts/qemu.py b/scripts/qemu.py index fd4249f7a8..6e3b0e6771 100644 --- a/scripts/qemu.py +++ b/scripts/qemu.py @@ -59,9 +59,9 @@ class QEMUMachineAddDeviceError(QEMUMachineError): """ class MonitorResponseError(qmp.qmp.QMPError): - ''' + """ Represents erroneous QMP monitor reply - ''' + """ def __init__(self, reply): try: desc = reply["error"]["desc"] @@ -72,14 +72,15 @@ class MonitorResponseError(qmp.qmp.QMPError): class QEMUMachine(object): - '''A QEMU VM + """ + A QEMU VM Use this object as a context manager to ensure the QEMU process terminates:: with VM(binary) as vm: ... # vm is guaranteed to be shut down here - ''' + """ def __init__(self, binary, args=None, wrapper=None, name=None, test_dir="/var/tmp", monitor_address=None, @@ -141,18 +142,28 @@ class QEMUMachine(object): self._args.append(args) def add_fd(self, fd, fdset, opaque, opts=''): - '''Pass a file descriptor to the VM''' + """ + Pass a file descriptor to the VM + """ options = ['fd=%d' % fd, 'set=%d' % fdset, 'opaque=%s' % opaque] if opts: options.append(opts) + # This did not exist before 3.4, but since then it is + # mandatory for our purpose + if hasattr(os, 'set_inheritable'): + os.set_inheritable(fd, True) + self._args.append('-add-fd') self._args.append(','.join(options)) return self - def send_fd_scm(self, fd_file_path): + # Exactly one of fd and file_path must be given. + # (If it is file_path, the helper will open that file and pass its + # own fd) + def send_fd_scm(self, fd=None, file_path=None): # In iotest.py, the qmp should always use unix socket. assert self._qmp.is_scm_available() if self._socket_scm_helper is None: @@ -160,12 +171,27 @@ class QEMUMachine(object): if not os.path.exists(self._socket_scm_helper): raise QEMUMachineError("%s does not exist" % self._socket_scm_helper) + + # This did not exist before 3.4, but since then it is + # mandatory for our purpose + if hasattr(os, 'set_inheritable'): + os.set_inheritable(self._qmp.get_sock_fd(), True) + if fd is not None: + os.set_inheritable(fd, True) + fd_param = ["%s" % self._socket_scm_helper, - "%d" % self._qmp.get_sock_fd(), - "%s" % fd_file_path] + "%d" % self._qmp.get_sock_fd()] + + if file_path is not None: + assert fd is None + fd_param.append(file_path) + else: + assert fd is not None + fd_param.append(str(fd)) + devnull = open(os.path.devnull, 'rb') proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, close_fds=False) output = proc.communicate()[0] if output: LOG.debug(output) @@ -174,7 +200,9 @@ class QEMUMachine(object): @staticmethod def _remove_if_exists(path): - '''Remove file object at path if it exists''' + """ + Remove file object at path if it exists + """ try: os.remove(path) except OSError as exception: @@ -277,7 +305,9 @@ class QEMUMachine(object): raise def _launch(self): - '''Launch the VM and establish a QMP connection''' + """ + Launch the VM and establish a QMP connection + """ devnull = open(os.path.devnull, 'rb') self._pre_launch() self._qemu_full_args = (self._wrapper + [self._binary] + @@ -286,18 +316,23 @@ class QEMUMachine(object): stdin=devnull, stdout=self._qemu_log_file, stderr=subprocess.STDOUT, - shell=False) + shell=False, + close_fds=False) self._post_launch() def wait(self): - '''Wait for the VM to power off''' + """ + Wait for the VM to power off + """ self._popen.wait() self._qmp.close() self._load_io_log() self._post_shutdown() def shutdown(self): - '''Terminate the VM and clean up''' + """ + Terminate the VM and clean up + """ if self.is_running(): try: self._qmp.cmd('quit') @@ -321,7 +356,9 @@ class QEMUMachine(object): self._launched = False def qmp(self, cmd, conv_keys=True, **args): - '''Invoke a QMP command and return the response dict''' + """ + Invoke a QMP command and return the response dict + """ qmp_args = dict() for key, value in args.items(): if conv_keys: @@ -332,11 +369,11 @@ class QEMUMachine(object): return self._qmp.cmd(cmd, args=qmp_args) def command(self, cmd, conv_keys=True, **args): - ''' + """ Invoke a QMP command. On success return the response dict. On failure raise an exception. - ''' + """ reply = self.qmp(cmd, conv_keys, **args) if reply is None: raise qmp.qmp.QMPError("Monitor is closed") @@ -345,13 +382,17 @@ class QEMUMachine(object): return reply["return"] def get_qmp_event(self, wait=False): - '''Poll for one queued QMP events and return it''' + """ + Poll for one queued QMP events and return it + """ if len(self._events) > 0: return self._events.pop(0) return self._qmp.pull_event(wait=wait) def get_qmp_events(self, wait=False): - '''Poll for queued QMP events and return a list of dicts''' + """ + Poll for queued QMP events and return a list of dicts + """ events = self._qmp.get_events(wait=wait) events.extend(self._events) del self._events[:] @@ -359,7 +400,7 @@ class QEMUMachine(object): return events def event_wait(self, name, timeout=60.0, match=None): - ''' + """ Wait for specified timeout on named event in QMP; optionally filter results by match. @@ -367,7 +408,7 @@ class QEMUMachine(object): branch processing on match's value None {"foo": {"bar": 1}} matches {"foo": None} {"foo": {"bar": 1}} does not matches {"foo": {"baz": None}} - ''' + """ def event_match(event, match=None): if match is None: return True @@ -400,29 +441,29 @@ class QEMUMachine(object): return None def get_log(self): - ''' + """ After self.shutdown or failed qemu execution, this returns the output of the qemu process. - ''' + """ return self._iolog def add_args(self, *args): - ''' + """ Adds to the list of extra arguments to be given to the QEMU binary - ''' + """ self._args.extend(args) def set_machine(self, machine_type): - ''' + """ Sets the machine type If set, the machine type will be added to the base arguments of the resulting QEMU command line. - ''' + """ self._machine = machine_type def set_console(self, device_type=None): - ''' + """ Sets the device type for a console device If set, the console device and a backing character device will @@ -440,7 +481,7 @@ class QEMUMachine(object): @param device_type: the device type, such as "isa-serial" @raises: QEMUMachineAddDeviceError if the device type is not given and can not be determined. - ''' + """ if device_type is None: if self._machine is None: raise QEMUMachineAddDeviceError("Can not add a console device:" diff --git a/scripts/qtest.py b/scripts/qtest.py index df0daf26ca..adf1fe3f26 100644 --- a/scripts/qtest.py +++ b/scripts/qtest.py @@ -64,7 +64,7 @@ class QEMUQtestProtocol(object): @param qtest_cmd: qtest command text to be sent """ - self._sock.sendall(qtest_cmd + "\n") + self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) def close(self): self._sock.close() diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index fe7aebdc19..b15b615ceb 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -273,12 +273,12 @@ const uint64_t pred_esz_masks[4] = { *** SVE Logical - Unpredicated Group */ -static bool trans_AND_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_AND_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_and, 0, a->rd, a->rn, a->rm); } -static bool trans_ORR_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ORR_zzz(DisasContext *s, arg_rrr_esz *a) { if (a->rn == a->rm) { /* MOV */ return do_mov_z(s, a->rd, a->rn); @@ -287,12 +287,12 @@ static bool trans_ORR_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) } } -static bool trans_EOR_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_EOR_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_xor, 0, a->rd, a->rn, a->rm); } -static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm); } @@ -301,32 +301,32 @@ static bool trans_BIC_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) *** SVE Integer Arithmetic - Unpredicated Group */ -static bool trans_ADD_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ADD_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_add, a->esz, a->rd, a->rn, a->rm); } -static bool trans_SUB_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_SUB_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_sub, a->esz, a->rd, a->rn, a->rm); } -static bool trans_SQADD_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_SQADD_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_ssadd, a->esz, a->rd, a->rn, a->rm); } -static bool trans_SQSUB_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_SQSUB_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_sssub, a->esz, a->rd, a->rn, a->rm); } -static bool trans_UQADD_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UQADD_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_usadd, a->esz, a->rd, a->rn, a->rm); } -static bool trans_UQSUB_zzz(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UQSUB_zzz(DisasContext *s, arg_rrr_esz *a) { return do_vector3_z(s, tcg_gen_gvec_ussub, a->esz, a->rd, a->rn, a->rm); } @@ -369,8 +369,7 @@ static void do_sel_z(DisasContext *s, int rd, int rn, int rm, int pg, int esz) } #define DO_ZPZZ(NAME, name) \ -static bool trans_##NAME##_zpzz(DisasContext *s, arg_rprr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_zpzz(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_4 * const fns[4] = { \ gen_helper_sve_##name##_zpzz_b, gen_helper_sve_##name##_zpzz_h, \ @@ -402,7 +401,7 @@ DO_ZPZZ(ASR, asr) DO_ZPZZ(LSR, lsr) DO_ZPZZ(LSL, lsl) -static bool trans_SDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_SDIV_zpzz(DisasContext *s, arg_rprr_esz *a) { static gen_helper_gvec_4 * const fns[4] = { NULL, NULL, gen_helper_sve_sdiv_zpzz_s, gen_helper_sve_sdiv_zpzz_d @@ -410,7 +409,7 @@ static bool trans_SDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn) return do_zpzz_ool(s, a, fns[a->esz]); } -static bool trans_UDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_UDIV_zpzz(DisasContext *s, arg_rprr_esz *a) { static gen_helper_gvec_4 * const fns[4] = { NULL, NULL, gen_helper_sve_udiv_zpzz_s, gen_helper_sve_udiv_zpzz_d @@ -418,7 +417,7 @@ static bool trans_UDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn) return do_zpzz_ool(s, a, fns[a->esz]); } -static bool trans_SEL_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_SEL_zpzz(DisasContext *s, arg_rprr_esz *a) { if (sve_access_check(s)) { do_sel_z(s, a->rd, a->rn, a->rm, a->pg, a->esz); @@ -448,7 +447,7 @@ static bool do_zpz_ool(DisasContext *s, arg_rpr_esz *a, gen_helper_gvec_3 *fn) } #define DO_ZPZ(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a) \ { \ static gen_helper_gvec_3 * const fns[4] = { \ gen_helper_sve_##name##_b, gen_helper_sve_##name##_h, \ @@ -465,7 +464,7 @@ DO_ZPZ(NOT_zpz, not_zpz) DO_ZPZ(ABS, abs) DO_ZPZ(NEG, neg) -static bool trans_FABS(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FABS(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -476,7 +475,7 @@ static bool trans_FABS(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_FNEG(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FNEG(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -487,7 +486,7 @@ static bool trans_FNEG(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_SXTB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SXTB(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -498,7 +497,7 @@ static bool trans_SXTB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_UXTB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UXTB(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -509,7 +508,7 @@ static bool trans_UXTB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_SXTH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SXTH(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, NULL, @@ -519,7 +518,7 @@ static bool trans_SXTH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_UXTH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UXTH(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, NULL, @@ -529,12 +528,12 @@ static bool trans_UXTH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_SXTW(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SXTW(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ool(s, a, a->esz == 3 ? gen_helper_sve_sxtw_d : NULL); } -static bool trans_UXTW(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UXTW(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ool(s, a, a->esz == 3 ? gen_helper_sve_uxtw_d : NULL); } @@ -579,7 +578,7 @@ static bool do_vpz_ool(DisasContext *s, arg_rpr_esz *a, } #define DO_VPZ(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a) \ { \ static gen_helper_gvec_reduc * const fns[4] = { \ gen_helper_sve_##name##_b, gen_helper_sve_##name##_h, \ @@ -598,7 +597,7 @@ DO_VPZ(UMAXV, umaxv) DO_VPZ(SMINV, sminv) DO_VPZ(UMINV, uminv) -static bool trans_SADDV(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SADDV(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_reduc * const fns[4] = { gen_helper_sve_saddv_b, gen_helper_sve_saddv_h, @@ -659,7 +658,7 @@ static bool do_zpzi_ool(DisasContext *s, arg_rpri_esz *a, return true; } -static bool trans_ASR_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) +static bool trans_ASR_zpzi(DisasContext *s, arg_rpri_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_asr_zpzi_b, gen_helper_sve_asr_zpzi_h, @@ -675,7 +674,7 @@ static bool trans_ASR_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) return do_zpzi_ool(s, a, fns[a->esz]); } -static bool trans_LSR_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) +static bool trans_LSR_zpzi(DisasContext *s, arg_rpri_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_lsr_zpzi_b, gen_helper_sve_lsr_zpzi_h, @@ -693,7 +692,7 @@ static bool trans_LSR_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) } } -static bool trans_LSL_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) +static bool trans_LSL_zpzi(DisasContext *s, arg_rpri_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_lsl_zpzi_b, gen_helper_sve_lsl_zpzi_h, @@ -711,7 +710,7 @@ static bool trans_LSL_zpzi(DisasContext *s, arg_rpri_esz *a, uint32_t insn) } } -static bool trans_ASRD(DisasContext *s, arg_rpri_esz *a, uint32_t insn) +static bool trans_ASRD(DisasContext *s, arg_rpri_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_asrd_b, gen_helper_sve_asrd_h, @@ -734,8 +733,7 @@ static bool trans_ASRD(DisasContext *s, arg_rpri_esz *a, uint32_t insn) */ #define DO_ZPZW(NAME, name) \ -static bool trans_##NAME##_zpzw(DisasContext *s, arg_rprr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_zpzw(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_4 * const fns[3] = { \ gen_helper_sve_##name##_zpzw_b, gen_helper_sve_##name##_zpzw_h, \ @@ -784,17 +782,17 @@ static bool do_shift_imm(DisasContext *s, arg_rri_esz *a, bool asr, return true; } -static bool trans_ASR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_ASR_zzi(DisasContext *s, arg_rri_esz *a) { return do_shift_imm(s, a, true, tcg_gen_gvec_sari); } -static bool trans_LSR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_LSR_zzi(DisasContext *s, arg_rri_esz *a) { return do_shift_imm(s, a, false, tcg_gen_gvec_shri); } -static bool trans_LSL_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_LSL_zzi(DisasContext *s, arg_rri_esz *a) { return do_shift_imm(s, a, false, tcg_gen_gvec_shli); } @@ -815,8 +813,7 @@ static bool do_zzw_ool(DisasContext *s, arg_rrr_esz *a, gen_helper_gvec_3 *fn) } #define DO_ZZW(NAME, name) \ -static bool trans_##NAME##_zzw(DisasContext *s, arg_rrr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_zzw(DisasContext *s, arg_rrr_esz *a) \ { \ static gen_helper_gvec_3 * const fns[4] = { \ gen_helper_sve_##name##_zzw_b, gen_helper_sve_##name##_zzw_h, \ @@ -851,7 +848,7 @@ static bool do_zpzzz_ool(DisasContext *s, arg_rprrr_esz *a, } #define DO_ZPZZZ(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a) \ { \ static gen_helper_gvec_5 * const fns[4] = { \ gen_helper_sve_##name##_b, gen_helper_sve_##name##_h, \ @@ -900,7 +897,7 @@ static void do_index(DisasContext *s, int esz, int rd, tcg_temp_free_i32(desc); } -static bool trans_INDEX_ii(DisasContext *s, arg_INDEX_ii *a, uint32_t insn) +static bool trans_INDEX_ii(DisasContext *s, arg_INDEX_ii *a) { if (sve_access_check(s)) { TCGv_i64 start = tcg_const_i64(a->imm1); @@ -912,7 +909,7 @@ static bool trans_INDEX_ii(DisasContext *s, arg_INDEX_ii *a, uint32_t insn) return true; } -static bool trans_INDEX_ir(DisasContext *s, arg_INDEX_ir *a, uint32_t insn) +static bool trans_INDEX_ir(DisasContext *s, arg_INDEX_ir *a) { if (sve_access_check(s)) { TCGv_i64 start = tcg_const_i64(a->imm); @@ -923,7 +920,7 @@ static bool trans_INDEX_ir(DisasContext *s, arg_INDEX_ir *a, uint32_t insn) return true; } -static bool trans_INDEX_ri(DisasContext *s, arg_INDEX_ri *a, uint32_t insn) +static bool trans_INDEX_ri(DisasContext *s, arg_INDEX_ri *a) { if (sve_access_check(s)) { TCGv_i64 start = cpu_reg(s, a->rn); @@ -934,7 +931,7 @@ static bool trans_INDEX_ri(DisasContext *s, arg_INDEX_ri *a, uint32_t insn) return true; } -static bool trans_INDEX_rr(DisasContext *s, arg_INDEX_rr *a, uint32_t insn) +static bool trans_INDEX_rr(DisasContext *s, arg_INDEX_rr *a) { if (sve_access_check(s)) { TCGv_i64 start = cpu_reg(s, a->rn); @@ -948,7 +945,7 @@ static bool trans_INDEX_rr(DisasContext *s, arg_INDEX_rr *a, uint32_t insn) *** SVE Stack Allocation Group */ -static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a, uint32_t insn) +static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a) { TCGv_i64 rd = cpu_reg_sp(s, a->rd); TCGv_i64 rn = cpu_reg_sp(s, a->rn); @@ -956,7 +953,7 @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a, uint32_t insn) return true; } -static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a, uint32_t insn) +static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a) { TCGv_i64 rd = cpu_reg_sp(s, a->rd); TCGv_i64 rn = cpu_reg_sp(s, a->rn); @@ -964,7 +961,7 @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a, uint32_t insn) return true; } -static bool trans_RDVL(DisasContext *s, arg_RDVL *a, uint32_t insn) +static bool trans_RDVL(DisasContext *s, arg_RDVL *a) { TCGv_i64 reg = cpu_reg(s, a->rd); tcg_gen_movi_i64(reg, a->imm * vec_full_reg_size(s)); @@ -987,22 +984,22 @@ static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn) return true; } -static bool trans_ADR_p32(DisasContext *s, arg_rrri *a, uint32_t insn) +static bool trans_ADR_p32(DisasContext *s, arg_rrri *a) { return do_adr(s, a, gen_helper_sve_adr_p32); } -static bool trans_ADR_p64(DisasContext *s, arg_rrri *a, uint32_t insn) +static bool trans_ADR_p64(DisasContext *s, arg_rrri *a) { return do_adr(s, a, gen_helper_sve_adr_p64); } -static bool trans_ADR_s32(DisasContext *s, arg_rrri *a, uint32_t insn) +static bool trans_ADR_s32(DisasContext *s, arg_rrri *a) { return do_adr(s, a, gen_helper_sve_adr_s32); } -static bool trans_ADR_u32(DisasContext *s, arg_rrri *a, uint32_t insn) +static bool trans_ADR_u32(DisasContext *s, arg_rrri *a) { return do_adr(s, a, gen_helper_sve_adr_u32); } @@ -1011,7 +1008,7 @@ static bool trans_ADR_u32(DisasContext *s, arg_rrri *a, uint32_t insn) *** SVE Integer Misc - Unpredicated Group */ -static bool trans_FEXPA(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_FEXPA(DisasContext *s, arg_rr_esz *a) { static gen_helper_gvec_2 * const fns[4] = { NULL, @@ -1031,7 +1028,7 @@ static bool trans_FEXPA(DisasContext *s, arg_rr_esz *a, uint32_t insn) return true; } -static bool trans_FTSSEL(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_FTSSEL(DisasContext *s, arg_rrr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -1120,7 +1117,7 @@ static void gen_and_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_and_vec(vece, pd, pd, pg); } -static bool trans_AND_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_AND_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_and_pg_i64, @@ -1156,7 +1153,7 @@ static void gen_bic_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_and_vec(vece, pd, pd, pg); } -static bool trans_BIC_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_BIC_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_bic_pg_i64, @@ -1186,7 +1183,7 @@ static void gen_eor_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_and_vec(vece, pd, pd, pg); } -static bool trans_EOR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_EOR_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_eor_pg_i64, @@ -1216,7 +1213,7 @@ static void gen_sel_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_or_vec(vece, pd, pn, pm); } -static bool trans_SEL_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_SEL_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_sel_pg_i64, @@ -1244,7 +1241,7 @@ static void gen_orr_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_and_vec(vece, pd, pd, pg); } -static bool trans_ORR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_ORR_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_orr_pg_i64, @@ -1274,7 +1271,7 @@ static void gen_orn_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_and_vec(vece, pd, pd, pg); } -static bool trans_ORN_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_ORN_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_orn_pg_i64, @@ -1302,7 +1299,7 @@ static void gen_nor_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_andc_vec(vece, pd, pg, pd); } -static bool trans_NOR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_NOR_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_nor_pg_i64, @@ -1330,7 +1327,7 @@ static void gen_nand_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, tcg_gen_andc_vec(vece, pd, pg, pd); } -static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a) { static const GVecGen4 op = { .fni8 = gen_nand_pg_i64, @@ -1349,7 +1346,7 @@ static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) *** SVE Predicate Misc Group */ -static bool trans_PTEST(DisasContext *s, arg_PTEST *a, uint32_t insn) +static bool trans_PTEST(DisasContext *s, arg_PTEST *a) { if (sve_access_check(s)) { int nofs = pred_full_reg_offset(s, a->rn); @@ -1491,24 +1488,24 @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag) return true; } -static bool trans_PTRUE(DisasContext *s, arg_PTRUE *a, uint32_t insn) +static bool trans_PTRUE(DisasContext *s, arg_PTRUE *a) { return do_predset(s, a->esz, a->rd, a->pat, a->s); } -static bool trans_SETFFR(DisasContext *s, arg_SETFFR *a, uint32_t insn) +static bool trans_SETFFR(DisasContext *s, arg_SETFFR *a) { /* Note pat == 31 is #all, to set all elements. */ return do_predset(s, 0, FFR_PRED_NUM, 31, false); } -static bool trans_PFALSE(DisasContext *s, arg_PFALSE *a, uint32_t insn) +static bool trans_PFALSE(DisasContext *s, arg_PFALSE *a) { /* Note pat == 32 is #unimp, to set no elements. */ return do_predset(s, 0, a->rd, 32, false); } -static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a, uint32_t insn) +static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a) { /* The path through do_pppp_flags is complicated enough to want to avoid * duplication. Frob the arguments into the form of a predicated AND. @@ -1517,15 +1514,15 @@ static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a, uint32_t insn) .rd = a->rd, .pg = a->pg, .s = a->s, .rn = FFR_PRED_NUM, .rm = FFR_PRED_NUM, }; - return trans_AND_pppp(s, &alt_a, insn); + return trans_AND_pppp(s, &alt_a); } -static bool trans_RDFFR(DisasContext *s, arg_RDFFR *a, uint32_t insn) +static bool trans_RDFFR(DisasContext *s, arg_RDFFR *a) { return do_mov_p(s, a->rd, FFR_PRED_NUM); } -static bool trans_WRFFR(DisasContext *s, arg_WRFFR *a, uint32_t insn) +static bool trans_WRFFR(DisasContext *s, arg_WRFFR *a) { return do_mov_p(s, FFR_PRED_NUM, a->rn); } @@ -1559,12 +1556,12 @@ static bool do_pfirst_pnext(DisasContext *s, arg_rr_esz *a, return true; } -static bool trans_PFIRST(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_PFIRST(DisasContext *s, arg_rr_esz *a) { return do_pfirst_pnext(s, a, gen_helper_sve_pfirst); } -static bool trans_PNEXT(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_PNEXT(DisasContext *s, arg_rr_esz *a) { return do_pfirst_pnext(s, a, gen_helper_sve_pnext); } @@ -1735,7 +1732,7 @@ static void do_sat_addsub_vec(DisasContext *s, int esz, int rd, int rn, tcg_temp_free_i32(desc); } -static bool trans_CNT_r(DisasContext *s, arg_CNT_r *a, uint32_t insn) +static bool trans_CNT_r(DisasContext *s, arg_CNT_r *a) { if (sve_access_check(s)) { unsigned fullsz = vec_full_reg_size(s); @@ -1745,7 +1742,7 @@ static bool trans_CNT_r(DisasContext *s, arg_CNT_r *a, uint32_t insn) return true; } -static bool trans_INCDEC_r(DisasContext *s, arg_incdec_cnt *a, uint32_t insn) +static bool trans_INCDEC_r(DisasContext *s, arg_incdec_cnt *a) { if (sve_access_check(s)) { unsigned fullsz = vec_full_reg_size(s); @@ -1758,8 +1755,7 @@ static bool trans_INCDEC_r(DisasContext *s, arg_incdec_cnt *a, uint32_t insn) return true; } -static bool trans_SINCDEC_r_32(DisasContext *s, arg_incdec_cnt *a, - uint32_t insn) +static bool trans_SINCDEC_r_32(DisasContext *s, arg_incdec_cnt *a) { if (!sve_access_check(s)) { return true; @@ -1785,8 +1781,7 @@ static bool trans_SINCDEC_r_32(DisasContext *s, arg_incdec_cnt *a, return true; } -static bool trans_SINCDEC_r_64(DisasContext *s, arg_incdec_cnt *a, - uint32_t insn) +static bool trans_SINCDEC_r_64(DisasContext *s, arg_incdec_cnt *a) { if (!sve_access_check(s)) { return true; @@ -1805,7 +1800,7 @@ static bool trans_SINCDEC_r_64(DisasContext *s, arg_incdec_cnt *a, return true; } -static bool trans_INCDEC_v(DisasContext *s, arg_incdec2_cnt *a, uint32_t insn) +static bool trans_INCDEC_v(DisasContext *s, arg_incdec2_cnt *a) { if (a->esz == 0) { return false; @@ -1829,8 +1824,7 @@ static bool trans_INCDEC_v(DisasContext *s, arg_incdec2_cnt *a, uint32_t insn) return true; } -static bool trans_SINCDEC_v(DisasContext *s, arg_incdec2_cnt *a, - uint32_t insn) +static bool trans_SINCDEC_v(DisasContext *s, arg_incdec2_cnt *a) { if (a->esz == 0) { return false; @@ -1872,22 +1866,22 @@ static bool do_zz_dbm(DisasContext *s, arg_rr_dbm *a, GVecGen2iFn *gvec_fn) return true; } -static bool trans_AND_zzi(DisasContext *s, arg_rr_dbm *a, uint32_t insn) +static bool trans_AND_zzi(DisasContext *s, arg_rr_dbm *a) { return do_zz_dbm(s, a, tcg_gen_gvec_andi); } -static bool trans_ORR_zzi(DisasContext *s, arg_rr_dbm *a, uint32_t insn) +static bool trans_ORR_zzi(DisasContext *s, arg_rr_dbm *a) { return do_zz_dbm(s, a, tcg_gen_gvec_ori); } -static bool trans_EOR_zzi(DisasContext *s, arg_rr_dbm *a, uint32_t insn) +static bool trans_EOR_zzi(DisasContext *s, arg_rr_dbm *a) { return do_zz_dbm(s, a, tcg_gen_gvec_xori); } -static bool trans_DUPM(DisasContext *s, arg_DUPM *a, uint32_t insn) +static bool trans_DUPM(DisasContext *s, arg_DUPM *a) { uint64_t imm; if (!logic_imm_decode_wmask(&imm, extract32(a->dbm, 12, 1), @@ -1934,7 +1928,7 @@ static void do_cpy_m(DisasContext *s, int esz, int rd, int rn, int pg, tcg_temp_free_i32(desc); } -static bool trans_FCPY(DisasContext *s, arg_FCPY *a, uint32_t insn) +static bool trans_FCPY(DisasContext *s, arg_FCPY *a) { if (a->esz == 0) { return false; @@ -1949,9 +1943,9 @@ static bool trans_FCPY(DisasContext *s, arg_FCPY *a, uint32_t insn) return true; } -static bool trans_CPY_m_i(DisasContext *s, arg_rpri_esz *a, uint32_t insn) +static bool trans_CPY_m_i(DisasContext *s, arg_rpri_esz *a) { - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -1962,14 +1956,14 @@ static bool trans_CPY_m_i(DisasContext *s, arg_rpri_esz *a, uint32_t insn) return true; } -static bool trans_CPY_z_i(DisasContext *s, arg_CPY_z_i *a, uint32_t insn) +static bool trans_CPY_z_i(DisasContext *s, arg_CPY_z_i *a) { static gen_helper_gvec_2i * const fns[4] = { gen_helper_sve_cpy_z_b, gen_helper_sve_cpy_z_h, gen_helper_sve_cpy_z_s, gen_helper_sve_cpy_z_d, }; - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -1987,7 +1981,7 @@ static bool trans_CPY_z_i(DisasContext *s, arg_CPY_z_i *a, uint32_t insn) *** SVE Permute Extract Group */ -static bool trans_EXT(DisasContext *s, arg_EXT *a, uint32_t insn) +static bool trans_EXT(DisasContext *s, arg_EXT *a) { if (!sve_access_check(s)) { return true; @@ -2021,7 +2015,7 @@ static bool trans_EXT(DisasContext *s, arg_EXT *a, uint32_t insn) *** SVE Permute - Unpredicated Group */ -static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a, uint32_t insn) +static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a) { if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); @@ -2031,7 +2025,7 @@ static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a, uint32_t insn) return true; } -static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a, uint32_t insn) +static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a) { if ((a->imm & 0x1f) == 0) { return false; @@ -2076,7 +2070,7 @@ static void do_insr_i64(DisasContext *s, arg_rrr_esz *a, TCGv_i64 val) tcg_temp_free_i32(desc); } -static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a) { if (sve_access_check(s)) { TCGv_i64 t = tcg_temp_new_i64(); @@ -2087,7 +2081,7 @@ static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a, uint32_t insn) return true; } -static bool trans_INSR_r(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_INSR_r(DisasContext *s, arg_rrr_esz *a) { if (sve_access_check(s)) { do_insr_i64(s, a, cpu_reg(s, a->rm)); @@ -2095,7 +2089,7 @@ static bool trans_INSR_r(DisasContext *s, arg_rrr_esz *a, uint32_t insn) return true; } -static bool trans_REV_v(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_REV_v(DisasContext *s, arg_rr_esz *a) { static gen_helper_gvec_2 * const fns[4] = { gen_helper_sve_rev_b, gen_helper_sve_rev_h, @@ -2111,7 +2105,7 @@ static bool trans_REV_v(DisasContext *s, arg_rr_esz *a, uint32_t insn) return true; } -static bool trans_TBL(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_TBL(DisasContext *s, arg_rrr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_tbl_b, gen_helper_sve_tbl_h, @@ -2128,7 +2122,7 @@ static bool trans_TBL(DisasContext *s, arg_rrr_esz *a, uint32_t insn) return true; } -static bool trans_UNPK(DisasContext *s, arg_UNPK *a, uint32_t insn) +static bool trans_UNPK(DisasContext *s, arg_UNPK *a) { static gen_helper_gvec_2 * const fns[4][2] = { { NULL, NULL }, @@ -2225,47 +2219,47 @@ static bool do_perm_pred2(DisasContext *s, arg_rr_esz *a, bool high_odd, return true; } -static bool trans_ZIP1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ZIP1_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 0, gen_helper_sve_zip_p); } -static bool trans_ZIP2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ZIP2_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 1, gen_helper_sve_zip_p); } -static bool trans_UZP1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UZP1_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 0, gen_helper_sve_uzp_p); } -static bool trans_UZP2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UZP2_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 1, gen_helper_sve_uzp_p); } -static bool trans_TRN1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_TRN1_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 0, gen_helper_sve_trn_p); } -static bool trans_TRN2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_TRN2_p(DisasContext *s, arg_rrr_esz *a) { return do_perm_pred3(s, a, 1, gen_helper_sve_trn_p); } -static bool trans_REV_p(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_REV_p(DisasContext *s, arg_rr_esz *a) { return do_perm_pred2(s, a, 0, gen_helper_sve_rev_p); } -static bool trans_PUNPKLO(DisasContext *s, arg_PUNPKLO *a, uint32_t insn) +static bool trans_PUNPKLO(DisasContext *s, arg_PUNPKLO *a) { return do_perm_pred2(s, a, 0, gen_helper_sve_punpk_p); } -static bool trans_PUNPKHI(DisasContext *s, arg_PUNPKHI *a, uint32_t insn) +static bool trans_PUNPKHI(DisasContext *s, arg_PUNPKHI *a) { return do_perm_pred2(s, a, 1, gen_helper_sve_punpk_p); } @@ -2305,12 +2299,12 @@ static bool do_zzz_data_ool(DisasContext *s, arg_rrr_esz *a, int data, return true; } -static bool trans_ZIP1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ZIP1_z(DisasContext *s, arg_rrr_esz *a) { return do_zip(s, a, false); } -static bool trans_ZIP2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_ZIP2_z(DisasContext *s, arg_rrr_esz *a) { return do_zip(s, a, true); } @@ -2320,12 +2314,12 @@ static gen_helper_gvec_3 * const uzp_fns[4] = { gen_helper_sve_uzp_s, gen_helper_sve_uzp_d, }; -static bool trans_UZP1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UZP1_z(DisasContext *s, arg_rrr_esz *a) { return do_zzz_data_ool(s, a, 0, uzp_fns[a->esz]); } -static bool trans_UZP2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_UZP2_z(DisasContext *s, arg_rrr_esz *a) { return do_zzz_data_ool(s, a, 1 << a->esz, uzp_fns[a->esz]); } @@ -2335,12 +2329,12 @@ static gen_helper_gvec_3 * const trn_fns[4] = { gen_helper_sve_trn_s, gen_helper_sve_trn_d, }; -static bool trans_TRN1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_TRN1_z(DisasContext *s, arg_rrr_esz *a) { return do_zzz_data_ool(s, a, 0, trn_fns[a->esz]); } -static bool trans_TRN2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) +static bool trans_TRN2_z(DisasContext *s, arg_rrr_esz *a) { return do_zzz_data_ool(s, a, 1 << a->esz, trn_fns[a->esz]); } @@ -2349,7 +2343,7 @@ static bool trans_TRN2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn) *** SVE Permute Vector - Predicated Group */ -static bool trans_COMPACT(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_COMPACT(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, NULL, gen_helper_sve_compact_s, gen_helper_sve_compact_d @@ -2516,12 +2510,12 @@ static bool do_clast_vector(DisasContext *s, arg_rprr_esz *a, bool before) return true; } -static bool trans_CLASTA_z(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_CLASTA_z(DisasContext *s, arg_rprr_esz *a) { return do_clast_vector(s, a, false); } -static bool trans_CLASTB_z(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_CLASTB_z(DisasContext *s, arg_rprr_esz *a) { return do_clast_vector(s, a, true); } @@ -2574,12 +2568,12 @@ static bool do_clast_fp(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -static bool trans_CLASTA_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CLASTA_v(DisasContext *s, arg_rpr_esz *a) { return do_clast_fp(s, a, false); } -static bool trans_CLASTB_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CLASTB_v(DisasContext *s, arg_rpr_esz *a) { return do_clast_fp(s, a, true); } @@ -2614,12 +2608,12 @@ static bool do_clast_general(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -static bool trans_CLASTA_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CLASTA_r(DisasContext *s, arg_rpr_esz *a) { return do_clast_general(s, a, false); } -static bool trans_CLASTB_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CLASTB_r(DisasContext *s, arg_rpr_esz *a) { return do_clast_general(s, a, true); } @@ -2654,12 +2648,12 @@ static bool do_last_fp(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -static bool trans_LASTA_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_LASTA_v(DisasContext *s, arg_rpr_esz *a) { return do_last_fp(s, a, false); } -static bool trans_LASTB_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_LASTB_v(DisasContext *s, arg_rpr_esz *a) { return do_last_fp(s, a, true); } @@ -2675,17 +2669,17 @@ static bool do_last_general(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -static bool trans_LASTA_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_LASTA_r(DisasContext *s, arg_rpr_esz *a) { return do_last_general(s, a, false); } -static bool trans_LASTB_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_LASTB_r(DisasContext *s, arg_rpr_esz *a) { return do_last_general(s, a, true); } -static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a) { if (sve_access_check(s)) { do_cpy_m(s, a->esz, a->rd, a->rd, a->pg, cpu_reg_sp(s, a->rn)); @@ -2693,7 +2687,7 @@ static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return true; } -static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a) { if (sve_access_check(s)) { int ofs = vec_reg_offset(s, a->rn, 0, a->esz); @@ -2704,7 +2698,7 @@ static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return true; } -static bool trans_REVB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_REVB(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -2715,7 +2709,7 @@ static bool trans_REVB(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_REVH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_REVH(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { NULL, @@ -2726,12 +2720,12 @@ static bool trans_REVH(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_REVW(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_REVW(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ool(s, a, a->esz == 3 ? gen_helper_sve_revw_d : NULL); } -static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3 * const fns[4] = { gen_helper_sve_rbit_b, @@ -2742,7 +2736,7 @@ static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ool(s, a, fns[a->esz]); } -static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a) { if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); @@ -2799,8 +2793,7 @@ static bool do_ppzz_flags(DisasContext *s, arg_rprr_esz *a, } #define DO_PPZZ(NAME, name) \ -static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_flags_4 * const fns[4] = { \ gen_helper_sve_##name##_ppzz_b, gen_helper_sve_##name##_ppzz_h, \ @@ -2819,8 +2812,7 @@ DO_PPZZ(CMPHS, cmphs) #undef DO_PPZZ #define DO_PPZW(NAME, name) \ -static bool trans_##NAME##_ppzw(DisasContext *s, arg_rprr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_ppzw(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_flags_4 * const fns[4] = { \ gen_helper_sve_##name##_ppzw_b, gen_helper_sve_##name##_ppzw_h, \ @@ -2883,8 +2875,7 @@ static bool do_ppzi_flags(DisasContext *s, arg_rpri_esz *a, } #define DO_PPZI(NAME, name) \ -static bool trans_##NAME##_ppzi(DisasContext *s, arg_rpri_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_ppzi(DisasContext *s, arg_rpri_esz *a) \ { \ static gen_helper_gvec_flags_3 * const fns[4] = { \ gen_helper_sve_##name##_ppzi_b, gen_helper_sve_##name##_ppzi_h, \ @@ -2977,37 +2968,37 @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a, return true; } -static bool trans_BRKPA(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_BRKPA(DisasContext *s, arg_rprr_s *a) { return do_brk3(s, a, gen_helper_sve_brkpa, gen_helper_sve_brkpas); } -static bool trans_BRKPB(DisasContext *s, arg_rprr_s *a, uint32_t insn) +static bool trans_BRKPB(DisasContext *s, arg_rprr_s *a) { return do_brk3(s, a, gen_helper_sve_brkpb, gen_helper_sve_brkpbs); } -static bool trans_BRKA_m(DisasContext *s, arg_rpr_s *a, uint32_t insn) +static bool trans_BRKA_m(DisasContext *s, arg_rpr_s *a) { return do_brk2(s, a, gen_helper_sve_brka_m, gen_helper_sve_brkas_m); } -static bool trans_BRKB_m(DisasContext *s, arg_rpr_s *a, uint32_t insn) +static bool trans_BRKB_m(DisasContext *s, arg_rpr_s *a) { return do_brk2(s, a, gen_helper_sve_brkb_m, gen_helper_sve_brkbs_m); } -static bool trans_BRKA_z(DisasContext *s, arg_rpr_s *a, uint32_t insn) +static bool trans_BRKA_z(DisasContext *s, arg_rpr_s *a) { return do_brk2(s, a, gen_helper_sve_brka_z, gen_helper_sve_brkas_z); } -static bool trans_BRKB_z(DisasContext *s, arg_rpr_s *a, uint32_t insn) +static bool trans_BRKB_z(DisasContext *s, arg_rpr_s *a) { return do_brk2(s, a, gen_helper_sve_brkb_z, gen_helper_sve_brkbs_z); } -static bool trans_BRKN(DisasContext *s, arg_rpr_s *a, uint32_t insn) +static bool trans_BRKN(DisasContext *s, arg_rpr_s *a) { return do_brk2(s, a, gen_helper_sve_brkn, gen_helper_sve_brkns); } @@ -3058,7 +3049,7 @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg) } } -static bool trans_CNTP(DisasContext *s, arg_CNTP *a, uint32_t insn) +static bool trans_CNTP(DisasContext *s, arg_CNTP *a) { if (sve_access_check(s)) { do_cntp(s, cpu_reg(s, a->rd), a->esz, a->rn, a->pg); @@ -3066,8 +3057,7 @@ static bool trans_CNTP(DisasContext *s, arg_CNTP *a, uint32_t insn) return true; } -static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a, - uint32_t insn) +static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a) { if (sve_access_check(s)) { TCGv_i64 reg = cpu_reg(s, a->rd); @@ -3084,8 +3074,7 @@ static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a, return true; } -static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a, - uint32_t insn) +static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a) { if (a->esz == 0) { return false; @@ -3102,8 +3091,7 @@ static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a, return true; } -static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a, - uint32_t insn) +static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a) { if (sve_access_check(s)) { TCGv_i64 reg = cpu_reg(s, a->rd); @@ -3115,8 +3103,7 @@ static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a, return true; } -static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a, - uint32_t insn) +static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a) { if (sve_access_check(s)) { TCGv_i64 reg = cpu_reg(s, a->rd); @@ -3128,8 +3115,7 @@ static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a, return true; } -static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a, - uint32_t insn) +static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a) { if (a->esz == 0) { return false; @@ -3146,7 +3132,7 @@ static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a, *** SVE Integer Compare Scalars Group */ -static bool trans_CTERM(DisasContext *s, arg_CTERM *a, uint32_t insn) +static bool trans_CTERM(DisasContext *s, arg_CTERM *a) { if (!sve_access_check(s)) { return true; @@ -3171,7 +3157,7 @@ static bool trans_CTERM(DisasContext *s, arg_CTERM *a, uint32_t insn) return true; } -static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn) +static bool trans_WHILE(DisasContext *s, arg_WHILE *a) { TCGv_i64 op0, op1, t0, t1, tmax; TCGv_i32 t2, t3; @@ -3260,7 +3246,7 @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn) *** SVE Integer Wide Immediate - Unpredicated Group */ -static bool trans_FDUP(DisasContext *s, arg_FDUP *a, uint32_t insn) +static bool trans_FDUP(DisasContext *s, arg_FDUP *a) { if (a->esz == 0) { return false; @@ -3279,9 +3265,9 @@ static bool trans_FDUP(DisasContext *s, arg_FDUP *a, uint32_t insn) return true; } -static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a, uint32_t insn) +static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a) { - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -3293,9 +3279,9 @@ static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a, uint32_t insn) return true; } -static bool trans_ADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_ADD_zzi(DisasContext *s, arg_rri_esz *a) { - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -3306,13 +3292,13 @@ static bool trans_ADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) return true; } -static bool trans_SUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_SUB_zzi(DisasContext *s, arg_rri_esz *a) { a->imm = -a->imm; - return trans_ADD_zzi(s, a, insn); + return trans_ADD_zzi(s, a); } -static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a) { static const GVecGen2s op[4] = { { .fni8 = tcg_gen_vec_sub8_i64, @@ -3342,7 +3328,7 @@ static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) .scalar_first = true } }; - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -3356,7 +3342,7 @@ static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) return true; } -static bool trans_MUL_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_MUL_zzi(DisasContext *s, arg_rri_esz *a) { if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); @@ -3366,10 +3352,9 @@ static bool trans_MUL_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) return true; } -static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, uint32_t insn, - bool u, bool d) +static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, bool u, bool d) { - if (a->esz == 0 && extract32(insn, 13, 1)) { + if (a->esz == 0 && extract32(s->insn, 13, 1)) { return false; } if (sve_access_check(s)) { @@ -3380,24 +3365,24 @@ static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, uint32_t insn, return true; } -static bool trans_SQADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_SQADD_zzi(DisasContext *s, arg_rri_esz *a) { - return do_zzi_sat(s, a, insn, false, false); + return do_zzi_sat(s, a, false, false); } -static bool trans_UQADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_UQADD_zzi(DisasContext *s, arg_rri_esz *a) { - return do_zzi_sat(s, a, insn, true, false); + return do_zzi_sat(s, a, true, false); } -static bool trans_SQSUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_SQSUB_zzi(DisasContext *s, arg_rri_esz *a) { - return do_zzi_sat(s, a, insn, false, true); + return do_zzi_sat(s, a, false, true); } -static bool trans_UQSUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn) +static bool trans_UQSUB_zzi(DisasContext *s, arg_rri_esz *a) { - return do_zzi_sat(s, a, insn, true, true); + return do_zzi_sat(s, a, true, true); } static bool do_zzi_ool(DisasContext *s, arg_rri_esz *a, gen_helper_gvec_2i *fn) @@ -3415,8 +3400,7 @@ static bool do_zzi_ool(DisasContext *s, arg_rri_esz *a, gen_helper_gvec_2i *fn) } #define DO_ZZI(NAME, name) \ -static bool trans_##NAME##_zzi(DisasContext *s, arg_rri_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_zzi(DisasContext *s, arg_rri_esz *a) \ { \ static gen_helper_gvec_2i * const fns[4] = { \ gen_helper_sve_##name##i_b, gen_helper_sve_##name##i_h, \ @@ -3432,7 +3416,7 @@ DO_ZZI(UMIN, umin) #undef DO_ZZI -static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a, uint32_t insn) +static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a) { static gen_helper_gvec_3 * const fns[2][2] = { { gen_helper_gvec_sdot_b, gen_helper_gvec_sdot_h }, @@ -3449,7 +3433,7 @@ static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a, uint32_t insn) return true; } -static bool trans_DOT_zzx(DisasContext *s, arg_DOT_zzx *a, uint32_t insn) +static bool trans_DOT_zzx(DisasContext *s, arg_DOT_zzx *a) { static gen_helper_gvec_3 * const fns[2][2] = { { gen_helper_gvec_sdot_idx_b, gen_helper_gvec_sdot_idx_h }, @@ -3471,7 +3455,7 @@ static bool trans_DOT_zzx(DisasContext *s, arg_DOT_zzx *a, uint32_t insn) *** SVE Floating Point Multiply-Add Indexed Group */ -static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a, uint32_t insn) +static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a) { static gen_helper_gvec_4_ptr * const fns[3] = { gen_helper_gvec_fmla_idx_h, @@ -3497,7 +3481,7 @@ static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a, uint32_t insn) *** SVE Floating Point Multiply Indexed Group */ -static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a, uint32_t insn) +static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a) { static gen_helper_gvec_3_ptr * const fns[3] = { gen_helper_gvec_fmul_idx_h, @@ -3552,7 +3536,7 @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a, } #define DO_VPZ(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a) \ { \ static gen_helper_fp_reduce * const fns[3] = { \ gen_helper_sve_##name##_h, \ @@ -3589,7 +3573,7 @@ static void do_zz_fp(DisasContext *s, arg_rr_esz *a, gen_helper_gvec_2_ptr *fn) tcg_temp_free_ptr(status); } -static bool trans_FRECPE(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_FRECPE(DisasContext *s, arg_rr_esz *a) { static gen_helper_gvec_2_ptr * const fns[3] = { gen_helper_gvec_frecpe_h, @@ -3605,7 +3589,7 @@ static bool trans_FRECPE(DisasContext *s, arg_rr_esz *a, uint32_t insn) return true; } -static bool trans_FRSQRTE(DisasContext *s, arg_rr_esz *a, uint32_t insn) +static bool trans_FRSQRTE(DisasContext *s, arg_rr_esz *a) { static gen_helper_gvec_2_ptr * const fns[3] = { gen_helper_gvec_frsqrte_h, @@ -3639,7 +3623,7 @@ static void do_ppz_fp(DisasContext *s, arg_rpr_esz *a, } #define DO_PPZ(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a) \ { \ static gen_helper_gvec_3_ptr * const fns[3] = { \ gen_helper_sve_##name##_h, \ @@ -3668,7 +3652,7 @@ DO_PPZ(FCMNE_ppz0, fcmne0) *** SVE floating-point trig multiply-add coefficient */ -static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a, uint32_t insn) +static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a) { static gen_helper_gvec_3_ptr * const fns[3] = { gen_helper_sve_ftmad_h, @@ -3695,7 +3679,7 @@ static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a, uint32_t insn) *** SVE Floating Point Accumulating Reduction Group */ -static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a, uint32_t insn) +static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) { typedef void fadda_fn(TCGv_i64, TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); @@ -3760,7 +3744,7 @@ static bool do_zzz_fp(DisasContext *s, arg_rrr_esz *a, #define DO_FP3(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rrr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rrr_esz *a) \ { \ static gen_helper_gvec_3_ptr * const fns[4] = { \ NULL, gen_helper_gvec_##name##_h, \ @@ -3802,7 +3786,7 @@ static bool do_zpzz_fp(DisasContext *s, arg_rprr_esz *a, } #define DO_FP3(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rprr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_4_ptr * const fns[4] = { \ NULL, gen_helper_sve_##name##_h, \ @@ -3862,8 +3846,7 @@ static void do_fp_imm(DisasContext *s, arg_rpri_esz *a, uint64_t imm, } #define DO_FP_IMM(NAME, name, const0, const1) \ -static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a) \ { \ static gen_helper_sve_fp2scalar * const fns[3] = { \ gen_helper_sve_##name##_h, \ @@ -3919,8 +3902,7 @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a, } #define DO_FPCMP(NAME, name) \ -static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a, \ - uint32_t insn) \ +static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a) \ { \ static gen_helper_gvec_4_ptr * const fns[4] = { \ NULL, gen_helper_sve_##name##_h, \ @@ -3939,7 +3921,7 @@ DO_FPCMP(FACGT, facgt) #undef DO_FPCMP -static bool trans_FCADD(DisasContext *s, arg_FCADD *a, uint32_t insn) +static bool trans_FCADD(DisasContext *s, arg_FCADD *a) { static gen_helper_gvec_4_ptr * const fns[3] = { gen_helper_sve_fcadd_h, @@ -3996,7 +3978,7 @@ static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_fmla *fn) } #define DO_FMLA(NAME, name) \ -static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a, uint32_t insn) \ +static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a) \ { \ static gen_helper_sve_fmla * const fns[4] = { \ NULL, gen_helper_sve_##name##_h, \ @@ -4012,8 +3994,7 @@ DO_FMLA(FNMLS_zpzzz, fnmls_zpzzz) #undef DO_FMLA -static bool trans_FCMLA_zpzzz(DisasContext *s, - arg_FCMLA_zpzzz *a, uint32_t insn) +static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a) { static gen_helper_sve_fmla * const fns[3] = { gen_helper_sve_fcmla_zpzzz_h, @@ -4049,7 +4030,7 @@ static bool trans_FCMLA_zpzzz(DisasContext *s, return true; } -static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a, uint32_t insn) +static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a) { static gen_helper_gvec_3_ptr * const fns[2] = { gen_helper_gvec_fcmlah_idx, @@ -4091,102 +4072,102 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg, return true; } -static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sh); } -static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hs); } -static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_dh); } -static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hd); } -static bool trans_FCVT_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_ds(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_ds); } -static bool trans_FCVT_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVT_sd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sd); } -static bool trans_FCVTZS_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_hh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hh); } -static bool trans_FCVTZU_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_hh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hh); } -static bool trans_FCVTZS_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_hs(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hs); } -static bool trans_FCVTZU_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_hs(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hs); } -static bool trans_FCVTZS_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_hd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hd); } -static bool trans_FCVTZU_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_hd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hd); } -static bool trans_FCVTZS_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_ss(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_ss); } -static bool trans_FCVTZU_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_ss(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_ss); } -static bool trans_FCVTZS_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_sd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_sd); } -static bool trans_FCVTZU_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_sd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_sd); } -static bool trans_FCVTZS_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_ds(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_ds); } -static bool trans_FCVTZU_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_ds(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_ds); } -static bool trans_FCVTZS_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZS_dd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_dd); } -static bool trans_FCVTZU_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FCVTZU_dd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_dd); } @@ -4197,7 +4178,7 @@ static gen_helper_gvec_3_ptr * const frint_fns[3] = { gen_helper_sve_frint_d }; -static bool trans_FRINTI(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTI(DisasContext *s, arg_rpr_esz *a) { if (a->esz == 0) { return false; @@ -4206,7 +4187,7 @@ static bool trans_FRINTI(DisasContext *s, arg_rpr_esz *a, uint32_t insn) frint_fns[a->esz - 1]); } -static bool trans_FRINTX(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTX(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3_ptr * const fns[3] = { gen_helper_sve_frintx_h, @@ -4243,32 +4224,32 @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode) return true; } -static bool trans_FRINTN(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTN(DisasContext *s, arg_rpr_esz *a) { return do_frint_mode(s, a, float_round_nearest_even); } -static bool trans_FRINTP(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTP(DisasContext *s, arg_rpr_esz *a) { return do_frint_mode(s, a, float_round_up); } -static bool trans_FRINTM(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTM(DisasContext *s, arg_rpr_esz *a) { return do_frint_mode(s, a, float_round_down); } -static bool trans_FRINTZ(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTZ(DisasContext *s, arg_rpr_esz *a) { return do_frint_mode(s, a, float_round_to_zero); } -static bool trans_FRINTA(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRINTA(DisasContext *s, arg_rpr_esz *a) { return do_frint_mode(s, a, float_round_ties_away); } -static bool trans_FRECPX(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FRECPX(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3_ptr * const fns[3] = { gen_helper_sve_frecpx_h, @@ -4281,7 +4262,7 @@ static bool trans_FRECPX(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]); } -static bool trans_FSQRT(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_FSQRT(DisasContext *s, arg_rpr_esz *a) { static gen_helper_gvec_3_ptr * const fns[3] = { gen_helper_sve_fsqrt_h, @@ -4294,72 +4275,72 @@ static bool trans_FSQRT(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]); } -static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh); } -static bool trans_SCVTF_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_sh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_sh); } -static bool trans_SCVTF_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_dh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_dh); } -static bool trans_SCVTF_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_ss(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_ss); } -static bool trans_SCVTF_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_ds(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_ds); } -static bool trans_SCVTF_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_sd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_sd); } -static bool trans_SCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_SCVTF_dd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_dd); } -static bool trans_UCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_hh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_hh); } -static bool trans_UCVTF_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_sh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_sh); } -static bool trans_UCVTF_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_dh(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_dh); } -static bool trans_UCVTF_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_ss(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_ss); } -static bool trans_UCVTF_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_ds(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_ds); } -static bool trans_UCVTF_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_sd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_sd); } -static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_dd); } @@ -4538,7 +4519,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) tcg_temp_free_i64(t0); } -static bool trans_LDR_zri(DisasContext *s, arg_rri *a, uint32_t insn) +static bool trans_LDR_zri(DisasContext *s, arg_rri *a) { if (sve_access_check(s)) { int size = vec_full_reg_size(s); @@ -4548,7 +4529,7 @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a, uint32_t insn) return true; } -static bool trans_LDR_pri(DisasContext *s, arg_rri *a, uint32_t insn) +static bool trans_LDR_pri(DisasContext *s, arg_rri *a) { if (sve_access_check(s)) { int size = pred_full_reg_size(s); @@ -4558,7 +4539,7 @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a, uint32_t insn) return true; } -static bool trans_STR_zri(DisasContext *s, arg_rri *a, uint32_t insn) +static bool trans_STR_zri(DisasContext *s, arg_rri *a) { if (sve_access_check(s)) { int size = vec_full_reg_size(s); @@ -4568,7 +4549,7 @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a, uint32_t insn) return true; } -static bool trans_STR_pri(DisasContext *s, arg_rri *a, uint32_t insn) +static bool trans_STR_pri(DisasContext *s, arg_rri *a) { if (sve_access_check(s)) { int size = pred_full_reg_size(s); @@ -4693,7 +4674,7 @@ static void do_ld_zpa(DisasContext *s, int zt, int pg, do_mem_zpa(s, zt, pg, addr, dtype, fn); } -static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) +static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a) { if (a->rm == 31) { return false; @@ -4707,7 +4688,7 @@ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) return true; } -static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) +static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a) { if (sve_access_check(s)) { int vsz = vec_full_reg_size(s); @@ -4722,7 +4703,7 @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) return true; } -static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) +static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a) { static gen_helper_gvec_mem * const fns[2][16] = { /* Little-endian */ @@ -4778,7 +4759,7 @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) return true; } -static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) +static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a) { static gen_helper_gvec_mem * const fns[2][16] = { /* Little-endian */ @@ -4890,7 +4871,7 @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz) } } -static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) +static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a) { if (a->rm == 31) { return false; @@ -4905,7 +4886,7 @@ static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) return true; } -static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) +static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a) { if (sve_access_check(s)) { TCGv_i64 addr = new_tmp_a64(s); @@ -4916,7 +4897,7 @@ static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) } /* Load and broadcast element. */ -static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) +static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a) { if (!sve_access_check(s)) { return true; @@ -5036,7 +5017,7 @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr, do_mem_zpa(s, zt, pg, addr, msz_dtype(msz), fn); } -static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn) +static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a) { if (a->rm == 31 || a->msz > a->esz) { return false; @@ -5050,7 +5031,7 @@ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn) return true; } -static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn) +static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a) { if (a->msz > a->esz) { return false; @@ -5264,7 +5245,7 @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = { gen_helper_sve_ldffdd_be_zd, } } } }, }; -static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn) +static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a) { gen_helper_gvec_mem_scatter *fn = NULL; int be = s->be_data == MO_BE; @@ -5288,7 +5269,7 @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn) return true; } -static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn) +static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a) { gen_helper_gvec_mem_scatter *fn = NULL; int be = s->be_data == MO_BE; @@ -5368,7 +5349,7 @@ static gen_helper_gvec_mem_scatter * const scatter_store_fn64[2][3][4] = { gen_helper_sve_stdd_be_zd, } }, }; -static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn) +static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a) { gen_helper_gvec_mem_scatter *fn; int be = s->be_data == MO_BE; @@ -5394,7 +5375,7 @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn) return true; } -static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn) +static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a) { gen_helper_gvec_mem_scatter *fn = NULL; int be = s->be_data == MO_BE; @@ -5430,14 +5411,14 @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn) * Prefetches */ -static bool trans_PRF(DisasContext *s, arg_PRF *a, uint32_t insn) +static bool trans_PRF(DisasContext *s, arg_PRF *a) { /* Prefetch is a nop within QEMU. */ (void)sve_access_check(s); return true; } -static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a, uint32_t insn) +static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a) { if (a->rm == 31) { return false; @@ -5461,12 +5442,12 @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a, uint32_t insn) * In the meantime, just emit the moves. */ -static bool trans_MOVPRFX(DisasContext *s, arg_MOVPRFX *a, uint32_t insn) +static bool trans_MOVPRFX(DisasContext *s, arg_MOVPRFX *a) { return do_mov_z(s, a->rd, a->rn); } -static bool trans_MOVPRFX_m(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_MOVPRFX_m(DisasContext *s, arg_rpr_esz *a) { if (sve_access_check(s)) { do_sel_z(s, a->rd, a->rn, a->rd, a->pg, a->esz); @@ -5474,7 +5455,7 @@ static bool trans_MOVPRFX_m(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return true; } -static bool trans_MOVPRFX_z(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +static bool trans_MOVPRFX_z(DisasContext *s, arg_rpr_esz *a) { if (sve_access_check(s)) { do_movz_zpz(s, a->rd, a->rn, a->pg, a->esz); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1469a1be01..af7e9f09cc 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -770,17 +770,36 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, /* missing: CPUID_XSAVE_XSAVEC, CPUID_XSAVE_XSAVES */ +typedef enum FeatureWordType { + CPUID_FEATURE_WORD, + MSR_FEATURE_WORD, +} FeatureWordType; + typedef struct FeatureWordInfo { + FeatureWordType type; /* feature flags names are taken from "Intel Processor Identification and * the CPUID Instruction" and AMD's "CPUID Specification". * In cases of disagreement between feature naming conventions, * aliases may be added. */ const char *feat_names[32]; - uint32_t cpuid_eax; /* Input EAX for CPUID */ - bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */ - uint32_t cpuid_ecx; /* Input ECX value for CPUID */ - int cpuid_reg; /* output register (R_* constant) */ + union { + /* If type==CPUID_FEATURE_WORD */ + struct { + uint32_t eax; /* Input EAX for CPUID */ + bool needs_ecx; /* CPUID instruction uses ECX as input */ + uint32_t ecx; /* Input ECX value for CPUID */ + int reg; /* output register (R_* constant) */ + } cpuid; + /* If type==MSR_FEATURE_WORD */ + struct { + uint32_t index; + struct { /*CPUID that enumerate this MSR*/ + FeatureWord cpuid_class; + uint32_t cpuid_flag; + } cpuid_dep; + } msr; + }; uint32_t tcg_features; /* Feature flags supported by TCG */ uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ uint32_t migratable_flags; /* Feature flags known to be migratable */ @@ -790,6 +809,7 @@ typedef struct FeatureWordInfo { static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { [FEAT_1_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", @@ -800,10 +820,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe", }, - .cpuid_eax = 1, .cpuid_reg = R_EDX, + .cpuid = {.eax = 1, .reg = R_EDX, }, .tcg_features = TCG_FEATURES, }, [FEAT_1_ECX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "pni" /* Intel,AMD sse3 */, "pclmulqdq", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est", @@ -814,7 +835,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "tsc-deadline", "aes", "xsave", NULL /* osxsave */, "avx", "f16c", "rdrand", "hypervisor", }, - .cpuid_eax = 1, .cpuid_reg = R_ECX, + .cpuid = { .eax = 1, .reg = R_ECX, }, .tcg_features = TCG_EXT_FEATURES, }, /* Feature names that are already defined on feature_name[] but @@ -823,6 +844,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { * to features[FEAT_8000_0001_EDX] if and only if CPU vendor is AMD. */ [FEAT_8000_0001_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */, NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */, @@ -833,10 +855,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL /* fxsr */, "fxsr-opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", }, - .cpuid_eax = 0x80000001, .cpuid_reg = R_EDX, + .cpuid = { .eax = 0x80000001, .reg = R_EDX, }, .tcg_features = TCG_EXT2_FEATURES, }, [FEAT_8000_0001_ECX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "lahf-lm", "cmp-legacy", "svm", "extapic", "cr8legacy", "abm", "sse4a", "misalignsse", @@ -847,7 +870,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "perfctr-nb", NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x80000001, .cpuid_reg = R_ECX, + .cpuid = { .eax = 0x80000001, .reg = R_ECX, }, .tcg_features = TCG_EXT3_FEATURES, /* * TOPOEXT is always allowed but can't be enabled blindly by @@ -857,6 +880,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .no_autoenable_flags = CPUID_EXT3_TOPOEXT, }, [FEAT_C000_0001_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, "xstore", "xstore-en", NULL, NULL, "xcrypt", "xcrypt-en", @@ -867,10 +891,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX, + .cpuid = { .eax = 0xC0000001, .reg = R_EDX, }, .tcg_features = TCG_EXT4_FEATURES, }, [FEAT_KVM] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", @@ -881,10 +906,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "kvmclock-stable-bit", NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX, + .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EAX, }, .tcg_features = TCG_KVM_FEATURES, }, [FEAT_KVM_HINTS] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "kvm-hint-dedicated", NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -895,7 +921,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EDX, + .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EDX, }, .tcg_features = TCG_KVM_FEATURES, /* * KVM hints aren't auto-enabled by -cpu host, they need to be @@ -904,6 +930,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .no_autoenable_flags = ~0U, }, [FEAT_HYPERV_EAX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL /* hv_msr_vp_runtime_access */, NULL /* hv_msr_time_refcount_access */, NULL /* hv_msr_synic_access */, NULL /* hv_msr_stimer_access */, @@ -918,9 +945,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x40000003, .cpuid_reg = R_EAX, + .cpuid = { .eax = 0x40000003, .reg = R_EAX, }, }, [FEAT_HYPERV_EBX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL /* hv_create_partitions */, NULL /* hv_access_partition_id */, NULL /* hv_access_memory_pool */, NULL /* hv_adjust_message_buffers */, @@ -934,9 +962,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x40000003, .cpuid_reg = R_EBX, + .cpuid = { .eax = 0x40000003, .reg = R_EBX, }, }, [FEAT_HYPERV_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL /* hv_mwait */, NULL /* hv_guest_debugging */, NULL /* hv_perf_monitor */, NULL /* hv_cpu_dynamic_part */, @@ -949,9 +978,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x40000003, .cpuid_reg = R_EDX, + .cpuid = { .eax = 0x40000003, .reg = R_EDX, }, }, [FEAT_SVM] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "npt", "lbrv", "svm-lock", "nrip-save", "tsc-scale", "vmcb-clean", "flushbyasid", "decodeassists", @@ -962,10 +992,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX, + .cpuid = { .eax = 0x8000000A, .reg = R_EDX, }, .tcg_features = TCG_SVM_FEATURES, }, [FEAT_7_0_EBX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "fsgsbase", "tsc-adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep", @@ -976,12 +1007,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "clwb", "intel-pt", "avx512pf", "avx512er", "avx512cd", "sha-ni", "avx512bw", "avx512vl", }, - .cpuid_eax = 7, - .cpuid_needs_ecx = true, .cpuid_ecx = 0, - .cpuid_reg = R_EBX, + .cpuid = { + .eax = 7, + .needs_ecx = true, .ecx = 0, + .reg = R_EBX, + }, .tcg_features = TCG_7_0_EBX_FEATURES, }, [FEAT_7_0_ECX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, "avx512vbmi", "umip", "pku", NULL /* ospke */, NULL, "avx512vbmi2", NULL, @@ -992,12 +1026,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, "cldemote", NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 7, - .cpuid_needs_ecx = true, .cpuid_ecx = 0, - .cpuid_reg = R_ECX, + .cpuid = { + .eax = 7, + .needs_ecx = true, .ecx = 0, + .reg = R_ECX, + }, .tcg_features = TCG_7_0_ECX_FEATURES, }, [FEAT_7_0_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", NULL, NULL, NULL, NULL, @@ -1008,13 +1045,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, "spec-ctrl", NULL, NULL, "arch-capabilities", NULL, "ssbd", }, - .cpuid_eax = 7, - .cpuid_needs_ecx = true, .cpuid_ecx = 0, - .cpuid_reg = R_EDX, + .cpuid = { + .eax = 7, + .needs_ecx = true, .ecx = 0, + .reg = R_EDX, + }, .tcg_features = TCG_7_0_EDX_FEATURES, .unmigratable_flags = CPUID_7_0_EDX_ARCH_CAPABILITIES, }, [FEAT_8000_0007_EDX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1025,12 +1065,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x80000007, - .cpuid_reg = R_EDX, + .cpuid = { .eax = 0x80000007, .reg = R_EDX, }, .tcg_features = TCG_APM_FEATURES, .unmigratable_flags = CPUID_APM_INVTSC, }, [FEAT_8000_0008_EBX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1041,12 +1081,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0x80000008, - .cpuid_reg = R_EBX, + .cpuid = { .eax = 0x80000008, .reg = R_EBX, }, .tcg_features = 0, .unmigratable_flags = 0, }, [FEAT_XSAVE] = { + .type = CPUID_FEATURE_WORD, .feat_names = { "xsaveopt", "xsavec", "xgetbv1", "xsaves", NULL, NULL, NULL, NULL, @@ -1057,12 +1097,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 0xd, - .cpuid_needs_ecx = true, .cpuid_ecx = 1, - .cpuid_reg = R_EAX, + .cpuid = { + .eax = 0xd, + .needs_ecx = true, .ecx = 1, + .reg = R_EAX, + }, .tcg_features = TCG_XSAVE_FEATURES, }, [FEAT_6_EAX] = { + .type = CPUID_FEATURE_WORD, .feat_names = { NULL, NULL, "arat", NULL, NULL, NULL, NULL, NULL, @@ -1073,13 +1116,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, - .cpuid_eax = 6, .cpuid_reg = R_EAX, + .cpuid = { .eax = 6, .reg = R_EAX, }, .tcg_features = TCG_6_EAX_FEATURES, }, [FEAT_XSAVE_COMP_LO] = { - .cpuid_eax = 0xD, - .cpuid_needs_ecx = true, .cpuid_ecx = 0, - .cpuid_reg = R_EAX, + .type = CPUID_FEATURE_WORD, + .cpuid = { + .eax = 0xD, + .needs_ecx = true, .ecx = 0, + .reg = R_EAX, + }, .tcg_features = ~0U, .migratable_flags = XSTATE_FP_MASK | XSTATE_SSE_MASK | XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK | @@ -1087,11 +1133,35 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { XSTATE_PKRU_MASK, }, [FEAT_XSAVE_COMP_HI] = { - .cpuid_eax = 0xD, - .cpuid_needs_ecx = true, .cpuid_ecx = 0, - .cpuid_reg = R_EDX, + .type = CPUID_FEATURE_WORD, + .cpuid = { + .eax = 0xD, + .needs_ecx = true, .ecx = 0, + .reg = R_EDX, + }, .tcg_features = ~0U, }, + /*Below are MSR exposed features*/ + [FEAT_ARCH_CAPABILITIES] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", + "ssb-no", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr = { + .index = MSR_IA32_ARCH_CAPABILITIES, + .cpuid_dep = { + FEAT_7_0_EDX, + CPUID_7_0_EDX_ARCH_CAPABILITIES + } + }, + }, }; typedef struct X86RegisterInfo32 { @@ -2322,6 +2392,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU, /* Missing: XSAVES (not supported by some Linux versions, * including v4.1 to v4.12). * KVM doesn't yet expose any XSAVES state save component, @@ -2372,6 +2444,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | CPUID_7_0_EBX_AVX512VL, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU, /* Missing: XSAVES (not supported by some Linux versions, * including v4.1 to v4.12). * KVM doesn't yet expose any XSAVES state save component, @@ -2387,6 +2461,60 @@ static X86CPUDefinition builtin_x86_defs[] = { .model_id = "Intel Xeon Processor (Skylake, IBRS)", }, { + .name = "Cascadelake-Server", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 85, + .stepping = 5, + .features[FEAT_1_EDX] = + CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .features[FEAT_1_ECX] = + CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | + CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | + CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | + CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, + .features[FEAT_7_0_EBX] = + CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | + CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | + CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | + CPUID_7_0_EBX_INTEL_PT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | + CPUID_7_0_ECX_AVX512VNNI, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, + /* Missing: XSAVES (not supported by some Linux versions, + * including v4.1 to v4.12). + * KVM doesn't yet expose any XSAVES state save component, + * and the only one defined in Skylake (processor tracing) + * probably will block migration anyway. + */ + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Cascadelake)", + }, + { .name = "Icelake-Client", .level = 0xd, .vendor = CPUID_VENDOR_INTEL, @@ -2975,21 +3103,41 @@ static const TypeInfo host_x86_cpu_type_info = { #endif +static char *feature_word_description(FeatureWordInfo *f, uint32_t bit) +{ + assert(f->type == CPUID_FEATURE_WORD || f->type == MSR_FEATURE_WORD); + + switch (f->type) { + case CPUID_FEATURE_WORD: + { + const char *reg = get_register_name_32(f->cpuid.reg); + assert(reg); + return g_strdup_printf("CPUID.%02XH:%s", + f->cpuid.eax, reg); + } + case MSR_FEATURE_WORD: + return g_strdup_printf("MSR(%02XH)", + f->msr.index); + } + + return NULL; +} + static void report_unavailable_features(FeatureWord w, uint32_t mask) { FeatureWordInfo *f = &feature_word_info[w]; int i; + char *feat_word_str; for (i = 0; i < 32; ++i) { if ((1UL << i) & mask) { - const char *reg = get_register_name_32(f->cpuid_reg); - assert(reg); - warn_report("%s doesn't support requested feature: " - "CPUID.%02XH:%s%s%s [bit %d]", + feat_word_str = feature_word_description(f, i); + warn_report("%s doesn't support requested feature: %s%s%s [bit %d]", accel_uses_host_cpuid() ? "host" : "TCG", - f->cpuid_eax, reg, + feat_word_str, f->feat_names[i] ? "." : "", f->feat_names[i] ? f->feat_names[i] : "", i); + g_free(feat_word_str); } } } @@ -3233,11 +3381,18 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, for (w = 0; w < FEATURE_WORDS; w++) { FeatureWordInfo *wi = &feature_word_info[w]; + /* + * We didn't have MSR features when "feature-words" was + * introduced. Therefore skipped other type entries. + */ + if (wi->type != CPUID_FEATURE_WORD) { + continue; + } X86CPUFeatureWordInfo *qwi = &word_infos[w]; - qwi->cpuid_input_eax = wi->cpuid_eax; - qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx; - qwi->cpuid_input_ecx = wi->cpuid_ecx; - qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum; + qwi->cpuid_input_eax = wi->cpuid.eax; + qwi->has_cpuid_input_ecx = wi->cpuid.needs_ecx; + qwi->cpuid_input_ecx = wi->cpuid.ecx; + qwi->cpuid_register = x86_reg_info_32[wi->cpuid.reg].qapi_enum; qwi->features = array[w]; /* List will be in reverse order, but order shouldn't matter */ @@ -3610,16 +3765,27 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, bool migratable_only) { FeatureWordInfo *wi = &feature_word_info[w]; - uint32_t r; + uint32_t r = 0; if (kvm_enabled()) { - r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax, - wi->cpuid_ecx, - wi->cpuid_reg); + switch (wi->type) { + case CPUID_FEATURE_WORD: + r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid.eax, + wi->cpuid.ecx, + wi->cpuid.reg); + break; + case MSR_FEATURE_WORD: + r = kvm_arch_get_supported_msr_feature(kvm_state, + wi->msr.index); + break; + } } else if (hvf_enabled()) { - r = hvf_get_supported_cpuid(wi->cpuid_eax, - wi->cpuid_ecx, - wi->cpuid_reg); + if (wi->type != CPUID_FEATURE_WORD) { + return 0; + } + r = hvf_get_supported_cpuid(wi->cpuid.eax, + wi->cpuid.ecx, + wi->cpuid.reg); } else if (tcg_enabled()) { r = wi->tcg_features; } else { @@ -4178,7 +4344,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = xsave_area_size(x86_cpu_xsave_components(cpu)); *eax = env->features[FEAT_XSAVE_COMP_LO]; *edx = env->features[FEAT_XSAVE_COMP_HI]; - *ebx = *ecx; + *ebx = xsave_area_size(env->xcr0); } else if (count == 1) { *eax = env->features[FEAT_XSAVE]; } else if (count < ARRAY_SIZE(x86_ext_save_areas)) { @@ -4680,9 +4846,10 @@ static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w) { CPUX86State *env = &cpu->env; FeatureWordInfo *fi = &feature_word_info[w]; - uint32_t eax = fi->cpuid_eax; + uint32_t eax = fi->cpuid.eax; uint32_t region = eax & 0xF0000000; + assert(feature_word_info[w].type == CPUID_FEATURE_WORD); if (!env->features[w]) { return; } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 663f3a5e67..ad0e0b4534 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -502,6 +502,7 @@ typedef enum FeatureWord { FEAT_6_EAX, /* CPUID[6].EAX */ FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, FEATURE_WORDS, } FeatureWord; @@ -730,6 +731,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8) #define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8) +/* MSR Feature Bits */ +#define MSR_ARCH_CAP_RDCL_NO (1U << 0) +#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) +#define MSR_ARCH_CAP_RSBA (1U << 2) +#define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) +#define MSR_ARCH_CAP_SSB_NO (1U << 4) + #ifndef HYPERV_SPINLOCK_NEVER_RETRY #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF #endif diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 115d8b4c14..796a049a0d 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -107,6 +107,7 @@ static int has_pit_state2; static bool has_msr_mcg_ext_ctl; static struct kvm_cpuid2 *cpuid_cache; +static struct kvm_msr_list *kvm_feature_msrs; int kvm_has_pit_state2(void) { @@ -420,6 +421,42 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, return ret; } +uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) +{ + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data; + uint32_t ret; + + if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */ + return 0; + } + + /* Check if requested MSR is supported feature MSR */ + int i; + for (i = 0; i < kvm_feature_msrs->nmsrs; i++) + if (kvm_feature_msrs->indices[i] == index) { + break; + } + if (i == kvm_feature_msrs->nmsrs) { + return 0; /* if the feature MSR is not supported, simply return 0 */ + } + + msr_data.info.nmsrs = 1; + msr_data.entries[0].index = index; + + ret = kvm_ioctl(s, KVM_GET_MSRS, &msr_data); + if (ret != 1) { + error_report("KVM get MSR (index=0x%x) feature failed, %s", + index, strerror(-ret)); + exit(1); + } + + return msr_data.entries[0].data; +} + + typedef struct HWPoisonPage { ram_addr_t ram_addr; QLIST_ENTRY(HWPoisonPage) list; @@ -1286,6 +1323,47 @@ void kvm_arch_do_init_vcpu(X86CPU *cpu) } } +static int kvm_get_supported_feature_msrs(KVMState *s) +{ + int ret = 0; + + if (kvm_feature_msrs != NULL) { + return 0; + } + + if (!kvm_check_extension(s, KVM_CAP_GET_MSR_FEATURES)) { + return 0; + } + + struct kvm_msr_list msr_list; + + msr_list.nmsrs = 0; + ret = kvm_ioctl(s, KVM_GET_MSR_FEATURE_INDEX_LIST, &msr_list); + if (ret < 0 && ret != -E2BIG) { + error_report("Fetch KVM feature MSR list failed: %s", + strerror(-ret)); + return ret; + } + + assert(msr_list.nmsrs > 0); + kvm_feature_msrs = (struct kvm_msr_list *) \ + g_malloc0(sizeof(msr_list) + + msr_list.nmsrs * sizeof(msr_list.indices[0])); + + kvm_feature_msrs->nmsrs = msr_list.nmsrs; + ret = kvm_ioctl(s, KVM_GET_MSR_FEATURE_INDEX_LIST, kvm_feature_msrs); + + if (ret < 0) { + error_report("Fetch KVM feature MSR list failed: %s", + strerror(-ret)); + g_free(kvm_feature_msrs); + kvm_feature_msrs = NULL; + return ret; + } + + return 0; +} + static int kvm_get_supported_msrs(KVMState *s) { static int kvm_supported_msrs; @@ -1439,6 +1517,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s) return ret; } + kvm_get_supported_feature_msrs(s); + uname(&utsname); lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0; @@ -1895,6 +1975,17 @@ static int kvm_put_msrs(X86CPU *cpu, int level) } #endif + /* If host supports feature MSR, write down. */ + if (kvm_feature_msrs) { + int i; + for (i = 0; i < kvm_feature_msrs->nmsrs; i++) + if (kvm_feature_msrs->indices[i] == MSR_IA32_ARCH_CAPABILITIES) { + kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, + env->features[FEAT_ARCH_CAPABILITIES]); + break; + } + } + /* * The following MSRs have side effects on the guest or are too heavy * for normal writeback. Limit them to reset or full state updates. diff --git a/target/i386/translate.c b/target/i386/translate.c index 83c1ebe491..f8bc7680af 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -7028,13 +7028,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #ifdef WANT_ICEBP case 0xf1: /* icebp (undocumented, exits to external debugger) */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); -#if 1 gen_debug(s, pc_start - s->cs_base); -#else - /* start debug */ - tb_flush(CPU(x86_env_get_cpu(env))); - qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); -#endif break; #endif case 0xfa: /* cli */ diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index c63adf772f..b288a3864e 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -70,7 +70,6 @@ #define EXCP_MMU_CONF 56 /* MMU Configuration Error */ #define EXCP_MMU_ILLEGAL 57 /* MMU Illegal Operation Error */ #define EXCP_MMU_ACCESS 58 /* MMU Access Level Violation Error */ -#define EXCP_UNSUPPORTED 61 #define EXCP_RTE 0x100 #define EXCP_HALT_INSN 0x101 diff --git a/target/m68k/translate.c b/target/m68k/translate.c index ae3651b867..752e46ef63 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -1553,7 +1553,7 @@ DISAS_INSN(undef) but actually illegal for CPU32 or pre-68020. */ qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n", insn, s->base.pc_next); - gen_exception(s, s->base.pc_next, EXCP_UNSUPPORTED); + gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); } DISAS_INSN(mulw) @@ -2800,7 +2800,7 @@ DISAS_INSN(mull) if (ext & 0x400) { if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { - gen_exception(s, s->base.pc_next, EXCP_UNSUPPORTED); + gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); return; } @@ -4510,7 +4510,7 @@ DISAS_INSN(strldsr) addr = s->pc - 2; ext = read_im16(env, s); if (ext != 0x46FC) { - gen_exception(s, addr, EXCP_UNSUPPORTED); + gen_exception(s, addr, EXCP_ILLEGAL); return; } ext = read_im16(env, s); diff --git a/target/openrisc/disas.c b/target/openrisc/disas.c index 4bfd2dd8a6..bc63093ee9 100644 --- a/target/openrisc/disas.c +++ b/target/openrisc/disas.c @@ -51,12 +51,11 @@ int print_insn_or1k(bfd_vma addr, disassemble_info *info) return 4; } -#define INSN(opcode, format, ...) \ -static bool trans_l_##opcode(disassemble_info *info, \ - arg_l_##opcode *a, uint32_t insn) \ -{ \ - output("l." #opcode, format, ##__VA_ARGS__); \ - return true; \ +#define INSN(opcode, format, ...) \ +static bool trans_l_##opcode(disassemble_info *info, arg_l_##opcode *a) \ +{ \ + output("l." #opcode, format, ##__VA_ARGS__); \ + return true; \ } INSN(add, "r%d, r%d, r%d", a->d, a->a, a->b) @@ -146,12 +145,12 @@ INSN(psync, "") INSN(csync, "") INSN(rfe, "") -#define FP_INSN(opcode, suffix, format, ...) \ -static bool trans_lf_##opcode##_##suffix(disassemble_info *info, \ - arg_lf_##opcode##_##suffix *a, uint32_t insn) \ -{ \ - output("lf." #opcode "." #suffix, format, ##__VA_ARGS__); \ - return true; \ +#define FP_INSN(opcode, suffix, format, ...) \ +static bool trans_lf_##opcode##_##suffix(disassemble_info *info, \ + arg_lf_##opcode##_##suffix *a) \ +{ \ + output("lf." #opcode "." #suffix, format, ##__VA_ARGS__); \ + return true; \ } FP_INSN(add, s, "r%d, r%d, r%d", a->d, a->a, a->b) diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index a271cd3903..c089914d6a 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -434,105 +434,105 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) gen_ove_cy(dc); } -static bool trans_l_add(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_add(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_addc(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_addc(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sub(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_sub(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_and(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_and(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_or(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_or(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_xor(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_xor(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sll(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_sll(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_srl(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_srl(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sra(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_sra(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_ror(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_ror(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_exths(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_exths(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]); return true; } -static bool trans_l_extbs(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_extbs(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]); return true; } -static bool trans_l_exthz(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_exthz(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]); return true; } -static bool trans_l_extbz(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_extbz(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]); return true; } -static bool trans_l_cmov(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_cmov(DisasContext *dc, arg_dab *a) { TCGv zero; @@ -544,7 +544,7 @@ static bool trans_l_cmov(DisasContext *dc, arg_dab *a, uint32_t insn) return true; } -static bool trans_l_ff1(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_ff1(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1); @@ -552,7 +552,7 @@ static bool trans_l_ff1(DisasContext *dc, arg_da *a, uint32_t insn) return true; } -static bool trans_l_fl1(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_l_fl1(DisasContext *dc, arg_da *a) { check_r0_write(a->d); tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS); @@ -560,47 +560,47 @@ static bool trans_l_fl1(DisasContext *dc, arg_da *a, uint32_t insn) return true; } -static bool trans_l_mul(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_mul(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_mulu(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_mulu(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_div(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_div(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_divu(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_l_divu(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_muld(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_muld(DisasContext *dc, arg_ab *a) { gen_muld(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_muldu(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_muldu(DisasContext *dc, arg_ab *a) { gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) +static bool trans_l_j(DisasContext *dc, arg_l_j *a) { target_ulong tmp_pc = dc->base.pc_next + a->n * 4; @@ -610,7 +610,7 @@ static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) return true; } -static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn) +static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) { target_ulong tmp_pc = dc->base.pc_next + a->n * 4; target_ulong ret_pc = dc->base.pc_next + 8; @@ -640,26 +640,26 @@ static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) dc->delayed_branch = 2; } -static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn) +static bool trans_l_bf(DisasContext *dc, arg_l_bf *a) { do_bf(dc, a, TCG_COND_NE); return true; } -static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn) +static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a) { do_bf(dc, a, TCG_COND_EQ); return true; } -static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn) +static bool trans_l_jr(DisasContext *dc, arg_l_jr *a) { tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); dc->delayed_branch = 2; return true; } -static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) +static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a) { tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); @@ -667,7 +667,7 @@ static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) return true; } -static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lwa(DisasContext *dc, arg_load *a) { TCGv ea; @@ -692,43 +692,43 @@ static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop) tcg_temp_free(ea); } -static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lwz(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_TEUL); return true; } -static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lws(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_TESL); return true; } -static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lbz(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_UB); return true; } -static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lbs(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_SB); return true; } -static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lhz(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_TEUW); return true; } -static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn) +static bool trans_l_lhs(DisasContext *dc, arg_load *a) { do_load(dc, a, MO_TESW); return true; } -static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn) +static bool trans_l_swa(DisasContext *dc, arg_store *a) { TCGv ea, val; TCGLabel *lab_fail, *lab_done; @@ -771,30 +771,30 @@ static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop) tcg_temp_free(t0); } -static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn) +static bool trans_l_sw(DisasContext *dc, arg_store *a) { do_store(dc, a, MO_TEUL); return true; } -static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn) +static bool trans_l_sb(DisasContext *dc, arg_store *a) { do_store(dc, a, MO_UB); return true; } -static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn) +static bool trans_l_sh(DisasContext *dc, arg_store *a) { do_store(dc, a, MO_TEUW); return true; } -static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn) +static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) { return true; } -static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) +static bool trans_l_addi(DisasContext *dc, arg_rri *a) { TCGv t0; @@ -805,7 +805,7 @@ static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) return true; } -static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) +static bool trans_l_addic(DisasContext *dc, arg_rri *a) { TCGv t0; @@ -816,7 +816,7 @@ static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) return true; } -static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) +static bool trans_l_muli(DisasContext *dc, arg_rri *a) { TCGv t0; @@ -827,7 +827,7 @@ static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) return true; } -static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) +static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) { TCGv t0; @@ -837,28 +837,28 @@ static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) return true; } -static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn) +static bool trans_l_andi(DisasContext *dc, arg_rrk *a) { check_r0_write(a->d); tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k); return true; } -static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn) +static bool trans_l_ori(DisasContext *dc, arg_rrk *a) { check_r0_write(a->d); tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k); return true; } -static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn) +static bool trans_l_xori(DisasContext *dc, arg_rri *a) { check_r0_write(a->d); tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i); return true; } -static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) +static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a) { check_r0_write(a->d); @@ -873,7 +873,7 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) return true; } -static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) +static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a) { if (is_user(dc)) { gen_illegal_exception(dc); @@ -901,66 +901,66 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) return true; } -static bool trans_l_mac(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_mac(DisasContext *dc, arg_ab *a) { gen_mac(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_msb(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_msb(DisasContext *dc, arg_ab *a) { gen_msb(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_macu(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_macu(DisasContext *dc, arg_ab *a) { gen_macu(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_msbu(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_l_msbu(DisasContext *dc, arg_ab *a) { gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_slli(DisasContext *dc, arg_dal *a, uint32_t insn) +static bool trans_l_slli(DisasContext *dc, arg_dal *a) { check_r0_write(a->d); tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); return true; } -static bool trans_l_srli(DisasContext *dc, arg_dal *a, uint32_t insn) +static bool trans_l_srli(DisasContext *dc, arg_dal *a) { check_r0_write(a->d); tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); return true; } -static bool trans_l_srai(DisasContext *dc, arg_dal *a, uint32_t insn) +static bool trans_l_srai(DisasContext *dc, arg_dal *a) { check_r0_write(a->d); tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); return true; } -static bool trans_l_rori(DisasContext *dc, arg_dal *a, uint32_t insn) +static bool trans_l_rori(DisasContext *dc, arg_dal *a) { check_r0_write(a->d); tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); return true; } -static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a, uint32_t insn) +static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a) { check_r0_write(a->d); tcg_gen_movi_tl(cpu_R[a->d], a->k << 16); return true; } -static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a, uint32_t insn) +static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a) { check_r0_write(a->d); tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac); @@ -968,127 +968,127 @@ static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a, uint32_t insn) return true; } -static bool trans_l_sfeq(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfeq(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfne(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfne(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfltu(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfltu(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfleu(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfleu(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfgts(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfgts(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfges(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfges(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sflts(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sflts(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfles(DisasContext *dc, arg_ab *a, TCGCond cond) +static bool trans_l_sfles(DisasContext *dc, arg_ab *a) { tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); return true; } -static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfnei(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfnei(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfltui(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfltui(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfleui(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfleui(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sflesi(DisasContext *dc, arg_ai *a, TCGCond cond) +static bool trans_l_sflesi(DisasContext *dc, arg_ai *a) { tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i); return true; } -static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) +static bool trans_l_sys(DisasContext *dc, arg_l_sys *a) { tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); gen_exception(dc, EXCP_SYSCALL); @@ -1096,7 +1096,7 @@ static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) return true; } -static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) +static bool trans_l_trap(DisasContext *dc, arg_l_trap *a) { tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); gen_exception(dc, EXCP_TRAP); @@ -1104,23 +1104,23 @@ static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) return true; } -static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) +static bool trans_l_msync(DisasContext *dc, arg_l_msync *a) { tcg_gen_mb(TCG_MO_ALL); return true; } -static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) +static bool trans_l_psync(DisasContext *dc, arg_l_psync *a) { return true; } -static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) +static bool trans_l_csync(DisasContext *dc, arg_l_csync *a) { return true; } -static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn) +static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a) { if (is_user(dc)) { gen_illegal_exception(dc); @@ -1162,49 +1162,49 @@ static void do_fpcmp(DisasContext *dc, arg_ab *a, gen_helper_update_fpcsr(cpu_env); } -static bool trans_lf_add_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_add_s(DisasContext *dc, arg_dab *a) { do_fp3(dc, a, gen_helper_float_add_s); return true; } -static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a) { do_fp3(dc, a, gen_helper_float_sub_s); return true; } -static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a) { do_fp3(dc, a, gen_helper_float_mul_s); return true; } -static bool trans_lf_div_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_div_s(DisasContext *dc, arg_dab *a) { do_fp3(dc, a, gen_helper_float_div_s); return true; } -static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a) { do_fp3(dc, a, gen_helper_float_rem_s); return true; } -static bool trans_lf_itof_s(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_lf_itof_s(DisasContext *dc, arg_da *a) { do_fp2(dc, a, gen_helper_itofs); return true; } -static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a, uint32_t insn) +static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a) { do_fp2(dc, a, gen_helper_ftois); return true; } -static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a, uint32_t insn) +static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a) { check_r0_write(a->d); gen_helper_float_madd_s(cpu_R[a->d], cpu_env, cpu_R[a->d], @@ -1213,37 +1213,37 @@ static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a, uint32_t insn) return true; } -static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); return true; } -static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); return true; } -static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); return true; } -static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_le_s, false, true); return true; } -static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); return true; } -static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a, uint32_t insn) +static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) { do_fpcmp(dc, a, gen_helper_float_le_s, false, false); return true; diff --git a/tests/Makefile.include b/tests/Makefile.include index f77a495109..d2e577eabb 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -11,7 +11,9 @@ check-help: @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" @echo " $(MAKE) check-block Run block tests" @echo " $(MAKE) check-tcg Run TCG tests" + @echo " $(MAKE) check-acceptance Run all acceptance (functional) tests" @echo " $(MAKE) check-report.html Generates an HTML test report" + @echo " $(MAKE) check-venv Creates a Python venv for tests" @echo " $(MAKE) check-clean Clean the tests" @echo @echo "Please note that HTML reports do not regenerate if the unit tests" @@ -899,6 +901,46 @@ check-decodetree: ./check.sh "$(PYTHON)" "$(SRC_PATH)/scripts/decodetree.py", \ TEST, decodetree.py) +# Python venv for running tests + +.PHONY: check-venv check-acceptance + +TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv +TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt +TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results +# Controls the output generated by Avocado when running tests. +# Any number of command separated loggers are accepted. For more +# information please refer to "avocado --help". +AVOCADO_SHOW=none + +$(shell $(PYTHON) -c 'import sys; assert sys.version_info >= (3,0)' >/dev/null 2>&1) +ifeq ($(.SHELLSTATUS),0) +$(TESTS_VENV_DIR): $(TESTS_VENV_REQ) + $(call quiet-command, \ + $(PYTHON) -m venv --system-site-packages $@, \ + VENV, $@) + $(call quiet-command, \ + $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ + PIP, $(TESTS_VENV_REQ)) + $(call quiet-command, touch $@) +else +$(TESTS_VENV_DIR): + $(error "venv directory for tests requires Python 3") +endif + +$(TESTS_RESULTS_DIR): + $(call quiet-command, mkdir -p $@, \ + MKDIR, $@) + +check-venv: $(TESTS_VENV_DIR) + +check-acceptance: check-venv $(TESTS_RESULTS_DIR) + $(call quiet-command, \ + $(TESTS_VENV_DIR)/bin/python -m avocado \ + --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ + --failfast=on $(SRC_PATH)/tests/acceptance, \ + "AVOCADO", "tests/acceptance") + # Consolidated targets .PHONY: check-qapi-schema check-qtest check-unit check check-clean @@ -912,6 +954,7 @@ check-clean: rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y) rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y)) rm -f tests/test-qapi-gen-timestamp + rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR) clean: check-clean diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 1dbc2ddc49..276e06b5ba 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -521,7 +521,7 @@ new_state = "2" state = "2" event = "%s" new_state = "1" -''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event)) +''' % (event, errno, self.STREAM_BUFFER_SIZE // 512, event, event)) file.close() class TestEIO(TestErrors): diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 1cb1ceeb33..b81133a474 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -195,7 +195,7 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top=mid_img, - base=backing_img, speed=(self.image_len / 4)) + base=backing_img, speed=(self.image_len // 4)) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('device_del', id='scsi0') self.assert_qmp(result, 'return', {}) @@ -225,7 +225,7 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top=mid_img, - base=backing_img, speed=(self.image_len / 4)) + base=backing_img, speed=(self.image_len // 4)) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('query-block') diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index 9336ab6ff5..3615011d98 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -404,7 +404,7 @@ new_state = "2" state = "2" event = "%s" new_state = "1" -''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event)) +''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event)) file.close() def setUp(self): @@ -569,7 +569,7 @@ new_state = "2" state = "2" event = "%s" new_state = "1" -''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event)) +''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event)) file.close() def setUp(self): diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044 index 11ea0f4d35..9ec3dba734 100755 --- a/tests/qemu-iotests/044 +++ b/tests/qemu-iotests/044 @@ -26,6 +26,10 @@ import iotests from iotests import qemu_img, qemu_img_verbose, qemu_io import struct import subprocess +import sys + +if sys.version_info.major == 2: + range = xrange test_img = os.path.join(iotests.test_dir, 'test.img') @@ -52,23 +56,23 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): # Write a refcount table fd.seek(off_reftable) - for i in xrange(0, h.refcount_table_clusters): - sector = ''.join(struct.pack('>Q', + for i in range(0, h.refcount_table_clusters): + sector = b''.join(struct.pack('>Q', off_refblock + i * 64 * 512 + j * 512) - for j in xrange(0, 64)) + for j in range(0, 64)) fd.write(sector) # Write the refcount blocks assert(fd.tell() == off_refblock) - sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256)) - for block in xrange(0, h.refcount_table_clusters): + sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256)) + for block in range(0, h.refcount_table_clusters): fd.write(sector) # Write the L1 table assert(fd.tell() == off_l1) assert(off_l2 + 512 * h.l1_size == off_data) - table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) - for j in xrange(0, h.l1_size)) + table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) + for j in range(0, h.l1_size)) fd.write(table) # Write the L2 tables @@ -79,14 +83,14 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): off = off_data while remaining > 1024 * 512: pytable = list((1 << 63) | off + 512 * j - for j in xrange(0, 1024)) + for j in range(0, 1024)) table = struct.pack('>1024Q', *pytable) fd.write(table) remaining = remaining - 1024 * 512 off = off + 1024 * 512 - table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) - for j in xrange(0, remaining / 512)) + table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) + for j in range(0, remaining // 512)) fd.write(table) diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045 index 6be8fc4912..55a5d31ca8 100755 --- a/tests/qemu-iotests/045 +++ b/tests/qemu-iotests/045 @@ -140,7 +140,7 @@ class TestSCMFd(iotests.QMPTestCase): os.remove(image0) def _send_fd_by_SCM(self): - ret = self.vm.send_fd_scm(image0) + ret = self.vm.send_fd_scm(file_path=image0) self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM') def test_add_fd(self): diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056 index 223292175a..3df323984d 100755 --- a/tests/qemu-iotests/056 +++ b/tests/qemu-iotests/056 @@ -32,7 +32,7 @@ target_img = os.path.join(iotests.test_dir, 'target.img') def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs): fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt)) optargs = [] - for k,v in kwargs.iteritems(): + for k,v in kwargs.items(): optargs = optargs + ['-o', '%s=%s' % (k,v)] args = ['create', '-f', fmt] + optargs + [fullname, size] iotests.qemu_img(*args) diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065 index 72aa9707c7..8bac383ea7 100755 --- a/tests/qemu-iotests/065 +++ b/tests/qemu-iotests/065 @@ -59,7 +59,7 @@ class TestQemuImgInfo(TestImageInfoSpecific): :data.index('')] for field in data: self.assertTrue(re.match('^ {4}[^ ]', field) is not None) - data = map(lambda line: line.strip(), data) + data = [line.strip() for line in data] self.assertEqual(data, self.human_compare) class TestQMP(TestImageInfoSpecific): @@ -80,7 +80,7 @@ class TestQMP(TestImageInfoSpecific): def test_qmp(self): result = self.vm.qmp('query-block')['return'] - drive = filter(lambda drive: drive['device'] == 'drive0', result)[0] + drive = next(drive for drive in result if drive['device'] == 'drive0') data = drive['inserted']['image']['format-specific'] self.assertEqual(data['type'], iotests.imgfmt) self.assertEqual(data['data'], self.compare) diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out index be6079d27e..f9af8bb691 100644 --- a/tests/qemu-iotests/083.out +++ b/tests/qemu-iotests/083.out @@ -41,6 +41,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo === Check disconnect after neg2 === +Unable to read from socket: Connection reset by peer Connection closed read failed: Input/output error @@ -54,6 +55,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo === Check disconnect before request === +Unable to read from socket: Connection reset by peer Connection closed read failed: Input/output error @@ -116,6 +118,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/ === Check disconnect after neg-classic === +Unable to read from socket: Connection reset by peer Connection closed read failed: Input/output error @@ -161,6 +164,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock === Check disconnect after neg2 === +Unable to read from socket: Connection reset by peer +Connection closed read failed: Input/output error === Check disconnect 8 neg2 === @@ -173,6 +178,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock === Check disconnect before request === +Unable to read from socket: Connection reset by peer +Connection closed read failed: Input/output error === Check disconnect after request === @@ -234,6 +241,8 @@ can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock === Check disconnect after neg-classic === +Unable to read from socket: Connection reset by peer +Connection closed read failed: Input/output error *** done diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093 index 9d1971a56c..d88fbc182e 100755 --- a/tests/qemu-iotests/093 +++ b/tests/qemu-iotests/093 @@ -69,18 +69,18 @@ class ThrottleTestCase(iotests.QMPTestCase): # in. The throttled requests won't be executed until we # advance the virtual clock. rq_size = 512 - rd_nr = max(params['bps'] / rq_size / 2, - params['bps_rd'] / rq_size, - params['iops'] / 2, + rd_nr = max(params['bps'] // rq_size // 2, + params['bps_rd'] // rq_size, + params['iops'] // 2, params['iops_rd']) rd_nr *= seconds * 2 - rd_nr /= ndrives - wr_nr = max(params['bps'] / rq_size / 2, - params['bps_wr'] / rq_size, - params['iops'] / 2, + rd_nr //= ndrives + wr_nr = max(params['bps'] // rq_size // 2, + params['bps_wr'] // rq_size, + params['iops'] // 2, params['iops_wr']) wr_nr *= seconds * 2 - wr_nr /= ndrives + wr_nr //= ndrives # Send I/O requests to all drives for i in range(rd_nr): @@ -196,7 +196,7 @@ class ThrottleTestCase(iotests.QMPTestCase): self.configure_throttle(ndrives, settings) # Wait for the bucket to empty so we can do bursts - wait_ns = nsec_per_sec * burst_length * burst_rate / rate + wait_ns = nsec_per_sec * burst_length * burst_rate // rate self.vm.qtest("clock_step %d" % wait_ns) # Test I/O at the max burst rate diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 index 3ea4ac53f5..9f189e3b54 100755 --- a/tests/qemu-iotests/124 +++ b/tests/qemu-iotests/124 @@ -39,7 +39,7 @@ def try_remove(img): def transaction_action(action, **kwargs): return { 'type': action, - 'data': dict((k.replace('_', '-'), v) for k, v in kwargs.iteritems()) + 'data': dict((k.replace('_', '-'), v) for k, v in kwargs.items()) } @@ -134,7 +134,7 @@ class TestIncrementalBackupBase(iotests.QMPTestCase): def img_create(self, img, fmt=iotests.imgfmt, size='64M', parent=None, parentFormat=None, **kwargs): optargs = [] - for k,v in kwargs.iteritems(): + for k,v in kwargs.items(): optargs = optargs + ['-o', '%s=%s' % (k,v)] args = ['create', '-f', fmt] + optargs + [img, size] if parent: diff --git a/tests/qemu-iotests/136 b/tests/qemu-iotests/136 index a154d8ef9d..af7ffa4540 100755 --- a/tests/qemu-iotests/136 +++ b/tests/qemu-iotests/136 @@ -24,7 +24,7 @@ import os interval_length = 10 nsec_per_sec = 1000000000 -op_latency = nsec_per_sec / 1000 # See qtest_latency_ns in accounting.c +op_latency = nsec_per_sec // 1000 # See qtest_latency_ns in accounting.c bad_sector = 8192 bad_offset = bad_sector * 512 blkdebug_file = os.path.join(iotests.test_dir, 'blkdebug.conf') diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139 index cc7fe337f3..62402c1c35 100755 --- a/tests/qemu-iotests/139 +++ b/tests/qemu-iotests/139 @@ -51,7 +51,7 @@ class TestBlockdevDel(iotests.QMPTestCase): # Check whether a BlockDriverState exists def checkBlockDriverState(self, node, must_exist = True): result = self.vm.qmp('query-named-block-nodes') - nodes = filter(lambda x: x['node-name'] == node, result['return']) + nodes = [x for x in result['return'] if x['node-name'] == node] self.assertLessEqual(len(nodes), 1) self.assertEqual(must_exist, len(nodes) == 1) diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147 index d2081df84b..05b374b7d3 100755 --- a/tests/qemu-iotests/147 +++ b/tests/qemu-iotests/147 @@ -229,7 +229,7 @@ class BuiltinNBD(NBDBlockdevAddBase): sockfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sockfd.connect(unix_socket) - result = self.vm.send_fd_scm(str(sockfd.fileno())) + result = self.vm.send_fd_scm(fd=sockfd.fileno()) self.assertEqual(result, 0, 'Failed to send socket FD') result = self.vm.qmp('getfd', fdname='nbd-fifo') diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 index 9e0cad76f9..4f363f295f 100755 --- a/tests/qemu-iotests/149 +++ b/tests/qemu-iotests/149 @@ -79,7 +79,7 @@ class LUKSConfig(object): def first_password_base64(self): (pw, slot) = self.first_password() - return base64.b64encode(pw) + return base64.b64encode(pw.encode('ascii')).decode('ascii') def active_slots(self): slots = [] @@ -98,7 +98,8 @@ def verify_passwordless_sudo(): proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + universal_newlines=True) msg = proc.communicate()[0] @@ -116,7 +117,8 @@ def cryptsetup(args, password=None): proc = subprocess.Popen(fullargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + universal_newlines=True) msg = proc.communicate(password)[0] @@ -312,13 +314,13 @@ def test_once(config, qemu_img=False): image_size = 4 * oneTB if qemu_img: iotests.log("# Create image") - qemu_img_create(config, image_size / oneMB) + qemu_img_create(config, image_size // oneMB) else: iotests.log("# Create image") - create_image(config, image_size / oneMB) + create_image(config, image_size // oneMB) lowOffsetMB = 100 - highOffsetMB = 3 * oneTB / oneMB + highOffsetMB = 3 * oneTB // oneMB try: if not qemu_img: diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151 index fe53b9f446..1bb74d67c4 100755 --- a/tests/qemu-iotests/151 +++ b/tests/qemu-iotests/151 @@ -67,9 +67,9 @@ class TestActiveMirror(iotests.QMPTestCase): 'write -P 1 0 %i' % self.image_len); # Start some background requests - for offset in range(1 * self.image_len / 8, 3 * self.image_len / 8, 1024 * 1024): + for offset in range(1 * self.image_len // 8, 3 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -P 2 %i 1M' % offset) - for offset in range(2 * self.image_len / 8, 3 * self.image_len / 8, 1024 * 1024): + for offset in range(2 * self.image_len // 8, 3 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -z %i 1M' % offset) # Start the block job @@ -83,9 +83,9 @@ class TestActiveMirror(iotests.QMPTestCase): self.assert_qmp(result, 'return', {}) # Start some more requests - for offset in range(3 * self.image_len / 8, 5 * self.image_len / 8, 1024 * 1024): + for offset in range(3 * self.image_len // 8, 5 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -P 3 %i 1M' % offset) - for offset in range(4 * self.image_len / 8, 5 * self.image_len / 8, 1024 * 1024): + for offset in range(4 * self.image_len // 8, 5 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -z %i 1M' % offset) # Wait for the READY event @@ -95,9 +95,9 @@ class TestActiveMirror(iotests.QMPTestCase): # the source) should be settled using the active mechanism. # The mirror code itself asserts that the source BDS's dirty # bitmap will stay clean between READY and COMPLETED. - for offset in range(5 * self.image_len / 8, 7 * self.image_len / 8, 1024 * 1024): + for offset in range(5 * self.image_len // 8, 7 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -P 3 %i 1M' % offset) - for offset in range(6 * self.image_len / 8, 7 * self.image_len / 8, 1024 * 1024): + for offset in range(6 * self.image_len // 8, 7 * self.image_len // 8, 1024 * 1024): self.vm.hmp_qemu_io('source', 'aio_write -z %i 1M' % offset) if sync_source_and_target: diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163 index 403842354e..158ba5d092 100755 --- a/tests/qemu-iotests/163 +++ b/tests/qemu-iotests/163 @@ -18,9 +18,12 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import os, random, iotests, struct, qcow2 +import os, random, iotests, struct, qcow2, sys from iotests import qemu_img, qemu_io, image_size +if sys.version_info.major == 2: + range = xrange + test_img = os.path.join(iotests.test_dir, 'test.img') check_img = os.path.join(iotests.test_dir, 'check.img') @@ -38,10 +41,10 @@ class ShrinkBaseClass(iotests.QMPTestCase): entry_bits = 3 entry_size = 1 << entry_bits l1_mask = 0x00fffffffffffe00 - div_roundup = lambda n, d: (n + d - 1) / d + div_roundup = lambda n, d: (n + d - 1) // d def split_by_n(data, n): - for x in xrange(0, len(data), n): + for x in range(0, len(data), n): yield struct.unpack('>Q', data[x:x + n])[0] & l1_mask def check_l1_table(h, l1_data): @@ -135,8 +138,8 @@ class ShrinkBaseClass(iotests.QMPTestCase): self.image_verify() def test_random_write(self): - offs_list = range(0, size_to_int(self.image_len), - size_to_int(self.chunk_size)) + offs_list = list(range(0, size_to_int(self.image_len), + size_to_int(self.chunk_size))) random.shuffle(offs_list) for offs in offs_list: qemu_io('-c', 'write -P 0xff %d %s' % (offs, self.chunk_size), diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169 index 69850c4c67..527aebd0cb 100755 --- a/tests/qemu-iotests/169 +++ b/tests/qemu-iotests/169 @@ -23,7 +23,6 @@ import iotests import time import itertools import operator -import new import re from iotests import qemu_img @@ -204,7 +203,7 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase): def inject_test_case(klass, name, method, *args, **kwargs): mc = operator.methodcaller(method, *args, **kwargs) - setattr(klass, 'test_' + method + name, new.instancemethod(mc, None, klass)) + setattr(klass, 'test_' + method + name, lambda self: mc(self)) for cmb in list(itertools.product((True, False), repeat=4)): name = ('_' if cmb[0] else '_not_') + 'persistent_' diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out index 50ac50da5e..71857853fb 100644 --- a/tests/qemu-iotests/194.out +++ b/tests/qemu-iotests/194.out @@ -1,18 +1,18 @@ Launching VMs... Launching NBD server on destination... -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} Starting `drive-mirror` on source... -{u'return': {}} +{"return": {}} Waiting for `drive-mirror` to complete... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'} +{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Starting migration... -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} +{"return": {}} +{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Gracefully ending the `drive-mirror` job on source... -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_COMPLETED'} +{"return": {}} +{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Stopping the NBD server on destination... -{u'return': {}} +{"return": {}} diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out index d5ea374e17..9a8619e796 100644 --- a/tests/qemu-iotests/202.out +++ b/tests/qemu-iotests/202.out @@ -1,11 +1,11 @@ Launching VM... Adding IOThread... -{u'return': {}} +{"return": {}} Adding blockdevs... -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} Setting iothread... -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} Creating external snapshots... -{u'return': {}} +{"return": {}} diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out index 1a11f0975c..9d4abba8c5 100644 --- a/tests/qemu-iotests/203.out +++ b/tests/qemu-iotests/203.out @@ -1,11 +1,11 @@ Launching VM... Setting IOThreads... -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} Enabling migration QMP events... -{u'return': {}} +{"return": {}} Starting migration... -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} +{"return": {}} +{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out index 789eebe57b..91f4db55d3 100644 --- a/tests/qemu-iotests/206.out +++ b/tests/qemu-iotests/206.out @@ -1,16 +1,16 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} - -{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}} -{u'return': {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -24,15 +24,15 @@ Format specific information: === Successful image creation (inline blockdev-add, explicit defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -46,15 +46,15 @@ Format specific information: === Successful image creation (v3 non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -68,15 +68,15 @@ Format specific information: === Successful image creation (v2 non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'backing-file': 'TEST_DIR/PID-t.qcow2.base', 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -90,10 +90,10 @@ Format specific information: === Successful image creation (encrypted) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'encrypt': {'key-secret': 'keysec0', 'iter-time': 10, 'cipher-mode': 'ctr', 'ivgen-hash-alg': 'md5', 'cipher-alg': 'twofish-128', 'format': 'luks', 'ivgen-alg': 'plain64', 'hash-alg': 'sha1'}, 'driver': 'qcow2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -144,113 +144,113 @@ Format specific information: === Invalid BlockdevRef === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}} +{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid sizes === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}} +{"return": {}} Job failed: Image size must be a multiple of 512 bytes -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}} +{"return": {}} Job failed: Could not resize image: Image size cannot be negative -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}} +{"return": {}} Job failed: Could not resize image: Image size cannot be negative -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}} +{"return": {}} Job failed: Could not resize image: Failed to grow the L1 table: File too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid version === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter 'v1'"}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}} +{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}} +{"return": {}} Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}} +{"return": {}} Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid backing file options === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} +{"return": {}} Job failed: Backing file and preallocation cannot be used at the same time -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Backing format cannot be used without backing file -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid cluster size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a power of two between 512 and 2048k -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}} +{"return": {}} Job failed: Could not resize image: Failed to grow the L1 table: File too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid refcount width === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}} +{"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}} +{"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}} +{"return": {}} Job failed: Refcount width must be a power of two and may not exceed 64 bits -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 index 444ae233ae..c617ee7453 100755 --- a/tests/qemu-iotests/207 +++ b/tests/qemu-iotests/207 @@ -28,7 +28,7 @@ iotests.verify_image_format(supported_fmts=['raw']) iotests.verify_protocol(supported=['ssh']) def filter_hash(msg): - return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg) + return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg) def blockdev_create(vm, options): result = vm.qmp_log('blockdev-create', job_id='job0', options=options, @@ -109,7 +109,7 @@ with iotests.FilePath('t.img') as disk_path, \ md5_key = subprocess.check_output( 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', - shell=True).rstrip() + shell=True).rstrip().decode('ascii') vm.launch() blockdev_create(vm, { 'driver': 'ssh', @@ -147,7 +147,7 @@ with iotests.FilePath('t.img') as disk_path, \ sha1_key = subprocess.check_output( 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', - shell=True).rstrip() + shell=True).rstrip().decode('ascii') vm.launch() blockdev_create(vm, { 'driver': 'ssh', diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out index 078b7e63cb..45ac7c2a8f 100644 --- a/tests/qemu-iotests/207.out +++ b/tests/qemu-iotests/207.out @@ -1,9 +1,9 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT @@ -16,49 +16,49 @@ virtual size: 4.0M (4194304 bytes) === Test host-key-check options === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 8.0M (8388608 bytes) -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 4.0M (4194304 bytes) -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} +{"return": {}} Job failed: remote host key does not match host_key_check 'wrong' -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 8.0M (8388608 bytes) -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} +{"return": {}} Job failed: remote host key does not match host_key_check 'wrong' -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT @@ -66,15 +66,15 @@ virtual size: 4.0M (4194304 bytes) === Invalid path and user === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} +{"return": {}} Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}} +{"return": {}} Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/208.out b/tests/qemu-iotests/208.out index 3687e9d0dd..9ff2582a42 100644 --- a/tests/qemu-iotests/208.out +++ b/tests/qemu-iotests/208.out @@ -1,9 +1,9 @@ Launching VM... Starting NBD server... -{u'return': {}} +{"return": {}} Adding NBD export... -{u'return': {}} +{"return": {}} Creating external snapshot... -{u'return': {}} +{"return": {}} Stopping NBD server... -{u'return': {}} +{"return": {}} diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out index 078ba544a1..923cb05117 100644 --- a/tests/qemu-iotests/210.out +++ b/tests/qemu-iotests/210.out @@ -1,16 +1,16 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} - -{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}} -{u'return': {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT @@ -54,15 +54,15 @@ Format specific information: === Successful image creation (with non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'hash-alg': 'sha1', 'cipher-mode': 'ctr', 'cipher-alg': 'twofish-128', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT @@ -106,18 +106,18 @@ Format specific information: === Invalid BlockdevRef === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}} +{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Zero size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT @@ -161,34 +161,34 @@ Format specific information: === Invalid sizes === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}} +{"return": {}} Job failed: The requested file size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}} +{"return": {}} Job failed: The requested file size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}} +{"return": {}} Job failed: The requested file size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Resize image with invalid sizes === -{'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}} -{u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}} -{'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}} -{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} -{'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}} -{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} -{'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}} -{u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}} +{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}} +{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} +{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}} +{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} +{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}} +{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} +{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}} +{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT virtual size: 0 (0 bytes) diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out index 6feaea3978..eebb0ea086 100644 --- a/tests/qemu-iotests/211.out +++ b/tests/qemu-iotests/211.out @@ -1,16 +1,16 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} - -{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}} -{u'return': {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -21,15 +21,15 @@ cluster_size: 1048576 === Successful image creation (explicit defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 67108864}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -40,15 +40,15 @@ cluster_size: 1048576 === Successful image creation (with non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -60,18 +60,18 @@ cluster_size: 1048576 === Invalid BlockdevRef === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}} +{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Zero size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -80,10 +80,10 @@ cluster_size: 1048576 === Maximum size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -92,21 +92,21 @@ cluster_size: 1048576 === Invalid sizes === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}} +{"return": {}} Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}} +{"return": {}} Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}} +{"return": {}} Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000) -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out index 9150da7a2c..01da467282 100644 --- a/tests/qemu-iotests/212.out +++ b/tests/qemu-iotests/212.out @@ -1,16 +1,16 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} - -{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}} -{u'return': {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -18,15 +18,15 @@ virtual size: 128M (134217728 bytes) === Successful image creation (explicit defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 67108864}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -34,15 +34,15 @@ virtual size: 64M (67108864 bytes) === Successful image creation (with non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -50,18 +50,18 @@ virtual size: 32M (33554432 bytes) === Invalid BlockdevRef === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}} +{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Zero size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -69,10 +69,10 @@ virtual size: 0 (0 bytes) === Maximum size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -80,77 +80,77 @@ virtual size: 4096T (4503599627369984 bytes) === Invalid sizes === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}} +{"return": {}} Job failed: Image size must be a multiple of 512 bytes -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid cluster size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a multiple of 512 bytes -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size must be a multiple of 512 bytes -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Cluster size is too large -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}} +{"return": {}} Job failed: Image size is too large for this cluster size -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out index e1dcd47201..0c9d65b2fe 100644 --- a/tests/qemu-iotests/213.out +++ b/tests/qemu-iotests/213.out @@ -1,16 +1,16 @@ === Successful image creation (defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} - -{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}} -{u'return': {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -19,15 +19,15 @@ cluster_size: 8388608 === Successful image creation (explicit defaults) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -36,15 +36,15 @@ cluster_size: 8388608 === Successful image creation (with non-default options) === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': False, 'size': 33554432}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -53,18 +53,18 @@ cluster_size: 268435456 === Invalid BlockdevRef === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}} +{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Zero size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -73,10 +73,10 @@ cluster_size: 8388608 === Maximum size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}} -{u'return': {}} -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} image: TEST_IMG file format: IMGFMT @@ -85,85 +85,85 @@ cluster_size: 67108864 === Invalid sizes === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}} +{"return": {}} Job failed: Image size too large; max of 64TB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}} +{"return": {}} Job failed: Image size too large; max of 64TB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}} +{"return": {}} Job failed: Image size too large; max of 64TB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}} +{"return": {}} Job failed: Image size too large; max of 64TB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid block size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Block size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Block size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Block size must be a power of two -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Block size must not exceed 268435456 -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}} +{"return": {}} Job failed: Block size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} === Invalid log size === -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}} +{"return": {}} Job failed: Log size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}} +{"return": {}} Job failed: Log size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}} +{"return": {}} Job failed: Log size must be smaller than 4 GB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} -{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} -{u'return': {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}} +{"return": {}} Job failed: Log size must be a multiple of 1 MB -{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} -{u'return': {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out index 45ea857ee1..a70aa5cdae 100644 --- a/tests/qemu-iotests/216.out +++ b/tests/qemu-iotests/216.out @@ -7,8 +7,8 @@ Done --- Doing COR --- -{u'return': {}} -{u'return': u''} +{"return": {}} +{"return": ""} --- Checking COR result --- diff --git a/tests/qemu-iotests/218.out b/tests/qemu-iotests/218.out index 7dbf78e682..825a657081 100644 --- a/tests/qemu-iotests/218.out +++ b/tests/qemu-iotests/218.out @@ -4,27 +4,27 @@ --- force=false --- Cancelling job -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} +{"return": {}} +{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} --- force=true --- Cancelling job -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} +{"return": {}} +{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} === Cancel mirror job after convergence === --- force=false --- -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} +{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Cancelling job -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_COMPLETED'} +{"return": {}} +{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} --- force=true --- -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} +{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Cancelling job -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_CANCELLED'} +{"return": {}} +{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out index 6dc07bc41e..8ebd3fee60 100644 --- a/tests/qemu-iotests/219.out +++ b/tests/qemu-iotests/219.out @@ -2,326 +2,326 @@ Launching VM... Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True) -{u'return': {}} -{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'mirror'}]} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{"return": {}} +{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "mirror"}]} +{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Pause/resume in RUNNING === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for READY state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} Pause/resume in READY === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{"return": {}} +{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} +{"return": {}} +{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for PENDING state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': []} +{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": []} Starting block job: drive-backup (auto-finalize: True; auto-dismiss: True) -{u'return': {}} -{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{"return": {}} +{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} +{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Pause/resume in RUNNING === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for PENDING state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': []} +{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": []} Starting block job: drive-backup (auto-finalize: True; auto-dismiss: False) -{u'return': {}} -{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{"return": {}} +{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} +{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Pause/resume in RUNNING === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for PENDING state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': []} +{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{"return": {}} +{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": []} Starting block job: drive-backup (auto-finalize: False; auto-dismiss: True) -{u'return': {}} -{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{"return": {}} +{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} +{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Pause/resume in RUNNING === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for PENDING state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': []} +{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{"return": {}} +{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": []} Starting block job: drive-backup (auto-finalize: False; auto-dismiss: False) -{u'return': {}} -{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{"return": {}} +{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} +{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} Pause/resume in RUNNING === Testing block-job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing block-job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/block-job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} === Testing job-pause/job-resume === -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} -{u'return': {}} +{"return": {}} +{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} +{"return": {}} +{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{"return": {}} Waiting for PENDING state... -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} -{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} -{u'return': []} +{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{"return": {}} +{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{"return": {}} +{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": []} diff --git a/tests/qemu-iotests/222.out b/tests/qemu-iotests/222.out index 48f336a02b..16643dde30 100644 --- a/tests/qemu-iotests/222.out +++ b/tests/qemu-iotests/222.out @@ -8,13 +8,13 @@ Done --- Setting up Fleecing Graph --- -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} --- Setting up NBD Export --- -{u'return': {}} -{u'return': {}} +{"return": {}} +{"return": {}} --- Sanity Check --- @@ -29,13 +29,13 @@ read -P0 0x3fe0000 64k --- Testing COW --- write -P0xab 0 64k -{u'return': u''} +{"return": ""} write -P0xad 0x00f8000 64k -{u'return': u''} +{"return": ""} write -P0x1d 0x2008000 64k -{u'return': u''} +{"return": ""} write -P0xea 0x3fe0000 64k -{u'return': u''} +{"return": ""} --- Verifying Data --- @@ -49,10 +49,10 @@ read -P0 0x3fe0000 64k --- Cleanup --- -{u'return': {}} -{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'drive0', u'type': u'backup', u'speed': 0, u'len': 67108864, u'offset': 393216}, u'event': u'BLOCK_JOB_CANCELLED'} -{u'return': {}} -{u'return': {}} +{"return": {}} +{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"return": {}} +{"return": {}} --- Confirming writes --- diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 4e67fbbe96..27bb2b600c 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -29,6 +29,7 @@ import json import signal import logging import atexit +import io sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts')) import qtest @@ -104,7 +105,8 @@ def qemu_img_pipe(*args): '''Run qemu-img and return its output''' subp = subprocess.Popen(qemu_img_args + list(args), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + universal_newlines=True) exitcode = subp.wait() if exitcode < 0: sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) @@ -128,7 +130,8 @@ def qemu_io(*args): '''Run qemu-io and return the stdout data''' args = qemu_io_args + list(args) subp = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + universal_newlines=True) exitcode = subp.wait() if exitcode < 0: sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) @@ -149,7 +152,8 @@ class QemuIoInteractive: self.args = qemu_io_args + list(args) self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + universal_newlines=True) assert self._p.stdout.read(9) == 'qemu-io> ' def close(self): @@ -178,6 +182,7 @@ class QemuIoInteractive: cmd = cmd.strip() assert cmd != 'q' and cmd != 'quit' self._p.stdin.write(cmd + '\n') + self._p.stdin.flush() return self._read_output() @@ -192,10 +197,10 @@ def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): def create_image(name, size): '''Create a fully-allocated raw image with sector markers''' - file = open(name, 'w') + file = open(name, 'wb') i = 0 while i < size: - sector = struct.pack('>l504xl', i / 512, i / 512) + sector = struct.pack('>l504xl', i // 512, i // 512) file.write(sector) i = i + 512 file.close() @@ -249,7 +254,10 @@ def filter_img_info(output, filename): def log(msg, filters=[]): for flt in filters: msg = flt(msg) - print(msg) + if type(msg) is dict or type(msg) is list: + print(json.dumps(msg, sort_keys=True)) + else: + print(msg) class Timeout: def __init__(self, seconds, errmsg = "Timeout"): @@ -437,10 +445,11 @@ class VM(qtest.QEMUQtestMachine): return result def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs): - logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs) + logmsg = '{"execute": "%s", "arguments": %s}' % \ + (cmd, json.dumps(kwargs, sort_keys=True)) log(logmsg, filters) result = self.qmp(cmd, **kwargs) - log(str(result), filters) + log(json.dumps(result, sort_keys=True), filters) return result def run_job(self, job, auto_finalize=True, auto_dismiss=False): @@ -677,15 +686,19 @@ def main(supported_fmts=[], supported_oses=['linux'], supported_cache_modes=[], verify_platform(supported_oses) verify_cache_mode(supported_cache_modes) - # We need to filter out the time taken from the output so that qemu-iotest - # can reliably diff the results against master output. - import StringIO if debug: output = sys.stdout verbosity = 2 sys.argv.remove('-d') else: - output = StringIO.StringIO() + # We need to filter out the time taken from the output so that + # qemu-iotest can reliably diff the results against master output. + if sys.version_info.major >= 3: + output = io.StringIO() + else: + # io.StringIO is for unicode strings, which is not what + # 2.x's test runner emits. + output = io.BytesIO() logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py index f9193c0fae..6b2d659dee 100755 --- a/tests/qemu-iotests/nbd-fault-injector.py +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -48,7 +48,10 @@ import sys import socket import struct import collections -import ConfigParser +if sys.version_info.major >= 3: + import configparser +else: + import ConfigParser as configparser FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB @@ -86,7 +89,7 @@ def recvall(sock, bufsize): raise Exception('unexpected disconnect') chunks.append(chunk) received += len(chunk) - return ''.join(chunks) + return b''.join(chunks) class Rule(object): def __init__(self, name, event, io, when): @@ -112,6 +115,7 @@ class FaultInjectionSocket(object): if rule.match(event, io): if rule.when == 0 or bufsize is None: print('Closing connection on rule match %s' % rule.name) + self.sock.flush() sys.exit(0) if rule.when != -1: return rule.when @@ -176,7 +180,7 @@ def handle_connection(conn, use_export): req = read_request(conn) if req.type == NBD_CMD_READ: write_reply(conn, 0, req.handle) - conn.send('\0' * req.len, event='data') + conn.send(b'\0' * req.len, event='data') elif req.type == NBD_CMD_WRITE: _ = conn.recv(req.len, event='data') write_reply(conn, 0, req.handle) @@ -224,7 +228,7 @@ def parse_config(config): return rules def load_rules(filename): - config = ConfigParser.RawConfigParser() + config = configparser.RawConfigParser() with open(filename, 'rt') as f: config.readfp(f, filename) return parse_config(config) diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index b95a837759..b392972d1b 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -10,7 +10,7 @@ class QcowHeaderExtension: def __init__(self, magic, length, data): if length % 8 != 0: padding = 8 - (length % 8) - data += "\0" * padding + data += b"\0" * padding self.magic = magic self.length = length @@ -103,7 +103,7 @@ class QcowHeader: fd.seek(self.header_length) extensions = self.extensions - extensions.append(QcowHeaderExtension(0, 0, "")) + extensions.append(QcowHeaderExtension(0, 0, b"")) for ex in extensions: buf = struct.pack('>II', ex.magic, ex.length) fd.write(buf) @@ -137,8 +137,8 @@ class QcowHeader: for ex in self.extensions: data = ex.data[:ex.length] - if all(c in string.printable for c in data): - data = "'%s'" % data + if all(c in string.printable.encode('ascii') for c in data): + data = "'%s'" % data.decode('ascii') else: data = "<binary>" @@ -178,7 +178,7 @@ def cmd_add_header_ext(fd, magic, data): sys.exit(1) h = QcowHeader(fd) - h.extensions.append(QcowHeaderExtension.create(magic, data)) + h.extensions.append(QcowHeaderExtension.create(magic, data.encode('ascii'))) h.update(fd) def cmd_add_header_ext_stdio(fd, magic): diff --git a/tests/qemu-iotests/qed.py b/tests/qemu-iotests/qed.py index ea469b9c48..8adaaf46c4 100755 --- a/tests/qemu-iotests/qed.py +++ b/tests/qemu-iotests/qed.py @@ -80,7 +80,7 @@ class QED(object): def load_l1_table(self): self.l1_table = self.read_table(self.header['l1_table_offset']) - self.table_nelems = self.header['table_size'] * self.header['cluster_size'] / table_elem_size + self.table_nelems = self.header['table_size'] * self.header['cluster_size'] // table_elem_size def write_table(self, offset, table): s = ''.join(pack_table_elem(x) for x in table) @@ -167,14 +167,14 @@ def cmd_zero_cluster(qed, pos, *args): n = int(args[0]) for i in xrange(n): - l1_index = pos / qed.header['cluster_size'] / len(qed.l1_table) + l1_index = pos // qed.header['cluster_size'] // len(qed.l1_table) if qed.l1_table[l1_index] == 0: err('no l2 table allocated') l2_offset = qed.l1_table[l1_index] l2_table = qed.read_table(l2_offset) - l2_index = (pos / qed.header['cluster_size']) % len(qed.l1_table) + l2_index = (pos // qed.header['cluster_size']) % len(qed.l1_table) l2_table[l2_index] = 1 # zero the data cluster qed.write_table(l2_offset, l2_table) pos += qed.header['cluster_size'] diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000000..64c6e27a94 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,4 @@ +# Add Python module requirements, one per line, to be installed +# in the tests/venv Python virtual environment. For more info, +# refer to: https://pip.pypa.io/en/stable/user_guide/#id1 +avocado-framework==65.0 diff --git a/tests/test-char.c b/tests/test-char.c index 831e37fbf4..19c3efad72 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -420,6 +420,130 @@ static void char_socket_fdpass_test(void) } +static void websock_server_read(void *opaque, const uint8_t *buf, int size) +{ + g_assert_cmpint(size, ==, 5); + g_assert(memcmp(buf, "world", size) == 0); + quit = true; +} + + +static int websock_server_can_read(void *opaque) +{ + return 10; +} + + +static bool websock_check_http_headers(char *buf, int size) +{ + int i; + const char *ans[] = { "HTTP/1.1 101 Switching Protocols\r\n", + "Server: QEMU VNC\r\n", + "Upgrade: websocket\r\n", + "Connection: Upgrade\r\n", + "Sec-WebSocket-Accept:", + "Sec-WebSocket-Protocol: binary\r\n" }; + + for (i = 0; i < 6; i++) { + if (g_strstr_len(buf, size, ans[i]) == NULL) { + return false; + } + } + + return true; +} + + +static void websock_client_read(void *opaque, const uint8_t *buf, int size) +{ + const uint8_t ping[] = { 0x89, 0x85, /* Ping header */ + 0x07, 0x77, 0x9e, 0xf9, /* Masking key */ + 0x6f, 0x12, 0xf2, 0x95, 0x68 /* "hello" */ }; + + const uint8_t binary[] = { 0x82, 0x85, /* Binary header */ + 0x74, 0x90, 0xb9, 0xdf, /* Masking key */ + 0x03, 0xff, 0xcb, 0xb3, 0x10 /* "world" */ }; + Chardev *chr_client = opaque; + + if (websock_check_http_headers((char *) buf, size)) { + qemu_chr_fe_write(chr_client->be, ping, sizeof(ping)); + } else if (buf[0] == 0x8a && buf[1] == 0x05) { + g_assert(strncmp((char *) buf + 2, "hello", 5) == 0); + qemu_chr_fe_write(chr_client->be, binary, sizeof(binary)); + } else { + g_assert(buf[0] == 0x88 && buf[1] == 0x16); + g_assert(strncmp((char *) buf + 4, "peer requested close", 10) == 0); + quit = true; + } +} + + +static int websock_client_can_read(void *opaque) +{ + return 4096; +} + + +static void char_websock_test(void) +{ + QObject *addr; + QDict *qdict; + const char *port; + char *tmp; + char *handshake_port; + CharBackend be; + CharBackend client_be; + Chardev *chr_client; + Chardev *chr = qemu_chr_new("server", + "websocket:127.0.0.1:0,server,nowait"); + const char handshake[] = "GET / HTTP/1.1\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Host: localhost:%s\r\n" + "Origin: http://localhost:%s\r\n" + "Sec-WebSocket-Key: o9JHNiS3/0/0zYE1wa3yIw==\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Protocol: binary\r\n\r\n"; + const uint8_t close[] = { 0x88, 0x82, /* Close header */ + 0xef, 0xaa, 0xc5, 0x97, /* Masking key */ + 0xec, 0x42 /* Status code */ }; + + addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort); + qdict = qobject_to(QDict, addr); + port = qdict_get_str(qdict, "port"); + tmp = g_strdup_printf("tcp:127.0.0.1:%s", port); + handshake_port = g_strdup_printf(handshake, port, port); + qobject_unref(qdict); + + qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_set_handlers(&be, websock_server_can_read, websock_server_read, + NULL, NULL, chr, NULL, true); + + chr_client = qemu_chr_new("client", tmp); + qemu_chr_fe_init(&client_be, chr_client, &error_abort); + qemu_chr_fe_set_handlers(&client_be, websock_client_can_read, + websock_client_read, + NULL, NULL, chr_client, NULL, true); + g_free(tmp); + + qemu_chr_write_all(chr_client, + (uint8_t *) handshake_port, + strlen(handshake_port)); + g_free(handshake_port); + main_loop(); + + g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort)); + g_assert(object_property_get_bool(OBJECT(chr_client), + "connected", &error_abort)); + + qemu_chr_write_all(chr_client, close, sizeof(close)); + main_loop(); + + object_unparent(OBJECT(chr_client)); + object_unparent(OBJECT(chr)); +} + + #ifndef _WIN32 static void char_pipe_test(void) { @@ -842,6 +966,7 @@ int main(int argc, char **argv) g_test_add_func("/char/serial", char_serial_test); #endif g_test_add_func("/char/hotswap", char_hotswap_test); + g_test_add_func("/char/websocket", char_websock_test); return g_test_run(); } diff --git a/tests/tpm-tests.c b/tests/tpm-tests.c index 10c6592aac..93a5beba01 100644 --- a/tests/tpm-tests.c +++ b/tests/tpm-tests.c @@ -18,6 +18,17 @@ #include "libqtest.h" #include "tpm-tests.h" +static bool +tpm_test_swtpm_skip(void) +{ + if (!tpm_util_swtpm_has_tpm2()) { + fprintf(stderr, "swtpm not in PATH or missing --tpm2 support; "); + return true; + } + + return false; +} + void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, const char *ifmodel) { @@ -28,12 +39,13 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, GPid swtpm_pid; GError *error = NULL; - succ = tpm_util_swtpm_start(src_tpm_path, &swtpm_pid, &addr, &error); - /* succ may be false if swtpm is not available */ - if (!succ) { + if (tpm_test_swtpm_skip()) { return; } + succ = tpm_util_swtpm_start(src_tpm_path, &swtpm_pid, &addr, &error); + g_assert_true(succ); + args = g_strdup_printf( "-chardev socket,id=chr,path=%s " "-tpmdev emulator,id=dev,chardev=chr " @@ -74,19 +86,17 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, GError *error = NULL; QTestState *src_qemu, *dst_qemu; - succ = tpm_util_swtpm_start(src_tpm_path, &src_tpm_pid, - &src_tpm_addr, &error); - /* succ may be false if swtpm is not available */ - if (!succ) { + if (tpm_test_swtpm_skip()) { return; } + succ = tpm_util_swtpm_start(src_tpm_path, &src_tpm_pid, + &src_tpm_addr, &error); + g_assert_true(succ); + succ = tpm_util_swtpm_start(dst_tpm_path, &dst_tpm_pid, &dst_tpm_addr, &error); - /* succ may be false if swtpm is not available */ - if (!succ) { - goto err_src_tpm_kill; - } + g_assert_true(succ); tpm_util_migration_start_qemu(&src_qemu, &dst_qemu, src_tpm_addr, dst_tpm_addr, uri, @@ -118,7 +128,6 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, qapi_free_SocketAddress(dst_tpm_addr); } -err_src_tpm_kill: tpm_util_swtpm_kill(src_tpm_pid); if (src_tpm_addr) { g_unlink(src_tpm_addr->u.q_unix.path); diff --git a/tests/tpm-util.c b/tests/tpm-util.c index 9f3f156e42..e08b137651 100644 --- a/tests/tpm-util.c +++ b/tests/tpm-util.c @@ -145,39 +145,33 @@ void tpm_util_pcrread(QTestState *s, tx_func *tx, g_assert_cmpmem(buffer, exp_resp_size, exp_resp, exp_resp_size); } -static gboolean tpm_util_swtpm_has_tpm2(void) +bool tpm_util_swtpm_has_tpm2(void) { - gint mystdout; - gboolean succ; - unsigned i; - char buffer[10240]; - ssize_t n; - gchar *swtpm_argv[] = { - g_strdup("swtpm"), g_strdup("socket"), g_strdup("--help"), NULL + bool has_tpm2 = false; + char *out = NULL; + static const char *argv[] = { + "swtpm", "socket", "--help", NULL }; - succ = g_spawn_async_with_pipes(NULL, swtpm_argv, NULL, - G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, - NULL, &mystdout, NULL, NULL); - if (!succ) { - goto cleanup; - } - - n = read(mystdout, buffer, sizeof(buffer) - 1); - if (n < 0) { - goto cleanup; - } - buffer[n] = 0; - if (!strstr(buffer, "--tpm2")) { - succ = false; + if (!g_spawn_sync(NULL /* working_dir */, + (char **)argv, + NULL /* envp */, + G_SPAWN_SEARCH_PATH, + NULL /* child_setup */, + NULL /* user_data */, + &out, + NULL /* err */, + NULL /* exit_status */, + NULL)) { + return false; } - cleanup: - for (i = 0; swtpm_argv[i]; i++) { - g_free(swtpm_argv[i]); + if (strstr(out, "--tpm2")) { + has_tpm2 = true; } - return succ; + g_free(out); + return has_tpm2; } gboolean tpm_util_swtpm_start(const char *path, GPid *pid, @@ -196,11 +190,6 @@ gboolean tpm_util_swtpm_start(const char *path, GPid *pid, gboolean succ; unsigned i; - succ = tpm_util_swtpm_has_tpm2(); - if (!succ) { - goto cleanup; - } - *addr = g_new0(SocketAddress, 1); (*addr)->type = SOCKET_ADDRESS_TYPE_UNIX; (*addr)->u.q_unix.path = g_build_filename(path, "sock", NULL); @@ -208,7 +197,6 @@ gboolean tpm_util_swtpm_start(const char *path, GPid *pid, succ = g_spawn_async(NULL, swtpm_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, pid, error); -cleanup: for (i = 0; swtpm_argv[i]; i++) { g_free(swtpm_argv[i]); } diff --git a/tests/tpm-util.h b/tests/tpm-util.h index 330b9657fe..9e98bc5124 100644 --- a/tests/tpm-util.h +++ b/tests/tpm-util.h @@ -32,6 +32,8 @@ void tpm_util_pcrextend(QTestState *s, tx_func *tx); void tpm_util_pcrread(QTestState *s, tx_func *tx, const unsigned char *exp_resp, size_t exp_resp_size); +bool tpm_util_swtpm_has_tpm2(void); + gboolean tpm_util_swtpm_start(const char *path, GPid *pid, SocketAddress **addr, GError **error); void tpm_util_swtpm_kill(GPid pid); |