Skip to content

Commit b6f96e7

Browse files
committed
Merge tag 'powerpc-5.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - A fix for undetected data corruption on Power9 Nimbus <= DD2.1 in the emulation of VSX loads. The affected CPUs were not widely available. - Two fixes for machine check handling in guests under PowerVM. - A fix for our recent changes to SMP setup, when CONFIG_CPUMASK_OFFSTACK=y. - Three fixes for races in the handling of some of our powernv sysfs attributes. - One change to remove TM from the set of Power10 CPU features. - A couple of other minor fixes. Thanks to: Aneesh Kumar K.V, Christophe Leroy, Ganesh Goudar, Jordan Niethe, Mahesh Salgaonkar, Michael Neuling, Oliver O'Halloran, Qian Cai, Srikar Dronamraju, Vasant Hegde. * tag 'powerpc-5.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/pseries: Avoid using addr_to_pfn in real mode powerpc/uaccess: Don't use "m<>" constraint with GCC 4.9 powerpc/eeh: Fix eeh_dev_check_failure() for PE#0 powerpc/64s: Remove TM from Power10 features selftests/powerpc: Make alignment handler test P9N DD2.1 vector CI load workaround powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation powerpc/powernv/dump: Handle multiple writes to ack attribute powerpc/powernv/dump: Fix race while processing OPAL dump powerpc/smp: Use GFP_ATOMIC while allocating tmp mask powerpc/smp: Remove unnecessary variable powerpc/mce: Avoid nmi_enter/exit in real mode on pseries hash powerpc/opal_elog: Handle multiple writes to ack attribute
2 parents 0593c1b + 4ff753f commit b6f96e7

12 files changed

Lines changed: 185 additions & 120 deletions

File tree

arch/powerpc/include/asm/asm-const.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,17 @@
1111
# define __ASM_CONST(x) x##UL
1212
# define ASM_CONST(x) __ASM_CONST(x)
1313
#endif
14+
15+
/*
16+
* Inline assembly memory constraint
17+
*
18+
* GCC 4.9 doesn't properly handle pre update memory constraint "m<>"
19+
*
20+
*/
21+
#if defined(GCC_VERSION) && GCC_VERSION < 50000
22+
#define UPD_CONSTR ""
23+
#else
24+
#define UPD_CONSTR "<>"
25+
#endif
26+
1427
#endif /* _ASM_POWERPC_ASM_CONST_H */

arch/powerpc/include/asm/cputable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ static inline void cpu_feature_keys_init(void) { }
477477
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
478478
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
479479
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
480-
CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \
480+
CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \
481481
CPU_FTR_DAWR | CPU_FTR_DAWR1)
482482
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
483483
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \

arch/powerpc/include/asm/uaccess.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ do { \
182182
"1: " op "%U1%X1 %0,%1 # put_user\n" \
183183
EX_TABLE(1b, %l2) \
184184
: \
185-
: "r" (x), "m<>" (*addr) \
185+
: "r" (x), "m"UPD_CONSTR (*addr) \
186186
: \
187187
: label)
188188

@@ -253,7 +253,7 @@ extern long __get_user_bad(void);
253253
".previous\n" \
254254
EX_TABLE(1b, 3b) \
255255
: "=r" (err), "=r" (x) \
256-
: "m<>" (*addr), "i" (-EFAULT), "0" (err))
256+
: "m"UPD_CONSTR (*addr), "i" (-EFAULT), "0" (err))
257257

258258
#ifdef __powerpc64__
259259
#define __get_user_asm2(x, addr, err) \

arch/powerpc/kernel/cputable.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,16 @@ extern void __restore_cpu_e6500(void);
121121
PPC_FEATURE2_DARN | \
122122
PPC_FEATURE2_SCV)
123123
#define COMMON_USER_POWER10 COMMON_USER_POWER9
124-
#define COMMON_USER2_POWER10 (COMMON_USER2_POWER9 | \
125-
PPC_FEATURE2_ARCH_3_1 | \
126-
PPC_FEATURE2_MMA)
124+
#define COMMON_USER2_POWER10 (PPC_FEATURE2_ARCH_3_1 | \
125+
PPC_FEATURE2_MMA | \
126+
PPC_FEATURE2_ARCH_3_00 | \
127+
PPC_FEATURE2_HAS_IEEE128 | \
128+
PPC_FEATURE2_DARN | \
129+
PPC_FEATURE2_SCV | \
130+
PPC_FEATURE2_ARCH_2_07 | \
131+
PPC_FEATURE2_DSCR | \
132+
PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \
133+
PPC_FEATURE2_VEC_CRYPTO)
127134

