From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:50:18
Hello,
ipistorm [*] can be used to benchmark the raw interrupt rate of an
interrupt controller by measuring the number of IPIs a system can
sustain. When applied to the XIVE interrupt controller of POWER9 and
POWER10 systems, a significant drop of the interrupt rate can be
observed when crossing the second node boundary.
This is due to the fact that a single IPI interrupt is used for all
CPUs of the system. The structure is shared and the cache line updates
impact greatly the traffic between nodes and the overall IPI
performance.
As a workaround, the impact can be reduced by deactivating the IRQ
lockup detector ("noirqdebug") which does a lot of accounting in the
Linux IRQ descriptor structure and is responsible for most of the
performance penalty.
As a fix, this proposal allocates an IPI interrupt per node, to be
shared by all CPUs of that node. It solves the scaling issue, the IRQ
lockup detector still has an impact but the XIVE interrupt rate scales
linearly. It also improves the "noirqdebug" case as showed in the
tables below.
* P9 DD2.2 - 2s * 64 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 4.984023 4.875405 4.996536 5.048892
0-31 10.879164 10.544040 10.757632 11.037859
0-47 15.345301 14.688764 14.926520 15.310053
0-63 17.064907 17.066812 17.613416 17.874511
2 0-79 11.768764 21.650749 22.689120 22.566508
0-95 10.616812 26.878789 28.434703 28.320324
0-111 10.151693 31.397803 31.771773 32.388122
0-127 9.948502 33.139336 34.875716 35.224548
* P10 DD1 - 4s (not homogeneous) 352 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 2.409402 2.364108 2.383303 2.395091
0-31 6.028325 6.046075 6.089999 6.073750
0-47 8.655178 8.644531 8.712830 8.724702
0-63 11.629652 11.735953 12.088203 12.055979
0-79 14.392321 14.729959 14.986701 14.973073
0-95 12.604158 13.004034 17.528748 17.568095
2 0-111 9.767753 13.719831 19.968606 20.024218
0-127 6.744566 16.418854 22.898066 22.995110
0-143 6.005699 19.174421 25.425622 25.417541
0-159 5.649719 21.938836 27.952662 28.059603
0-175 5.441410 24.109484 31.133915 31.127996
3 0-191 5.318341 24.405322 33.999221 33.775354
0-207 5.191382 26.449769 36.050161 35.867307
0-223 5.102790 29.356943 39.544135 39.508169
0-239 5.035295 31.933051 42.135075 42.071975
0-255 4.969209 34.477367 44.655395 44.757074
4 0-271 4.907652 35.887016 47.080545 47.318537
0-287 4.839581 38.076137 50.464307 50.636219
0-303 4.786031 40.881319 53.478684 53.310759
0-319 4.743750 43.448424 56.388102 55.973969
0-335 4.709936 45.623532 59.400930 58.926857
0-351 4.681413 45.646151 62.035804 61.830057
[*] https://github.com/antonblanchard/ipistorm
Thanks,
C.
Changes in v2:
- extra simplification on xmon
- fixes on issues reported by the kernel test robot
Cédric Le Goater (8):
powerpc/xive: Use cpu_to_node() instead of ibm,chip-id property
powerpc/xive: Introduce an IPI interrupt domain
powerpc/xive: Remove useless check on XIVE_IPI_HW_IRQ
powerpc/xive: Simplify xive_core_debug_show()
powerpc/xive: Drop check on irq_data in xive_core_debug_show()
powerpc/xive: Simplify the dump of XIVE interrupts under xmon
powerpc/xive: Fix xmon command "dxi"
powerpc/xive: Map one IPI interrupt per node
arch/powerpc/include/asm/xive.h | 1 +
arch/powerpc/sysdev/xive/xive-internal.h | 2 -
arch/powerpc/sysdev/xive/common.c | 163 +++++++++++++----------
arch/powerpc/xmon/xmon.c | 28 +---
4 files changed, 93 insertions(+), 101 deletions(-)
--
2.26.2
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:49:38
Move the xmon routine under XIVE subsystem and rework the loop on the
interrupts taking into account the xive_irq_domain to filter out IPIs.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/include/asm/xive.h | 1 +
arch/powerpc/sysdev/xive/common.c | 14 ++++++++++++++
arch/powerpc/xmon/xmon.c | 28 ++--------------------------
3 files changed, 17 insertions(+), 26 deletions(-)
@@ -2727,30 +2727,6 @@ static void dump_all_xives(void)dump_one_xive(cpu);}-staticvoiddump_one_xive_irq(u32num,structirq_data*d)-{-xmon_xive_get_irq_config(num,d);-}--staticvoiddump_all_xive_irq(void)-{-unsignedinti;-structirq_desc*desc;--for_each_irq_desc(i,desc){-structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthwirq;--if(!d)-continue;--hwirq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hwirq)-dump_one_xive_irq(hwirq,d);-}-}-staticvoiddump_xives(void){unsignedlongnum;
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:49:56
ipistorm [*] can be used to benchmark the raw interrupt rate of an
interrupt controller by measuring the number of IPIs a system can
sustain. When applied to the XIVE interrupt controller of POWER9 and
POWER10 systems, a significant drop of the interrupt rate can be
observed when crossing the second node boundary.
This is due to the fact that a single IPI interrupt is used for all
CPUs of the system. The structure is shared and the cache line updates
impact greatly the traffic between nodes and the overall IPI
performance.
As a workaround, the impact can be reduced by deactivating the IRQ
lockup detector ("noirqdebug") which does a lot of accounting in the
Linux IRQ descriptor structure and is responsible for most of the
performance penalty.
As a fix, this proposal allocates an IPI interrupt per node, to be
shared by all CPUs of that node. It solves the scaling issue, the IRQ
lockup detector still has an impact but the XIVE interrupt rate scales
linearly. It also improves the "noirqdebug" case as showed in the
tables below.
* P9 DD2.2 - 2s * 64 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 4.984023 4.875405 4.996536 5.048892
0-31 10.879164 10.544040 10.757632 11.037859
0-47 15.345301 14.688764 14.926520 15.310053
0-63 17.064907 17.066812 17.613416 17.874511
2 0-79 11.768764 21.650749 22.689120 22.566508
0-95 10.616812 26.878789 28.434703 28.320324
0-111 10.151693 31.397803 31.771773 32.388122
0-127 9.948502 33.139336 34.875716 35.224548
* P10 DD1 - 4s (not homogeneous) 352 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 2.409402 2.364108 2.383303 2.395091
0-31 6.028325 6.046075 6.089999 6.073750
0-47 8.655178 8.644531 8.712830 8.724702
0-63 11.629652 11.735953 12.088203 12.055979
0-79 14.392321 14.729959 14.986701 14.973073
0-95 12.604158 13.004034 17.528748 17.568095
2 0-111 9.767753 13.719831 19.968606 20.024218
0-127 6.744566 16.418854 22.898066 22.995110
0-143 6.005699 19.174421 25.425622 25.417541
0-159 5.649719 21.938836 27.952662 28.059603
0-175 5.441410 24.109484 31.133915 31.127996
3 0-191 5.318341 24.405322 33.999221 33.775354
0-207 5.191382 26.449769 36.050161 35.867307
0-223 5.102790 29.356943 39.544135 39.508169
0-239 5.035295 31.933051 42.135075 42.071975
0-255 4.969209 34.477367 44.655395 44.757074
4 0-271 4.907652 35.887016 47.080545 47.318537
0-287 4.839581 38.076137 50.464307 50.636219
0-303 4.786031 40.881319 53.478684 53.310759
0-319 4.743750 43.448424 56.388102 55.973969
0-335 4.709936 45.623532 59.400930 58.926857
0-351 4.681413 45.646151 62.035804 61.830057
[*] https://github.com/antonblanchard/ipistorm
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/xive-internal.h | 2 --
arch/powerpc/sysdev/xive/common.c | 39 ++++++++++++++++++------
2 files changed, 30 insertions(+), 11 deletions(-)
@@ -65,8 +65,16 @@ static struct irq_domain *xive_irq_domain;#ifdef CONFIG_SMPstaticstructirq_domain*xive_ipi_irq_domain;-/* The IPIs all use the same logical irq number */-staticu32xive_ipi_irq;+/* The IPIs use the same logical irq number when on the same chip */+staticstructxive_ipi_desc{+unsignedintirq;+charname[8];/* enough bytes to fit IPI-XXX */+}*xive_ipis;++staticunsignedintxive_ipi_cpu_to_irq(unsignedintcpu)+{+returnxive_ipis[cpu_to_node(cpu)].irq;+}#endif/* Xive state for each CPU */
@@ -1106,25 +1114,36 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = {staticvoid__initxive_request_ipi(void){-unsignedintvirq;+unsignedintnode;-xive_ipi_irq_domain=irq_domain_add_linear(NULL,1,+xive_ipi_irq_domain=irq_domain_add_linear(NULL,nr_node_ids,&xive_ipi_irq_domain_ops,NULL);if(WARN_ON(xive_ipi_irq_domain==NULL))return;-/* Initialize it */-virq=irq_create_mapping(xive_ipi_irq_domain,XIVE_IPI_HW_IRQ);-xive_ipi_irq=virq;+xive_ipis=kcalloc(nr_node_ids,sizeof(*xive_ipis),GFP_KERNEL|__GFP_NOFAIL);+for_each_node(node){+structxive_ipi_desc*xid=&xive_ipis[node];+irq_hw_number_tnode_ipi_hwirq=node;++/*+*MaponeIPIinterruptpernodeforallcpusofthatnode.+*SincetheHWinterruptnumberdoesn'thaveanymeaning,+*simplyusethenodenumber.+*/+xid->irq=irq_create_mapping(xive_ipi_irq_domain,node_ipi_hwirq);+snprintf(xid->name,sizeof(xid->name),"IPI-%d",node);-WARN_ON(request_irq(virq,xive_muxed_ipi_action,-IRQF_PERCPU|IRQF_NO_THREAD,"IPI",NULL));+WARN_ON(request_irq(xid->irq,xive_muxed_ipi_action,+IRQF_PERCPU|IRQF_NO_THREAD,xid->name,NULL));+}}staticintxive_setup_cpu_ipi(unsignedintcpu){structxive_cpu*xc;intrc;+unsignedintxive_ipi_irq=xive_ipi_cpu_to_irq(cpu);pr_debug("Setting up IPI for CPU %d\n",cpu);
@@ -1165,6 +1184,8 @@ static int xive_setup_cpu_ipi(unsigned int cpu)staticvoidxive_cleanup_cpu_ipi(unsignedintcpu,structxive_cpu*xc){+unsignedintxive_ipi_irq=xive_ipi_cpu_to_irq(cpu);+/* Disable the IPI and free the IRQ data *//* Already cleaned up ? */
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:50:37
When under xmon, the "dxi" command dumps the state of the XIVE
interrupts. If an interrupt number is specified, only the state of
the associated XIVE interrupt is dumped. This form of the command
lacks an irq_data parameter which is nevertheless used by
xmon_xive_get_irq_config(), leading to an xmon crash.
Fix that by doing a lookup in the system IRQ mapping to query the IRQ
descriptor data. Invalid interrupt numbers, or not belonging to the
XIVE IRQ domain, OPAL event interrupt number for instance, should be
caught by the previous query done at the firmware level.
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 97ef27507793 ("powerpc/xive: Fix xmon support on the PowerNV platform")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/common.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:51:02
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/common.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:51:20
The IPI interrupt is a special case of the XIVE IRQ domain. When
mapping and unmapping the interrupts in the Linux interrupt number
space, the HW interrupt number 0 (XIVE_IPI_HW_IRQ) is checked to
distinguish the IPI interrupt from other interrupts of the system.
Simplify the XIVE interrupt domain by introducing a specific domain
for the IPI.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/common.c | 51 +++++++++++++------------------
1 file changed, 22 insertions(+), 29 deletions(-)
@@ -63,6 +63,8 @@ static const struct xive_ops *xive_ops;staticstructirq_domain*xive_irq_domain;#ifdef CONFIG_SMP+staticstructirq_domain*xive_ipi_irq_domain;+/* The IPIs all use the same logical irq number */staticu32xive_ipi_irq;#endif
@@ -1178,19 +1192,6 @@ static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,*/irq_clear_status_flags(virq,IRQ_LEVEL);-#ifdef CONFIG_SMP-/* IPIs are special and come up with HW number 0 */-if(hw==XIVE_IPI_HW_IRQ){-/*-*IPIsaremarkedper-cpu.WeuseseparateHWinterruptsunder-*thehoodbutassociatedwiththesame"linux"interrupt-*/-irq_set_chip_and_handler(virq,&xive_ipi_chip,-handle_percpu_irq);-return0;-}-#endif-rc=xive_irq_alloc_data(virq,hw);if(rc)returnrc;
@@ -1202,15 +1203,7 @@ static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,staticvoidxive_irq_domain_unmap(structirq_domain*d,unsignedintvirq){-structirq_data*data=irq_get_irq_data(virq);-unsignedinthw_irq;--/* XXX Assign BAD number */-if(!data)-return;-hw_irq=(unsignedint)irqd_to_hwirq(data);-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_irq_free_data(virq);+xive_irq_free_data(virq);}staticintxive_irq_domain_xlate(structirq_domain*h,structdevice_node*ct,
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:51:55
The IPI interrupt has its own domain now. Testing the HW interrupt
number is not needed anymore.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/common.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-03 17:52:14
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/common.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
@@ -1335,16 +1335,11 @@ static int xive_prepare_cpu(unsigned int cpu)xc=per_cpu(xive_cpu,cpu);if(!xc){-structdevice_node*np;-xc=kzalloc_node(sizeof(structxive_cpu),GFP_KERNEL,cpu_to_node(cpu));if(!xc)return-ENOMEM;-np=of_get_cpu_node(cpu,NULL);-if(np)-xc->chip_id=of_get_ibm_chip_id(np);-of_node_put(np);+xc->chip_id=cpu_to_node(cpu);xc->hw_ipi=XIVE_BAD_IRQ;per_cpu(xive_cpu,cpu)=xc;
From: Greg Kurz <hidden> Date: 2021-03-08 17:24:01
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT. It
looks like the chip id is only used for localization purpose in
this case, right ?
In this case, what about doing this change for pSeries only,
somewhere in spapr.c ?
@@ -1335,16 +1335,11 @@ static int xive_prepare_cpu(unsigned int cpu)xc=per_cpu(xive_cpu,cpu);if(!xc){-structdevice_node*np;-xc=kzalloc_node(sizeof(structxive_cpu),GFP_KERNEL,cpu_to_node(cpu));if(!xc)return-ENOMEM;-np=of_get_cpu_node(cpu,NULL);-if(np)-xc->chip_id=of_get_ibm_chip_id(np);-of_node_put(np);+xc->chip_id=cpu_to_node(cpu);xc->hw_ipi=XIVE_BAD_IRQ;per_cpu(xive_cpu,cpu)=xc;
From: Greg Kurz <hidden> Date: 2021-03-08 18:16:15
On Wed, 3 Mar 2021 18:48:53 +0100
Cédric Le Goater [off-list ref] wrote:
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Shouldn't this have the following tags ?
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
Anyway,
Reviewed-by: Greg Kurz <redacted>
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-08 18:16:54
On 3/8/21 7:07 PM, Greg Kurz wrote:
On Wed, 3 Mar 2021 18:48:53 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Shouldn't this have the following tags ?
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
The next patch has because it removes the useless check on irq_data.
C.
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Greg Kurz <hidden> Date: 2021-03-08 20:24:15
On Wed, 3 Mar 2021 18:48:51 +0100
Cédric Le Goater [off-list ref] wrote:
The IPI interrupt is a special case of the XIVE IRQ domain. When
mapping and unmapping the interrupts in the Linux interrupt number
space, the HW interrupt number 0 (XIVE_IPI_HW_IRQ) is checked to
distinguish the IPI interrupt from other interrupts of the system.
Simplify the XIVE interrupt domain by introducing a specific domain
for the IPI.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
@@ -63,6 +63,8 @@ static const struct xive_ops *xive_ops;staticstructirq_domain*xive_irq_domain;#ifdef CONFIG_SMP+staticstructirq_domain*xive_ipi_irq_domain;+/* The IPIs all use the same logical irq number */staticu32xive_ipi_irq;#endif
@@ -1178,19 +1192,6 @@ static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,*/irq_clear_status_flags(virq,IRQ_LEVEL);-#ifdef CONFIG_SMP-/* IPIs are special and come up with HW number 0 */-if(hw==XIVE_IPI_HW_IRQ){-/*-*IPIsaremarkedper-cpu.WeuseseparateHWinterruptsunder-*thehoodbutassociatedwiththesame"linux"interrupt-*/-irq_set_chip_and_handler(virq,&xive_ipi_chip,-handle_percpu_irq);-return0;-}-#endif-rc=xive_irq_alloc_data(virq,hw);if(rc)returnrc;
@@ -1202,15 +1203,7 @@ static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,staticvoidxive_irq_domain_unmap(structirq_domain*d,unsignedintvirq){-structirq_data*data=irq_get_irq_data(virq);-unsignedinthw_irq;--/* XXX Assign BAD number */-if(!data)-return;-hw_irq=(unsignedint)irqd_to_hwirq(data);-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_irq_free_data(virq);+xive_irq_free_data(virq);}staticintxive_irq_domain_xlate(structirq_domain*h,structdevice_node*ct,
From: Greg Kurz <hidden> Date: 2021-03-09 09:14:08
On Mon, 8 Mar 2021 19:11:11 +0100
Cédric Le Goater [off-list ref] wrote:
On 3/8/21 7:07 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:53 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Shouldn't this have the following tags ?
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
The next patch has because it removes the useless check on irq_data.
Ok I get it. This report isn't about an actual crash. Just a false
positive because of the not needed check in the caller.
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Greg Kurz <hidden> Date: 2021-03-09 09:23:09
On Wed, 3 Mar 2021 18:48:55 +0100
Cédric Le Goater [off-list ref] wrote:
Move the xmon routine under XIVE subsystem and rework the loop on the
interrupts taking into account the xive_irq_domain to filter out IPIs.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
@@ -2727,30 +2727,6 @@ static void dump_all_xives(void)dump_one_xive(cpu);}-staticvoiddump_one_xive_irq(u32num,structirq_data*d)-{-xmon_xive_get_irq_config(num,d);-}--staticvoiddump_all_xive_irq(void)-{-unsignedinti;-structirq_desc*desc;--for_each_irq_desc(i,desc){-structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthwirq;--if(!d)-continue;--hwirq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hwirq)-dump_one_xive_irq(hwirq,d);-}-}-staticvoiddump_xives(void){unsignedlongnum;
From: Greg Kurz <hidden> Date: 2021-03-09 09:28:45
On Wed, 3 Mar 2021 18:48:54 +0100
Cédric Le Goater [off-list ref] wrote:
When looping on IRQ descriptor, irq_data is always valid.
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
From: Greg Kurz <hidden> Date: 2021-03-09 09:42:48
On Tue, 9 Mar 2021 10:13:39 +0100
Greg Kurz [off-list ref] wrote:
On Mon, 8 Mar 2021 19:11:11 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/8/21 7:07 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:53 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Shouldn't this have the following tags ?
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
The next patch has because it removes the useless check on irq_data.
Ok I get it. This report isn't about an actual crash. Just a false
positive because of the not needed check in the caller.
Hrm... I meant because of the check in xive_debug_show_irq(). On the
contrary, the check removed by this patch in xive_core_debug_show()
was rather an explicit hint that xive_debug_show_irq() couldn't be
called with d being NULL.
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Greg Kurz <hidden> Date: 2021-03-09 10:23:53
On Wed, 3 Mar 2021 18:48:56 +0100
Cédric Le Goater [off-list ref] wrote:
When under xmon, the "dxi" command dumps the state of the XIVE
interrupts. If an interrupt number is specified, only the state of
the associated XIVE interrupt is dumped. This form of the command
lacks an irq_data parameter which is nevertheless used by
xmon_xive_get_irq_config(), leading to an xmon crash.
Fix that by doing a lookup in the system IRQ mapping to query the IRQ
descriptor data. Invalid interrupt numbers, or not belonging to the
XIVE IRQ domain, OPAL event interrupt number for instance, should be
caught by the previous query done at the firmware level.
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 97ef27507793 ("powerpc/xive: Fix xmon support on the PowerNV platform")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
I've tested this in a KVM guest and it seems to do the job.
6:mon> dxi 1201
IRQ 0x00001201 : target=0xfffffc00 prio=ff lirq=0x0 flags= LH PQ=-Q
Bad HW irq numbers are filtered by the hypervisor:
6:mon> dxi bad
[ 696.390577] xive: H_INT_GET_SOURCE_CONFIG lisn=2989 failed -55
IRQ 0x00000bad : no config rc=-6
Note that this also allows to show IPIs:
6:mon> dxi 0
IRQ 0x00000000 : target=0x0 prio=06 lirq=0x10
This is a bit inconsistent with output of the 0-argument form of "dxi",
which filters them out for a reason that isn't obvious to me. No big
deal though, this should be addressed in another patch anyway.
Reviewed-and-tested-by: Greg Kurz [off-list ref]
From: Greg Kurz <hidden> Date: 2021-03-09 13:23:59
On Wed, 3 Mar 2021 18:48:57 +0100
Cédric Le Goater [off-list ref] wrote:
quoted hunk
ipistorm [*] can be used to benchmark the raw interrupt rate of an
interrupt controller by measuring the number of IPIs a system can
sustain. When applied to the XIVE interrupt controller of POWER9 and
POWER10 systems, a significant drop of the interrupt rate can be
observed when crossing the second node boundary.
This is due to the fact that a single IPI interrupt is used for all
CPUs of the system. The structure is shared and the cache line updates
impact greatly the traffic between nodes and the overall IPI
performance.
As a workaround, the impact can be reduced by deactivating the IRQ
lockup detector ("noirqdebug") which does a lot of accounting in the
Linux IRQ descriptor structure and is responsible for most of the
performance penalty.
As a fix, this proposal allocates an IPI interrupt per node, to be
shared by all CPUs of that node. It solves the scaling issue, the IRQ
lockup detector still has an impact but the XIVE interrupt rate scales
linearly. It also improves the "noirqdebug" case as showed in the
tables below.
* P9 DD2.2 - 2s * 64 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 4.984023 4.875405 4.996536 5.048892
0-31 10.879164 10.544040 10.757632 11.037859
0-47 15.345301 14.688764 14.926520 15.310053
0-63 17.064907 17.066812 17.613416 17.874511
2 0-79 11.768764 21.650749 22.689120 22.566508
0-95 10.616812 26.878789 28.434703 28.320324
0-111 10.151693 31.397803 31.771773 32.388122
0-127 9.948502 33.139336 34.875716 35.224548
* P10 DD1 - 4s (not homogeneous) 352 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 2.409402 2.364108 2.383303 2.395091
0-31 6.028325 6.046075 6.089999 6.073750
0-47 8.655178 8.644531 8.712830 8.724702
0-63 11.629652 11.735953 12.088203 12.055979
0-79 14.392321 14.729959 14.986701 14.973073
0-95 12.604158 13.004034 17.528748 17.568095
2 0-111 9.767753 13.719831 19.968606 20.024218
0-127 6.744566 16.418854 22.898066 22.995110
0-143 6.005699 19.174421 25.425622 25.417541
0-159 5.649719 21.938836 27.952662 28.059603
0-175 5.441410 24.109484 31.133915 31.127996
3 0-191 5.318341 24.405322 33.999221 33.775354
0-207 5.191382 26.449769 36.050161 35.867307
0-223 5.102790 29.356943 39.544135 39.508169
0-239 5.035295 31.933051 42.135075 42.071975
0-255 4.969209 34.477367 44.655395 44.757074
4 0-271 4.907652 35.887016 47.080545 47.318537
0-287 4.839581 38.076137 50.464307 50.636219
0-303 4.786031 40.881319 53.478684 53.310759
0-319 4.743750 43.448424 56.388102 55.973969
0-335 4.709936 45.623532 59.400930 58.926857
0-351 4.681413 45.646151 62.035804 61.830057
[*] https://github.com/antonblanchard/ipistorm
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/xive-internal.h | 2 --
arch/powerpc/sysdev/xive/common.c | 39 ++++++++++++++++++------
2 files changed, 30 insertions(+), 11 deletions(-)
@@ -65,8 +65,16 @@ static struct irq_domain *xive_irq_domain;#ifdef CONFIG_SMPstaticstructirq_domain*xive_ipi_irq_domain;-/* The IPIs all use the same logical irq number */-staticu32xive_ipi_irq;+/* The IPIs use the same logical irq number when on the same chip */+staticstructxive_ipi_desc{+unsignedintirq;+charname[8];/* enough bytes to fit IPI-XXX */
So this assumes that the node number that node is <= 999 ? This
is certainly the case for now since CONFIG_NODES_SHIFT is 8
on ppc64 but starting with 10, you'd have truncated names.
What about deriving the size of name[] from CONFIG_NODES_SHIFT ?
Apart from that, LGTM. Probably not worth to respin just for
this.
I also could give a try in a KVM guest.
Topology passed to QEMU:
-smp 8,maxcpus=8,cores=2,threads=2,sockets=2 \
-numa node,nodeid=0,cpus=0-4 \
-numa node,nodeid=1,cpus=4-7
Topology observed in guest with lstopo :
Package L#0
NUMANode L#0 (P#0 30GB)
L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
PU L#0 (P#0)
PU L#1 (P#1)
L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
PU L#2 (P#2)
PU L#3 (P#3)
Package L#1
NUMANode L#1 (P#1 32GB)
L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2
PU L#4 (P#4)
PU L#5 (P#5)
L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3
PU L#6 (P#6)
PU L#7 (P#7)
Interrupts in guest:
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
16: 1023 871 1042 749 0 0 0 0 XIVE-IPI 0 Edge IPI-0
17: 0 0 0 0 2123 1019 1263 1288 XIVE-IPI 1 Edge IPI-1
IPIs are mapped to the appropriate nodes, and the numbers indicate
that everything is working as expected.
Reviewed-and-tested-by: Greg Kurz [off-list ref]
quoted hunk
+} *xive_ipis;
+
+static unsigned int xive_ipi_cpu_to_irq(unsigned int cpu)
+{
+ return xive_ipis[cpu_to_node(cpu)].irq;
+}
#endif
/* Xive state for each CPU */
@@ -1106,25 +1114,36 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = { static void __init xive_request_ipi(void) {- unsigned int virq;+ unsigned int node;- xive_ipi_irq_domain = irq_domain_add_linear(NULL, 1,+ xive_ipi_irq_domain = irq_domain_add_linear(NULL, nr_node_ids, &xive_ipi_irq_domain_ops, NULL); if (WARN_ON(xive_ipi_irq_domain == NULL)) return;- /* Initialize it */- virq = irq_create_mapping(xive_ipi_irq_domain, XIVE_IPI_HW_IRQ);- xive_ipi_irq = virq;+ xive_ipis = kcalloc(nr_node_ids, sizeof(*xive_ipis), GFP_KERNEL | __GFP_NOFAIL);+ for_each_node(node) {+ struct xive_ipi_desc *xid = &xive_ipis[node];+ irq_hw_number_t node_ipi_hwirq = node;++ /*+ * Map one IPI interrupt per node for all cpus of that node.+ * Since the HW interrupt number doesn't have any meaning,+ * simply use the node number.+ */+ xid->irq = irq_create_mapping(xive_ipi_irq_domain, node_ipi_hwirq);+ snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);- WARN_ON(request_irq(virq, xive_muxed_ipi_action,- IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL));+ WARN_ON(request_irq(xid->irq, xive_muxed_ipi_action,+ IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL));+ } } static int xive_setup_cpu_ipi(unsigned int cpu) { struct xive_cpu *xc; int rc;+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu); pr_debug("Setting up IPI for CPU %d\n", cpu);
@@ -1165,6 +1184,8 @@ static int xive_setup_cpu_ipi(unsigned int cpu) static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) {+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);+ /* Disable the IPI and free the IRQ data */ /* Already cleaned up ? */
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-09 15:34:05
On 3/8/21 6:13 PM, Greg Kurz wrote:
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
It looks like the chip id is only used for localization purpose in
this case, right ?
Yes and PAPR sources are not localized. So it's not used. MSI sources
could be if we rewrote the MSI driver.
In this case, what about doing this change for pSeries only,
somewhere in spapr.c ?
The IPI code is common to all platforms and all have the same issue.
I rather not.
Thanks,
C.
@@ -1335,16 +1335,11 @@ static int xive_prepare_cpu(unsigned int cpu)xc=per_cpu(xive_cpu,cpu);if(!xc){-structdevice_node*np;-xc=kzalloc_node(sizeof(structxive_cpu),GFP_KERNEL,cpu_to_node(cpu));if(!xc)return-ENOMEM;-np=of_get_cpu_node(cpu,NULL);-if(np)-xc->chip_id=of_get_ibm_chip_id(np);-of_node_put(np);+xc->chip_id=cpu_to_node(cpu);xc->hw_ipi=XIVE_BAD_IRQ;per_cpu(xive_cpu,cpu)=xc;
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-09 15:40:23
On 3/9/21 10:42 AM, Greg Kurz wrote:
On Tue, 9 Mar 2021 10:13:39 +0100
Greg Kurz [off-list ref] wrote:
quoted
On Mon, 8 Mar 2021 19:11:11 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/8/21 7:07 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:53 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
Now that the IPI interrupt has its own domain, the checks on the HW
interrupt number XIVE_IPI_HW_IRQ and on the chip can be replaced by a
check on the domain.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Shouldn't this have the following tags ?
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 930914b7d528 ("powerpc/xive: Add a debugfs file to dump internal XIVE state")
The next patch has because it removes the useless check on irq_data.
Ok I get it. This report isn't about an actual crash. Just a false
positive because of the not needed check in the caller.
Hrm... I meant because of the check in xive_debug_show_irq(). On the
contrary, the check removed by this patch in xive_core_debug_show()
was rather an explicit hint that xive_debug_show_irq() couldn't be
called with d being NULL.
yes. irq_desc_get_irq_data() does not return a NULL value and
xive_debug_show_irq() is only called from the for_each_irq_desc()
loop.
C.
@@ -1579,17 +1579,14 @@ static void xive_debug_show_cpu(struct seq_file *m, int cpu)seq_puts(m,"\n");}-staticvoidxive_debug_show_irq(structseq_file*m,u32hw_irq,structirq_data*d)+staticvoidxive_debug_show_irq(structseq_file*m,structirq_data*d){-structirq_chip*chip=irq_data_get_irq_chip(d);+unsignedinthw_irq=(unsignedint)irqd_to_hwirq(d);intrc;u32target;u8prio;u32lirq;-if(!is_xive_irq(chip))-return;-rc=xive_ops->get_irq_config(hw_irq,&target,&prio,&lirq);if(rc){seq_printf(m,"IRQ 0x%08x : no config rc=%d\n",hw_irq,rc);
@@ -1627,16 +1624,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)for_each_irq_desc(i,desc){structirq_data*d=irq_desc_get_irq_data(desc);-unsignedinthw_irq;--if(!d)-continue;--hw_irq=(unsignedint)irqd_to_hwirq(d);-/* IPIs are special (HW number 0) */-if(hw_irq!=XIVE_IPI_HW_IRQ)-xive_debug_show_irq(m,hw_irq,d);+if(d->domain==xive_irq_domain)+xive_debug_show_irq(m,d);}return0;}
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-09 15:49:36
On 3/9/21 11:23 AM, Greg Kurz wrote:
On Wed, 3 Mar 2021 18:48:56 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
When under xmon, the "dxi" command dumps the state of the XIVE
interrupts. If an interrupt number is specified, only the state of
the associated XIVE interrupt is dumped. This form of the command
lacks an irq_data parameter which is nevertheless used by
xmon_xive_get_irq_config(), leading to an xmon crash.
Fix that by doing a lookup in the system IRQ mapping to query the IRQ
descriptor data. Invalid interrupt numbers, or not belonging to the
XIVE IRQ domain, OPAL event interrupt number for instance, should be
caught by the previous query done at the firmware level.
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>
Fixes: 97ef27507793 ("powerpc/xive: Fix xmon support on the PowerNV platform")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
I've tested this in a KVM guest and it seems to do the job.
6:mon> dxi 1201
IRQ 0x00001201 : target=0xfffffc00 prio=ff lirq=0x0 flags= LH PQ=-Q
Bad HW irq numbers are filtered by the hypervisor:
6:mon> dxi bad
[ 696.390577] xive: H_INT_GET_SOURCE_CONFIG lisn=2989 failed -55
IRQ 0x00000bad : no config rc=-6
Note that this also allows to show IPIs:
6:mon> dxi 0
IRQ 0x00000000 : target=0x0 prio=06 lirq=0x10
This is a bit inconsistent with output of the 0-argument form of "dxi",
It's an hidden feature ! :)
Yes. You can query at the FW level the configuration of any valid HW
interrupt number where as "dxi" without an argument only loops on the
XIVE IRQ domain which does not include the XIVE CPU IPIs which are
special. You should "dxa" for these.
which filters them out for a reason that isn't obvious to me.
For historical reason. XIVE support for PowerNV was the first to reach
Linux. If you run the same xmon commands on a PowerNV machine (you could
use QEMU), the ouput is different. it has more low level details.
No big deal though, this should be addressed in another patch anyway.
We could simplify the xmon helpers to be sync with the debugfs one
and the QEMU/KVM "info pic" command. I agree.
Thanks,
C.
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-09 17:08:49
On 3/9/21 2:23 PM, Greg Kurz wrote:
On Wed, 3 Mar 2021 18:48:57 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
ipistorm [*] can be used to benchmark the raw interrupt rate of an
interrupt controller by measuring the number of IPIs a system can
sustain. When applied to the XIVE interrupt controller of POWER9 and
POWER10 systems, a significant drop of the interrupt rate can be
observed when crossing the second node boundary.
This is due to the fact that a single IPI interrupt is used for all
CPUs of the system. The structure is shared and the cache line updates
impact greatly the traffic between nodes and the overall IPI
performance.
As a workaround, the impact can be reduced by deactivating the IRQ
lockup detector ("noirqdebug") which does a lot of accounting in the
Linux IRQ descriptor structure and is responsible for most of the
performance penalty.
As a fix, this proposal allocates an IPI interrupt per node, to be
shared by all CPUs of that node. It solves the scaling issue, the IRQ
lockup detector still has an impact but the XIVE interrupt rate scales
linearly. It also improves the "noirqdebug" case as showed in the
tables below.
* P9 DD2.2 - 2s * 64 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 4.984023 4.875405 4.996536 5.048892
0-31 10.879164 10.544040 10.757632 11.037859
0-47 15.345301 14.688764 14.926520 15.310053
0-63 17.064907 17.066812 17.613416 17.874511
2 0-79 11.768764 21.650749 22.689120 22.566508
0-95 10.616812 26.878789 28.434703 28.320324
0-111 10.151693 31.397803 31.771773 32.388122
0-127 9.948502 33.139336 34.875716 35.224548
* P10 DD1 - 4s (not homogeneous) 352 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 2.409402 2.364108 2.383303 2.395091
0-31 6.028325 6.046075 6.089999 6.073750
0-47 8.655178 8.644531 8.712830 8.724702
0-63 11.629652 11.735953 12.088203 12.055979
0-79 14.392321 14.729959 14.986701 14.973073
0-95 12.604158 13.004034 17.528748 17.568095
2 0-111 9.767753 13.719831 19.968606 20.024218
0-127 6.744566 16.418854 22.898066 22.995110
0-143 6.005699 19.174421 25.425622 25.417541
0-159 5.649719 21.938836 27.952662 28.059603
0-175 5.441410 24.109484 31.133915 31.127996
3 0-191 5.318341 24.405322 33.999221 33.775354
0-207 5.191382 26.449769 36.050161 35.867307
0-223 5.102790 29.356943 39.544135 39.508169
0-239 5.035295 31.933051 42.135075 42.071975
0-255 4.969209 34.477367 44.655395 44.757074
4 0-271 4.907652 35.887016 47.080545 47.318537
0-287 4.839581 38.076137 50.464307 50.636219
0-303 4.786031 40.881319 53.478684 53.310759
0-319 4.743750 43.448424 56.388102 55.973969
0-335 4.709936 45.623532 59.400930 58.926857
0-351 4.681413 45.646151 62.035804 61.830057
[*] https://github.com/antonblanchard/ipistorm
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/xive-internal.h | 2 --
arch/powerpc/sysdev/xive/common.c | 39 ++++++++++++++++++------
2 files changed, 30 insertions(+), 11 deletions(-)
@@ -65,8 +65,16 @@ static struct irq_domain *xive_irq_domain;#ifdef CONFIG_SMPstaticstructirq_domain*xive_ipi_irq_domain;-/* The IPIs all use the same logical irq number */-staticu32xive_ipi_irq;+/* The IPIs use the same logical irq number when on the same chip */+staticstructxive_ipi_desc{+unsignedintirq;+charname[8];/* enough bytes to fit IPI-XXX */
So this assumes that the node number that node is <= 999 ? This
is certainly the case for now since CONFIG_NODES_SHIFT is 8
on ppc64 but starting with 10, you'd have truncated names.
It should be harmless though. I agree this is a useless optimization.
What about deriving the size of name[] from CONFIG_NODES_SHIFT ?
Yes.
Apart from that, LGTM. Probably not worth to respin just for
this.
I also could give a try in a KVM guest.
Topology passed to QEMU:
-smp 8,maxcpus=8,cores=2,threads=2,sockets=2 \
-numa node,nodeid=0,cpus=0-4 \
-numa node,nodeid=1,cpus=4-7
Topology observed in guest with lstopo :
Package L#0
NUMANode L#0 (P#0 30GB)
L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
PU L#0 (P#0)
PU L#1 (P#1)
L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
PU L#2 (P#2)
PU L#3 (P#3)
Package L#1
NUMANode L#1 (P#1 32GB)
L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2
PU L#4 (P#4)
PU L#5 (P#5)
L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3
PU L#6 (P#6)
PU L#7 (P#7)
Interrupts in guest:
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
16: 1023 871 1042 749 0 0 0 0 XIVE-IPI 0 Edge IPI-0
17: 0 0 0 0 2123 1019 1263 1288 XIVE-IPI 1 Edge IPI-1
IPIs are mapped to the appropriate nodes, and the numbers indicate
that everything is working as expected.
You should see the same on 2 socket PowerNV QEMU machine.
Reviewed-and-tested-by: Greg Kurz [off-list ref]
Thanks,
C.
quoted
+} *xive_ipis;
+
+static unsigned int xive_ipi_cpu_to_irq(unsigned int cpu)
+{
+ return xive_ipis[cpu_to_node(cpu)].irq;
+}
#endif
/* Xive state for each CPU */
@@ -1106,25 +1114,36 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = { static void __init xive_request_ipi(void) {- unsigned int virq;+ unsigned int node;- xive_ipi_irq_domain = irq_domain_add_linear(NULL, 1,+ xive_ipi_irq_domain = irq_domain_add_linear(NULL, nr_node_ids, &xive_ipi_irq_domain_ops, NULL); if (WARN_ON(xive_ipi_irq_domain == NULL)) return;- /* Initialize it */- virq = irq_create_mapping(xive_ipi_irq_domain, XIVE_IPI_HW_IRQ);- xive_ipi_irq = virq;+ xive_ipis = kcalloc(nr_node_ids, sizeof(*xive_ipis), GFP_KERNEL | __GFP_NOFAIL);+ for_each_node(node) {+ struct xive_ipi_desc *xid = &xive_ipis[node];+ irq_hw_number_t node_ipi_hwirq = node;++ /*+ * Map one IPI interrupt per node for all cpus of that node.+ * Since the HW interrupt number doesn't have any meaning,+ * simply use the node number.+ */+ xid->irq = irq_create_mapping(xive_ipi_irq_domain, node_ipi_hwirq);+ snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);- WARN_ON(request_irq(virq, xive_muxed_ipi_action,- IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL));+ WARN_ON(request_irq(xid->irq, xive_muxed_ipi_action,+ IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL));+ } } static int xive_setup_cpu_ipi(unsigned int cpu) { struct xive_cpu *xc; int rc;+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu); pr_debug("Setting up IPI for CPU %d\n", cpu);
@@ -1165,6 +1184,8 @@ static int xive_setup_cpu_ipi(unsigned int cpu) static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) {+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);+ /* Disable the IPI and free the IRQ data */ /* Already cleaned up ? */
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-09 18:24:20
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
That's correct. H_HOME_NODE_ASSOCIATIVITY returns not only the node_id, but
a list with the ibm,associativity domains of the CPU that "proc-no" (processor
identifier) is mapped to inside QEMU.
node_id in this case, considering that we're working with a reference-points
of size 4, is the 4th element of the returned list. The last element is
"procno" itself.
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
Thanks,
C.
Thanks,
DHB
quoted
quoted
It looks like the chip id is only used for localization purpose in
this case, right ?
Yes and PAPR sources are not localized. So it's not used. MSI sources
could be if we rewrote the MSI driver.
quoted
In this case, what about doing this change for pSeries only,
somewhere in spapr.c ?
The IPI code is common to all platforms and all have the same issue.
I rather not.
Thanks,
C.
@@ -1335,16 +1335,11 @@ static int xive_prepare_cpu(unsigned int cpu)xc=per_cpu(xive_cpu,cpu);if(!xc){-structdevice_node*np;-xc=kzalloc_node(sizeof(structxive_cpu),GFP_KERNEL,cpu_to_node(cpu));if(!xc)return-ENOMEM;-np=of_get_cpu_node(cpu,NULL);-if(np)-xc->chip_id=of_get_ibm_chip_id(np);-of_node_put(np);+xc->chip_id=cpu_to_node(cpu);xc->hw_ipi=XIVE_BAD_IRQ;per_cpu(xive_cpu,cpu)=xc;
From: Daniel Henrique Barboza <hidden> Date: 2021-03-09 21:42:58
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
That's correct. H_HOME_NODE_ASSOCIATIVITY returns not only the node_id, but
a list with the ibm,associativity domains of the CPU that "proc-no" (processor
identifier) is mapped to inside QEMU.
node_id in this case, considering that we're working with a reference-points
of size 4, is the 4th element of the returned list. The last element is
"procno" itself.
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
Thanks,
DHB
quoted
It looks like the chip id is only used for localization purpose in
this case, right ?
Yes and PAPR sources are not localized. So it's not used. MSI sources
could be if we rewrote the MSI driver.
quoted
In this case, what about doing this change for pSeries only,
somewhere in spapr.c ?
The IPI code is common to all platforms and all have the same issue.
I rather not.
Thanks,
C.
@@ -1335,16 +1335,11 @@ static int xive_prepare_cpu(unsigned int cpu)xc=per_cpu(xive_cpu,cpu);if(!xc){-structdevice_node*np;-xc=kzalloc_node(sizeof(structxive_cpu),GFP_KERNEL,cpu_to_node(cpu));if(!xc)return-ENOMEM;-np=of_get_cpu_node(cpu,NULL);-if(np)-xc->chip_id=of_get_ibm_chip_id(np);-of_node_put(np);+xc->chip_id=cpu_to_node(cpu);xc->hw_ipi=XIVE_BAD_IRQ;per_cpu(xive_cpu,cpu)=xc;
From: David Gibson <hidden> Date: 2021-03-12 01:56:17
On Tue, 9 Mar 2021 18:26:35 +0100
Cédric Le Goater [off-list ref] wrote:
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
quoted
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
[...]
quoted
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
As I mentioned to Daniel on our call this morning, oddly it *does*
appear to be used in the RHEL kernel, even though that's 4.18 based.
This patch seems to have caused a minor regression; not in the
identification of NUMA nodes, but in the number of sockets shown be
lscpu, etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1934421
for more information.
Since the value was used by some PAPR kernels - even if they shouldn't
have - I think we should only remove this for newer machine types. We
also need to check what we're not supplying that the guest kernel is
showing a different number of sockets than specified on the qemu
command line.
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-12 10:04:37
On 3/12/21 2:55 AM, David Gibson wrote:
On Tue, 9 Mar 2021 18:26:35 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
quoted
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
[...]
quoted
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
As I mentioned to Daniel on our call this morning, oddly it *does*
appear to be used in the RHEL kernel, even though that's 4.18 based.
This patch seems to have caused a minor regression; not in the
identification of NUMA nodes, but in the number of sockets shown be
lscpu, etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1934421
for more information.
Yes. The property "ibm,chip-id" is wrongly calculated in QEMU. If we
remove it, we get with 4.18.0-295.el8.ppc64le or 5.12.0-rc2 :
[root@localhost ~]# lscpu
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 4
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 2
Model: 2.2 (pvr 004e 1202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: KVM
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
[root@localhost ~]# grep . /sys/devices/system/cpu/*/topology/physical_package_id
/sys/devices/system/cpu/cpu0/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu100/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu101/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu102/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu103/topology/physical_package_id:-1
....
"ibm,chip-id" is still being used on some occasion on pSeries machines.
This is wrong :/ The problem is :
#define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu))
We should be using cpu_to_node().
C.
Since the value was used by some PAPR kernels - even if they shouldn't
have - I think we should only remove this for newer machine types. We
also need to check what we're not supplying that the guest kernel is
showing a different number of sockets than specified on the qemu
command line.
From: Daniel Henrique Barboza <hidden> Date: 2021-03-12 12:19:32
On 3/12/21 6:53 AM, Cédric Le Goater wrote:
On 3/12/21 2:55 AM, David Gibson wrote:
quoted
On Tue, 9 Mar 2021 18:26:35 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
quoted
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
[...]
quoted
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
As I mentioned to Daniel on our call this morning, oddly it *does*
appear to be used in the RHEL kernel, even though that's 4.18 based.
This patch seems to have caused a minor regression; not in the
identification of NUMA nodes, but in the number of sockets shown be
lscpu, etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1934421
for more information.
Yes. The property "ibm,chip-id" is wrongly calculated in QEMU. If we
remove it, we get with 4.18.0-295.el8.ppc64le or 5.12.0-rc2 :
[root@localhost ~]# lscpu
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 4
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 2
Model: 2.2 (pvr 004e 1202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: KVM
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
[root@localhost ~]# grep . /sys/devices/system/cpu/*/topology/physical_package_id
/sys/devices/system/cpu/cpu0/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu100/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu101/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu102/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu103/topology/physical_package_id:-1
....
"ibm,chip-id" is still being used on some occasion on pSeries machines.
This is wrong :/ The problem is :
#define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu))
We should be using cpu_to_node().
IIUC the "real fix" then is this change you mentioned above, together with
this xive patch as well, to stop using ibm,chip-id for good in the pserie
kernel. With these changes QEMU can remove 'ibm,chip-id' from the pseries
machine without impact. Is this correct?
If that's the case, then I believe it's ok to go forward with the QEMU side
change (just for 6.0.0 and newer machines). Or should I wait for the kernel
changes to be merged upstream first?
Thanks,
DHB
C.
quoted
Since the value was used by some PAPR kernels - even if they shouldn't
have - I think we should only remove this for newer machine types. We
also need to check what we're not supplying that the guest kernel is
showing a different number of sockets than specified on the qemu
command line.
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-12 13:29:26
On 3/12/21 1:18 PM, Daniel Henrique Barboza wrote:
On 3/12/21 6:53 AM, Cédric Le Goater wrote:
quoted
On 3/12/21 2:55 AM, David Gibson wrote:
quoted
On Tue, 9 Mar 2021 18:26:35 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
quoted
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
[...]
quoted
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
As I mentioned to Daniel on our call this morning, oddly it *does*
appear to be used in the RHEL kernel, even though that's 4.18 based.
This patch seems to have caused a minor regression; not in the
identification of NUMA nodes, but in the number of sockets shown be
lscpu, etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1934421
for more information.
Yes. The property "ibm,chip-id" is wrongly calculated in QEMU. If we
remove it, we get with 4.18.0-295.el8.ppc64le or 5.12.0-rc2 :
[root@localhost ~]# lscpu
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 4
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 2
Model: 2.2 (pvr 004e 1202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: KVM
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
[root@localhost ~]# grep . /sys/devices/system/cpu/*/topology/physical_package_id
/sys/devices/system/cpu/cpu0/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu100/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu101/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu102/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu103/topology/physical_package_id:-1
....
"ibm,chip-id" is still being used on some occasion on pSeries machines.
This is wrong :/ The problem is :
#define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu))
We should be using cpu_to_node().
IIUC the "real fix" then is this change you mentioned above, together with
this xive patch as well,
These are independent.
The XIVE patch just raised the issue because it's another usage example of
cpu_to_chip_id() or directly "ibm,chip-id" in the XIVE case, on a pseries
machine.
The use of cpu_to_node(cpu) for topology_physical_package_id(cpu) is a fix
for the sysfs issue reported in the redhat BZ.
to stop using ibm,chip-id for good in the pserie
kernel. With these changes QEMU can remove 'ibm,chip-id' from the pseries
machine without impact. Is this correct?
Linux is already "broken" on PowerVM today since we don't have the "ibm,chip-id"
property. QEMU is just hiding the problem on KVM.
But we have to be bug compatible :) if the QEMU fix is under the pseries-6.x
machine we should be fine.
If that's the case, then I believe it's ok to go forward with the QEMU side
change (just for 6.0.0 and newer machines). Or should I wait for the kernel
changes to be merged upstream first?
Once Linux is fixed, we shouldn't care if QEMU exports 'ibm,chip-id' or not.
I don't think the order is very important. These are independent.
C.
From: Greg Kurz <hidden> Date: 2021-03-12 13:39:14
On Fri, 12 Mar 2021 09:18:39 -0300
Daniel Henrique Barboza [off-list ref] wrote:
On 3/12/21 6:53 AM, Cédric Le Goater wrote:
quoted
On 3/12/21 2:55 AM, David Gibson wrote:
quoted
On Tue, 9 Mar 2021 18:26:35 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
On 3/9/21 6:08 PM, Daniel Henrique Barboza wrote:
quoted
On 3/9/21 12:33 PM, Cédric Le Goater wrote:
quoted
On 3/8/21 6:13 PM, Greg Kurz wrote:
quoted
On Wed, 3 Mar 2021 18:48:50 +0100
Cédric Le Goater [off-list ref] wrote:
quoted
The 'chip_id' field of the XIVE CPU structure is used to choose a
target for a source located on the same chip when possible. This field
is assigned on the PowerNV platform using the "ibm,chip-id" property
on pSeries under KVM when NUMA nodes are defined but it is undefined
This sentence seems to have a syntax problem... like it is missing an
'and' before 'on pSeries'.
ah yes, or simply a comma.
quoted
quoted
under PowerVM. The XIVE source structure has a similar field
'src_chip' which is only assigned on the PowerNV platform.
cpu_to_node() returns a compatible value on all platforms, 0 being the
default node. It will also give us the opportunity to set the affinity
of a source on pSeries when we can localize them.
IIUC this relies on the fact that the NUMA node id is == to chip id
on PowerNV, i.e. xc->chip_id which is passed to OPAL remain stable
with this change.
Linux sets the NUMA node in numa_setup_cpu(). On pseries, the hcall
H_HOME_NODE_ASSOCIATIVITY returns the node id if I am correct (Daniel
in Cc:)
[...]
quoted
quoted
On PowerNV, Linux uses "ibm,associativity" property of the CPU to find
the node id. This value is built from the chip id in OPAL, so the
value returned by cpu_to_node(cpu) and the value of the "ibm,chip-id"
property are unlikely to be different.
cpu_to_node(cpu) is used in many places to allocate the structures
locally to the owning node. XIVE is not an exception (see below in the
same patch), it is better to be consistent and get the same information
(node id) using the same routine.
In Linux, "ibm,chip-id" is only used in low level PowerNV drivers :
LPC, XSCOM, RNG, VAS, NX. XIVE should be in that list also but skiboot
unifies the controllers of the system to only expose one the OS. This
is problematic and should be changed but it's another topic.
quoted
On the other hand, you have the pSeries case under PowerVM that
doesn't xc->chip_id, which isn't passed to any hcall AFAICT.
yes "ibm,chip-id" is an OPAL concept unfortunately and it has no meaning
under PAPR. xc->chip_id on pseries (PowerVM) will contains an invalid
chip id.
QEMU/KVM exposes "ibm,chip-id" but it's not used. (its value is not
always correct btw)
If you have a way to reliably reproduce this, let me know and I'll fix it
up in QEMU.
with :
-smp 4,cores=1,maxcpus=8 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x01>;
ibm,chip-id = <0x02>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x03>;
with :
-smp 4,cores=4,maxcpus=8,threads=1 -object memory-backend-ram,id=ram-node0,size=2G -numa node,nodeid=0,cpus=0-1,cpus=4-5,memdev=ram-node0 -object memory-backend-ram,id=ram-node1,size=2G -numa node,nodeid=1,cpus=2-3,cpus=6-7,memdev=ram-node1
# dmesg | grep numa
[ 0.013106] numa: Node 0 CPUs: 0-1
[ 0.013136] numa: Node 1 CPUs: 2-3
# dtc -I fs /proc/device-tree/cpus/ -f | grep ibm,chip-id
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
ibm,chip-id = <0x00>;
I think we should simply remove "ibm,chip-id" since it's not used and
not in the PAPR spec.
As I mentioned to Daniel on our call this morning, oddly it *does*
appear to be used in the RHEL kernel, even though that's 4.18 based.
This patch seems to have caused a minor regression; not in the
identification of NUMA nodes, but in the number of sockets shown be
lscpu, etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1934421
for more information.
Yes. The property "ibm,chip-id" is wrongly calculated in QEMU. If we
remove it, we get with 4.18.0-295.el8.ppc64le or 5.12.0-rc2 :
[root@localhost ~]# lscpu
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 4
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 2
Model: 2.2 (pvr 004e 1202)
Model name: POWER9 (architected), altivec supported
Hypervisor vendor: KVM
Virtualization type: para
L1d cache: 32K
L1i cache: 32K
NUMA node0 CPU(s): 0-63
NUMA node1 CPU(s): 64-127
[root@localhost ~]# grep . /sys/devices/system/cpu/*/topology/physical_package_id
/sys/devices/system/cpu/cpu0/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu100/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu101/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu102/topology/physical_package_id:-1
/sys/devices/system/cpu/cpu103/topology/physical_package_id:-1
....
"ibm,chip-id" is still being used on some occasion on pSeries machines.
This is wrong :/ The problem is :
#define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu))
We should be using cpu_to_node().
IIUC the "real fix" then is this change you mentioned above, together with
this xive patch as well, to stop using ibm,chip-id for good in the pserie
kernel. With these changes QEMU can remove 'ibm,chip-id' from the pseries
machine without impact. Is this correct?
If that's the case, then I believe it's ok to go forward with the QEMU side
change (just for 6.0.0 and newer machines). Or should I wait for the kernel
changes to be merged upstream first?
I'd say the latter since this is a breaking change and people will want
to identify the upstream commits they have to backport to their kernel
in order to support the disappearance of "ibm,chip-id".
Cheers,
--
Greg
Thanks,
DHB
quoted
C.
quoted
Since the value was used by some PAPR kernels - even if they shouldn't
have - I think we should only remove this for newer machine types. We
also need to check what we're not supplying that the guest kernel is
showing a different number of sockets than specified on the qemu
command line.
From: Cédric Le Goater <clg@kaod.org> Date: 2021-03-30 16:18:43
On 3/3/21 6:48 PM, Cédric Le Goater wrote:
quoted hunk
ipistorm [*] can be used to benchmark the raw interrupt rate of an
interrupt controller by measuring the number of IPIs a system can
sustain. When applied to the XIVE interrupt controller of POWER9 and
POWER10 systems, a significant drop of the interrupt rate can be
observed when crossing the second node boundary.
This is due to the fact that a single IPI interrupt is used for all
CPUs of the system. The structure is shared and the cache line updates
impact greatly the traffic between nodes and the overall IPI
performance.
As a workaround, the impact can be reduced by deactivating the IRQ
lockup detector ("noirqdebug") which does a lot of accounting in the
Linux IRQ descriptor structure and is responsible for most of the
performance penalty.
As a fix, this proposal allocates an IPI interrupt per node, to be
shared by all CPUs of that node. It solves the scaling issue, the IRQ
lockup detector still has an impact but the XIVE interrupt rate scales
linearly. It also improves the "noirqdebug" case as showed in the
tables below.
* P9 DD2.2 - 2s * 64 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 4.984023 4.875405 4.996536 5.048892
0-31 10.879164 10.544040 10.757632 11.037859
0-47 15.345301 14.688764 14.926520 15.310053
0-63 17.064907 17.066812 17.613416 17.874511
2 0-79 11.768764 21.650749 22.689120 22.566508
0-95 10.616812 26.878789 28.434703 28.320324
0-111 10.151693 31.397803 31.771773 32.388122
0-127 9.948502 33.139336 34.875716 35.224548
* P10 DD1 - 4s (not homogeneous) 352 threads
"noirqdebug"
Mint/s Mint/s
chips cpus IPI/sys IPI/chip IPI/chip IPI/sys
--------------------------------------------------------------
1 0-15 2.409402 2.364108 2.383303 2.395091
0-31 6.028325 6.046075 6.089999 6.073750
0-47 8.655178 8.644531 8.712830 8.724702
0-63 11.629652 11.735953 12.088203 12.055979
0-79 14.392321 14.729959 14.986701 14.973073
0-95 12.604158 13.004034 17.528748 17.568095
2 0-111 9.767753 13.719831 19.968606 20.024218
0-127 6.744566 16.418854 22.898066 22.995110
0-143 6.005699 19.174421 25.425622 25.417541
0-159 5.649719 21.938836 27.952662 28.059603
0-175 5.441410 24.109484 31.133915 31.127996
3 0-191 5.318341 24.405322 33.999221 33.775354
0-207 5.191382 26.449769 36.050161 35.867307
0-223 5.102790 29.356943 39.544135 39.508169
0-239 5.035295 31.933051 42.135075 42.071975
0-255 4.969209 34.477367 44.655395 44.757074
4 0-271 4.907652 35.887016 47.080545 47.318537
0-287 4.839581 38.076137 50.464307 50.636219
0-303 4.786031 40.881319 53.478684 53.310759
0-319 4.743750 43.448424 56.388102 55.973969
0-335 4.709936 45.623532 59.400930 58.926857
0-351 4.681413 45.646151 62.035804 61.830057
[*] https://github.com/antonblanchard/ipistorm
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/sysdev/xive/xive-internal.h | 2 --
arch/powerpc/sysdev/xive/common.c | 39 ++++++++++++++++++------
2 files changed, 30 insertions(+), 11 deletions(-)
@@ -65,8 +65,16 @@ static struct irq_domain *xive_irq_domain;#ifdef CONFIG_SMPstaticstructirq_domain*xive_ipi_irq_domain;-/* The IPIs all use the same logical irq number */-staticu32xive_ipi_irq;+/* The IPIs use the same logical irq number when on the same chip */+staticstructxive_ipi_desc{+unsignedintirq;+charname[8];/* enough bytes to fit IPI-XXX */+}*xive_ipis;++staticunsignedintxive_ipi_cpu_to_irq(unsignedintcpu)+{+returnxive_ipis[cpu_to_node(cpu)].irq;
This should be using early_cpu_to_node() for hotplugged CPU, else the CPU IPI
will be mapped on default node 0. Still works but this is not what we want.
There, we need to filter cpu-less nodes. There is no need to allocate IPIs
for these.
+ /*
+ * Map one IPI interrupt per node for all cpus of that node.
+ * Since the HW interrupt number doesn't have any meaning,
+ * simply use the node number.
+ */
+ xid->irq = irq_create_mapping(xive_ipi_irq_domain, node_ipi_hwirq);
+ snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);
and this mapping needs some modernization. If we use a domain allocator, the
IPI irq descriptor will be allocated on the node it is serving which is even
better for cache performance.
I will send a v3 with these changes.
C.
quoted hunk
- WARN_ON(request_irq(virq, xive_muxed_ipi_action,
- IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL));
+ WARN_ON(request_irq(xid->irq, xive_muxed_ipi_action,
+ IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL));
+ }
}
static int xive_setup_cpu_ipi(unsigned int cpu)
{
struct xive_cpu *xc;
int rc;
+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);
pr_debug("Setting up IPI for CPU %d\n", cpu);
@@ -1165,6 +1184,8 @@ static int xive_setup_cpu_ipi(unsigned int cpu) static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) {+ unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);+ /* Disable the IPI and free the IRQ data */ /* Already cleaned up ? */