powerpc: Emulate the dcbz instruction

This adds code to analyse_instr() and emulate_step() to understand the
dcbz (data cache block zero) instruction.  The emulate_dcbz() function
is made public so it can be used by the alignment handler in future.
(The apparently unnecessary cropping of the address to 32 bits is
there because it will be needed in that situation.)

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Paul Mackerras
2017-08-30 14:12:36 +10:00
committed by Michael Ellerman
parent 1f41fb7904
commit b2543f7b20
2 changed files with 34 additions and 0 deletions

View File

@@ -780,6 +780,30 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op,
}
#endif /* CONFIG_VSX */
int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
{
int err;
unsigned long i, size;
#ifdef __powerpc64__
size = ppc64_caches.l1d.block_size;
if (!(regs->msr & MSR_64BIT))
ea &= 0xffffffffUL;
#else
size = L1_CACHE_BYTES;
#endif
ea &= ~(size - 1);
if (!address_ok(regs, ea, size))
return -EFAULT;
for (i = 0; i < size; i += sizeof(long)) {
err = __put_user(0, (unsigned long __user *) (ea + i));
if (err)
return err;
}
return 0;
}
NOKPROBE_SYMBOL(emulate_dcbz);
#define __put_user_asmx(x, addr, err, op, cr) \
__asm__ __volatile__( \
"1: " op " %2,0,%3\n" \
@@ -1748,6 +1772,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
op->type = MKOP(CACHEOP, ICBI, 0);
op->ea = xform_ea(instr, regs);
return 0;
case 1014: /* dcbz */
op->type = MKOP(CACHEOP, DCBZ, 0);
op->ea = xform_ea(instr, regs);
return 0;
}
break;
}
@@ -2607,6 +2636,9 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)
case ICBI:
__cacheop_user_asmx(ea, err, "icbi");
break;
case DCBZ:
err = emulate_dcbz(ea, regs);
break;
}
if (err)
return 0;