128135
#ifdef CONFIG_PPC_BOOK3E_64
129136
#define COMMON_USER_BOOKE (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE)

arch/powerpc/kernel/eeh.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,6 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
466466
return 0;
467467
}
468468

469-
if (!pe->addr) {
470-
eeh_stats.no_cfg_addr++;
471-
return 0;
472-
}
473-
474469
/*
475470
* On PowerNV platform, we might already have fenced PHB
476471
* there and we need take care of that firstly.

arch/powerpc/kernel/mce.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,12 +591,11 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
591591
long notrace machine_check_early(struct pt_regs *regs)
592592
{
593593
long handled = 0;
594-
bool nested = in_nmi();
595594
u8 ftrace_enabled = this_cpu_get_ftrace_enabled();
596595

597596
this_cpu_set_ftrace_enabled(0);
598-
599-
if (!nested)
597+
/* Do not use nmi_enter/exit for pseries hpte guest */
598+
if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
600599
nmi_enter();
601600

602601
hv_nmi_check_nonrecoverable(regs);
@@ -607,7 +606,7 @@ long notrace machine_check_early(struct pt_regs *regs)
607606
if (ppc_md.machine_check_early)
608607
handled = ppc_md.machine_check_early(regs);
609608

610-
if (!nested)
609+
if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
611610
nmi_exit();
612611

613612
this_cpu_set_ftrace_enabled(ftrace_enabled);

arch/powerpc/kernel/smp.c

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,43 +1240,33 @@ static struct device_node *cpu_to_l2cache(int cpu)
12401240
return cache;
12411241
}
12421242

1243-
static bool update_mask_by_l2(int cpu)
1243+
static bool update_mask_by_l2(int cpu, cpumask_var_t *mask)
12441244
{
12451245
struct cpumask *(*submask_fn)(int) = cpu_sibling_mask;
12461246
struct device_node *l2_cache, *np;
1247-
cpumask_var_t mask;
12481247
int i;
12491248

1250-
l2_cache = cpu_to_l2cache(cpu);
1251-
if (!l2_cache) {
1252-
struct cpumask *(*sibling_mask)(int) = cpu_sibling_mask;
1253-
1254-
/*
1255-
* If no l2cache for this CPU, assume all siblings to share
1256-
* cache with this CPU.
1257-
*/
1258-
if (has_big_cores)
1259-
sibling_mask = cpu_smallcore_mask;
1249+
if (has_big_cores)
1250+
submask_fn = cpu_smallcore_mask;
12601251

1261-
for_each_cpu(i, sibling_mask(cpu))
1252+
l2_cache = cpu_to_l2cache(cpu);
1253+
if (!l2_cache || !*mask) {
1254+
/* Assume only core siblings share cache with this CPU */
1255+
for_each_cpu(i, submask_fn(cpu))
12621256
set_cpus_related(cpu, i, cpu_l2_cache_mask);
12631257

12641258
return false;
12651259
}
12661260

1267-
alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu));
1268-
cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu));
1269-
1270-
if (has_big_cores)
1271-
submask_fn = cpu_smallcore_mask;
1261+
cpumask_and(*mask, cpu_online_mask, cpu_cpu_mask(cpu));
12721262

12731263
/* Update l2-cache mask with all the CPUs that are part of submask */
12741264
or_cpumasks_related(cpu, cpu, submask_fn, cpu_l2_cache_mask);
12751265

12761266
/* Skip all CPUs already part of current CPU l2-cache mask */
1277-
cpumask_andnot(mask, mask, cpu_l2_cache_mask(cpu));
1267+
cpumask_andnot(*mask, *mask, cpu_l2_cache_mask(cpu));
12781268

1279-
for_each_cpu(i, mask) {
1269+
for_each_cpu(i, *mask) {
12801270
/*
12811271
* when updating the marks the current CPU has not been marked
12821272
* online, but we need to update the cache masks
@@ -1286,15 +1276,14 @@ static bool update_mask_by_l2(int cpu)
12861276
/* Skip all CPUs already part of current CPU l2-cache */
12871277
if (np == l2_cache) {
12881278
or_cpumasks_related(cpu, i, submask_fn, cpu_l2_cache_mask);
1289-
cpumask_andnot(mask, mask, submask_fn(i));
1279+
cpumask_andnot(*mask, *mask, submask_fn(i));
12901280
} else {
1291-
cpumask_andnot(mask, mask, cpu_l2_cache_mask(i));
1281+
cpumask_andnot(*mask, *mask, cpu_l2_cache_mask(i));
12921282
}
12931283

12941284
of_node_put(np);
12951285
}
12961286
of_node_put(l2_cache);
1297-
free_cpumask_var(mask);
12981287

12991288
return true;
13001289
}
@@ -1337,40 +1326,46 @@ static inline void add_cpu_to_smallcore_masks(int cpu)
13371326
}
13381327
}
13391328

1340-
static void update_coregroup_mask(int cpu)
1329+
static void update_coregroup_mask(int cpu, cpumask_var_t *mask)
13411330
{
13421331
struct cpumask *(*submask_fn)(int) = cpu_sibling_mask;
1343-
cpumask_var_t mask;
13441332
int coregroup_id = cpu_to_coregroup_id(cpu);
13451333
int i;
13461334

1347-
alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu));
1348-
cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu));
1349-
13501335
if (shared_caches)
13511336
submask_fn = cpu_l2_cache_mask;
13521337

1338+
if (!*mask) {
1339+
/* Assume only siblings are part of this CPU's coregroup */
1340+
for_each_cpu(i, submask_fn(cpu))
1341+
set_cpus_related(cpu, i, cpu_coregroup_mask);
1342+
1343+
return;
1344+
}
1345+
1346+
cpumask_and(*mask, cpu_online_mask, cpu_cpu_mask(cpu));
1347+
13531348
/* Update coregroup mask with all the CPUs that are part of submask */
13541349
or_cpumasks_related(cpu, cpu, submask_fn, cpu_coregroup_mask);
13551350

13561351
/* Skip all CPUs already part of coregroup mask */
1357-
cpumask_andnot(mask, mask, cpu_coregroup_mask(cpu));
1352+
cpumask_andnot(*mask, *mask, cpu_coregroup_mask(cpu));
13581353

1359-
for_each_cpu(i, mask) {
1354+
for_each_cpu(i, *mask) {
13601355
/* Skip all CPUs not part of this coregroup */
13611356
if (coregroup_id == cpu_to_coregroup_id(i)) {
13621357
or_cpumasks_related(cpu, i, submask_fn, cpu_coregroup_mask);
1363-
cpumask_andnot(mask, mask, submask_fn(i));
1358+
cpumask_andnot(*mask, *mask, submask_fn(i));
13641359
} else {
1365-
cpumask_andnot(mask, mask, cpu_coregroup_mask(i));
1360+
cpumask_andnot(*mask, *mask, cpu_coregroup_mask(i));
13661361
}
13671362
}
1368-
free_cpumask_var(mask);
13691363
}
13701364

13711365
static void add_cpu_to_masks(int cpu)
13721366
{
13731367
int first_thread = cpu_first_thread_sibling(cpu);
1368+
cpumask_var_t mask;
13741369
int i;
13751370

13761371
/*
@@ -1384,10 +1379,15 @@ static void add_cpu_to_masks(int cpu)
13841379
set_cpus_related(i, cpu, cpu_sibling_mask);
13851380

13861381
add_cpu_to_smallcore_masks(cpu);
1387-
update_mask_by_l2(cpu);
1382+
1383+
/* In CPU-hotplug path, hence use GFP_ATOMIC */
1384+
alloc_cpumask_var_node(&mask, GFP_ATOMIC, cpu_to_node(cpu));
1385+
update_mask_by_l2(cpu, &mask);
13881386

13891387
if (has_coregroup_support())
1390-
update_coregroup_mask(cpu);
1388+
update_coregroup_mask(cpu, &mask);
1389+
1390+
free_cpumask_var(mask);
13911391
}
13921392

13931393
/* Activate a secondary processor. */

arch/powerpc/kernel/traps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ static void p9_hmi_special_emu(struct pt_regs *regs)
885885
{
886886
unsigned int ra, rb, t, i, sel, instr, rc;
887887
const void __user *addr;
888-
u8 vbuf[16], *vdst;
888+
u8 vbuf[16] __aligned(16), *vdst;
889889
unsigned long ea, msr, msr_mask;
890890
bool swap;
891891

arch/powerpc/platforms/powernv/opal-dump.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ static ssize_t dump_ack_store(struct dump_obj *dump_obj,
8888
const char *buf,
8989
size_t count)
9090
{
91-
dump_send_ack(dump_obj->id);
92-
sysfs_remove_file_self(&dump_obj->kobj, &attr->attr);
93-
kobject_put(&dump_obj->kobj);
91+
/*
92+
* Try to self remove this attribute. If we are successful,
93+
* delete the kobject itself.
94+
*/
95+
if (sysfs_remove_file_self(&dump_obj->kobj, &attr->attr)) {
96+
dump_send_ack(dump_obj->id);
97+
kobject_put(&dump_obj->kobj);
98+
}
9499
return count;
95100
}
96101

@@ -318,15 +323,14 @@ static ssize_t dump_attr_read(struct file *filep, struct kobject *kobj,
318323
return count;
319324
}
320325

321-
static struct dump_obj *create_dump_obj(uint32_t id, size_t size,
322-
uint32_t type)
326+
static void create_dump_obj(uint32_t id, size_t size, uint32_t type)
323327
{
324328
struct dump_obj *dump;
325329
int rc;
326330

327331
dump = kzalloc(sizeof(*dump), GFP_KERNEL);
328332
if (!dump)
329-
return NULL;
333+
return;
330334

331335
dump->kobj.kset = dump_kset;
332336

@@ -346,21 +350,39 @@ static struct dump_obj *create_dump_obj(uint32_t id, size_t size,
346350
rc = kobject_add(&dump->kobj, NULL, "0x%x-0x%x", type, id);
347351
if (rc) {
348352
kobject_put(&dump->kobj);
349-
return NULL;
353+
return;
350354
}
351355

356+
/*
357+
* As soon as the sysfs file for this dump is created/activated there is
358+
* a chance the opal_errd daemon (or any userspace) might read and
359+
* acknowledge the dump before kobject_uevent() is called. If that
360+
* happens then there is a potential race between
361+
* dump_ack_store->kobject_put() and kobject_uevent() which leads to a
362+
* use-after-free of a kernfs object resulting in a kernel crash.
363+
*
364+
* To avoid that, we need to take a reference on behalf of the bin file,
365+
* so that our reference remains valid while we call kobject_uevent().
366+
* We then drop our reference before exiting the function, leaving the
367+
* bin file to drop the last reference (if it hasn't already).
368+
*/
369+
370+
/* Take a reference for the bin file */
371+
kobject_get(&dump->kobj);
352372
rc = sysfs_create_bin_file(&dump->kobj, &dump->dump_attr);
353-
if (rc) {
373+
if (rc == 0) {
374+
kobject_uevent(&dump->kobj, KOBJ_ADD);
375+
376+
pr_info("%s: New platform dump. ID = 0x%x Size %u\n",
377+
__func__, dump->id, dump->size);
378+
} else {
379+
/* Drop reference count taken for bin file */
354380
kobject_put(&dump->kobj);
355-
return NULL;
356381
}
357382

358-
pr_info("%s: New platform dump. ID = 0x%x Size %u\n",
359-
__func__, dump->id, dump->size);
360-
361-
kobject_uevent(&dump->kobj, KOBJ_ADD);
362-
363-
return dump;
383+
/* Drop our reference */
384+
kobject_put(&dump->kobj);
385+
return;
364386
}
365387

366388
static irqreturn_t process_dump(int irq, void *data)

arch/powerpc/platforms/powernv/opal-elog.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,14 @@ static ssize_t elog_ack_store(struct elog_obj *elog_obj,
7272
const char *buf,
7373
size_t count)
7474
{
75-
opal_send_ack_elog(elog_obj->id);
76-
sysfs_remove_file_self(&elog_obj->kobj, &attr->attr);
77-
kobject_put(&elog_obj->kobj);
75+
/*
76+
* Try to self remove this attribute. If we are successful,
77+
* delete the kobject itself.
78+
*/
79+
if (sysfs_remove_file_self(&elog_obj->kobj, &attr->attr)) {
80+
opal_send_ack_elog(elog_obj->id);
81+
kobject_put(&elog_obj->kobj);
82+
}
7883
return count;
7984
}
8085

0 commit comments

Comments
 (0)