diff options
| -rw-r--r-- | MAINTAINERS | 6 | ||||
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | accel/kvm/kvm-all.c | 15 | ||||
| -rw-r--r-- | disas/nanomips.c | 194 | ||||
| -rw-r--r-- | migration/savevm.c | 21 | ||||
| -rw-r--r-- | target/arm/helper.c | 10 |
6 files changed, 140 insertions, 108 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 249b678fc6..f1f6922025 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2170,7 +2170,7 @@ S: Supported F: hw/vfio/* F: include/hw/vfio/ F: docs/igd-assign.txt -F: docs/devel/vfio-migration.rst +F: docs/devel/migration/vfio.rst vfio-ccw M: Eric Farman <farman@linux.ibm.com> @@ -2231,6 +2231,7 @@ F: qapi/virtio.json F: net/vhost-user.c F: include/hw/virtio/ F: docs/devel/virtio* +F: docs/devel/migration/virtio.rst virtio-balloon M: Michael S. Tsirkin <mst@redhat.com> @@ -3417,7 +3418,7 @@ F: migration/ F: scripts/vmstate-static-checker.py F: tests/vmstate-static-checker-data/ F: tests/qtest/migration-test.c -F: docs/devel/migration.rst +F: docs/devel/migration/ F: qapi/migration.json F: tests/migration/ F: util/userfaultfd.c @@ -3437,6 +3438,7 @@ F: include/sysemu/dirtylimit.h F: migration/dirtyrate.c F: migration/dirtyrate.h F: include/sysemu/dirtyrate.h +F: docs/devel/migration/dirty-limit.rst Detached LUKS header M: Hyman Huang <yong.huang@smartx.com> diff --git a/Makefile b/Makefile index 8f36990335..183756018f 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ MAKE.k = $(findstring k,$(firstword $(filter-out --%,$(MAKEFLAGS)))) MAKE.q = $(findstring q,$(firstword $(filter-out --%,$(MAKEFLAGS)))) MAKE.nq = $(if $(word 2, $(MAKE.n) $(MAKE.q)),nq) NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \ - $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \ + $(or $(filter -l% -j%, $(MAKEFLAGS)), $(if $(filter --jobserver-auth=%, $(MAKEFLAGS)),, -j1)) \ -d keepdepfile ninja-cmd-goals = $(or $(MAKECMDGOALS), all) ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g)) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index a8cecd040e..931f74256e 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -1999,12 +1999,17 @@ int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev) return -EINVAL; } - trace_kvm_irqchip_add_msi_route(dev ? dev->name : (char *)"N/A", - vector, virq); + if (s->irq_routes->nr < s->gsi_count) { + trace_kvm_irqchip_add_msi_route(dev ? dev->name : (char *)"N/A", + vector, virq); - kvm_add_routing_entry(s, &kroute); - kvm_arch_add_msi_route_post(&kroute, vector, dev); - c->changes++; + kvm_add_routing_entry(s, &kroute); + kvm_arch_add_msi_route_post(&kroute, vector, dev); + c->changes++; + } else { + kvm_irqchip_release_virq(s, virq); + return -ENOSPC; + } return virq; } diff --git a/disas/nanomips.c b/disas/nanomips.c index a0253598dd..db0c297b8d 100644 --- a/disas/nanomips.c +++ b/disas/nanomips.c @@ -36,35 +36,6 @@ typedef uint32_t uint32; typedef uint16_t uint16; typedef uint64_t img_address; -typedef enum { - instruction, - call_instruction, - branch_instruction, - return_instruction, - reserved_block, - pool, -} TABLE_ENTRY_TYPE; - -typedef enum { - MIPS64_ = 0x00000001, - XNP_ = 0x00000002, - XMMS_ = 0x00000004, - EVA_ = 0x00000008, - DSP_ = 0x00000010, - MT_ = 0x00000020, - EJTAG_ = 0x00000040, - TLBINV_ = 0x00000080, - CP0_ = 0x00000100, - CP1_ = 0x00000200, - CP2_ = 0x00000400, - UDI_ = 0x00000800, - MCU_ = 0x00001000, - VZ_ = 0x00002000, - TLB_ = 0x00004000, - MVH_ = 0x00008000, - ALL_ATTRIBUTES = 0xffffffffull, -} TABLE_ATTRIBUTE_TYPE; - typedef struct Dis_info { img_address m_pc; fprintf_function fprintf_func; @@ -72,22 +43,6 @@ typedef struct Dis_info { sigjmp_buf buf; } Dis_info; -typedef bool (*conditional_function)(uint64 instruction); -typedef char * (*disassembly_function)(uint64 instruction, - Dis_info *info); - -typedef struct Pool { - TABLE_ENTRY_TYPE type; - const struct Pool *next_table; - int next_table_size; - int instructions_size; - uint64 mask; - uint64 value; - disassembly_function disassembly; - conditional_function condition; - uint64 attributes; -} Pool; - #define IMGASSERTONCE(test) @@ -544,58 +499,6 @@ static uint64 extract_op_code_value(const uint16 *data, int size) } -/* - * Recurse through tables until the instruction is found then return - * the string and size - * - * inputs: - * pointer to a word stream, - * disassember table and size - * returns: - * instruction size - negative is error - * disassembly string - on error will constain error string - */ -static int Disassemble(const uint16 *data, char **dis, - TABLE_ENTRY_TYPE *type, const Pool *table, - int table_size, Dis_info *info) -{ - for (int i = 0; i < table_size; i++) { - uint64 op_code = extract_op_code_value(data, - table[i].instructions_size); - if ((op_code & table[i].mask) == table[i].value) { - /* possible match */ - conditional_function cond = table[i].condition; - if ((cond == NULL) || cond(op_code)) { - if (table[i].type == pool) { - return Disassemble(data, dis, type, - table[i].next_table, - table[i].next_table_size, - info); - } else if ((table[i].type == instruction) || - (table[i].type == call_instruction) || - (table[i].type == branch_instruction) || - (table[i].type == return_instruction)) { - disassembly_function dis_fn = table[i].disassembly; - if (dis_fn == 0) { - *dis = g_strdup( - "disassembler failure - bad table entry"); - return -6; - } - *type = table[i].type; - *dis = dis_fn(op_code, info); - return table[i].instructions_size; - } else { - *dis = g_strdup("reserved instruction"); - return -2; - } - } - } - } - *dis = g_strdup("failed to disassemble"); - return -1; /* failed to disassemble */ -} - - static uint64 extract_code_18_to_0(uint64 instruction) { uint64 value = 0; @@ -16213,6 +16116,51 @@ static char *YIELD(uint64 instruction, Dis_info *info) * */ +typedef enum { + instruction, + call_instruction, + branch_instruction, + return_instruction, + reserved_block, + pool, +} TABLE_ENTRY_TYPE; + +typedef enum { + MIPS64_ = 0x00000001, + XNP_ = 0x00000002, + XMMS_ = 0x00000004, + EVA_ = 0x00000008, + DSP_ = 0x00000010, + MT_ = 0x00000020, + EJTAG_ = 0x00000040, + TLBINV_ = 0x00000080, + CP0_ = 0x00000100, + CP1_ = 0x00000200, + CP2_ = 0x00000400, + UDI_ = 0x00000800, + MCU_ = 0x00001000, + VZ_ = 0x00002000, + TLB_ = 0x00004000, + MVH_ = 0x00008000, + ALL_ATTRIBUTES = 0xffffffffull, +} TABLE_ATTRIBUTE_TYPE; + +typedef bool (*conditional_function)(uint64 instruction); +typedef char * (*disassembly_function)(uint64 instruction, + Dis_info *info); + +typedef struct Pool { + TABLE_ENTRY_TYPE type; + const struct Pool *next_table; + int next_table_size; + int instructions_size; + uint64 mask; + uint64 value; + disassembly_function disassembly; + conditional_function condition; + uint64 attributes; +} Pool; + static const Pool P_SYSCALL[2] = { { instruction , 0 , 0 , 32, 0xfffc0000, 0x00080000, &SYSCALL_32_ , 0, @@ -21907,6 +21855,58 @@ static const Pool MAJOR[2] = { 0x0 }, /* P16 */ }; +/* + * Recurse through tables until the instruction is found then return + * the string and size + * + * inputs: + * pointer to a word stream, + * disassember table and size + * returns: + * instruction size - negative is error + * disassembly string - on error will constain error string + */ +static int Disassemble(const uint16 *data, char **dis, + TABLE_ENTRY_TYPE *type, const Pool *table, + int table_size, Dis_info *info) +{ + for (int i = 0; i < table_size; i++) { + uint64 op_code = extract_op_code_value(data, + table[i].instructions_size); + if ((op_code & table[i].mask) == table[i].value) { + /* possible match */ + conditional_function cond = table[i].condition; + if ((cond == NULL) || cond(op_code)) { + if (table[i].type == pool) { + return Disassemble(data, dis, type, + table[i].next_table, + table[i].next_table_size, + info); + } else if ((table[i].type == instruction) || + (table[i].type == call_instruction) || + (table[i].type == branch_instruction) || + (table[i].type == return_instruction)) { + disassembly_function dis_fn = table[i].disassembly; + if (dis_fn == 0) { + *dis = g_strdup( + "disassembler failure - bad table entry"); + return -6; + } + *type = table[i].type; + *dis = dis_fn(op_code, info); + return table[i].instructions_size; + } else { + *dis = g_strdup("reserved instruction"); + return -2; + } + } + } + } + *dis = g_strdup("failed to disassemble"); + return -1; /* failed to disassemble */ +} + + static bool nanomips_dis(const uint16_t *data, char **buf, Dis_info *info) { TABLE_ENTRY_TYPE type; diff --git a/migration/savevm.c b/migration/savevm.c index 388d7af7cd..e7c1215671 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2342,6 +2342,27 @@ static int loadvm_handle_cmd_packaged(MigrationIncomingState *mis) QEMUFile *packf = qemu_file_new_input(QIO_CHANNEL(bioc)); + /* + * Before loading the guest states, ensure that the preempt channel has + * been ready to use, as some of the states (e.g. via virtio_load) might + * trigger page faults that will be handled through the preempt channel. + * So yield to the main thread in the case that the channel create event + * hasn't been dispatched. + * + * TODO: if we can move migration loadvm out of main thread, then we + * won't block main thread from polling the accept() fds. We can drop + * this as a whole when that is done. + */ + do { + if (!migrate_postcopy_preempt() || !qemu_in_coroutine() || + mis->postcopy_qemufile_dst) { + break; + } + + aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self()); + qemu_coroutine_yield(); + } while (1); + ret = qemu_loadvm_state_main(packf, mis); trace_loadvm_handle_cmd_packaged_main(ret); qemu_fclose(packf); diff --git a/target/arm/helper.c b/target/arm/helper.c index 3f3a5b55d4..a620481d7c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3452,7 +3452,8 @@ static CPAccessResult gt_cntpoff_access(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) { - if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) { + if (arm_current_el(env) == 2 && arm_feature(env, ARM_FEATURE_EL3) && + !(env->cp15.scr_el3 & SCR_ECVEN)) { return CP_ACCESS_TRAP_EL3; } return CP_ACCESS_OK; @@ -3878,6 +3879,8 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, ARMMMUIdx mmu_idx; uint64_t hcr_el2 = arm_hcr_el2_eff(env); bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE); + bool for_el3 = false; + ARMSecuritySpace ss; switch (ri->opc2 & 6) { case 0: @@ -3895,6 +3898,7 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, break; case 6: /* AT S1E3R, AT S1E3W */ mmu_idx = ARMMMUIdx_E3; + for_el3 = true; break; default: g_assert_not_reached(); @@ -3913,8 +3917,8 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, g_assert_not_reached(); } - env->cp15.par_el[1] = do_ats_write(env, value, access_type, - mmu_idx, arm_security_space(env)); + ss = for_el3 ? arm_security_space(env) : arm_security_space_below_el3(env); + env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx, ss); #else /* Handled by hardware accelerator. */ g_assert_not_reached(); |