x86 and machine queue, 2016-07-27
Highlights: * Fixes to allow CPU hotplug/unplug in any order; * Exit QEMU on invalid global properties. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJXmMUlAAoJECgHk2+YTcWmLooP/ioPaesxxcz4u7SMS2h6c12z shC2ERzGNeB+d6KZvscYG/fbR5SV3P1JAtOE5+BbiVvnZRbyvv0NaYhPlnLV/P5C KKIK3uimaSNyxaDF7zZiImZWLWq8vl51SXITIQenrCjPYPE6q32m3pvlbGJvVi8P x4lW9LMyRG1a2yOqF9nt+eTqkcigSj6z9cL8MQRoSnDhkXAh/q3ySofKfJ9RAhWQ tGg5xIa+B/0mjZQwS2e0vnDnVxeYRgQ0o7sdZJD9zjgog8HTKX2cei0b/+FINAKM bzDAQI97ECsWQ8MxXdcXsu9dHr7mwovmpBvecsU0DZtWnMv0vmd0OxmWJXoI4uh2 4rcg576z9rQU7eA4CbU7Wh4PTeKcKYvjocIQlMN2mgrVNZK7FXsRDdUdyusE8JQC HHc/990kboC2Ui1MPi/QJm1RvA8+ofAk3py8DK5ixYvBPfeLxtcgHM8d3MpgeLbp jG1DgnhEcO5lg29vWUsPM8XujUdPSJ8sgJtjCQIiACKgpZhuYKHirrnq+TNtd0Ly qVrlVNWUuT0zWb9/kRgtcczgXFzP2+DQHH4jRc0csyFtxolt5SmA2tZ3vnlXnoUn SIOH4V16aY3tndt/uAJh7+Qo1ZsGoeTqzrFWYLdpynDxpNwjWcaLenJ9MogUmbWh FK+cKsazPWn3MOCxjhgj =2Abo -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging x86 and machine queue, 2016-07-27 Highlights: * Fixes to allow CPU hotplug/unplug in any order; * Exit QEMU on invalid global properties. # gpg: Signature made Wed 27 Jul 2016 15:28:53 BST # gpg: using RSA key 0x2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/x86-pull-request: vl: exit if a bad property value is passed to -global qdev: ignore GlobalProperty.errp for hotplugged devices machine: Add comment to abort path in machine_set_kernel_irqchip Revert "pc: Enforce adding CPUs contiguously and removing them in opposite order" pc: Init CPUState->cpu_index with index in possible_cpus[] qdev: Fix object reference leak in case device.realize() fails exec: Set cpu_index only if it's not been explictly set exec: Don't use cpu_index to detect if cpu_exec_init()'s been called exec: Reduce CONFIG_USER_ONLY ifdeffenery Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
21a21b853a
|
@ -209,8 +209,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||||
abi_ulong new_addr);
|
abi_ulong new_addr);
|
||||||
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||||
extern unsigned long last_brk;
|
extern unsigned long last_brk;
|
||||||
void cpu_list_lock(void);
|
|
||||||
void cpu_list_unlock(void);
|
|
||||||
#if defined(CONFIG_USE_NPTL)
|
#if defined(CONFIG_USE_NPTL)
|
||||||
void mmap_fork_start(void);
|
void mmap_fork_start(void);
|
||||||
void mmap_fork_end(int child);
|
void mmap_fork_end(int child);
|
||||||
|
|
66
exec.c
66
exec.c
|
@ -598,30 +598,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
static int cpu_get_free_index(void)
|
||||||
static DECLARE_BITMAP(cpu_index_map, MAX_CPUMASK_BITS);
|
|
||||||
|
|
||||||
static int cpu_get_free_index(Error **errp)
|
|
||||||
{
|
|
||||||
int cpu = find_first_zero_bit(cpu_index_map, MAX_CPUMASK_BITS);
|
|
||||||
|
|
||||||
if (cpu >= MAX_CPUMASK_BITS) {
|
|
||||||
error_setg(errp, "Trying to use more CPUs than max of %d",
|
|
||||||
MAX_CPUMASK_BITS);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap_set(cpu_index_map, cpu, 1);
|
|
||||||
return cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cpu_release_index(CPUState *cpu)
|
|
||||||
{
|
|
||||||
bitmap_clear(cpu_index_map, cpu->cpu_index, 1);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
static int cpu_get_free_index(Error **errp)
|
|
||||||
{
|
{
|
||||||
CPUState *some_cpu;
|
CPUState *some_cpu;
|
||||||
int cpu_index = 0;
|
int cpu_index = 0;
|
||||||
|
@ -632,33 +609,21 @@ static int cpu_get_free_index(Error **errp)
|
||||||
return cpu_index;
|
return cpu_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_release_index(CPUState *cpu)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void cpu_exec_exit(CPUState *cpu)
|
void cpu_exec_exit(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
cpu_list_lock();
|
cpu_list_lock();
|
||||||
#endif
|
if (cpu->node.tqe_prev == NULL) {
|
||||||
if (cpu->cpu_index == -1) {
|
/* there is nothing to undo since cpu_exec_init() hasn't been called */
|
||||||
/* cpu_index was never allocated by this @cpu or was already freed. */
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
cpu_list_unlock();
|
cpu_list_unlock();
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_REMOVE(&cpus, cpu, node);
|
QTAILQ_REMOVE(&cpus, cpu, node);
|
||||||
cpu_release_index(cpu);
|
cpu->node.tqe_prev = NULL;
|
||||||
cpu->cpu_index = -1;
|
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
cpu_list_unlock();
|
cpu_list_unlock();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cc->vmsd != NULL) {
|
if (cc->vmsd != NULL) {
|
||||||
vmstate_unregister(NULL, cc->vmsd, cpu);
|
vmstate_unregister(NULL, cc->vmsd, cpu);
|
||||||
|
@ -670,8 +635,8 @@ void cpu_exec_exit(CPUState *cpu)
|
||||||
|
|
||||||
void cpu_exec_init(CPUState *cpu, Error **errp)
|
void cpu_exec_init(CPUState *cpu, Error **errp)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);
|
||||||
Error *local_err = NULL;
|
Error *local_err ATTRIBUTE_UNUSED = NULL;
|
||||||
|
|
||||||
cpu->as = NULL;
|
cpu->as = NULL;
|
||||||
cpu->num_ases = 0;
|
cpu->num_ases = 0;
|
||||||
|
@ -694,22 +659,15 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
|
||||||
object_ref(OBJECT(cpu->memory));
|
object_ref(OBJECT(cpu->memory));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
cpu_list_lock();
|
cpu_list_lock();
|
||||||
#endif
|
if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
|
||||||
cpu->cpu_index = cpu_get_free_index(&local_err);
|
cpu->cpu_index = cpu_get_free_index();
|
||||||
if (local_err) {
|
assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
|
||||||
error_propagate(errp, local_err);
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
cpu_list_unlock();
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
|
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
(void) cc;
|
|
||||||
cpu_list_unlock();
|
cpu_list_unlock();
|
||||||
#else
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
|
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
|
||||||
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
|
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,9 @@ static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
|
||||||
ms->kernel_irqchip_split = true;
|
ms->kernel_irqchip_split = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* The value was checked in visit_type_OnOffSplit() above. If
|
||||||
|
* we get here, then something is wrong in QEMU.
|
||||||
|
*/
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1084,7 +1084,7 @@ int qdev_prop_check_globals(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qdev_prop_set_globals_for_type(DeviceState *dev,
|
static void qdev_prop_set_globals_for_type(DeviceState *dev,
|
||||||
const char *typename)
|
const char *typename)
|
||||||
{
|
{
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
|
@ -1100,7 +1100,7 @@ static void qdev_prop_set_globals_for_type(DeviceState *dev,
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
error_prepend(&err, "can't apply global %s.%s=%s: ",
|
error_prepend(&err, "can't apply global %s.%s=%s: ",
|
||||||
prop->driver, prop->property, prop->value);
|
prop->driver, prop->property, prop->value);
|
||||||
if (prop->errp) {
|
if (!dev->hotplugged && prop->errp) {
|
||||||
error_propagate(prop->errp, err);
|
error_propagate(prop->errp, err);
|
||||||
} else {
|
} else {
|
||||||
assert(prop->user_provided);
|
assert(prop->user_provided);
|
||||||
|
|
|
@ -885,6 +885,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
HotplugHandler *hotplug_ctrl;
|
HotplugHandler *hotplug_ctrl;
|
||||||
BusState *bus;
|
BusState *bus;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
bool unattached_parent = false;
|
||||||
|
static int unattached_count;
|
||||||
|
|
||||||
if (dev->hotplugged && !dc->hotpluggable) {
|
if (dev->hotplugged && !dc->hotpluggable) {
|
||||||
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
|
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
|
||||||
|
@ -893,12 +895,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
|
|
||||||
if (value && !dev->realized) {
|
if (value && !dev->realized) {
|
||||||
if (!obj->parent) {
|
if (!obj->parent) {
|
||||||
static int unattached_count;
|
|
||||||
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
|
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
|
||||||
|
|
||||||
object_property_add_child(container_get(qdev_get_machine(),
|
object_property_add_child(container_get(qdev_get_machine(),
|
||||||
"/unattached"),
|
"/unattached"),
|
||||||
name, obj, &error_abort);
|
name, obj, &error_abort);
|
||||||
|
unattached_parent = true;
|
||||||
g_free(name);
|
g_free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +989,10 @@ post_realize_fail:
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
if (unattached_parent) {
|
||||||
|
object_unparent(OBJECT(dev));
|
||||||
|
unattached_count--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool device_get_hotpluggable(Object *obj, Error **errp)
|
static bool device_get_hotpluggable(Object *obj, Error **errp)
|
||||||
|
|
38
hw/i386/pc.c
38
hw/i386/pc.c
|
@ -1818,23 +1818,6 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx < pcms->possible_cpus->len - 1 &&
|
|
||||||
pcms->possible_cpus->cpus[idx + 1].cpu != NULL) {
|
|
||||||
X86CPU *cpu;
|
|
||||||
|
|
||||||
for (idx = pcms->possible_cpus->len - 1;
|
|
||||||
pcms->possible_cpus->cpus[idx].cpu == NULL; idx--) {
|
|
||||||
;;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu = X86_CPU(pcms->possible_cpus->cpus[idx].cpu);
|
|
||||||
error_setg(&local_err, "CPU [socket-id: %u, core-id: %u,"
|
|
||||||
" thread-id: %u] should be removed first",
|
|
||||||
cpu->socket_id, cpu->core_id, cpu->thread_id);
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
|
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
|
||||||
hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
|
hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
|
||||||
|
|
||||||
|
@ -1875,6 +1858,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
|
CPUState *cs;
|
||||||
CPUArchId *cpu_slot;
|
CPUArchId *cpu_slot;
|
||||||
X86CPUTopoInfo topo;
|
X86CPUTopoInfo topo;
|
||||||
X86CPU *cpu = X86_CPU(dev);
|
X86CPU *cpu = X86_CPU(dev);
|
||||||
|
@ -1931,23 +1915,6 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx != 0 && pcms->possible_cpus->cpus[idx - 1].cpu == NULL) {
|
|
||||||
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
|
||||||
|
|
||||||
for (idx = 1; pcms->possible_cpus->cpus[idx].cpu != NULL; idx++) {
|
|
||||||
;;
|
|
||||||
}
|
|
||||||
|
|
||||||
x86_topo_ids_from_apicid(pcms->possible_cpus->cpus[idx].arch_id,
|
|
||||||
smp_cores, smp_threads, &topo);
|
|
||||||
|
|
||||||
if (!pcmc->legacy_cpu_hotplug) {
|
|
||||||
error_setg(errp, "CPU [socket: %u, core: %u, thread: %u] should be"
|
|
||||||
" added first", topo.pkg_id, topo.core_id, topo.smt_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if 'address' properties socket-id/core-id/thread-id are not set, set them
|
/* if 'address' properties socket-id/core-id/thread-id are not set, set them
|
||||||
* so that query_hotpluggable_cpus would show correct values
|
* so that query_hotpluggable_cpus would show correct values
|
||||||
*/
|
*/
|
||||||
|
@ -1975,6 +1942,9 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cpu->thread_id = topo.smt_id;
|
cpu->thread_id = topo.smt_id;
|
||||||
|
|
||||||
|
cs = CPU(cpu);
|
||||||
|
cs->cpu_index = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
|
|
|
@ -56,6 +56,18 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||||
target_ulong pc, target_ulong cs_base,
|
target_ulong pc, target_ulong cs_base,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
int cflags);
|
int cflags);
|
||||||
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
void cpu_list_lock(void);
|
||||||
|
void cpu_list_unlock(void);
|
||||||
|
#else
|
||||||
|
static inline void cpu_list_unlock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void cpu_list_lock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void cpu_exec_init(CPUState *cpu, Error **errp);
|
void cpu_exec_init(CPUState *cpu, Error **errp);
|
||||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
||||||
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
||||||
|
|
|
@ -261,7 +261,9 @@ struct PropertyInfo {
|
||||||
* @used: Set to true if property was used when initializing a device.
|
* @used: Set to true if property was used when initializing a device.
|
||||||
* @errp: Error destination, used like first argument of error_setg()
|
* @errp: Error destination, used like first argument of error_setg()
|
||||||
* in case property setting fails later. If @errp is NULL, we
|
* in case property setting fails later. If @errp is NULL, we
|
||||||
* print warnings instead of ignoring errors silently.
|
* print warnings instead of ignoring errors silently. For
|
||||||
|
* hotplugged devices, errp is always ignored and warnings are
|
||||||
|
* printed instead.
|
||||||
*/
|
*/
|
||||||
typedef struct GlobalProperty {
|
typedef struct GlobalProperty {
|
||||||
const char *driver;
|
const char *driver;
|
||||||
|
|
|
@ -883,4 +883,6 @@ extern const struct VMStateDescription vmstate_cpu_common;
|
||||||
.offset = 0, \
|
.offset = 0, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UNASSIGNED_CPU_INDEX -1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -419,8 +419,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||||
extern unsigned long last_brk;
|
extern unsigned long last_brk;
|
||||||
extern abi_ulong mmap_next_start;
|
extern abi_ulong mmap_next_start;
|
||||||
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
|
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
|
||||||
void cpu_list_lock(void);
|
|
||||||
void cpu_list_unlock(void);
|
|
||||||
void mmap_fork_start(void);
|
void mmap_fork_start(void);
|
||||||
void mmap_fork_end(int child);
|
void mmap_fork_end(int child);
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@ static void cpu_common_initfn(Object *obj)
|
||||||
CPUState *cpu = CPU(obj);
|
CPUState *cpu = CPU(obj);
|
||||||
CPUClass *cc = CPU_GET_CLASS(obj);
|
CPUClass *cc = CPU_GET_CLASS(obj);
|
||||||
|
|
||||||
cpu->cpu_index = -1;
|
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
||||||
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
|
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
|
||||||
qemu_mutex_init(&cpu->work_mutex);
|
qemu_mutex_init(&cpu->work_mutex);
|
||||||
QTAILQ_INIT(&cpu->breakpoints);
|
QTAILQ_INIT(&cpu->breakpoints);
|
||||||
|
|
1
vl.c
1
vl.c
|
@ -2922,6 +2922,7 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
g->property = qemu_opt_get(opts, "property");
|
g->property = qemu_opt_get(opts, "property");
|
||||||
g->value = qemu_opt_get(opts, "value");
|
g->value = qemu_opt_get(opts, "value");
|
||||||
g->user_provided = true;
|
g->user_provided = true;
|
||||||
|
g->errp = &error_fatal;
|
||||||
qdev_prop_register_global(g);
|
qdev_prop_register_global(g);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue