Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+186 -121
+13
arch/powerpc/include/asm/asm-const.h
··· 11 11 # define __ASM_CONST(x) x##UL 12 12 # define ASM_CONST(x) __ASM_CONST(x) 13 13 #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 + 14 27 #endif /* _ASM_POWERPC_ASM_CONST_H */
+1 -1
arch/powerpc/include/asm/cputable.h
··· 477 477 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ 478 478 CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ 479 479 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 | \ 481 481 CPU_FTR_DAWR | CPU_FTR_DAWR1) 482 482 #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ 483 483 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+2 -2
arch/powerpc/include/asm/uaccess.h
··· 182 182 "1: " op "%U1%X1 %0,%1 # put_user\n" \ 183 183 EX_TABLE(1b, %l2) \ 184 184 : \ 185 - : "r" (x), "m<>" (*addr) \ 185 + : "r" (x), "m"UPD_CONSTR (*addr) \ 186 186 : \ 187 187 : label) 188 188 ··· 253 253 ".previous\n" \ 254 254 EX_TABLE(1b, 3b) \ 255 255 : "=r" (err), "=r" (x) \ 256 - : "m<>" (*addr), "i" (-EFAULT), "0" (err)) 256 + : "m"UPD_CONSTR (*addr), "i" (-EFAULT), "0" (err)) 257 257 258 258 #ifdef __powerpc64__ 259 259 #define __get_user_asm2(x, addr, err) \
+10 -3
arch/powerpc/kernel/cputable.c
··· 121 121 PPC_FEATURE2_DARN | \ 122 122 PPC_FEATURE2_SCV) 123 123 #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) 127 134 128 135 #ifdef CONFIG_PPC_BOOK3E_64 129 136 #define COMMON_USER_BOOKE (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE)
-5
arch/powerpc/kernel/eeh.c
··· 466 466 return 0; 467 467 } 468 468 469 - if (!pe->addr) { 470 - eeh_stats.no_cfg_addr++; 471 - return 0; 472 - } 473 - 474 469 /* 475 470 * On PowerNV platform, we might already have fenced PHB 476 471 * there and we need take care of that firstly.
+3 -4
arch/powerpc/kernel/mce.c
··· 591 591 long notrace machine_check_early(struct pt_regs *regs) 592 592 { 593 593 long handled = 0; 594 - bool nested = in_nmi(); 595 594 u8 ftrace_enabled = this_cpu_get_ftrace_enabled(); 596 595 597 596 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)) 600 599 nmi_enter(); 601 600 602 601 hv_nmi_check_nonrecoverable(regs); ··· 606 607 if (ppc_md.machine_check_early) 607 608 handled = ppc_md.machine_check_early(regs); 608 609 609 - if (!nested) 610 + if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR)) 610 611 nmi_exit(); 611 612 612 613 this_cpu_set_ftrace_enabled(ftrace_enabled);
+35 -35
arch/powerpc/kernel/smp.c
··· 1240 1240 return cache; 1241 1241 } 1242 1242 1243 - static bool update_mask_by_l2(int cpu) 1243 + static bool update_mask_by_l2(int cpu, cpumask_var_t *mask) 1244 1244 { 1245 1245 struct cpumask *(*submask_fn)(int) = cpu_sibling_mask; 1246 1246 struct device_node *l2_cache, *np; 1247 - cpumask_var_t mask; 1248 1247 int i; 1249 1248 1249 + if (has_big_cores) 1250 + submask_fn = cpu_smallcore_mask; 1251 + 1250 1252 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; 1260 - 1261 - for_each_cpu(i, sibling_mask(cpu)) 1253 + if (!l2_cache || !*mask) { 1254 + /* Assume only core siblings share cache with this CPU */ 1255 + for_each_cpu(i, submask_fn(cpu)) 1262 1256 set_cpus_related(cpu, i, cpu_l2_cache_mask); 1263 1257 1264 1258 return false; 1265 1259 } 1266 1260 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)); 1272 1262 1273 1263 /* Update l2-cache mask with all the CPUs that are part of submask */ 1274 1264 or_cpumasks_related(cpu, cpu, submask_fn, cpu_l2_cache_mask); 1275 1265 1276 1266 /* 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)); 1278 1268 1279 - for_each_cpu(i, mask) { 1269 + for_each_cpu(i, *mask) { 1280 1270 /* 1281 1271 * when updating the marks the current CPU has not been marked 1282 1272 * online, but we need to update the cache masks ··· 1276 1286 /* Skip all CPUs already part of current CPU l2-cache */ 1277 1287 if (np == l2_cache) { 1278 1288 or_cpumasks_related(cpu, i, submask_fn, cpu_l2_cache_mask); 1279 - cpumask_andnot(mask, mask, submask_fn(i)); 1289 + cpumask_andnot(*mask, *mask, submask_fn(i)); 1280 1290 } else { 1281 - cpumask_andnot(mask, mask, cpu_l2_cache_mask(i)); 1291 + cpumask_andnot(*mask, *mask, cpu_l2_cache_mask(i)); 1282 1292 } 1283 1293 1284 1294 of_node_put(np); 1285 1295 } 1286 1296 of_node_put(l2_cache); 1287 - free_cpumask_var(mask); 1288 1297 1289 1298 return true; 1290 1299 } ··· 1326 1337 } 1327 1338 } 1328 1339 1329 - static void update_coregroup_mask(int cpu) 1340 + static void update_coregroup_mask(int cpu, cpumask_var_t *mask) 1330 1341 { 1331 1342 struct cpumask *(*submask_fn)(int) = cpu_sibling_mask; 1332 - cpumask_var_t mask; 1333 1343 int coregroup_id = cpu_to_coregroup_id(cpu); 1334 1344 int i; 1335 1345 1336 - alloc_cpumask_var_node(&mask, GFP_KERNEL, cpu_to_node(cpu)); 1337 - cpumask_and(mask, cpu_online_mask, cpu_cpu_mask(cpu)); 1338 - 1339 1346 if (shared_caches) 1340 1347 submask_fn = cpu_l2_cache_mask; 1348 + 1349 + if (!*mask) { 1350 + /* Assume only siblings are part of this CPU's coregroup */ 1351 + for_each_cpu(i, submask_fn(cpu)) 1352 + set_cpus_related(cpu, i, cpu_coregroup_mask); 1353 + 1354 + return; 1355 + } 1356 + 1357 + cpumask_and(*mask, cpu_online_mask, cpu_cpu_mask(cpu)); 1341 1358 1342 1359 /* Update coregroup mask with all the CPUs that are part of submask */ 1343 1360 or_cpumasks_related(cpu, cpu, submask_fn, cpu_coregroup_mask); 1344 1361 1345 1362 /* Skip all CPUs already part of coregroup mask */ 1346 - cpumask_andnot(mask, mask, cpu_coregroup_mask(cpu)); 1363 + cpumask_andnot(*mask, *mask, cpu_coregroup_mask(cpu)); 1347 1364 1348 - for_each_cpu(i, mask) { 1365 + for_each_cpu(i, *mask) { 1349 1366 /* Skip all CPUs not part of this coregroup */ 1350 1367 if (coregroup_id == cpu_to_coregroup_id(i)) { 1351 1368 or_cpumasks_related(cpu, i, submask_fn, cpu_coregroup_mask); 1352 - cpumask_andnot(mask, mask, submask_fn(i)); 1369 + cpumask_andnot(*mask, *mask, submask_fn(i)); 1353 1370 } else { 1354 - cpumask_andnot(mask, mask, cpu_coregroup_mask(i)); 1371 + cpumask_andnot(*mask, *mask, cpu_coregroup_mask(i)); 1355 1372 } 1356 1373 } 1357 - free_cpumask_var(mask); 1358 1374 } 1359 1375 1360 1376 static void add_cpu_to_masks(int cpu) 1361 1377 { 1362 1378 int first_thread = cpu_first_thread_sibling(cpu); 1379 + cpumask_var_t mask; 1363 1380 int i; 1364 1381 1365 1382 /* ··· 1379 1384 set_cpus_related(i, cpu, cpu_sibling_mask); 1380 1385 1381 1386 add_cpu_to_smallcore_masks(cpu); 1382 - update_mask_by_l2(cpu); 1387 + 1388 + /* In CPU-hotplug path, hence use GFP_ATOMIC */ 1389 + alloc_cpumask_var_node(&mask, GFP_ATOMIC, cpu_to_node(cpu)); 1390 + update_mask_by_l2(cpu, &mask); 1383 1391 1384 1392 if (has_coregroup_support()) 1385 - update_coregroup_mask(cpu); 1393 + update_coregroup_mask(cpu, &mask); 1394 + 1395 + free_cpumask_var(mask); 1386 1396 } 1387 1397 1388 1398 /* Activate a secondary processor. */
+1 -1
arch/powerpc/kernel/traps.c
··· 885 885 { 886 886 unsigned int ra, rb, t, i, sel, instr, rc; 887 887 const void __user *addr; 888 - u8 vbuf[16], *vdst; 888 + u8 vbuf[16] __aligned(16), *vdst; 889 889 unsigned long ea, msr, msr_mask; 890 890 bool swap; 891 891
+37 -15
arch/powerpc/platforms/powernv/opal-dump.c
··· 88 88 const char *buf, 89 89 size_t count) 90 90 { 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 + } 94 99 return count; 95 100 } 96 101 ··· 323 318 return count; 324 319 } 325 320 326 - static struct dump_obj *create_dump_obj(uint32_t id, size_t size, 327 - uint32_t type) 321 + static void create_dump_obj(uint32_t id, size_t size, uint32_t type) 328 322 { 329 323 struct dump_obj *dump; 330 324 int rc; 331 325 332 326 dump = kzalloc(sizeof(*dump), GFP_KERNEL); 333 327 if (!dump) 334 - return NULL; 328 + return; 335 329 336 330 dump->kobj.kset = dump_kset; 337 331 ··· 350 346 rc = kobject_add(&dump->kobj, NULL, "0x%x-0x%x", type, id); 351 347 if (rc) { 352 348 kobject_put(&dump->kobj); 353 - return NULL; 349 + return; 354 350 } 355 351 352 + /* 353 + * As soon as the sysfs file for this dump is created/activated there is 354 + * a chance the opal_errd daemon (or any userspace) might read and 355 + * acknowledge the dump before kobject_uevent() is called. If that 356 + * happens then there is a potential race between 357 + * dump_ack_store->kobject_put() and kobject_uevent() which leads to a 358 + * use-after-free of a kernfs object resulting in a kernel crash. 359 + * 360 + * To avoid that, we need to take a reference on behalf of the bin file, 361 + * so that our reference remains valid while we call kobject_uevent(). 362 + * We then drop our reference before exiting the function, leaving the 363 + * bin file to drop the last reference (if it hasn't already). 364 + */ 365 + 366 + /* Take a reference for the bin file */ 367 + kobject_get(&dump->kobj); 356 368 rc = sysfs_create_bin_file(&dump->kobj, &dump->dump_attr); 357 - if (rc) { 369 + if (rc == 0) { 370 + kobject_uevent(&dump->kobj, KOBJ_ADD); 371 + 372 + pr_info("%s: New platform dump. ID = 0x%x Size %u\n", 373 + __func__, dump->id, dump->size); 374 + } else { 375 + /* Drop reference count taken for bin file */ 358 376 kobject_put(&dump->kobj); 359 - return NULL; 360 377 } 361 378 362 - pr_info("%s: New platform dump. ID = 0x%x Size %u\n", 363 - __func__, dump->id, dump->size); 364 - 365 - kobject_uevent(&dump->kobj, KOBJ_ADD); 366 - 367 - return dump; 379 + /* Drop our reference */ 380 + kobject_put(&dump->kobj); 381 + return; 368 382 } 369 383 370 384 static irqreturn_t process_dump(int irq, void *data)
+8 -3
arch/powerpc/platforms/powernv/opal-elog.c
··· 72 72 const char *buf, 73 73 size_t count) 74 74 { 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 + } 78 83 return count; 79 84 } 80 85
+70 -50
arch/powerpc/platforms/pseries/ras.c
··· 521 521 return 0; /* need to perform reset */ 522 522 } 523 523 524 + static int mce_handle_err_realmode(int disposition, u8 error_type) 525 + { 526 + #ifdef CONFIG_PPC_BOOK3S_64 527 + if (disposition == RTAS_DISP_NOT_RECOVERED) { 528 + switch (error_type) { 529 + case MC_ERROR_TYPE_SLB: 530 + case MC_ERROR_TYPE_ERAT: 531 + /* 532 + * Store the old slb content in paca before flushing. 533 + * Print this when we go to virtual mode. 534 + * There are chances that we may hit MCE again if there 535 + * is a parity error on the SLB entry we trying to read 536 + * for saving. Hence limit the slb saving to single 537 + * level of recursion. 538 + */ 539 + if (local_paca->in_mce == 1) 540 + slb_save_contents(local_paca->mce_faulty_slbs); 541 + flush_and_reload_slb(); 542 + disposition = RTAS_DISP_FULLY_RECOVERED; 543 + break; 544 + default: 545 + break; 546 + } 547 + } else if (disposition == RTAS_DISP_LIMITED_RECOVERY) { 548 + /* Platform corrected itself but could be degraded */ 549 + pr_err("MCE: limited recovery, system may be degraded\n"); 550 + disposition = RTAS_DISP_FULLY_RECOVERED; 551 + } 552 + #endif 553 + return disposition; 554 + } 524 555 525 - static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp) 556 + static int mce_handle_err_virtmode(struct pt_regs *regs, 557 + struct rtas_error_log *errp, 558 + struct pseries_mc_errorlog *mce_log, 559 + int disposition) 526 560 { 527 561 struct mce_error_info mce_err = { 0 }; 528 - unsigned long eaddr = 0, paddr = 0; 529 - struct pseries_errorlog *pseries_log; 530 - struct pseries_mc_errorlog *mce_log; 531 - int disposition = rtas_error_disposition(errp); 532 562 int initiator = rtas_error_initiator(errp); 533 563 int severity = rtas_error_severity(errp); 564 + unsigned long eaddr = 0, paddr = 0; 534 565 u8 error_type, err_sub_type; 566 + 567 + if (!mce_log) 568 + goto out; 569 + 570 + error_type = mce_log->error_type; 571 + err_sub_type = rtas_mc_error_sub_type(mce_log); 535 572 536 573 if (initiator == RTAS_INITIATOR_UNKNOWN) 537 574 mce_err.initiator = MCE_INITIATOR_UNKNOWN; ··· 608 571 mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN; 609 572 mce_err.error_class = MCE_ECLASS_UNKNOWN; 610 573 611 - if (!rtas_error_extended(errp)) 612 - goto out; 613 - 614 - pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); 615 - if (pseries_log == NULL) 616 - goto out; 617 - 618 - mce_log = (struct pseries_mc_errorlog *)pseries_log->data; 619 - error_type = mce_log->error_type; 620 - err_sub_type = rtas_mc_error_sub_type(mce_log); 621 - 622 - switch (mce_log->error_type) { 574 + switch (error_type) { 623 575 case MC_ERROR_TYPE_UE: 624 576 mce_err.error_type = MCE_ERROR_TYPE_UE; 625 577 mce_common_process_ue(regs, &mce_err); ··· 708 682 mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN; 709 683 break; 710 684 } 711 - 712 - #ifdef CONFIG_PPC_BOOK3S_64 713 - if (disposition == RTAS_DISP_NOT_RECOVERED) { 714 - switch (error_type) { 715 - case MC_ERROR_TYPE_SLB: 716 - case MC_ERROR_TYPE_ERAT: 717 - /* 718 - * Store the old slb content in paca before flushing. 719 - * Print this when we go to virtual mode. 720 - * There are chances that we may hit MCE again if there 721 - * is a parity error on the SLB entry we trying to read 722 - * for saving. Hence limit the slb saving to single 723 - * level of recursion. 724 - */ 725 - if (local_paca->in_mce == 1) 726 - slb_save_contents(local_paca->mce_faulty_slbs); 727 - flush_and_reload_slb(); 728 - disposition = RTAS_DISP_FULLY_RECOVERED; 729 - break; 730 - default: 731 - break; 732 - } 733 - } else if (disposition == RTAS_DISP_LIMITED_RECOVERY) { 734 - /* Platform corrected itself but could be degraded */ 735 - printk(KERN_ERR "MCE: limited recovery, system may " 736 - "be degraded\n"); 737 - disposition = RTAS_DISP_FULLY_RECOVERED; 738 - } 739 - #endif 740 - 741 685 out: 686 + save_mce_event(regs, disposition == RTAS_DISP_FULLY_RECOVERED, 687 + &mce_err, regs->nip, eaddr, paddr); 688 + return disposition; 689 + } 690 + 691 + static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp) 692 + { 693 + struct pseries_errorlog *pseries_log; 694 + struct pseries_mc_errorlog *mce_log = NULL; 695 + int disposition = rtas_error_disposition(errp); 696 + u8 error_type; 697 + 698 + if (!rtas_error_extended(errp)) 699 + goto out; 700 + 701 + pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); 702 + if (!pseries_log) 703 + goto out; 704 + 705 + mce_log = (struct pseries_mc_errorlog *)pseries_log->data; 706 + error_type = mce_log->error_type; 707 + 708 + disposition = mce_handle_err_realmode(disposition, error_type); 709 + 742 710 /* 743 711 * Enable translation as we will be accessing per-cpu variables 744 712 * in save_mce_event() which may fall outside RMO region, also ··· 743 723 * Note: All the realmode handling like flushing SLB entries for 744 724 * SLB multihit is done by now. 745 725 */ 726 + out: 746 727 mtmsr(mfmsr() | MSR_IR | MSR_DR); 747 - save_mce_event(regs, disposition == RTAS_DISP_FULLY_RECOVERED, 748 - &mce_err, regs->nip, eaddr, paddr); 749 - 728 + disposition = mce_handle_err_virtmode(regs, errp, mce_log, 729 + disposition); 750 730 return disposition; 751 731 } 752 732
+6 -2
tools/testing/selftests/powerpc/alignment/alignment_handler.c
··· 266 266 } 267 267 268 268 rc = 0; 269 - /* offset = 0 no alignment fault, so skip */ 270 - for (offset = 1; offset < 16; offset++) { 269 + /* 270 + * offset = 0 is aligned but tests the workaround for the P9N 271 + * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s: 272 + * Add workaround for P9 vector CI load issue") 273 + */ 274 + for (offset = 0; offset < 16; offset++) { 271 275 width = 16; /* vsx == 16 bytes */ 272 276 r = 0; 273 277