linux/arch/powerpc/include/asm
Christophe Leroy 663fdcecce powerpc/bitops: Fix possible undefined behaviour with fls() and fls64()
[ Upstream commit 1891ef21d9 ]

fls() and fls64() are using __builtin_ctz() and _builtin_ctzll().
On powerpc, those builtins trivially use ctlzw and ctlzd power
instructions.

Allthough those instructions provide the expected result with
input argument 0, __builtin_ctz() and __builtin_ctzll() are
documented as undefined for value 0.

The easiest fix would be to use fls() and fls64() functions
defined in include/asm-generic/bitops/builtin-fls.h and
include/asm-generic/bitops/fls64.h, but GCC output is not optimal:

00000388 <testfls>:
 388:   2c 03 00 00     cmpwi   r3,0
 38c:   41 82 00 10     beq     39c <testfls+0x14>
 390:   7c 63 00 34     cntlzw  r3,r3
 394:   20 63 00 20     subfic  r3,r3,32
 398:   4e 80 00 20     blr
 39c:   38 60 00 00     li      r3,0
 3a0:   4e 80 00 20     blr

000003b0 <testfls64>:
 3b0:   2c 03 00 00     cmpwi   r3,0
 3b4:   40 82 00 1c     bne     3d0 <testfls64+0x20>
 3b8:   2f 84 00 00     cmpwi   cr7,r4,0
 3bc:   38 60 00 00     li      r3,0
 3c0:   4d 9e 00 20     beqlr   cr7
 3c4:   7c 83 00 34     cntlzw  r3,r4
 3c8:   20 63 00 20     subfic  r3,r3,32
 3cc:   4e 80 00 20     blr
 3d0:   7c 63 00 34     cntlzw  r3,r3
 3d4:   20 63 00 40     subfic  r3,r3,64
 3d8:   4e 80 00 20     blr

When the input of fls(x) is a constant, just check x for nullity and
return either 0 or __builtin_clz(x). Otherwise, use cntlzw instruction
directly.

For fls64() on PPC64, do the same but with __builtin_clzll() and
cntlzd instruction. On PPC32, lets take the generic fls64() which
will use our fls(). The result is as expected:

00000388 <testfls>:
 388:   7c 63 00 34     cntlzw  r3,r3
 38c:   20 63 00 20     subfic  r3,r3,32
 390:   4e 80 00 20     blr

000003a0 <testfls64>:
 3a0:   2c 03 00 00     cmpwi   r3,0
 3a4:   40 82 00 10     bne     3b4 <testfls64+0x14>
 3a8:   7c 83 00 34     cntlzw  r3,r4
 3ac:   20 63 00 20     subfic  r3,r3,32
 3b0:   4e 80 00 20     blr
 3b4:   7c 63 00 34     cntlzw  r3,r3
 3b8:   20 63 00 40     subfic  r3,r3,64
 3bc:   4e 80 00 20     blr

Fixes: 2fcff790dc ("powerpc: Use builtin functions for fls()/__fls()/fls64()")
Cc: stable@vger.kernel.org
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Acked-by: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/348c2d3f19ffcff8abe50d52513f989c4581d000.1603375524.git.christophe.leroy@csgroup.eu
Signed-off-by: Sasha Levin <sashal@kernel.org>
2021-01-06 14:44:59 +01:00
..
book3s powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at 2020-12-30 11:26:12 +01:00
nohash powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at 2020-12-30 11:26:12 +01:00
8xx_immap.h
accounting.h
agp.h
archrandom.h
asm-405.h
asm-compat.h
asm-const.h
asm-offsets.h
asm-prototypes.h
async_tx.h
atomic.h
backlight.h
barrier.h
bitops.h powerpc/bitops: Fix possible undefined behaviour with fls() and fls64() 2021-01-06 14:44:59 +01:00
bootx.h
btext.h
bug.h
bugs.h
cache.h
cacheflush.h
cell-pmu.h
cell-regs.h
checksum.h
cmpxchg.h
code-patching-asm.h
code-patching.h
compat.h
context_tracking.h
copro.h
cpm.h
cpm1.h
cpm2.h
cpu_has_feature.h
cpufeature.h
cpuidle.h
cputable.h powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32 2020-12-30 11:25:55 +01:00
cputhreads.h
cputime.h
current.h
dbdma.h
dbell.h
dcr-generic.h
dcr-mmio.h
dcr-native.h
dcr-regs.h
dcr.h
debug.h
debugfs.h
delay.h
device.h
disassemble.h
dma-direct.h
dma-mapping.h
dma.h
drmem.h powerpc/drmem: Make lmb_size 64 bit 2020-11-05 11:08:51 +01:00
dt_cpu_ftrs.h
edac.h
eeh_event.h
eeh.h
ehv_pic.h
elf.h
emergency-restart.h
emulated_ops.h
epapr_hcalls.h
exception-64e.h
exception-64s.h powerpc/64s: flush L1D on kernel entry 2020-11-22 10:02:25 +01:00
exec.h
extable.h
fadump.h
fb.h
feature-fixups.h powerpc/64s: flush L1D after user accesses 2020-11-22 10:02:26 +01:00
firmware.h
fixmap.h
floppy.h
fs_pd.h
fsl_85xx_cache_sram.h
fsl_gtm.h
fsl_hcalls.h
fsl_lbc.h
fsl_pamu_stash.h
fsl_pm.h
ftrace.h
futex.h powerpc: Add a framework for user access tracking 2020-11-22 10:02:25 +01:00
grackle.h
hardirq.h
head-64.h
heathrow.h
highmem.h
hmi.h
hugetlb.h
hvcall.h
hvconsole.h
hvcserver.h
hvsi.h
hw_breakpoint.h
hw_irq.h
hydra.h
i8259.h
ibmebus.h
icswx.h
ide.h
ima.h
imc-pmu.h
immap_cpm2.h
io_event_irq.h
io-defs.h
io-workarounds.h
io.h
iommu.h
ipic.h
irq_work.h
irq.h
irqflags.h
isa-bridge.h
jump_label.h
Kbuild
kdebug.h
kdump.h
kexec.h
keylargo.h
kgdb.h
kmap_types.h
kprobes.h
kup.h powerpc/64s: flush L1D after user accesses 2020-11-22 10:02:26 +01:00
kvm_asm.h KVM: PPC: Book3S HV: Treat TM-related invalid form instructions on P9 like the valid ones 2020-10-01 13:14:38 +02:00
kvm_book3s_32.h
kvm_book3s_64.h
kvm_book3s_asm.h
kvm_book3s.h
kvm_booke_hv_asm.h
kvm_booke.h
kvm_fpu.h
kvm_host.h KVM: Pass MMU notifier range flags to kvm_unmap_hva_range() 2020-08-26 10:31:07 +02:00
kvm_para.h
kvm_ppc.h
libata-portmap.h
linkage.h
livepatch.h
local.h
lppaca.h
lv1call.h
machdep.h
macio.h
mc146818rtc.h
mce.h
mediabay.h
membarrier.h
mm-arch-hooks.h
mman.h
mmu_context.h powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM 2020-11-05 11:08:38 +01:00
mmu-8xx.h
mmu-40x.h
mmu-44x.h
mmu-book3e.h
mmu.h
mmzone.h
module.h
mpc5xxx.h
mpc6xx.h
mpc52xx_psc.h
mpc52xx.h
mpc85xx.h
mpc5121.h
mpc8260.h
mpic_msgr.h
mpic_timer.h
mpic.h
msi_bitmap.h
nmi.h
nvram.h
ohare.h
opal-api.h
opal.h
oprofile_impl.h
paca.h
page_32.h
page_64.h
page.h
parport.h
pasemi_dma.h
pci-bridge.h
pci.h
percpu.h powerpc: Fix circular dependency between percpu.h and mmu.h 2020-08-21 11:05:31 +02:00
perf_event_fsl_emb.h
perf_event_server.h
perf_event.h
pgalloc.h
pgtable-be-types.h
pgtable-types.h
pgtable.h
pkeys.h
plpar_wrappers.h
pmac_feature.h
pmac_low_i2c.h
pmac_pfunc.h
pmc.h
pmi.h
pnv-ocxl.h
pnv-pci.h
powernv.h
ppc_asm.h
ppc-opcode.h
ppc-pci.h
ppc4xx_ocm.h
ppc4xx.h
probes.h
processor.h
prom.h
ps3.h
ps3av.h
ps3gpu.h
ps3stor.h
pte-common.h
pte-walk.h
ptrace.h
reg_8xx.h
reg_a2.h
reg_booke.h
reg_fsl_emb.h
reg.h powerpc/tau: Use appropriate temperature sample interval 2020-10-29 09:55:18 +01:00
rheap.h
rio.h
rtas.h
runlatch.h
scom.h
seccomp.h
sections.h
security_features.h powerpc/64s: flush L1D after user accesses 2020-11-22 10:02:26 +01:00
serial.h
setjmp.h
setup.h powerpc/64s: flush L1D after user accesses 2020-11-22 10:02:26 +01:00
sfp-machine.h
shmparam.h
signal.h
slice.h
smp.h
smu.h
sparsemem.h
spinlock_types.h
spinlock.h
spu_csa.h
spu_info.h
spu_priv1.h
spu.h
sstep.h
stacktrace.h
string.h
swab.h
swiotlb.h
switch_to.h
synch.h
syscall.h
syscalls.h
systbl.h
tce.h
termios.h
thread_info.h
time.h
timex.h
tlb.h powerpc/64s/radix: Fix mm_cpumask trimming race vs kthread_use_mm 2020-10-30 10:38:19 +01:00
tlbflush.h
tm.h
topology.h
trace_clock.h
trace.h
tsi108_irq.h
tsi108_pci.h
tsi108.h
types.h
uaccess.h powerpc/uaccess: Evaluate macro arguments once, before user access is allowed 2020-11-22 10:02:25 +01:00
udbg.h
uic.h
unaligned.h
uninorth.h
unistd.h
uprobes.h
user.h
vas.h
vdso_datapage.h
vdso.h
vga.h
vio.h
word-at-a-time.h
xics.h
xilinx_intc.h
xilinx_pci.h
xive-regs.h
xive.h
xmon.h
xor_altivec.h
xor.h