fix migration issues after hotplug a discontinuous cpuid
cover fix migration issues after hotplug a discontinuous cpuid
At present, after hotplug a discontinuous cpu id on source side, then done migration, hotplug again will fail on destination side. for example:
on source side:
1) boot with -smp 1,maxcpus=4
2) cpu-add id=2
3) live-migration
on destination side:
1) boot with -smp 2,maxcpus=4
1) cpu-add id=1
the root cause is the generated apicid is sequential from 0 to smp_cpus when initialize cpus at booting time on destination side, there apicid will be 0 and 1, but on source side the existed apicid after hotplug are 0 and 2. so if add cpu with id=1, this will show error with this cpu alreay exists.
this patches added -smp X,apics=0x option to specify apic map. follow above example:
on destination side:
1) boot with -smp 2,maxcpus=4,apics=0xA
this apics value is a hex number as existed apicid bitmap, 0xA is 1010B for apicid are 0 and 2.
this patches will be helpful for arbitrary CPU hot-remove as well.
Chen Fan (3):
target-i386: moving registers of vmstate from cpu_exec_init() to
x86_cpu_realizefn()
target-i386: add -smp X,apics=0x option
target-i386: add qmp command 'query-cpus' to display apic_id
cpus.c | 1 + exec.c | 5 ++++ hw/i386/pc.c | 9 +++++-- include/sysemu/sysemu.h | 4 ++++ qapi-schema.json | 4 +++- qemu-options.hx | 15 +++++++++--- target-i386/cpu.c | 9 +++++++ vl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 102 insertions(+), 7 deletions(-)
Signature · 1 line
1.8.1.4
RFC 1/3 target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of apic_id is behind the cpu initialization. so we move the registers of cpu vmstate from cpu_exec_init() to x86_cpu_realizefn() to let the set apicid as the parameter.
--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)
exec.c +5 -0
@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;
@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }
@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )
target-i386/cpu.c +9 -0
@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;
@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs); xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + } out:if (local_err !=NULL ) {error_propagate (errp, local_err);
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()
Quoted 56 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 10 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }
how about doing it in common CPUclass.realize()
you can use get_arch_id() for getting CPU id, it returns cpu_index by default and apic_id for target-i386.
Pls note that changing vmstate id should be done only for new machine types so not to break old qemu -> new qemu migration.
Quoted 3 lines
target-i386/cpu.c +0
-0out:if (local_err !=NULL ) {error_propagate (errp, local_err);
Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);
Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.
Thanks for your kind suggestion, does this mean we can directly move vmstate_register to cpu_common_realizefn()?
Quoted 2 lines
Pls note that changing vmstate id should be done only for new machine types so not to break old qemu -> new qemu migration.
Yes.
Thanks.
Chen
Quoted 6 lines
Quoted 4 lines
target-i386/cpu.c +0
-0out:if (local_err !=NULL ) {error_propagate (errp, local_err);
Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.
Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?
yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use cpu_index and the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.
Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.
But nobody took on implementing it yet.
CCing Eduardo as hi might be interested in this as well.
Quoted 16 lines
Quoted 3 lines
Pls note that changing vmstate id should be done only for new machine types so not to break old qemu -> new qemu migration.
Yes.
Thanks.
ChenQuoted 6 lines
Quoted 4 lines
target-i386/cpu.c +0
-0out:if (local_err !=NULL ) {error_propagate (errp, local_err);
Signature · 2 lines
Regards, Igor
[Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 93 lines · Igor Mammedov
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use
cpu_indexand the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
[1] See target-i386/topology.h for references
Signature · 1 line
Eduardo
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 94 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 93 lines · Igor Mammedov
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use
cpu_indexand the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.
Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.
Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
Quoted 2 lines
[1] See
target-i386/topology.hfor references
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 111 lines · Igor Mammedov
Quoted 94 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 93 lines · Igor Mammedov
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use
cpu_indexand the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 1 line
Quoted 8 lines
Quoted 3 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
Thanks,
Chen
Quoted 4 lines
Quoted 3 lines
[1] See
target-i386/topology.hfor references
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 116 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 115 lines · Igor Mammedov
Quoted 94 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 93 lines · Igor Mammedov
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use
cpu_indexand the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1
Quoted 11 lines
Thanks,
ChenQuoted 4 lines
Quoted 3 lines
[1] See
target-i386/topology.hfor references
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 123 lines · Igor Mammedov
Quoted 120 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 119 lines · Igor Mammedov
Quoted 94 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 93 lines · Igor Mammedov
Quoted 74 lines · On Wed, 15 Jan 2014 20:24:01 +0800 Chen Fan <[email protected]>…
Quoted 60 lines · Igor Mammedov
Quoted 57 lines · On Tue, 14 Jan 2014 17:27:20 +0800 Chen Fan <[email protected]>…
the intend of this patch is to register cpu vmstates with apic id instead of cpu index, due to the property setting of
apic_idis behind the cpu initialization. so we move the registers of cpu vmstate fromcpu_exec_init()tox86_cpu_realizefn()to let the set apicid as the parameter.Signed-off-by Chen Fan <[email protected]>--- exec.c | 5 +++++ target-i386/cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+)exec.c +5
-0@@ -438,7 +438,9 @@ CPUState *qemu_get_cpu(int index)void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); +#if !defined(TARGET_I386 )CPUClass *cc =CPU_GET_CLASS (cpu); +#endif CPUState *some_cpu;int cpu_index;@@ -460,6 +462,8 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif + +#if !defined(TARGET_I386 )if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) {vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); }@@ -472,6 +476,7 @@ void cpu_exec_init(CPUArchState *env)if (cc->vmsd !=NULL ) {vmstate_register (NULL , cpu_index, cc->vmsd, cpu); } +#endif /* !TARGET_I386 */ }#if defined(TARGET_HAS_ICE )target-i386/cpu.c +1
-0@@ -2552,6 +2552,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)static void x86_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); +CPUClass *cc =CPU_GET_CLASS (cs);X86CPU *cpu =X86_CPU (dev);X86CPUClass *xcc =X86_CPU_GET_CLASS (dev);CPUX86State *env = &cpu->env;@@ -2615,6 +2616,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)cpu_reset (cs);Quoted 12 lines
target-i386/cpu.c static void x86_cpu_realizefn(DeviceState *dev, Error **errp) · line 2626
Quoted 9 lines
target-i386/cpu.c +8
-0xcc->parent_realize (dev, &local_err); + +if (qdev_get_vmsd (DEVICE (cs)) ==NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, &vmstate_cpu_common, cs); + } + +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , env->cpuid_apic_id, cc->vmsd, cs); + }how about doing it in common
CPUclass.realize()
you can useget_arch_id()for getting CPU id, it returnscpu_indexby default andapic_idfor target-i386.Quoted 2 lines
Thanks for your kind suggestion, does this mean we can directly move
vmstate_registertocpu_common_realizefn()?yep, that is a gist of it.
There is more to the issue with discontinuous CPUs, a lot of code still use
cpu_indexand the way it's allocated is not compatible with discontinuous CPUs, so this issue should be fixed as well.Also you propose to use a raw apic id with CLI/user interface. I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
Quoted 9 lines
Quoted 2 lines
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1
Thanks, I hope I can take some time to make some patches to implement it.
Quoted 13 lines
Quoted 12 lines
Thanks,
ChenQuoted 4 lines
Quoted 3 lines
[1] See
target-i386/topology.hfor references
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.
The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Regards,
Andreas
Signature · 2 lines
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 70 lines · Andreas Färber
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
Quoted 3 lines
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Hi, Igor, Andreas,
In addition, I want to know what way user could use to specify an
arbitrary CPU if using /machine/node/N/socket/X/core/Y/thread/Z idea? -device qemu64,socket=X,core=Y,thread=Z? or add a new optional command line?
Thanks,
Chen
Quoted 4 lines
Regards,
Andreas
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 74 lines · On Thu, 13 Feb 2014 14:14:08 +0800 Chen Fan <[email protected]>…
Quoted 70 lines · Andreas Färber
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
Quoted 3 lines
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Quoted 6 lines
Hi, Igor, Andreas,
In addition, I want to know what way user could use to specify an
arbitrary CPU if using /machine/node/N/socket/X/core/Y/thread/Z idea? -device qemu64,socket=X,core=Y,thread=Z? or add a new optional command line?
Definitely not another CLU option.
I see a couple of options,
1. as you suggest with additional 'numa=N' so that QEMU could know where to attach a new CPU.
2. add 'parent' like option tied to link<cpu> property and specify full QOM path on CLI: -device cpufoo,parent=/machine/node[N]/socket[X]/...
Quoted 9 lines
Thanks,
ChenQuoted 4 lines
Regards,
Andreas
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 83 lines · Igor Mammedov
Quoted 74 lines · On Thu, 13 Feb 2014 14:14:08 +0800 Chen Fan <[email protected]>…
Quoted 70 lines · Andreas Färber
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
Quoted 3 lines
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Quoted 6 lines
Hi, Igor, Andreas,
In addition, I want to know what way user could use to specify an
arbitrary CPU if using /machine/node/N/socket/X/core/Y/thread/Z idea? -device qemu64,socket=X,core=Y,thread=Z? or add a new optional command line?
Quoted 7 lines
Definitely not another CLU option.
I see a couple of options,
1. as you suggest with additional 'numa=N' so that QEMU could know where to attach a new CPU.
2. add 'parent' like option tied to link<cpu> property and specify full QOM path on CLI: -device cpufoo,parent=/machine/node[N]/socket[X]/...
Hi, Igor,
Currently, we know, after adding an arbitrary CPU then do migration,
on target, there will be not aware that which CPU have been added.
in order to notify target of the cpu topo, can we specify full QOM
path that you mentioned 2th point on target? if we can simply make smp n + 1 work as well at target to be better, but target how to know the cpu topo on source side?
Quoted 12 lines
Quoted 10 lines
Thanks,
ChenQuoted 4 lines
Regards,
Andreas
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
Quoted 91 lines · On Mon, 17 Feb 2014 18:24:09 +0800 Chen Fan <[email protected]>…
Quoted 83 lines · Igor Mammedov
Quoted 74 lines · On Thu, 13 Feb 2014 14:14:08 +0800 Chen Fan <[email protected]>…
Quoted 70 lines · Andreas Färber
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
Quoted 3 lines
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Quoted 6 lines
Hi, Igor, Andreas,
In addition, I want to know what way user could use to specify an
arbitrary CPU if using /machine/node/N/socket/X/core/Y/thread/Z idea? -device qemu64,socket=X,core=Y,thread=Z? or add a new optional command line?Quoted 7 lines
Definitely not another CLU option.
I see a couple of options,
1. as you suggest with additional 'numa=N' so that QEMU could know where to attach a new CPU.
2. add 'parent' like option tied to link<cpu> property and specify full QOM path on CLI: -device cpufoo,parent=/machine/node[N]/socket[X]/...
Quoted 7 lines
Hi, Igor,
Currently, we know, after adding an arbitrary CPU then do migration,
on target, there will be not aware that which CPU have been added.
in order to notify target of the cpu topo, can we specify full QOM
path that you mentioned 2th point on target? if we can simply make smp n + 1 work as well at target to be better, but target how to know the cpu topo on source side?
Regarding topology, I suppose -smp & -numa options should match on both, that should give the same topology on target as on source.
As for specifying present CPUs on target, there is work in progress to make CPUs work with -device/device_add (x86 cpu properties, x86 CPU subclasses)
Quoted 16 lines
Quoted 14 lines
Quoted 12 lines
Thanks,
ChenQuoted 4 lines
Regards,
Andreas
Signature · 2 lines
Regards, Igor
cover prebuild cpu QOM tree /machine/node/socket/core/thread/..
Hi,
at present, after hotplug a discontinuous cpu id on source, then done migration,
on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.
I suppose we could use apic_id as instance_id which was used at registering vmstate when create cpu. on target, we prebuild the specified cpu using QOM comand line:
/machine/node/socket/core/thread, then migration, we could keep the same cpu infrastructure on both side.
at first, I introduce a empty QOM tree /machine/node/socket/core/thread/, then when create cpu, link each created cpu into the tree. which idea was suggested by Igor. thanks.
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
I don't know wether this way is right or not. pls tell me. :)
Thanks,
Chen
Chen Fan (2):
qom: introduce cpu QOM hierarchy tree
/machine/node/socket/core/thread/cpu.
cpu: link each new cpu to QOM tree
/machine/node/socket/core/thread/cpu respectively.
hw/i386/pc.c | 40 ++++++++++++-- include/qom/node.h | 66 +++++++++++++++++++++++ qom/Makefile.objs | 2 +- qom/node.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 include/qom/node.h create mode 100644 qom/node.c
Signature · 1 line
1.8.1.4
RFC PATCH 1/2 qom: introduce cpu QOM hierarchy tree /machine/node/socket/core/thread/cpu.
--- include/qom/node.h | 66 +++++++++++++++++++++++ qom/Makefile.objs | 2 +- qom/node.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 include/qom/node.h create mode 100644 qom/node.c
include/qom/node.h new file +66 -0
@@ -0,0 +1,66 @@ +/* +* QEMU System Emulator +* +* Copyright (c) 2013 Fujitsu Ltd. +* Author: Chen Fan <[email protected]> +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "hw/qdev-core.h" + +#define TYPE_NODE "node" +#define TYPE_SOCKET "socket" +#define TYPE_CORE "core" +#define TYPE_THREAD "thread" + +#define NODE (obj) OBJECT_CHECK(NodeState, (obj), TYPE_NODE) + +#define SOCKET (obj) OBJECT_CHECK(SocketState, (obj), TYPE_SOCKET) + +#define CORE (obj) OBJECT_CHECK(CoreState, (obj), TYPE_CORE) + +#define THREAD (obj) OBJECT_CHECK(ThreadState, (obj), TYPE_THREAD) + +Object *object_get_thread_from_index (int64_t cpu_index); + +typedef struct ThreadState { +/*< private >*/ +Object parent_obj; +/*< public >*/ +CPUState **cpu; +}ThreadState ; + +typedef struct CoreState { +/*< private >*/ +Object parent_obj; +/*< public >*/ +}CoreState ; + +typedef struct SocketState { +/*< private >*/ +Object parent_obj; +/*< public >*/ +}SocketState ; + +typedef struct NodeState { +/*< private >*/ +Object parent_obj; +/*< public >*/ +}NodeState ;
qom/Makefile.objs +1 -1
@@ -1,3 +1,3 @@ common-obj-y = object.o container.o qom-qobject.o -common-obj-y += cpu.o +common-obj-y += cpu.o node.o common-obj-y += object_interfaces.o
qom/node.c new file +156 -0
156 lines not on this page · raw message
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [PATCH 1/2][RFC] qom: introduce cpu QOM hierarchy tree /machine/node/socket/core/thread/cpu.
Quoted 15 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- include/qom/node.h | 66 +++++++++++++++++++++++ qom/Makefile.objs | 2 +- qom/node.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 include/qom/node.h create mode 100644 qom/node.cinclude/qom/node.h new file +0
-0
include/qom/node.h line 4
Quoted 4 lines
include/qom/node.h new file +4
-0@@ -0,0 +1,66 @@ +/* +* QEMU System Emulator +* +* Copyright (c) 2013 Fujitsu Ltd.
It's 2014 now.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 1/2][RFC] qom: introduce cpu QOM hierarchy tree /machine/node/socket/core/thread/cpu.
Quoted 10 lines · Eric Blake
Quoted 9 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- include/qom/node.h | 66 +++++++++++++++++++++++ qom/Makefile.objs | 2 +- qom/node.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 include/qom/node.h create mode 100644 qom/node.c
Quoted 13 lines
include/qom/node.h line 4
Quoted 10 lines
include/qom/node.h new file +4
-0@@ -0,0 +1,66 @@ +/* +* QEMU System Emulator +* +* Copyright (c) 2013 Fujitsu Ltd. It's 2014 now.
oh, thanks.
Re: [Qemu-devel] [PATCH 1/2][RFC] qom: introduce cpu QOM hierarchy tree /machine/node/socket/core/thread/cpu.
In reply to Chen FanOn Tue, Feb 25, 2014 at 05:07:31PM +0800, Chen Fan wrote:
[...]
Quoted 1 line
+Object *object_get_thread_from_index(int64_t
cpu_index)
Probably the code that is going to call this function already knows what will be the node/socket/core/thread IDs for the CPU. And if it doesn't, we need to make the code node-/socket-/core-/thread-aware, instead of making the code dependent on CPU-index-based logic.
I believe we should try to make CPU indexes unnecessary, except on places where we are already forced to deal with them for compatibility reasons.
Quoted 5 lines
qom/node.c new file +5
-0+{ +gchar *path; +Object *thread; +int nodes, cpus_pre_nodes, smp_sockets; +unsigned node_id, socket_id, core_id, thread_id;
qom/node.c line 49
Quoted 10 lines
qom/node.c new file +10
-0+unsigned core_index, socket_index; + + nodes = nb_numa_nodes ? nb_numa_nodes :1 ; + cpus_pre_nodes = max_cpus / nodes; + smp_sockets = cpus_pre_nodes / (smp_cores * smp_threads); + + core_index = cpu_index / smp_threads; + thread_id = cpu_index % smp_threads; + socket_index = core_index / smp_cores; + core_id = core_index % smp_cores;
This is duplicating logic that already exists at topo_ids_from_idx().
Quoted 1 line
+
node_id=socket_index/smp_sockets;
This is not how CPUs are distributed along NUMA nodes. They are distributed depending on the -numa options. Grep for node_cpumask in the code.
Quoted 10 lines
qom/node.c new file +10
-0+ socket_id = socket_index % smp_sockets; + + path =g_strdup_printf ("/machine/node[%d]/socket[%d]/core[%d]/thread[%d]" , + node_id, socket_id, core_id, thread_id); + thread =object_resolve_path (path,NULL ); +g_free (path); + +return thread; +} +
Signature · 1 line
Eduardo
Re: [Qemu-devel] [PATCH 1/2][RFC] qom: introduce cpu QOM hierarchy tree /machine/node/socket/core/thread/cpu.
Quoted 4 lines · Eduardo Habkost
On Tue, Feb 25, 2014 at 05:07:31PM +0800, Chen Fan wrote:
[...]Quoted 1 line
+Object *object_get_thread_from_index(int64_t
cpu_index)
Quoted 9 lines
Probably the code that is going to call this function already knows what will be the node/socket/core/thread IDs for the CPU. And if it doesn't, we need to make the code node-/socket-/core-/thread-aware, instead of making the code dependent on CPU-index-based logic.
I believe we should try to make CPU indexes unnecessary, except on places where we are already forced to deal with them for compatibility reasons.
firstly, thanks for you important feedback.
I suppose that if we try to make CPU indexes unnecessary we should add "-device cpufoo" support, and we should also need to add a "path" in command line to let function pc_new_cpu() know the IDs which can be calculated from the "path". then which one should the commend line be "-device cpufoo,sockets=X,cores=Y,threads=Z" or "-device cpufoo,paths=/ node-/socket-/core-/thread-/", or any other better?
Quoted 36 lines
Quoted 5 lines
qom/node.c new file +5
-0+{ +gchar *path; +Object *thread; +int nodes, cpus_pre_nodes, smp_sockets; +unsigned node_id, socket_id, core_id, thread_id;qom/node.c line 49
Quoted 10 lines
qom/node.c new file +10
-0+unsigned core_index, socket_index; + + nodes = nb_numa_nodes ? nb_numa_nodes :1 ; + cpus_pre_nodes = max_cpus / nodes; + smp_sockets = cpus_pre_nodes / (smp_cores * smp_threads); + + core_index = cpu_index / smp_threads; + thread_id = cpu_index % smp_threads; + socket_index = core_index / smp_cores; + core_id = core_index % smp_cores;This is duplicating logic that already exists at
topo_ids_from_idx().Quoted 1 line
+
node_id=socket_index/smp_sockets;This is not how CPUs are distributed along NUMA nodes. They are distributed depending on the -numa options. Grep for
node_cpumaskin the code.Quoted 10 lines
qom/node.c new file +10
-0+ socket_id = socket_index % smp_sockets; + + path =g_strdup_printf ("/machine/node[%d]/socket[%d]/core[%d]/thread[%d]" , + node_id, socket_id, core_id, thread_id); + thread =object_resolve_path (path,NULL ); +g_free (path); + +return thread; +} +
v2 cover prebuild cpu QOM tree /machine/node/socket/core/thread/..
at present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.
I suppose we could use apic_id as instance_id which was used at registering vmstate when create cpu. on target, we prebuild the specified cpu using QOM comand line:
/machine/node/socket/core/thread, then migration, we could keep the same cpu infrastructure on both side.
at first, I introduce a empty QOM tree /machine/node/socket/core/thread/, then when create cpu, link each created cpu into the tree. which idea was suggested by Igor. thanks.
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
I don't know wether this way is right or not. pls tell me. :)
Chen Fan (2):
i386: introduce "struct X86TopoInfo" for saving cpu topology
information
i386: introduce cpu QOM hierarchy tree
hw/i386/pc.c | 19 ++++-- target-i386/Makefile.objs | 2 +- target-i386/cpu-qom.h | 1 + target-i386/cpu-topology.c | 163 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++++++ target-i386/cpu.c | 45 +++++++++++++ target-i386/cpu.h | 6 ++ target-i386/topology.h | 7 ++ 8 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
Signature · 1 line
1.8.1.4
RFC v2 1/2 i386: introduce "struct X86TopoInfo" for saving cpu topology information
--- hw/i386/pc.c | 13 +++++++++---- target-i386/cpu.c | 16 ++++++++++++++++ target-i386/cpu.h | 4 ++++ target-i386/topology.h | 7 +++++++ 4 files changed, 36 insertions(+), 4 deletions(-)
hw/i386/pc.c +9 -4
@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,X86TopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +int64_t apic_id =x86_cpu_apic_id_from_index (topo->cpu_index); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {
@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id); +X86TopoInfo *topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);
@@ -976,7 +978,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); + topo =x86_cpu_topo_from_index (id); +pc_new_cpu (current_cpu_model, topo, icc_bridge, errp); +g_free (topo); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
@@ -996,8 +1000,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +X86TopoInfo *topo =x86_cpu_topo_from_index (i); + cpu =pc_new_cpu (cpu_model, topo, icc_bridge, &error); +g_free (topo);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
target-i386/cpu.c +16 -0
@@ -2609,6 +2609,22 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } +X86TopoInfo *x86_cpu_topo_from_index (unsigned int cpu_index) +{ +unsigned pkg_id, core_id, smt_id; +X86TopoInfo *x86TopoInfo; + + x86TopoInfo =g_malloc0 (sizeof (X86TopoInfo)); +x86_topo_ids_from_idx (smp_cores, smp_threads, cpu_index, + &pkg_id, &core_id, &smt_id); + x86TopoInfo->pkg_id = pkg_id; + x86TopoInfo->core_id = core_id; + x86TopoInfo->smt_id = smt_id; + x86TopoInfo->cpu_index = cpu_index; + +return x86TopoInfo; +} +static void x86_cpu_initfn (Object *obj) {CPUState *cs =CPU (obj);
target-i386/cpu.h +4 -0
@@ -1283,6 +1283,10 @@ const char *get_register_name_32(unsigned int reg);uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index);void enable_compat_apic_id_mode (void ); +#include "topology.h" + +X86TopoInfo *x86_cpu_topo_from_index (unsigned int cpu_index); +#define APIC_DEFAULT_ADDRESS 0xfee00000#define APIC_SPACE_SIZE 0x100000
target-i386/topology.h +7 -0
@@ -131,4 +131,11 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id); } +typedef struct X86TopoInfo { +unsigned smt_id; +unsigned core_id; +unsigned pkg_id; +unsigned cpu_index; +}X86TopoInfo ; +#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC v2 1/2] i386: introduce "struct X86TopoInfo" for saving cpu topology information
Quoted 13 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- hw/i386/pc.c | 13 +++++++++---- target-i386/cpu.c | 16 ++++++++++++++++ target-i386/cpu.h | 4 ++++ target-i386/topology.h | 7 +++++++ 4 files changed, 36 insertions(+), 4 deletions(-)hw/i386/pc.c +0
-0
hw/i386/pc.c void pc_acpi_smi_interrupt(void *opaque, int irq, int level) · line 935
Quoted 10 lines
hw/i386/pc.c +2
-1@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,X86TopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +int64_t apic_id =x86_cpu_apic_id_from_index (topo->cpu_index);
You can rewrite apicid_from_topo_ids() to be:
void x86_apicid_from_topo(X86TopoInfo *topo)
then x86_cpu_apic_id_from_index() won't need to exist anymore.
Quoted 12 lines
hw/i386/pc.c +1
-0cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id); +X86TopoInfo *topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);
hw/i386/pc.c void pc_hot_add_cpu(const int64_t id, Error **errp) · line 983
Quoted 7 lines
hw/i386/pc.c +3
-1@@ -976,7 +978,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); + topo =x86_cpu_topo_from_index (id); +pc_new_cpu (current_cpu_model, topo, icc_bridge, errp); +g_free (topo);
See comment below about simplifying x86_cpu_topo_from_index() to not require malloc/free. The code would be much simpler if it looked like this:
X86TopoInfo topo;
x86_cpu_topo_from_index(cpu_index, &topo)
pc_new_cpu(current_cpu_model, &topo, icc_bridge, errp)Quoted 20 lines
hw/i386/pc.c +3
-2}void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)@@ -996,8 +1000,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +X86TopoInfo *topo =x86_cpu_topo_from_index (i); + cpu =pc_new_cpu (cpu_model, topo, icc_bridge, &error); +g_free (topo);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);target-i386/cpu.c +0
-0
target-i386/cpu.c uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) · line 2612
Quoted 4 lines
target-i386/cpu.c +1
-0@@ -2609,6 +2609,22 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } +X86TopoInfo *x86_cpu_topo_from_index (unsigned int cpu_index)
What about simply making it:
void x86_cpu_topo_from_index(unsigned int cpu_index, X86TopoInfo *topo)
so code can use a stack variable for X86TopoInfo. Much simpler than having to manually allocate/free X86TopoInfo.
What about rewriting x86_topo_ids_from_idx() to get X86TopoInfo* as argument, instead of creating this new function? Both functions have exactly the same purpose.
Quoted 14 lines
target-i386/cpu.c +14
-0+{ +unsigned pkg_id, core_id, smt_id; +X86TopoInfo *x86TopoInfo; + + x86TopoInfo =g_malloc0 (sizeof (X86TopoInfo)); +x86_topo_ids_from_idx (smp_cores, smp_threads, cpu_index, + &pkg_id, &core_id, &smt_id); + x86TopoInfo->pkg_id = pkg_id; + x86TopoInfo->core_id = core_id; + x86TopoInfo->smt_id = smt_id; + x86TopoInfo->cpu_index = cpu_index; + +return x86TopoInfo; +}
[...]
Signature · 1 line
Eduardo
Re: [Qemu-devel] [RFC v2 1/2] i386: introduce "struct X86TopoInfo" for saving cpu topology information
Quoted 55 lines · Eduardo Habkost
Quoted 13 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- hw/i386/pc.c | 13 +++++++++---- target-i386/cpu.c | 16 ++++++++++++++++ target-i386/cpu.h | 4 ++++ target-i386/topology.h | 7 +++++++ 4 files changed, 36 insertions(+), 4 deletions(-)hw/i386/pc.c +0
-0hw/i386/pc.c void pc_acpi_smi_interrupt(void *opaque, int irq, int level) · line 935
Quoted 10 lines
hw/i386/pc.c +2
-1@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,X86TopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +int64_t apic_id =x86_cpu_apic_id_from_index (topo->cpu_index);You can rewrite
apicid_from_topo_ids()to be:void
x86_apicid_from_topo(X86TopoInfo *topo)then
x86_cpu_apic_id_from_index()won't need to exist anymore.Quoted 12 lines
hw/i386/pc.c +1
-0cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id); +X86TopoInfo *topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);hw/i386/pc.c void pc_hot_add_cpu(const int64_t id, Error **errp) · line 983
Quoted 7 lines
hw/i386/pc.c +3
-1@@ -976,7 +978,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); + topo =x86_cpu_topo_from_index (id); +pc_new_cpu (current_cpu_model, topo, icc_bridge, errp); +g_free (topo);See comment below about simplifying
x86_cpu_topo_from_index()to not require malloc/free. The code would be much simpler if it looked like this:
Quoted 4 lines
X86TopoInfo topo;
x86_cpu_topo_from_index(cpu_index, &topo)
pc_new_cpu(current_cpu_model, &topo, icc_bridge, errp)Ok, that will be better. thanks.
Quoted 29 lines
Quoted 21 lines
hw/i386/pc.c +3
-2}void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)@@ -996,8 +1000,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +X86TopoInfo *topo =x86_cpu_topo_from_index (i); + cpu =pc_new_cpu (cpu_model, topo, icc_bridge, &error); +g_free (topo);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);target-i386/cpu.c +0
-0target-i386/cpu.c uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) · line 2612
Quoted 4 lines
target-i386/cpu.c +1
-0@@ -2609,6 +2609,22 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } +X86TopoInfo *x86_cpu_topo_from_index (unsigned int cpu_index)What about simply making it:
Quoted 8 lines
void
x86_cpu_topo_from_index(unsigned int cpu_index, X86TopoInfo *topo)so code can use a stack variable for X86TopoInfo. Much simpler than having to manually allocate/free X86TopoInfo.
What about rewriting
x86_topo_ids_from_idx()to get X86TopoInfo* as argument, instead of creating this new function? Both functions have exactly the same purpose.
I will have a try, thanks for you advice.
Thanks,
Chen
Quoted 16 lines
Quoted 15 lines
target-i386/cpu.c +14
-0+{ +unsigned pkg_id, core_id, smt_id; +X86TopoInfo *x86TopoInfo; + + x86TopoInfo =g_malloc0 (sizeof (X86TopoInfo)); +x86_topo_ids_from_idx (smp_cores, smp_threads, cpu_index, + &pkg_id, &core_id, &smt_id); + x86TopoInfo->pkg_id = pkg_id; + x86TopoInfo->core_id = core_id; + x86TopoInfo->smt_id = smt_id; + x86TopoInfo->cpu_index = cpu_index; + +return x86TopoInfo; +}[...]
v3 cover prebuild cpu QOM tree /machine/node/socket/core ->link-cpu
From: "chen.fan.fnst" <[email protected]>
at present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.
I suppose we could use apic_id as instance_id which was used at registering vmstate when create cpu. on target, we prebuild the specified cpu topology using comand line:
-device /machine/node[]/socket[]/core[]/cpu[], then migration, we could keep the same
cpu infrastructure on both side.
V3: get rid of thread object and tie link<cpu> to <core> directly. and prebuild full
core[] and thread[] as init socket[] according to smp_cores and smp_threads.
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
I don't know wether this way is right or not. pls tell me. :)
chen.fan.fnst (3):
cpu: introduce CpuTopoInfo structure for argument simplification
i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
i386: introduce cpu QOM hierarchy tree
hw/i386/pc.c | 15 +++- target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 15 +++- target-i386/cpu.h | 6 ++ target-i386/topology.h | 33 ++++---- 7 files changed, 317 insertions(+), 23 deletions(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
Signature · 1 line
1.8.1.4
RFC v3 1/3 cpu: introduce CpuTopoInfo structure for argument simplification
From: "chen.fan.fnst" <[email protected]>
--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct CpuTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}CpuTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +CpuTopoInfo *topo) { -return (pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | - (core_id <<apicid_core_offset (nr_cores, nr_threads)) | - smt_id; +return (topo->pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | + (topo->core_id <<apicid_core_offset (nr_cores, nr_threads)) | + topo->smt_id; }/* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,static inline void x86_topo_ids_from_idx (unsigned nr_cores,unsigned nr_threads,unsigned cpu_index, -unsigned *pkg_id, -unsigned *core_id, -unsigned *smt_id) +CpuTopoInfo *topo) {unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; }/* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); -return apicid_from_topo_ids (nr_cores, nr_threads, pkg_id, core_id, smt_id); +CpuTopoInfo topo; +x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); +return apicid_from_topo_ids (nr_cores, nr_threads, &topo); }#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC v3 1/3] cpu: introduce CpuTopoInfo structure for argument simplification
Quoted 12 lines · chen.fan.fnst
From: "chen.fan.fnst" <[email protected]>
Signed-off-by Chen Fan <[email protected]>--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)target-i386/topology.h +0
-0
target-i386/topology.h line 54
Quoted 8 lines
target-i386/topology.h +5
-0@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct CpuTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}CpuTopoInfo ;
I suggest naming it "CPUTopoInfo". Maybe "X86CPUTopoInfo", to indicate it is x86-specific.
The rest of the patch looks good.
Signature · 1 line
Eduardo
RFC v3 2/3 i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
In reply to chen.fan.fnstFrom: "chen.fan.fnst" <[email protected]>
--- hw/i386/pc.c | 12 ++++++++---- target-i386/cpu.c | 2 -- target-i386/cpu.h | 3 +++ 3 files changed, 11 insertions(+), 6 deletions(-)
hw/i386/pc.c +8 -4
@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,CpuTopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +uint32_t apic_id =apicid_from_topo_ids (smp_cores, smp_threads, topo); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {
@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id); +CpuTopoInfo topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);
@@ -976,7 +978,8 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +x86_topo_ids_from_idx (smp_cores, smp_threads, id, &topo); +pc_new_cpu (current_cpu_model, &topo, icc_bridge, errp); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
@@ -996,8 +999,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +CpuTopoInfo topo; +x86_topo_ids_from_idx (smp_cores, smp_threads, i, &topo); + cpu =pc_new_cpu (cpu_model, &topo, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
target-i386/cpu.c +0 -2
@@ -23,8 +23,6 @@#include "cpu.h" #include "sysemu/kvm.h" -#include "sysemu/cpus.h" -#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h"
target-i386/cpu.h +3 -0
@@ -22,6 +22,9 @@#include "config.h" #include "qemu-common.h" +#include "sysemu/cpus.h" +#include "topology.h" +#ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64#else
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC v3 2/3] i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
Quoted 28 lines · chen.fan.fnst
From: "chen.fan.fnst" <[email protected]>
Signed-off-by Chen Fan <[email protected]>--- hw/i386/pc.c | 12 ++++++++---- target-i386/cpu.c | 2 -- target-i386/cpu.h | 3 +++ 3 files changed, 11 insertions(+), 6 deletions(-)hw/i386/pc.c +2
-1@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,CpuTopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +uint32_t apic_id =apicid_from_topo_ids (smp_cores, smp_threads, topo); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {
hw/i386/pc.c void pc_hot_add_cpu(const int64_t id, Error **errp) · line 959
Quoted 3 lines
hw/i386/pc.c +0
-0@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id);
With this patch, pc_new_cpu() is CPUTopoInfo-based, but cpu_exists() is apic_id-based. This requires apic_id to be calculated here, but pc_new_cpu() doesn't require it anymore.
We could make this more consistent, and avoid calculating the APIC ID in two different places. We are eveng using two different methods: here we use x86_cpu_apic_id_from_index() and pc_new_cpu() is using apicid_from_topo_ids().
Maybe we could simply move the cpu_exists() check inside pc_new_cpu()?
Quoted 15 lines
hw/i386/pc.c +3
-1+CpuTopoInfo topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);@@ -976,7 +978,8 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +x86_topo_ids_from_idx (smp_cores, smp_threads, id, &topo); +pc_new_cpu (current_cpu_model, &topo, icc_bridge, errp); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
hw/i386/pc.c void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) · line 1000
Quoted 5 lines
hw/i386/pc.c +0
-2@@ -996,8 +999,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error);
x86_cpu_apic_id_from_index() has compat code to keep compatibility on older machine-types, and you are removing the compat behavior.
To keep the compat code isolated on pc_cpus_init() and keep pc_new_cpu() interface saner, we could do something like this, on pc_cpus_init() only:
CPUTopoInfo topo;
x86_topo_ids_from_idx(cpu_index, &topo);
if (apic_id_compat) {
correct_apic_id = apicid_from_topo_ids(&topo);
apic_id = cpu_index;
if (apic_id != correct_apic_id) {
error_report("APIC IDs set in compatibility mode, "
"CPU topology won't match the configuration");
}
// get_topo_from_apic_id() needs to be written:
get_topo_from_apic_id(apic_id, &topo);
// just in case:
assert(apicid_from_topo_ids(&topo) == apic_id);
}And on pc_hot_add_cpu():
if (apic_id_compat) {
error_setg(errp, "CPU hotplug is not supported on this machine");
return;
}Quoted 36 lines
hw/i386/pc.c +3
-0+CpuTopoInfo topo; +x86_topo_ids_from_idx (smp_cores, smp_threads, i, &topo); + cpu =pc_new_cpu (cpu_model, &topo, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);target-i386/cpu.c +0
-2@@ -23,8 +23,6 @@#include "cpu.h" #include "sysemu/kvm.h" -#include "sysemu/cpus.h" -#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h" target-i386/cpu.h +3
-0@@ -22,6 +22,9 @@#include "config.h" #include "qemu-common.h" +#include "sysemu/cpus.h" +#include "topology.h" +#ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64#else Signature · 1 line
1.8.1.4
Signature · 1 line
Eduardo
Re: [Qemu-devel] [RFC v3 2/3] i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
Quoted 73 lines · Eduardo Habkost
Quoted 28 lines · chen.fan.fnst
From: "chen.fan.fnst" <[email protected]>
Signed-off-by Chen Fan <[email protected]>--- hw/i386/pc.c | 12 ++++++++---- target-i386/cpu.c | 2 -- target-i386/cpu.h | 3 +++ 3 files changed, 11 insertions(+), 6 deletions(-)hw/i386/pc.c +2
-1@@ -927,11 +927,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,CpuTopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +uint32_t apic_id =apicid_from_topo_ids (smp_cores, smp_threads, topo); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {hw/i386/pc.c void pc_hot_add_cpu(const int64_t id, Error **errp) · line 959
Quoted 3 lines
hw/i386/pc.c +0
-0@@ -956,6 +957,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) {DeviceState *icc_bridge;int64_t apic_id =x86_cpu_apic_id_from_index (id);With this patch,
pc_new_cpu()is CPUTopoInfo-based, butcpu_exists()is apic_id-based. This requiresapic_idto be calculated here, butpc_new_cpu()doesn't require it anymore.We could make this more consistent, and avoid calculating the APIC ID in two different places. We are eveng using two different methods: here we use
x86_cpu_apic_id_from_index()andpc_new_cpu()is usingapicid_from_topo_ids().Maybe we could simply move the
cpu_exists()check insidepc_new_cpu()?Quoted 15 lines
hw/i386/pc.c +3
-1+CpuTopoInfo topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);@@ -976,7 +978,8 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +x86_topo_ids_from_idx (smp_cores, smp_threads, id, &topo); +pc_new_cpu (current_cpu_model, &topo, icc_bridge, errp); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)hw/i386/pc.c void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) · line 1000
Quoted 5 lines
hw/i386/pc.c +0
-2@@ -996,8 +999,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error);
x86_cpu_apic_id_from_index()has compat code to keep compatibility on older machine-types, and you are removing the compat behavior.To keep the compat code isolated on
pc_cpus_init()and keeppc_new_cpu()interface saner, we could do something like this, onpc_cpus_init()only:
Quoted 14 lines
CPUTopoInfo topo;
x86_topo_ids_from_idx(cpu_index, &topo);
if (apic_id_compat) {
correct_apic_id = apicid_from_topo_ids(&topo);
apic_id = cpu_index;
if (apic_id != correct_apic_id) {
error_report("APIC IDs set in compatibility mode, "
"CPU topology won't match the configuration");
}
// get_topo_from_apic_id() needs to be written:
get_topo_from_apic_id(apic_id, &topo);
// just in case:
assert(apicid_from_topo_ids(&topo) == apic_id);
}I think we can write new x86_cpu_topo_ids_from_index() to do this
compat work. I think I can make it soon.
Quoted 7 lines
And on
pc_hot_add_cpu():if (apic_id_compat) { error_setg(errp, "CPU hotplug is not supported on this machine"); return; }
cpu hotplug supported since pc 1.5, and apic_id_compat is below pc 1.3, so I think this must be unnecessary.
Thanks,
Chen
Quoted 40 lines
Quoted 39 lines
hw/i386/pc.c +3
-0+CpuTopoInfo topo; +x86_topo_ids_from_idx (smp_cores, smp_threads, i, &topo); + cpu =pc_new_cpu (cpu_model, &topo, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);target-i386/cpu.c +0
-2@@ -23,8 +23,6 @@#include "cpu.h" #include "sysemu/kvm.h" -#include "sysemu/cpus.h" -#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h" target-i386/cpu.h +3
-0@@ -22,6 +22,9 @@#include "config.h" #include "qemu-common.h" +#include "sysemu/cpus.h" +#include "topology.h" +#ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64#else Signature · 1 line
1.8.1.4
v4 cover prebuild cpu QOM tree /machine/node/socket/core ->link-cpu
In reply to Eduardo Habkostat present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.
I suppose we could use apic_id as instance_id which was used at registering vmstate when create cpu. on target, we prebuild the specified cpu topology using comand line:
-device /machine/node[]/socket[]/core[]/cpu[], then migration, we could keep the same
cpu infrastructure on both side.
V4: rename CpuTopoInfo to X86CPUTopoInfo. and move cpu_exsit() to pc_new_cpu().
V3: get rid of thread object and tie link<cpu> to <core> directly. and prebuild full
core[] and thread[] as init socket[] according to smp_cores and smp_threads.
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
I don't know wether this way is right or not. pls tell me. :)
Chen Fan (3):
i386: introduce cpu QOM hierarchy tree
cpu: introduce X86CPUTopoInfo structure for argument simplification
i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
hw/i386/pc.c | 28 ++++--- target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 41 ++++++++-- target-i386/cpu.h | 8 ++ target-i386/topology.h | 51 ++++++++---- 7 files changed, 367 insertions(+), 33 deletions(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
Signature · 1 line
1.8.1.4
RFC v4 1/3 cpu: introduce CpuTopoInfo structure for argument simplification
--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct X86CPUTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}X86CPUTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +X86CPUTopoInfo *topo) { -return (pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | - (core_id <<apicid_core_offset (nr_cores, nr_threads)) | - smt_id; +return (topo->pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | + (topo->core_id <<apicid_core_offset (nr_cores, nr_threads)) | + topo->smt_id; }/* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,static inline void x86_topo_ids_from_idx (unsigned nr_cores,unsigned nr_threads,unsigned cpu_index, -unsigned *pkg_id, -unsigned *core_id, -unsigned *smt_id) +X86CPUTopoInfo *topo) {unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; }/* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); -return apicid_from_topo_ids (nr_cores, nr_threads, pkg_id, core_id, smt_id); +X86CPUTopoInfo topo; +x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); +return apicid_from_topo_ids (nr_cores, nr_threads, &topo); }#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC v4 1/3] cpu: introduce CpuTopoInfo structure for argument simplification
Quoted 23 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)target-i386/topology.h +6
-0@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct X86CPUTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}X86CPUTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)
target-i386/topology.h static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads) · line 101
Quoted 7 lines
target-i386/topology.h +1
-3@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +X86CPUTopoInfo *topo)
topo could be const X86CPUTopoInfo*, but not a big deal.
Signature · 1 line
Eduardo
cover prebuild cpu QOM tree /machine/node/socket/core ->link-cpu
at present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.
I suppose we could use apic_id as instance_id which was used at registering vmstate when create cpu. on target, we prebuild the specified cpu topology using comand line:
-device /machine/node[]/socket[]/core[]/cpu[], then migration, we could keep the same
cpu infrastructure on both side.
RFC:
V4: rename CpuTopoInfo to X86CPUTopoInfo. and move cpu_exsit() to pc_new_cpu().
V3: get rid of thread object and tie link<cpu> to <core> directly. and prebuild full
core[] and thread[] as init socket[] according to smp_cores and smp_threads.
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
I don't know wether this way is right or not. pls tell me. :)
Chen Fan (4):
cpu: introduce CpuTopoInfo structure for argument simplification
i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu() topo unit-test: update Unit tests to test-x86-cpuid.c
i386: introduce cpu QOM hierarchy tree
hw/i386/pc.c | 25 +++--- target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 55 +++++++++---- target-i386/cpu.h | 8 ++ target-i386/topology.h | 53 +++++++----- tests/test-x86-cpuid.c | 165 +++++++++++++++++++++++++++++-------- 8 files changed, 494 insertions(+), 84 deletions(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
Signature · 1 line
1.8.1.4
PATCH 1/4 cpu: introduce CpuTopoInfo structure for argument simplification
--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct X86CPUTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}X86CPUTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +const X86CPUTopoInfo *topo) { -return (pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | - (core_id <<apicid_core_offset (nr_cores, nr_threads)) | - smt_id; +return (topo->pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | + (topo->core_id <<apicid_core_offset (nr_cores, nr_threads)) | + topo->smt_id; }/* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,static inline void x86_topo_ids_from_idx (unsigned nr_cores,unsigned nr_threads,unsigned cpu_index, -unsigned *pkg_id, -unsigned *core_id, -unsigned *smt_id) +X86CPUTopoInfo *topo) {unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; }/* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); -return apicid_from_topo_ids (nr_cores, nr_threads, pkg_id, core_id, smt_id); +X86CPUTopoInfo topo; +x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); +return apicid_from_topo_ids (nr_cores, nr_threads, &topo); }#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
PATCH 2/4 i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
In reply to Chen Fanintroduce x86_cpu_topo_ids_from_index() to calculate the cpu topology information, and the compat old mode mechanism moved into there. remove unused funciton x86_apicid_from_cpu_idx().
--- hw/i386/pc.c | 22 ++++++++++++---------- target-i386/cpu.c | 33 ++++++++++++++++++--------------- target-i386/cpu.h | 5 +++++ target-i386/topology.h | 26 +++++++++++++++++--------- 4 files changed, 52 insertions(+), 34 deletions(-)
hw/i386/pc.c +12 -10
@@ -927,7 +927,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,X86CPUTopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;
@@ -939,7 +939,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,return NULL ; } -object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err); +object_property_set_int (OBJECT (cpu), topo->apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err);if (local_err) {
@@ -955,28 +955,29 @@ static const char *current_cpu_model;void pc_hot_add_cpu (const int64_t id,Error **errp) {DeviceState *icc_bridge; -int64_t apic_id =x86_cpu_apic_id_from_index (id); +X86CPUTopoInfo topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);return ; } -if (cpu_exists (apic_id)) { +if (id >= max_cpus) {error_setg (errp,"Unable to add CPU: %" PRIi64 -", it already exists" , id); +", max allowed: %d" , id, max_cpus -1 );return ; } -if (id >= max_cpus) { +x86_cpu_topo_ids_from_index (id, &topo); +if (cpu_exists (topo.apic_id)) {error_setg (errp,"Unable to add CPU: %" PRIi64 -", max allowed: %d" , id, max_cpus -1 ); +", it already exists" , id);return ; } icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +pc_new_cpu (current_cpu_model, &topo, icc_bridge, errp); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
@@ -996,8 +997,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +X86CPUTopoInfo topo; +x86_cpu_topo_ids_from_index (i, &topo); + cpu =pc_new_cpu (cpu_model, &topo, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
target-i386/cpu.c +18 -15
@@ -23,8 +23,6 @@#include "cpu.h" #include "sysemu/kvm.h" -#include "sysemu/cpus.h" -#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h"
@@ -2584,6 +2582,21 @@ void enable_compat_apic_id_mode(void) compat_apic_id_mode = true; } +void x86_cpu_topo_ids_from_index (unsigned int cpu_index,X86CPUTopoInfo *topo) +{ +static bool warned; + +x86_topo_ids_from_idx (smp_cores, smp_threads, cpu_index, topo); +if (compat_apic_id_mode) { +if (cpu_index != topo->apic_id && !warned) { +error_report ("APIC IDs set in compatibility mode, " +"CPU topology won't match the configuration" ); + warned = true; + } +x86_topo_ids_from_apic_id (smp_cores, smp_threads, cpu_index, topo); + } +} +/* Calculates initial APIC ID for a specific CPU index * * Currently we need to be able to calculate the APIC ID from the CPU index
@@ -2593,20 +2606,10 @@ void enable_compat_apic_id_mode(void)*/ uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index) { -uint32_t correct_id; -static bool warned; +X86CPUTopoInfo topo; - correct_id =x86_apicid_from_cpu_idx (smp_cores, smp_threads, cpu_index); -if (compat_apic_id_mode) { -if (cpu_index != correct_id && !warned) { -error_report ("APIC IDs set in compatibility mode, " -"CPU topology won't match the configuration" ); - warned = true; - } -return cpu_index; - }else { -return correct_id; - } +x86_cpu_topo_ids_from_index (cpu_index, &topo); +return topo.apic_id; }static void x86_cpu_initfn (Object *obj)
target-i386/cpu.h +5 -0
@@ -22,6 +22,9 @@#include "config.h" #include "qemu-common.h" +#include "sysemu/cpus.h" +#include "topology.h" +#ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64#else
@@ -1286,6 +1289,8 @@ void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,const char *get_register_name_32 (unsigned int reg);uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index); +void x86_cpu_topo_ids_from_index (unsigned int cpu_index, +X86CPUTopoInfo *topo);void enable_compat_apic_id_mode (void );#define APIC_DEFAULT_ADDRESS 0xfee00000
target-i386/topology.h +17 -9
@@ -51,6 +51,7 @@ typedef struct X86CPUTopoInfo {unsigned pkg_id;unsigned core_id;unsigned smt_id; +apic_id_t apic_id; } X86CPUTopoInfo;/* Return the bit width needed for 'count' IDs
@@ -117,19 +118,26 @@ static inline void x86_topo_ids_from_idx(unsigned nr_cores, topo->smt_id = cpu_index % nr_threads; topo->core_id = core_index % nr_cores; topo->pkg_id = core_index / nr_cores; + topo->apic_id = apicid_from_topo_ids(nr_cores, nr_threads, topo); } -/* Make APIC ID for the CPU 'cpu_index' -* -* 'cpu_index' is a sequential, contiguous ID for the CPU. +/* Calculate CPU topology based on CPU APIC ID. */ -static inline apic_id_t x86_apicid_from_cpu_idx (unsigned nr_cores, -unsigned nr_threads, -unsigned cpu_index) +static inline void x86_topo_ids_from_apic_id (unsigned nr_cores, +unsigned nr_threads, +apic_id_t apic_id, +X86CPUTopoInfo *topo) { -X86CPUTopoInfo topo; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); -return apicid_from_topo_ids (nr_cores, nr_threads, &topo); +unsigned offset_mask; + topo->pkg_id = apic_id >>apicid_pkg_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_pkg_offset (nr_cores, nr_threads)) -1 ; + topo->core_id = (apic_id & offset_mask) + >>apicid_core_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_core_offset (nr_cores, nr_threads)) -1 ; + topo->smt_id = apic_id & offset_mask; + topo->apic_id = apic_id; }#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [PATCH v1 2/4] i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
Quoted 5 lines · Chen Fan
introduce
x86_cpu_topo_ids_from_index()to calculate the cpu topology information, and the compat old mode mechanism moved into there. remove unused funcitonx86_apicid_from_cpu_idx().Signed-off-by Chen Fan <[email protected]>
[...]
target-i386/topology.h static inline void x86_topo_ids_from_idx(unsigned nr_cores, · line 129
Quoted 7 lines
target-i386/topology.h +4
-3-static inline apic_id_t x86_apicid_from_cpu_idx (unsigned nr_cores, -unsigned nr_threads, -unsigned cpu_index) +static inline void x86_topo_ids_from_apic_id (unsigned nr_cores, +unsigned nr_threads, +apic_id_t apic_id, +X86CPUTopoInfo *topo)
You need to squash this patch and patch 3/4 together, otherwise we get unit test failures in the intermediate tree.
Otherwise, patch looks good.
Signature · 1 line
Eduardo
Re: [Qemu-devel] [PATCH v1 2/4] i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
Quoted 7 lines · Eduardo Habkost
Quoted 5 lines · Chen Fan
introduce
x86_cpu_topo_ids_from_index()to calculate the cpu topology information, and the compat old mode mechanism moved into there. remove unused funcitonx86_apicid_from_cpu_idx().Signed-off-by Chen Fan <[email protected]>[...]
Quoted 10 lines
target-i386/topology.h static inline void x86_topo_ids_from_idx(unsigned nr_cores, · line 129
Quoted 7 lines
target-i386/topology.h +4
-3-static inline apic_id_t x86_apicid_from_cpu_idx (unsigned nr_cores, -unsigned nr_threads, -unsigned cpu_index) +static inline void x86_topo_ids_from_apic_id (unsigned nr_cores, +unsigned nr_threads, +apic_id_t apic_id, +X86CPUTopoInfo *topo)You need to squash this patch and patch 3/4 together, otherwise we get unit test failures in the intermediate tree.
Ok, this patches will come soon.
Thanks
Quoted 3 lines
Otherwise, patch looks good.
PATCH 3/4 topo unit-test: update Unit tests to test-x86-cpuid.c
In reply to Chen Fanremove redundant x86_apicid_from_cpu_idx() tests. add tests to check x86_topo_ids_from_apic_id() and x86_topo_ids_from_apic_id() output.
--- tests/test-x86-cpuid.c | 165 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 36 deletions(-)
tests/test-x86-cpuid.c +129 -36
@@ -32,11 +32,36 @@ static void test_topo_bits(void) g_assert_cmpuint(apicid_smt_width(1, 1), ==, 0); g_assert_cmpuint(apicid_core_width(1, 1), ==, 0); - g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 0), ==, 0); - g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1), ==, 1); - g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 2), ==, 2); - g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 3), ==, 3); - +X86CPUTopoInfo topo = {0 }; + +x86_topo_ids_from_idx (1 ,1 ,0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 0); +x86_topo_ids_from_idx (1 ,1 ,1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 1); +x86_topo_ids_from_idx (1 ,1 ,2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 2); +x86_topo_ids_from_idx (1 ,1 ,3 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 3); + +x86_topo_ids_from_apic_id (1 ,1 ,0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0); + +x86_topo_ids_from_apic_id (1 ,1 ,1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 1); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0); + +x86_topo_ids_from_apic_id (1 ,1 ,2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 2); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0); + +x86_topo_ids_from_apic_id (1 ,1 ,3 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 3); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0);/* Test field width calculation for multiple values */
@@ -65,37 +90,105 @@ static void test_topo_bits(void) g_assert_cmpuint(apicid_core_width(6, 3), ==, 3); g_assert_cmpuint(apicid_pkg_offset(6, 3), ==, 5); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 0), ==, 0); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1), ==, 1); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2), ==, 2); - - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 0), ==, - (1 <<2 ) |0 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 1), ==, - (1 <<2 ) |1 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 2), ==, - (1 <<2 ) |2 ); - - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 0), ==, - (2 <<2 ) |0 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 1), ==, - (2 <<2 ) |1 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 2), ==, - (2 <<2 ) |2 ); - - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 0), ==, - (5 <<2 ) |0 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 1), ==, - (5 <<2 ) |1 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 2), ==, - (5 <<2 ) |2 ); - - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 6 * 3 + 0 * 3 + 0), ==, - (1 <<5 )); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 6 * 3 + 1 * 3 + 1), ==, - (1 <<5 ) | (1 <<2 ) |1 ); - g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 3 * 6 * 3 + 5 * 3 + 2), ==, - (3 <<5 ) | (5 <<2 ) |2 ); +x86_topo_ids_from_idx (6 ,3 ,0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 0); +x86_topo_ids_from_idx (6 ,3 ,1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 1); +x86_topo_ids_from_idx (6 ,3 ,2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, 2); + +x86_topo_ids_from_idx (6 ,3 ,1 *3 +0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (1 << 2) | 0); +x86_topo_ids_from_idx (6 ,3 ,1 *3 +1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (1 << 2) | 1); +x86_topo_ids_from_idx (6 ,3 ,1 *3 +2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (1 << 2) | 2); + +x86_topo_ids_from_idx (6 ,3 ,2 *3 +0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (2 << 2) | 0); +x86_topo_ids_from_idx (6 ,3 ,2 *3 +1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (2 << 2) | 1); +x86_topo_ids_from_idx (6 ,3 ,2 *3 +2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (2 << 2) | 2); + +x86_topo_ids_from_idx (6 ,3 ,5 *3 +0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (5 << 2) | 0); +x86_topo_ids_from_idx (6 ,3 ,5 *3 +1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (5 << 2) | 1); +x86_topo_ids_from_idx (6 ,3 ,5 *3 +2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (5 << 2) | 2); + +x86_topo_ids_from_idx (6 ,3 ,1 *6 *3 +0 *3 +0 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (1 << 5) | 0); +x86_topo_ids_from_idx (6 ,3 ,1 *6 *3 +1 *3 +1 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (1 << 5) | (1 << 2) | 1); +x86_topo_ids_from_idx (6 ,3 ,3 *6 *3 +5 *3 +2 , &topo); + g_assert_cmpuint(topo.apic_id, ==, (3 << 5) | (5 << 2) | 2); + +x86_topo_ids_from_apic_id (6 ,3 ,0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0); +x86_topo_ids_from_apic_id (6 ,3 ,1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 1); +x86_topo_ids_from_apic_id (6 ,3 ,2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 2); + +x86_topo_ids_from_apic_id (6 ,3 , (1 <<2 ) |0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 1); + g_assert_cmpuint(topo.smt_id, ==, 0); +x86_topo_ids_from_apic_id (6 ,3 , (1 <<2 ) |1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 1); + g_assert_cmpuint(topo.smt_id, ==, 1); +x86_topo_ids_from_apic_id (6 ,3 , (1 <<2 ) |2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 1); + g_assert_cmpuint(topo.smt_id, ==, 2); + +x86_topo_ids_from_apic_id (6 ,3 , (2 <<2 ) |0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 2); + g_assert_cmpuint(topo.smt_id, ==, 0); +x86_topo_ids_from_apic_id (6 ,3 , (2 <<2 ) |1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 2); + g_assert_cmpuint(topo.smt_id, ==, 1); +x86_topo_ids_from_apic_id (6 ,3 , (2 <<2 ) |2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 2); + g_assert_cmpuint(topo.smt_id, ==, 2); + +x86_topo_ids_from_apic_id (6 ,3 , (5 <<2 ) |0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 5); + g_assert_cmpuint(topo.smt_id, ==, 0); +x86_topo_ids_from_apic_id (6 ,3 , (5 <<2 ) |1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 5); + g_assert_cmpuint(topo.smt_id, ==, 1); +x86_topo_ids_from_apic_id (6 ,3 , (5 <<2 ) |2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 0); + g_assert_cmpuint(topo.core_id, ==, 5); + g_assert_cmpuint(topo.smt_id, ==, 2); + +x86_topo_ids_from_apic_id (6 ,3 , (1 <<5 ) |0 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 1); + g_assert_cmpuint(topo.core_id, ==, 0); + g_assert_cmpuint(topo.smt_id, ==, 0); +x86_topo_ids_from_apic_id (6 ,3 , (1 <<5 ) | (1 <<2 ) |1 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 1); + g_assert_cmpuint(topo.core_id, ==, 1); + g_assert_cmpuint(topo.smt_id, ==, 1); +x86_topo_ids_from_apic_id (6 ,3 , (1 <<5 ) | (1 <<2 ) |2 , &topo); + g_assert_cmpuint(topo.pkg_id, ==, 1); + g_assert_cmpuint(topo.core_id, ==, 1); + g_assert_cmpuint(topo.smt_id, ==, 2); }int main (int argc,char **argv)
Signature · 1 line
1.8.1.4
PATCH 4/4 i386: introduce cpu QOM hierarchy tree
In reply to Chen Fanadd cpu-topology.h cpu-topology.c files for prebuilding cpu qom tree "/machine/node[X]/socket[Y]/core[Z]->link cpu"
--- hw/i386/pc.c | 3 + target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 22 +++++ target-i386/cpu.h | 3 + 6 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
hw/i386/pc.c +3 -0
@@ -941,6 +941,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, X86CPUTopoInfo *topo,object_property_set_int (OBJECT (cpu), topo->apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); +x86_topo_cpu_set_link (OBJECT (cpu), topo, &local_err);if (local_err) {error_propagate (errp, local_err);
@@ -996,6 +997,8 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +cpu_topo_init (); +for (i =0 ; i < smp_cpus; i++) {X86CPUTopoInfo topo;x86_cpu_topo_ids_from_index (i, &topo);
target-i386/Makefile.objs +1 -1
@@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o cpu-topology.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o
target-i386/cpu-topology.c new file +199 -0
199 lines not on this page · raw message
target-i386/cpu-topology.h new file +71 -0
71 lines not on this page · raw message
target-i386/cpu.c +22 -0
@@ -2698,6 +2698,28 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } +void x86_topo_cpu_set_link (Object *obj,X86CPUTopoInfo *topo,Error **errp) +{ +gchar *name; +CoreState *core; +Error *local_err =NULL ; + + core =cpu_topo_object_core_find (topo); +if (!core) { +error_set (&local_err,QERR_DEVICE_NOT_FOUND ,TYPE_CORE ); + goto out; + } + + name =g_strdup_printf ("cpu[%" PRIu32"]" , topo->smt_id); +object_property_set_link (OBJECT (core), obj, name, &local_err); +g_free (name); + +out: +if (local_err !=NULL ) { +error_propagate (errp, local_err); + } +} +static Property x86_cpu_properties[] = {DEFINE_PROP_BOOL ("pmu" ,X86CPU , enable_pmu, false), { .name ="hv-spinlocks" , .info = &qdev_prop_spinlocks },
target-i386/cpu.h +3 -0
@@ -24,6 +24,7 @@#include "sysemu/cpus.h" #include "topology.h" +#include "cpu-topology.h" #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64
@@ -1293,6 +1294,8 @@ void x86_cpu_topo_ids_from_index(unsigned int cpu_index, X86CPUTopoInfo *topo);void enable_compat_apic_id_mode (void ); +void x86_topo_cpu_set_link (Object *obj,X86CPUTopoInfo *topo,Error **errp); +#define APIC_DEFAULT_ADDRESS 0xfee00000#define APIC_SPACE_SIZE 0x100000
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [PATCH v1 0/4] prebuild cpu QOM tree /machine/node/socket/core ->link-cpu
In reply to Chen FanQuoted 16 lines · Chen Fan
at present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous
cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.I suppose we could use
apic_idasinstance_idwhich was used at registering vmstate when create cpu. on target, we prebuild the specified cpu topology using comand line:
-device /machine/node[]/socket[]/core[]/cpu[], then migration, we could keep the same
cpu infrastructure on both side.RFC:
V4: rename CpuTopoInfo to X86CPUTopoInfo. and movecpu_exsit()topc_new_cpu().V3: get rid of thread object and tie link<cpu> to <core> directly. and prebuild full
core[] and thread[] as init socket[] according tosmp_coresandsmp_threads.
Quoted 6 lines
TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.I don't know wether this way is right or not. pls tell me. :)
When sending a cover letter for a new revision of a patch series, we generally do NOT use In-Reply-To headers, but instead send it as a new thread. Patches are harder to see when they are buried as a reply to another thread.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH v1 0/4] prebuild cpu QOM tree /machine/node/socket/core ->link-cpu
Quoted 22 lines · Eric Blake
Quoted 21 lines · Chen Fan
at present, after hotplug a discontinuous cpu id on source, then done migration, on target, it will fail to add the unoccupied cpu id which was skipped at source, this cause is on target Qemu prebuild CPU with continuous
cpu_index. so after migration, the cpu infrastructure bewteen source and target are different.I suppose we could use
apic_idasinstance_idwhich was used at registering vmstate when create cpu. on target, we prebuild the specified cpu topology using comand line:
-device /machine/node[]/socket[]/core[]/cpu[], then migration, we could keep the same
cpu infrastructure on both side.RFC:
V4: rename CpuTopoInfo to X86CPUTopoInfo. and movecpu_exsit()topc_new_cpu().V3: get rid of thread object and tie link<cpu> to <core> directly. and prebuild full
core[] and thread[] as init socket[] according tosmp_coresandsmp_threads.TODO:
1. add cpu "path" property which used for specifying the QOM path.
2. add -device cpu-foo.path supported.
3. then we could introduce hot-remove cpu probably.
Quoted 7 lines
Quoted 1 line
I don't know wether this way is right or not. pls tell me. :)
When sending a cover letter for a new revision of a patch series, we generally do NOT use In-Reply-To headers, but instead send it as a new thread. Patches are harder to see when they are buried as a reply to another thread.
I see, Thanks.
Chen
RFC v4 2/3 i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
In reply to Chen Fan--- hw/i386/pc.c | 25 ++++++++++++++----------- target-i386/cpu.c | 28 +++++++++++++++++++++++----- target-i386/cpu.h | 5 +++++ target-i386/topology.h | 18 ++++++++++++++++++ 4 files changed, 60 insertions(+), 16 deletions(-)
hw/i386/pc.c +14 -11
@@ -927,11 +927,18 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,X86CPUTopoInfo *topo,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +int64_t apic_id =apicid_from_topo_ids (smp_cores, smp_threads, topo); + +if (cpu_exists (apic_id)) { +error_setg (errp,"Unable to add CPU with APIC ID: %" PRIi64 +", it already exists" , apic_id); +return NULL ; + } cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {
@@ -955,19 +962,13 @@ static const char *current_cpu_model;void pc_hot_add_cpu (const int64_t id,Error **errp) {DeviceState *icc_bridge; -int64_t apic_id =x86_cpu_apic_id_from_index (id); +X86CPUTopoInfo topo;if (id <0 ) {error_setg (errp,"Invalid CPU id: %" PRIi64, id);return ; } -if (cpu_exists (apic_id)) { -error_setg (errp,"Unable to add CPU: %" PRIi64 -", it already exists" , id); -return ; - } -if (id >= max_cpus) {error_setg (errp,"Unable to add CPU: %" PRIi64", max allowed: %d" , id, max_cpus -1 );
@@ -976,7 +977,8 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +x86_cpu_topo_ids_from_index (id, &topo); +pc_new_cpu (current_cpu_model, &topo, icc_bridge, errp); }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
@@ -996,8 +998,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +X86CPUTopoInfo topo; +x86_cpu_topo_ids_from_index (i, &topo); + cpu =pc_new_cpu (cpu_model, &topo, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
target-i386/cpu.c +23 -5
@@ -23,8 +23,6 @@#include "cpu.h" #include "sysemu/kvm.h" -#include "sysemu/cpus.h" -#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h"
@@ -2584,6 +2582,8 @@ void enable_compat_apic_id_mode(void) compat_apic_id_mode = true; } +static bool compat_apic_id_warned; +/* Calculates initial APIC ID for a specific CPU index * * Currently we need to be able to calculate the APIC ID from the CPU index
@@ -2594,14 +2594,13 @@ void enable_compat_apic_id_mode(void)uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index) {uint32_t correct_id; -static bool warned; correct_id =x86_apicid_from_cpu_idx (smp_cores, smp_threads, cpu_index);if (compat_apic_id_mode) { -if (cpu_index != correct_id && !warned) { +if (cpu_index != correct_id && !compat_apic_id_warned) {error_report ("APIC IDs set in compatibility mode, " "CPU topology won't match the configuration" ); - warned = true; + compat_apic_id_warned = true; }return cpu_index; }else {
@@ -2609,6 +2608,25 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } +void x86_cpu_topo_ids_from_index (unsigned int cpu_index,X86CPUTopoInfo *topo) +{ +int64_t correct_apic_id; + +x86_topo_ids_from_idx (smp_cores, smp_threads, cpu_index, topo); +if (compat_apic_id_mode) { + correct_apic_id =apicid_from_topo_ids (smp_cores, + smp_threads, + topo); +if (cpu_index != correct_apic_id && !compat_apic_id_warned) { +error_report ("APIC IDs set in compatibility mode, " +"CPU topology won't match the configuration" ); + compat_apic_id_warned = true; + } +x86_topo_ids_from_apic_id (smp_cores, smp_threads, cpu_index, topo); +assert (apicid_from_topo_ids (smp_cores, smp_threads, topo) == cpu_index); + } +} +static void x86_cpu_initfn (Object *obj) {CPUState *cs =CPU (obj);
target-i386/cpu.h +5 -0
@@ -22,6 +22,9 @@#include "config.h" #include "qemu-common.h" +#include "sysemu/cpus.h" +#include "topology.h" +#ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64#else
@@ -1286,6 +1289,8 @@ void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,const char *get_register_name_32 (unsigned int reg);uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index); +void x86_cpu_topo_ids_from_index (unsigned int cpu_index, +X86CPUTopoInfo *topo);void enable_compat_apic_id_mode (void );#define APIC_DEFAULT_ADDRESS 0xfee00000
target-i386/topology.h +18 -0
@@ -132,4 +132,22 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, return apicid_from_topo_ids(nr_cores, nr_threads, &topo); } +/* Calculate CPU topology based on CPU APIC ID. +*/ +static inline void x86_topo_ids_from_apic_id (unsigned nr_cores, +unsigned nr_threads, +apic_id_t apic_id, +X86CPUTopoInfo *topo) +{ +unsigned offset_mask; + topo->pkg_id = apic_id >>apicid_pkg_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_pkg_offset (nr_cores, nr_threads)) -1 ; + topo->core_id = (apic_id & offset_mask) + >>apicid_core_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_core_offset (nr_cores, nr_threads)) -1 ; + topo->smt_id = apic_id & offset_mask; +} +#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC v4 2/3] i386: use CpuTopoInfo instead apic_id as argument for pc_new_cpu()
On Wed, Mar 12, 2014 at 03:51:35PM +0800, Chen Fan wrote:
[...]
Quoted 7 lines
if (compat_apic_id_mode) {target-i386/cpu.c +2
-2-if (cpu_index != correct_id && !warned) { +if (cpu_index != correct_id && !compat_apic_id_warned) {error_report ("APIC IDs set in compatibility mode, " "CPU topology won't match the configuration" ); - warned = true; + compat_apic_id_warned = true;
[...]
target-i386/cpu.c uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) · line 2623
Quoted 8 lines
target-i386/cpu.c +8
-0+if (compat_apic_id_mode) { + correct_apic_id =apicid_from_topo_ids (smp_cores, + smp_threads, + topo); +if (cpu_index != correct_apic_id && !compat_apic_id_warned) { +error_report ("APIC IDs set in compatibility mode, " +"CPU topology won't match the configuration" ); + compat_apic_id_warned = true;
The new logic makes sense, but please don't duplicate code.
Signature · 1 line
Eduardo
RFC v4 3/3 i386: introduce cpu QOM hierarchy tree
In reply to Chen Fanadd cpu-topology.h cpu-topology.c files for prebuilding cpu qom tree
"/machine/node[X]/socket[Y]/core[Z]->link cpu"
--- hw/i386/pc.c | 3 + target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 13 +++ target-i386/cpu.h | 3 + 6 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
hw/i386/pc.c +3 -0
@@ -948,6 +948,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, X86CPUTopoInfo *topo,object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); +x86_topo_cpu_set_link (OBJECT (cpu), topo);if (local_err) {error_propagate (errp, local_err);
@@ -997,6 +998,8 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +cpu_topo_init (); +for (i =0 ; i < smp_cpus; i++) {X86CPUTopoInfo topo;x86_cpu_topo_ids_from_index (i, &topo);
target-i386/Makefile.objs +1 -1
@@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o cpu-topology.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o
target-i386/cpu-topology.c new file +199 -0
199 lines not on this page · raw message
target-i386/cpu-topology.h new file +71 -0
71 lines not on this page · raw message
target-i386/cpu.c +13 -0
@@ -2713,6 +2713,19 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } +void x86_topo_cpu_set_link (Object *obj,X86CPUTopoInfo *topo) +{ +gchar *name; +CoreState *core; + + core =cpu_topo_object_core_find (topo); +if (core) { + name =g_strdup_printf ("cpu[%" PRIu32"]" , topo->smt_id); +object_property_set_link (OBJECT (core), obj, name,NULL ); +g_free (name); + } +} +static Property x86_cpu_properties[] = {DEFINE_PROP_BOOL ("pmu" ,X86CPU , enable_pmu, false), { .name ="hv-spinlocks" , .info = &qdev_prop_spinlocks },
target-i386/cpu.h +3 -0
@@ -24,6 +24,7 @@#include "sysemu/cpus.h" #include "topology.h" +#include "cpu-topology.h" #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64
@@ -1293,6 +1294,8 @@ void x86_cpu_topo_ids_from_index(unsigned int cpu_index, X86CPUTopoInfo *topo);void enable_compat_apic_id_mode (void ); +void x86_topo_cpu_set_link (Object *obj,X86CPUTopoInfo *topo); +#define APIC_DEFAULT_ADDRESS 0xfee00000#define APIC_SPACE_SIZE 0x100000
Signature · 1 line
1.8.1.4
RFC v3 3/3 i386: introduce cpu QOM hierarchy tree
In reply to chen.fan.fnstFrom: "chen.fan.fnst" <[email protected]>
add cpu-topology.h cpu-topology.c files for prebuilding cpu qom tree "/machine/node[X]/socket[Y]/core[Z]->link cpu"
--- hw/i386/pc.c | 3 + target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 13 +++ target-i386/cpu.h | 3 + 6 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
hw/i386/pc.c +3 -0
@@ -942,6 +942,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, CpuTopoInfo *topo,object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); +x86_topo_cpu_set_link (OBJECT (cpu), topo);if (local_err) {error_propagate (errp, local_err);
@@ -998,6 +999,8 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +cpu_topo_init (); +for (i =0 ; i < smp_cpus; i++) {CpuTopoInfo topo;x86_topo_ids_from_idx (smp_cores, smp_threads, i, &topo);
target-i386/Makefile.objs +1 -1
@@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o cpu-topology.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o
target-i386/cpu-topology.c new file +198 -0
198 lines not on this page · raw message
target-i386/cpu-topology.h new file +71 -0
71 lines not on this page · raw message
target-i386/cpu.c +13 -0
@@ -2693,6 +2693,19 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } +void x86_topo_cpu_set_link (Object *obj,CpuTopoInfo *topo) +{ +gchar *name; +CoreState *core; + + core =cpu_topo_object_core_find (topo); +if (core) { + name =g_strdup_printf ("cpu[%" PRIu32"]" , topo->smt_id); +object_property_set_link (OBJECT (core), obj, name,NULL ); +g_free (name); + } +} +static Property x86_cpu_properties[] = {DEFINE_PROP_BOOL ("pmu" ,X86CPU , enable_pmu, false), { .name ="hv-spinlocks" , .info = &qdev_prop_spinlocks },
target-i386/cpu.h +3 -0
@@ -24,6 +24,7 @@#include "sysemu/cpus.h" #include "topology.h" +#include "cpu-topology.h" #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64
@@ -1291,6 +1292,8 @@ const char *get_register_name_32(unsigned int reg);uint32_t x86_cpu_apic_id_from_index (unsigned int cpu_index);void enable_compat_apic_id_mode (void ); +void x86_topo_cpu_set_link (Object *obj,CpuTopoInfo *topo); +#define APIC_DEFAULT_ADDRESS 0xfee00000#define APIC_SPACE_SIZE 0x100000
Signature · 1 line
1.8.1.4
RFC v2 2/2 i386: introduce cpu QOM hierarchy tree
In reply to Chen Fanadd cpu-topology.h cpu-topology.c files for prebuild cpu qom tree "/machine/node[X]/socket[Y]/core[Z]/thread[N]/cpu"
--- hw/i386/pc.c | 6 +- target-i386/Makefile.objs | 2 +- target-i386/cpu-qom.h | 1 + target-i386/cpu-topology.c | 163 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++++++ target-i386/cpu.c | 29 ++++++++ target-i386/cpu.h | 2 + 7 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h
hw/i386/pc.c +5 -1
@@ -942,7 +942,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, X86TopoInfo *topo,object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); - +x86_topo_cpu_set_link (topo,OBJECT (cpu));if (local_err) {error_propagate (errp, local_err);object_unref (OBJECT (cpu));
@@ -999,6 +999,10 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +for (i =0 ; i < max_cpus; i++) { +x86_topo_cpu_create (i); + } +for (i =0 ; i < smp_cpus; i++) {X86TopoInfo *topo =x86_cpu_topo_from_index (i); cpu =pc_new_cpu (cpu_model, topo, icc_bridge, &error);
target-i386/Makefile.objs +1 -1
@@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o cpu-topology.c obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o
target-i386/cpu-qom.h +1 -0
@@ -23,6 +23,7 @@#include "qom/cpu.h" #include "cpu.h" #include "qapi/error.h" +#include "cpu-topology.h" #ifdef TARGET_X86_64 #define TYPE_X86_CPU "x86_64-cpu"
target-i386/cpu-topology.c new file +163 -0
163 lines not on this page · raw message
target-i386/cpu-topology.h new file +71 -0
71 lines not on this page · raw message
target-i386/cpu.c +29 -0
@@ -2711,6 +2711,35 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } +void x86_topo_cpu_set_link (X86TopoInfo *topo,Object *obj) +{ +gchar *name; +ThreadState *thread; + + name =g_strdup_printf ("cpu[%" PRIu32"]" , +x86_cpu_apic_id_from_index (topo->cpu_index)); + + thread =cpu_topo_thread_get (topo); +object_property_set_link (OBJECT (thread), obj, name,NULL ); +g_free (name); +} + +void x86_topo_cpu_create (unsigned int cpu_index) +{ +X86TopoInfo *topo =x86_cpu_topo_from_index (cpu_index); +ThreadState *thread; +gchar *name; + + thread =cpu_topo_thread_get (topo); + + name =g_strdup_printf ("cpu[%" PRIu32"]" , +x86_cpu_apic_id_from_index (cpu_index)); + +object_property_add_link (OBJECT (thread), name,TYPE_CPU , + (Object **)thread->link_cpu,NULL ); +g_free (name); +} +static Property x86_cpu_properties[] = {DEFINE_PROP_BOOL ("pmu" ,X86CPU , enable_pmu, false), { .name ="hv-spinlocks" , .info = &qdev_prop_spinlocks },
target-i386/cpu.h +2 -0
@@ -1286,6 +1286,8 @@ void enable_compat_apic_id_mode(void);#include "topology.h" X86TopoInfo *x86_cpu_topo_from_index (unsigned int cpu_index); +void x86_topo_cpu_create (unsigned int cpu_index); +void x86_topo_cpu_set_link (X86TopoInfo *topo,Object *obj);#define APIC_DEFAULT_ADDRESS 0xfee00000#define APIC_SPACE_SIZE 0x100000
Signature · 1 line
1.8.1.4
RFC PATCH 2/2 cpu: link each new cpu to QOM tree /machine/node/socket/core/thread/cpu respectively.
In reply to Chen Fan--- hw/i386/pc.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)
hw/i386/pc.c +36 -4
@@ -57,6 +57,7 @@#include "hw/boards.h" #include "hw/pci/pci_host.h" #include "acpi-build.h" +#include "qom/node.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ
@@ -927,11 +928,13 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,int64_t id,DeviceState *icc_bridge,Error **errp) {X86CPU *cpu;Error *local_err =NULL ; +Object *thread; +int64_t apic_id =x86_cpu_apic_id_from_index (id); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {
@@ -942,11 +945,17 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); + thread =object_get_thread_from_index (id); +if (thread) { +object_property_set_link (thread,OBJECT (cpu),"cpu" , &local_err); + } +if (local_err) {error_propagate (errp, local_err);object_unref (OBJECT (cpu)); cpu =NULL ; } +return cpu; }
@@ -976,7 +985,29 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +pc_new_cpu (current_cpu_model, id, icc_bridge, errp); +} + +static void qdev_cpus_init (void ) +{ +int i, nodes; +gchar *node_name; +Object *obj; + +if (nb_numa_nodes) { + nodes = nb_numa_nodes; + }else { + nodes =1 ; + } + +for (i =0 ; i < nodes; i++) { + obj =object_new (TYPE_NODE ); + node_name =g_strdup_printf ("node[%" PRIi32"]" , i); +object_property_add_child (qdev_get_machine (), + node_name, obj,NULL ); +g_free (node_name); + } + }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)
@@ -995,9 +1026,10 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +qdev_cpus_init (); +for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); + cpu =pc_new_cpu (cpu_model, i, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [PATCH 2/2][RFC] cpu: link each new cpu to QOM tree /machine/node/socket/core/thread/cpu respectively.
Quoted 18 lines · Chen Fan
Signed-off-by Chen Fan <[email protected]>--- hw/i386/pc.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)hw/i386/pc.c +1
-0@@ -57,6 +57,7 @@#include "hw/boards.h" #include "hw/pci/pci_host.h" #include "acpi-build.h" +#include "qom/node.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ
hw/i386/pc.c void pc_acpi_smi_interrupt(void *opaque, int irq, int level) · line 932
Quoted 6 lines
hw/i386/pc.c +1
-1@@ -927,11 +928,13 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu (const char *cpu_model,int64_t apic_id, +static X86CPU *pc_new_cpu (const char *cpu_model,int64_t id,DeviceState *icc_bridge,Error **errp)
What about "decoding" the CPU index as soon as possible, and making this function get the full CPU "location", instead of adding more CPU-index-based logic to the rest of the code?
hw/i386/pc.c static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, · line 948
Quoted 13 lines
hw/i386/pc.c +3
-0{X86CPU *cpu;Error *local_err =NULL ; +Object *thread; +int64_t apic_id =x86_cpu_apic_id_from_index (id); cpu =cpu_x86_create (cpu_model, icc_bridge, &local_err);if (local_err !=NULL ) {@@ -942,11 +945,17 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,object_property_set_int (OBJECT (cpu), apic_id,"apic-id" , &local_err);object_property_set_bool (OBJECT (cpu), true,"realized" , &local_err); + thread =object_get_thread_from_index (id);
If you just separate the topo_ids_from_idx() and topo_make_apicid() calls, the IDs calculated by topo_ids_from_idx() will be useful for two
things: 1) QOM object path construction; and 2) APIC ID calculation (topo_make_apicid()), and you won't even need to implement object_get_thread_from_index().
(...except when compat_apic_id_mode bug-compatibility is enabled. In this case, either the APIC IDs won't match the QOM hierarchy, or we will present a QOM hierarchy different from the one requested by the user.)
By the way: a hierarchical node/socket/core/thread abstraction will probably break with current NUMA command-lines that are working. e.g.:
$ qemu-system-x86_64 -smp 8,cores=2,threads=2 \
-numa node,cpus=0-2 \
-numa node,cpus=3-5 \
-numa node,cpus=6-7The above command-line makes threads on the same socket/core appear on different NUMA nodes. Do we want to keep this (weird) topology configuration working?
Quoted 60 lines
hw/i386/pc.c +31
-3+if (thread) { +object_property_set_link (thread,OBJECT (cpu),"cpu" , &local_err); + } +if (local_err) {error_propagate (errp, local_err);object_unref (OBJECT (cpu)); cpu =NULL ; } +return cpu; }@@ -976,7 +985,29 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge =DEVICE (object_resolve_path_type ("icc-bridge" ,TYPE_ICC_BRIDGE ,NULL )); -pc_new_cpu (current_cpu_model, apic_id, icc_bridge, errp); +pc_new_cpu (current_cpu_model, id, icc_bridge, errp); +} + +static void qdev_cpus_init (void ) +{ +int i, nodes; +gchar *node_name; +Object *obj; + +if (nb_numa_nodes) { + nodes = nb_numa_nodes; + }else { + nodes =1 ; + } + +for (i =0 ; i < nodes; i++) { + obj =object_new (TYPE_NODE ); + node_name =g_strdup_printf ("node[%" PRIi32"]" , i); +object_property_add_child (qdev_get_machine (), + node_name, obj,NULL ); +g_free (node_name); + } + }void pc_cpus_init (const char *cpu_model,DeviceState *icc_bridge)@@ -995,9 +1026,10 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; +qdev_cpus_init (); +for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); + cpu =pc_new_cpu (cpu_model, i, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);Signature · 1 line
1.8.1.4
Signature · 1 line
Eduardo
Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn())
In reply to Andreas FärberQuoted 56 lines · On Tue, 21 Jan 2014 11:10:30 +0100 Andreas Färber <[email protected]> wrote:
Am 21.01.2014 10:51, schrieb Chen Fan:
Quoted 41 lines · Igor Mammedov
Quoted 40 lines
Quoted 30 lines · On Tue, 21 Jan 2014 15:12:45 +0800 Chen Fan <[email protected]>…
Quoted 29 lines · Igor Mammedov
Quoted 9 lines · On Fri, 17 Jan 2014 17:13:55 -0200 Eduardo Habkost <[email protected]> wrote:
Quoted 8 lines · Igor Mammedov
I recall there were objections to it since APIC ID contains topology information and it's not trivial for user to get it right. The last idea that was discussed to fix it was not expose APIC ID to user but rather introduce QOM hierarchy like:
/machine/node/N/socket/X/core/Y/thread/Z
and use it in user interface as a means to specify an arbitrary CPU and let QEMU calculate APIC ID based on this path.Quoted 6 lines
Quoted 1 line
But nobody took on implementing it yet.
We're taking so long to get a decent interface implemented, that part of me is considering exposing the APIC ID directly like suggested before, and requiring libvirt to calculate topology-aware APIC IDs[1] to properly implement CPU hotplug (and possibly for other tasks).
If you are speaking about
'qemu will core dump with "-smp 254, sockets=2, cores=3, threads=2"'
http://patchwork.ozlabs.org/patch/301272/
bug then it's limitation of ACPI implementation,
I'm going to refactor it to use full APIC ids instead of using bitmap, so that we won't ever run into issue regardless of cpu supported CPU count.Quoted 4 lines
Another part of me is hoping that the libvirt developers ask us to please not do that, so I can use it as argument against exposing the APIC IDs directly the next time we discuss this. :)
Quoted 6 lines
Quoted 4 lines
why not try your /machine/node/N/socket/X/core/Y/thread/Z idea first. It will benefit not only cpu hotplug but also '-numa' and topology description in general.
have there been any plan/model of the idea? Need to add a new option to qemu command?
I suppose we can start with internal default implementation first.
Quoted 7 lines
Quoted 5 lines
one way could be
1. let machine prebuild empty QOM tree /machine/node/N/socket/X/core/Y/thread/Z
2. add node, socket, core, thread properties to CPU and link CPU into respective link created by #1Thanks, I hope I can take some time to make some patches to implement it.
Please give us a few hours to reply. :)
/machine/node seems too broad a term to me.
You can't prebuild the full tree, you can only prepare the nodes. core[Y]/thread[Z] was previously discussed as syntax.
Quoted 13 lines
The important part to decide on will be what is going to be child<> and what link<>. Has anyone played with the Intel Quark platform for instance? (Galileo board or upcoming Edison card) On a regular mainboard, we would have socket[X] as a link<x86_64-cpu>, which might point to a child<cpu> /machine/memory-node[W]/cpu[X]. But if we do so we can't reassign it to another memory node - acceptable? With Quark (or Qseven modules etc.) there would be a container object rather than the /machine itself that has a child<i386-cpu> instead of a link<i386-cpu>. I guess the memory nodes could still be on the /machine though. The other point of discussion between Anthony and me was whether core[Y] should be a link<> or child<>, same for thread. I believe a child<> is better as it enforces that unrealizing the CPU will unrealize all its cores and all its threads in the future.
In terms of parent/child relationship, I guess we are not going to come up with uniform design, since boards could differ very much in that aspect.
I was rather thinking in terms of providing stable/uniform CLI/QMP NUMA interface using QOM tree.
At startup we potentially have cpu topology information and set of NUMA nodes, so we could pre-build containers up to the point where CPU threads are attached and pre-create empty links<CPU> and fill them later with actual CPU threads.
Quoted 8 lines
More issues may pop up when thinking about it longer than a few minutes. But yes, we need to start investigating this, and so far I had other priorities like getting the CPUState mess I created cleaned up.
Regards,
Andreas
RFC 2/3 target-i386: add -smp X,apics=0x option
In reply to Chen FanThis option provides the infrastructure for specifying apicids when boot VM, For example:
#boot with apicid 0 and 2:
-smp 2,apics=0xA,maxcpus=4 /* 1010 */
#boot with apicid 1 and 7:
-smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */
--- hw/i386/pc.c | 9 +++++-- include/sysemu/sysemu.h | 4 ++++ qemu-options.hx | 15 +++++++++--- vl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 6 deletions(-)
hw/i386/pc.c +7 -2
@@ -991,8 +991,13 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) current_cpu_model = cpu_model;for (i =0 ; i < smp_cpus; i++) { - cpu =pc_new_cpu (cpu_model,x86_cpu_apic_id_from_index (i), - icc_bridge, &error); +int64_t apic_id; +if (nb_boot_apics ==0 ) { + apic_id =x86_cpu_apic_id_from_index (i); + }else { + apic_id =x86_cpu_apic_id_from_index (boot_apics[i]); + } + cpu =pc_new_cpu (cpu_model, apic_id, icc_bridge, &error);if (error) {error_report ("%s" ,error_get_pretty (error));error_free (error);
include/sysemu/sysemu.h +4 -0
@@ -149,6 +149,10 @@ extern int nb_option_roms;extern const char *prom_envs[MAX_PROM_ENVS ];extern unsigned int nb_prom_envs; +#define MAX_APICS 255 +extern int nb_boot_apics; +extern int64_t boot_apics[MAX_APICS ]; +/* pci-hotplug */ void pci_device_hot_add (Monitor *mon,const QDict *qdict);int pci_drive_hot_add (Monitor *mon,const QDict *qdict,DriveInfo *dinfo);
qemu-options.hx +12 -3
@@ -73,16 +73,17 @@ Select CPU model (@code{-cpu help} for list and additional feature selection) ETEXI DEF("smp", HAS_ARG, QEMU_OPTION_smp, - "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n" + "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets][,apics=apics]\n" " set the number of CPUs to 'n' [default=1]\n" " maxcpus= maximum number of total cpus, including\n" " offline CPUs for hotplug, etc\n" " cores= number of CPU cores on one socket\n" " threads= number of threads on one CPU core\n" - " sockets= number of discrete sockets in the system\n", + " sockets= number of discrete sockets in the system\n" + " apics= a hex number with leading '0x' as boot bitmap of existed apicid\n", QEMU_ARCH_ALL) STEXI -@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}] +@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}][,apics=@var{apics}] @findex -smp Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255 CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
@@ -92,6 +93,14 @@ of @var{threads} per cores and the total number of @var{sockets} can be specified. Missing values will be computed. If any on the three values is given, the total number of CPUs @var{n} can be omitted. @var{maxcpus} specifies the maximum number of hotpluggable CPUs. +@var{apics} specifies the boot bitmap of existed apicid. + +@example +#specify the boot bitmap of apicid with 0 and 2: +qemu-system-i386 -smp 2,apics=0xA,maxcpus=4 /* 1010 */ +#specify the boot bitmap of apicid with 1 and 7: +qemu-system-i386 -smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */ +@end example ETEXI DEF("numa", HAS_ARG, QEMU_OPTION_numa,
vl.c +61 -1
92 lines not on this page · raw message
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC 2/3] target-i386: add -smp X,apics=0x option
Quoted 7 lines · Chen Fan
This option provides the infrastructure for specifying apicids when boot VM, For example:
#boot with apicid 0 and 2:
-smp 2,apics=0xA,maxcpus=4 /* 1010 */
#boot with apicid 1 and 7:
-smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */
This syntax feels a bit odd when maxcpus is not a multiple of 8, and even harder when not a multiple of 4. I think part of my confusion stems from you treating the lsb as the left-most bit, but expect me to
write in hex where I'm used to the right-most bit being lsb Wouldn't
it be easier to express:
msb .... lsb
with leading 0s implied as needed, as in:
0x5 => 0101 => id 0 (lsb) and id 2 are enabled, regardless of whether maxcpus=4 or maxcpus=80x82 => 1000 0010 => id 1 and id 7 are enabled, regardless of whether maxcpus=8 or maxcpus=256
0x100000000 => id 32 is enabled
Or even better, why not reuse existing parsers that take cpu ids directly as numbers instead of making me compute a bitmap (as in maxcpus=4,id=0,id=2 - although I don't quite know QemuOpts well enough to know if you can repeat id= for forming a list of disjoint id numbers)
qemu-options.hx of @var{threads} per cores and the total number of @var{sockets} can be · line 96
Quoted 5 lines
qemu-options.hx +1
-0@@ -92,6 +93,14 @@ of @var{threads} per cores and the total number of @var{sockets} can be specified. Missing values will be computed. If any on the three values is given, the total number of CPUs @var{n} can be omitted. @var{maxcpus} specifies the maximum number of hotpluggable CPUs. +@var{apics} specifies the boot bitmap of existed apicid.
s/existed/existing/
qemu-options.hx of @var{threads} per cores and the total number of @var{sockets} can be · line 103
Quoted 7 lines
qemu-options.hx +7
-0+ +@example +#specify the boot bitmap of apicid with 0 and 2: +qemu-system-i386 -smp 2,apics=0xA,maxcpus=4 /* 1010 */ +#specify the boot bitmap of apicid with 1 and 7: +qemu-system-i386 -smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */ +@end example
These examples would need updating to match my concerns.
vl.c static QemuOptsList qemu_smp_opts = { · line 1387
Quoted 7 lines
vl.c +3
-0@@ -1379,6 +1382,9 @@ static QemuOptsList qemu_smp_opts = { }, { .name = "maxcpus", .type = QEMU_OPT_NUMBER, + }, { + .name = "apics", + .type = QEMU_OPT_STRING,
Why a string with your own ad-hoc parser? Can't we reuse some of the existing parsers that already know how to handle (possibly-disjoint) lists of cpu numbers?
vl.c static void smp_parse(QemuOpts *opts) · line 1427
Quoted 2 lines
vl.c +2
-0+if (apics) { +if (strstart (apics,"0x" , &apics)) {
Why not also allow 0X?
vl.c static void smp_parse(QemuOpts *opts) · line 1439
Quoted 12 lines
vl.c +12
-0+if (*apics !='\0' ) { +int i, count; +int64_t max_apicid =0 ; +uint32_t val; +char tmp[2 ]; + + count =strlen (apics); + +for (i =0 ; i < count; i++) { + tmp[0 ] = apics[i]; + tmp[1 ] ='\0' ; +sscanf (tmp,"%x" , &val);
sscanf is evil. It has undefined behavior on input overflow (that is, if I say 0x10000000000000000, there is no guarantee what sscanf will stick into val). All the more reason you should be using an existing parser which gracefully handles overflow.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [RFC 2/3] target-i386: add -smp X,apics=0x option
Quoted 24 lines · Eric Blake
Quoted 7 lines · Chen Fan
This option provides the infrastructure for specifying apicids when boot VM, For example:
#boot with apicid 0 and 2:
-smp 2,apics=0xA,maxcpus=4 /* 1010 */
#boot with apicid 1 and 7:
-smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */This syntax feels a bit odd when maxcpus is not a multiple of 8, and even harder when not a multiple of 4. I think part of my confusion stems from you treating the lsb as the left-most bit, but expect me to
write in hex where I'm used to the right-most bit being lsb Wouldn't
it be easier to express:msb .... lsb
with leading 0s implied as needed, as in:
0x5=> 0101 => id 0 (lsb) and id 2 are enabled, regardless of whether maxcpus=4 or maxcpus=80x82=> 1000 0010 => id 1 and id 7 are enabled, regardless of whether maxcpus=8 or maxcpus=256
Quoted 7 lines
0x100000000=> id 32 is enabledOr even better, why not reuse existing parsers that take cpu ids directly as numbers instead of making me compute a bitmap (as in maxcpus=4,id=0,id=2 - although I don't quite know QemuOpts well enough to know if you can repeat id= for forming a list of disjoint id numbers)
Thanks for your review, but this form was deprecated. Igor proposed using -device /-device-add to specify the disjoint id numbers.
Thanks,
Chen
Quoted 53 lines
qemu-options.hx of @var{threads} per cores and the total number of @var{sockets} can be · line 96
Quoted 5 lines
qemu-options.hx +1
-0@@ -92,6 +93,14 @@ of @var{threads} per cores and the total number of @var{sockets} can be specified. Missing values will be computed. If any on the three values is given, the total number of CPUs @var{n} can be omitted. @var{maxcpus} specifies the maximum number of hotpluggable CPUs. +@var{apics} specifies the boot bitmap of existed apicid.s/existed/existing/
qemu-options.hx of @var{threads} per cores and the total number of @var{sockets} can be · line 103
Quoted 7 lines
qemu-options.hx +7
-0+ +@example +#specify the boot bitmap of apicid with 0 and 2: +qemu-system-i386 -smp 2,apics=0xA,maxcpus=4 /* 1010 */ +#specify the boot bitmap of apicid with 1 and 7: +qemu-system-i386 -smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */ +@end exampleThese examples would need updating to match my concerns.
vl.c static QemuOptsList qemu_smp_opts = { · line 1387
Quoted 7 lines
vl.c +3
-0@@ -1379,6 +1382,9 @@ static QemuOptsList qemu_smp_opts = { }, { .name = "maxcpus", .type = QEMU_OPT_NUMBER, + }, { + .name = "apics", + .type = QEMU_OPT_STRING,Why a string with your own ad-hoc parser? Can't we reuse some of the existing parsers that already know how to handle (possibly-disjoint) lists of cpu numbers?
vl.c static void smp_parse(QemuOpts *opts) · line 1427
Quoted 2 lines
vl.c +2
-0+if (apics) { +if (strstart (apics,"0x" , &apics)) {Why not also allow 0X?
vl.c static void smp_parse(QemuOpts *opts) · line 1439
Quoted 12 lines
vl.c +12
-0+if (*apics !='\0' ) { +int i, count; +int64_t max_apicid =0 ; +uint32_t val; +char tmp[2 ]; + + count =strlen (apics); + +for (i =0 ; i < count; i++) { + tmp[0 ] = apics[i]; + tmp[1 ] ='\0' ; +sscanf (tmp,"%x" , &val);sscanf is evil. It has undefined behavior on input overflow (that is, if I say
0x10000000000000000, there is no guarantee what sscanf will stick into val). All the more reason you should be using an existing parser which gracefully handles overflow.
RFC 3/3 target-i386: add qmp command 'query-cpus' to display apic_id
In reply to Chen Fanthis patch provided the apic_id display as using command 'query-cpus'.
--- cpus.c | 1 + qapi-schema.json | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
cpus.c +1 -0
@@ -1351,6 +1351,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)#if defined(TARGET_I386 ) info->value->has_pc = true; info->value->pc = env->eip + env->segs[R_CS ].base; + info->value->apic_id = env->cpuid_apic_id;#elif defined(TARGET_PPC ) info->value->has_nip = true; info->value->nip = env->nip;
qapi-schema.json +3 -1
@@ -783,6 +783,8 @@ # # @thread_id: ID of the underlying host thread # +# @apic_id: the apic id of the virtual CPU +# # Since: 0.14.0 # # Notes: @halted is a transient state that changes frequently. By the time the
@@ -790,7 +792,7 @@ ## { 'type': 'CpuInfo', 'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int', - '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} } + '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int', 'apic_id': 'int'} } ## # @query-cpus:
Signature · 1 line
1.8.1.4
Re: [Qemu-devel] [RFC 3/3] target-i386: add qmp command 'query-cpus' to display apic_id
Quoted 11 lines · Chen Fan
this patch provided the
apic_iddisplay as using command 'query-cpus'.Signed-off-by Chen Fan <[email protected]>--- cpus.c | 1 + qapi-schema.json | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)+++
b/qapi-schema.json
qapi-schema.json line 787
Quoted 5 lines
qapi-schema.json +2
-0@@ -783,6 +783,8 @@ # # @thread_id: ID of the underlying host thread # +# @apic_id: the apic id of the virtual CPU +#
Needs a (since 2.0) designation on this line.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org