Commit f3c832f1 authored by Ravi Bangoria's avatar Ravi Bangoria Committed by Michael Ellerman

powerpc/watchpoint: Fix DAWR exception for CACHEOP

'ea' returned by analyse_instr() needs to be aligned down to cache
block size for CACHEOP instructions. analyse_instr() does not set
size for CACHEOP, thus size also needs to be calculated manually.

Fixes: 27985b2a ("powerpc/watchpoint: Don't ignore extraneous exceptions blindly")
Fixes: 74c68810 ("powerpc/watchpoint: Prepare handler to handle more than one watchpoint")
Signed-off-by: default avatarRavi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200723090813.303838-4-ravi.bangoria@linux.ibm.com
parent f6780ce6
...@@ -538,7 +538,12 @@ static bool check_dawrx_constraints(struct pt_regs *regs, int type, ...@@ -538,7 +538,12 @@ static bool check_dawrx_constraints(struct pt_regs *regs, int type,
if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ)) if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ))
return false; return false;
if (OP_IS_STORE(type) && !(info->type & HW_BRK_TYPE_WRITE)) /*
* The Cache Management instructions other than dcbz never
* cause a match. i.e. if type is CACHEOP, the instruction
* is dcbz, and dcbz is treated as Store.
*/
if ((OP_IS_STORE(type) || type == CACHEOP) && !(info->type & HW_BRK_TYPE_WRITE))
return false; return false;
if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL)) if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL))
...@@ -601,6 +606,15 @@ static bool check_constraints(struct pt_regs *regs, struct ppc_inst instr, ...@@ -601,6 +606,15 @@ static bool check_constraints(struct pt_regs *regs, struct ppc_inst instr,
return false; return false;
} }
static int cache_op_size(void)
{
#ifdef __powerpc64__
return ppc64_caches.l1d.block_size;
#else
return L1_CACHE_BYTES;
#endif
}
static void get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, static void get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr,
int *type, int *size, unsigned long *ea) int *type, int *size, unsigned long *ea)
{ {
...@@ -616,7 +630,12 @@ static void get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, ...@@ -616,7 +630,12 @@ static void get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr,
if (!(regs->msr & MSR_64BIT)) if (!(regs->msr & MSR_64BIT))
*ea &= 0xffffffffUL; *ea &= 0xffffffffUL;
#endif #endif
*size = GETSIZE(op.type); *size = GETSIZE(op.type);
if (*type == CACHEOP) {
*size = cache_op_size();
*ea &= ~(*size - 1);
}
} }
static bool is_larx_stcx_instr(int type) static bool is_larx_stcx_instr(int type)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment