Skip to content

Commit 5995497

Browse files
committed
Merge tag 'powerpc-6.0-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix handling of PCI domains in /proc on 32-bit systems using the recently added support for numbering buses from zero for each domain. - A fix and a revert for some changes to use READ/WRITE_ONCE() which caused problems with KASAN enabled due to sanitisation calls being introduced in low-level paths that can't cope with it. - Fix build errors on 32-bit caused by the syscall table being misaligned sometimes. - Two fixes to get IBM Cell native machines booting again, which had bit-rotted while my QS22 was temporarily out of action. - Fix the papr_scm driver to not assume the order of events returned by the hypervisor is stable, and a related compile fix. Thanks to Aneesh Kumar K.V, Christophe Leroy, Jordan Niethe, Kajol Jain, Masahiro Yamada, Nathan Chancellor, Pali Rohár, Vaibhav Jain, and Zhouyi Zhou. * tag 'powerpc-6.0-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/papr_scm: Ensure rc is always initialized in papr_scm_pmu_register() Revert "powerpc/irq: Don't open code irq_soft_mask helpers" powerpc: Fix hard_irq_disable() with sanitizer powerpc/rtas: Fix RTAS MSR[HV] handling for Cell Revert "powerpc: Remove unused FW_FEATURE_NATIVE references" powerpc: align syscall table for ppc32 powerpc/pci: Enable PCI domains in /proc when PCI bus numbers are not unique powerpc/papr_scm: Fix nvdimm event mappings
2 parents 685ed98 + 6cf0781 commit 5995497

File tree

6 files changed

+89
-69
lines changed

6 files changed

+89
-69
lines changed

arch/powerpc/include/asm/firmware.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ enum {
8383
FW_FEATURE_POWERNV_ALWAYS = 0,
8484
FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
8585
FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
86+
FW_FEATURE_NATIVE_POSSIBLE = 0,
87+
FW_FEATURE_NATIVE_ALWAYS = 0,
8688
FW_FEATURE_POSSIBLE =
8789
#ifdef CONFIG_PPC_PSERIES
8890
FW_FEATURE_PSERIES_POSSIBLE |
@@ -92,6 +94,9 @@ enum {
9294
#endif
9395
#ifdef CONFIG_PPC_PS3
9496
FW_FEATURE_PS3_POSSIBLE |
97+
#endif
98+
#ifdef CONFIG_PPC_HASH_MMU_NATIVE
99+
FW_FEATURE_NATIVE_ALWAYS |
95100
#endif
96101
0,
97102
FW_FEATURE_ALWAYS =
@@ -103,6 +108,9 @@ enum {
103108
#endif
104109
#ifdef CONFIG_PPC_PS3
105110
FW_FEATURE_PS3_ALWAYS &
111+
#endif
112+
#ifdef CONFIG_PPC_HASH_MMU_NATIVE
113+
FW_FEATURE_NATIVE_ALWAYS &
106114
#endif
107115
FW_FEATURE_POSSIBLE,
108116

arch/powerpc/include/asm/hw_irq.h

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,14 @@ static inline void __hard_RI_enable(void)
113113

114114
static inline notrace unsigned long irq_soft_mask_return(void)
115115
{
116-
return READ_ONCE(local_paca->irq_soft_mask);
116+
unsigned long flags;
117+
118+
asm volatile(
119+
"lbz %0,%1(13)"
120+
: "=r" (flags)
121+
: "i" (offsetof(struct paca_struct, irq_soft_mask)));
122+
123+
return flags;
117124
}
118125

119126
/*
@@ -140,24 +147,46 @@ static inline notrace void irq_soft_mask_set(unsigned long mask)
140147
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
141148
WARN_ON(mask && !(mask & IRQS_DISABLED));
142149

143-
WRITE_ONCE(local_paca->irq_soft_mask, mask);
144-
barrier();
150+
asm volatile(
151+
"stb %0,%1(13)"
152+
:
153+
: "r" (mask),
154+
"i" (offsetof(struct paca_struct, irq_soft_mask))
155+
: "memory");
145156
}
146157

147158
static inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
148159
{
149-
unsigned long flags = irq_soft_mask_return();
160+
unsigned long flags;
150161

151-
irq_soft_mask_set(mask);
162+
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
163+
WARN_ON(mask && !(mask & IRQS_DISABLED));
164+
#endif
165+
166+
asm volatile(
167+
"lbz %0,%1(13); stb %2,%1(13)"
168+
: "=&r" (flags)
169+
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
170+
"r" (mask)
171+
: "memory");
152172

153173
return flags;
154174
}
155175

156176
static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
157177
{
158-
unsigned long flags = irq_soft_mask_return();
178+
unsigned long flags, tmp;
179+
180+
asm volatile(
181+
"lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
182+
: "=&r" (flags), "=r" (tmp)
183+
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
184+
"r" (mask)
185+
: "memory");
159186

160-
irq_soft_mask_set(flags | mask);
187+
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
188+
WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
189+
#endif
161190

162191
return flags;
163192
}
@@ -282,7 +311,8 @@ static inline bool pmi_irq_pending(void)
282311
flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \
283312
local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \
284313
if (!arch_irqs_disabled_flags(flags)) { \
285-
WRITE_ONCE(local_paca->saved_r1, current_stack_pointer);\
314+
asm volatile("std%X0 %1,%0" : "=m" (local_paca->saved_r1) \
315+
: "r" (current_stack_pointer)); \
286316
trace_hardirqs_off(); \
287317
} \
288318
} while(0)

arch/powerpc/kernel/pci_32.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,15 @@ static int __init pcibios_init(void)
245245

246246
printk(KERN_INFO "PCI: Probing PCI hardware\n");
247247

248+
#ifdef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
249+
/*
250+
* Enable PCI domains in /proc when PCI bus numbers are not unique
251+
* across all PCI domains to prevent conflicts. And keep PCI domain 0
252+
* backward compatible in /proc for video cards.
253+
*/
254+
pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
255+
#endif
256+
248257
if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
249258
pci_assign_all_buses = 1;
250259

arch/powerpc/kernel/rtas_entry.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,12 @@ __enter_rtas:
109109
* its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
110110
* is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
111111
* MSR[S] is set, it will remain when entering RTAS.
112+
* If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
113+
* from the saved MSR value and insert into the value RTAS will use.
112114
*/
115+
extrdi r0, r6, 1, 63 - MSR_HV_LG
113116
LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
117+
insrdi r6, r0, 1, 63 - MSR_HV_LG
114118

115119
li r0,0
116120
mtmsrd r0,1 /* disable RI before using SRR0/1 */

arch/powerpc/kernel/systbl.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
.p2align 3
1919
#define __SYSCALL(nr, entry) .8byte entry
2020
#else
21+
.p2align 2
2122
#define __SYSCALL(nr, entry) .long entry
2223
#endif
2324

arch/powerpc/platforms/pseries/papr_scm.c

Lines changed: 29 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,6 @@ struct papr_scm_priv {
124124

125125
/* The bits which needs to be overridden */
126126
u64 health_bitmap_inject_mask;
127-
128-
/* array to have event_code and stat_id mappings */
129-
u8 *nvdimm_events_map;
130127
};
131128

132129
static int papr_scm_pmem_flush(struct nd_region *nd_region,
@@ -350,18 +347,41 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p,
350347
#ifdef CONFIG_PERF_EVENTS
351348
#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu)
352349

350+
static const char * const nvdimm_events_map[] = {
351+
[1] = "CtlResCt",
352+
[2] = "CtlResTm",
353+
[3] = "PonSecs ",
354+
[4] = "MemLife ",
355+
[5] = "CritRscU",
356+
[6] = "HostLCnt",
357+
[7] = "HostSCnt",
358+
[8] = "HostSDur",
359+
[9] = "HostLDur",
360+
[10] = "MedRCnt ",
361+
[11] = "MedWCnt ",
362+
[12] = "MedRDur ",
363+
[13] = "MedWDur ",
364+
[14] = "CchRHCnt",
365+
[15] = "CchWHCnt",
366+
[16] = "FastWCnt",
367+
};
368+
353369
static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count)
354370
{
355371
struct papr_scm_perf_stat *stat;
356372
struct papr_scm_perf_stats *stats;
357373
struct papr_scm_priv *p = dev_get_drvdata(dev);
358374
int rc, size;
359375

376+
/* Invalid eventcode */
377+
if (event->attr.config == 0 || event->attr.config >= ARRAY_SIZE(nvdimm_events_map))
378+
return -EINVAL;
379+
360380
/* Allocate request buffer enough to hold single performance stat */
361381
size = sizeof(struct papr_scm_perf_stats) +
362382
sizeof(struct papr_scm_perf_stat);
363383

364-
if (!p || !p->nvdimm_events_map)
384+
if (!p)
365385
return -EINVAL;
366386

367387
stats = kzalloc(size, GFP_KERNEL);
@@ -370,7 +390,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
370390

371391
stat = &stats->scm_statistic[0];
372392
memcpy(&stat->stat_id,
373-
&p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)],
393+
nvdimm_events_map[event->attr.config],
374394
sizeof(stat->stat_id));
375395
stat->stat_val = 0;
376396

@@ -458,56 +478,6 @@ static void papr_scm_pmu_del(struct perf_event *event, int flags)
458478
papr_scm_pmu_read(event);
459479
}
460480

461-
static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu)
462-
{
463-
struct papr_scm_perf_stat *stat;
464-
struct papr_scm_perf_stats *stats;
465-
u32 available_events;
466-
int index, rc = 0;
467-
468-
if (!p->stat_buffer_len)
469-
return -ENOENT;
470-
471-
available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats))
472-
/ sizeof(struct papr_scm_perf_stat);
473-
if (available_events == 0)
474-
return -EOPNOTSUPP;
475-
476-
/* Allocate the buffer for phyp where stats are written */
477-
stats = kzalloc(p->stat_buffer_len, GFP_KERNEL);
478-
if (!stats) {
479-
rc = -ENOMEM;
480-
return rc;
481-
}
482-
483-
/* Called to get list of events supported */
484-
rc = drc_pmem_query_stats(p, stats, 0);
485-
if (rc)
486-
goto out;
487-
488-
/*
489-
* Allocate memory and populate nvdimm_event_map.
490-
* Allocate an extra element for NULL entry
491-
*/
492-
p->nvdimm_events_map = kcalloc(available_events + 1,
493-
sizeof(stat->stat_id),
494-
GFP_KERNEL);
495-
if (!p->nvdimm_events_map) {
496-
rc = -ENOMEM;
497-
goto out;
498-
}
499-
500-
/* Copy all stat_ids to event map */
501-
for (index = 0, stat = stats->scm_statistic;
502-
index < available_events; index++, ++stat) {
503-
memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)],
504-
&stat->stat_id, sizeof(stat->stat_id));
505-
}
506-
out:
507-
kfree(stats);
508-
return rc;
509-
}
510-
511481
static void papr_scm_pmu_register(struct papr_scm_priv *p)
512482
{
513483
struct nvdimm_pmu *nd_pmu;
@@ -519,9 +489,10 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
519489
goto pmu_err_print;
520490
}
521491

522-
rc = papr_scm_pmu_check_events(p, nd_pmu);
523-
if (rc)
492+
if (!p->stat_buffer_len) {
493+
rc = -ENOENT;
524494
goto pmu_check_events_err;
495+
}
525496

526497
nd_pmu->pmu.task_ctx_nr = perf_invalid_context;
527498
nd_pmu->pmu.name = nvdimm_name(p->nvdimm);
@@ -539,7 +510,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
539510

540511
rc = register_nvdimm_pmu(nd_pmu, p->pdev);
541512
if (rc)
542-
goto pmu_register_err;
513+
goto pmu_check_events_err;
543514

544515
/*
545516
* Set archdata.priv value to nvdimm_pmu structure, to handle the
@@ -548,8 +519,6 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
548519
p->pdev->archdata.priv = nd_pmu;
549520
return;
550521

551-
pmu_register_err:
552-
kfree(p->nvdimm_events_map);
553522
pmu_check_events_err:
554523
kfree(nd_pmu);
555524
pmu_err_print:
@@ -1560,7 +1529,6 @@ static int papr_scm_remove(struct platform_device *pdev)
15601529
unregister_nvdimm_pmu(pdev->archdata.priv);
15611530

15621531
pdev->archdata.priv = NULL;
1563-
kfree(p->nvdimm_events_map);
15641532
kfree(p->bus_desc.provider_name);
15651533
kfree(p);
15661534

0 commit comments

Comments
 (0)