Le 01/04/2020 Ã 08:13, Ravi Bangoria a ÃcritÂ:
Currently we assume that we have only one watchpoint supported by hw.
Get rid of that assumption and use dynamic loop instead. This should
make supporting more watchpoints very easy.
With more than one watchpoint, exception handler need to know which
DAWR caused the exception, and hw currently does not provide it. So
we need sw logic for the same. To figure out which DAWR caused the
exception, check all different combinations of user specified range,
dawr address range, actual access range and dawrx constrains. For ex,
if user specified range and actual access range overlaps but dawrx is
configured for readonly watchpoint and the instruction is store, this
DAWR must not have caused exception.
Signed-off-by: Ravi Bangoria <ravi.bangoria@xxxxxxxxxxxxx>
---
 arch/powerpc/include/asm/processor.h | 2 +-
 arch/powerpc/include/asm/sstep.h | 2 +
 arch/powerpc/kernel/hw_breakpoint.c | 396 +++++++++++++++++++++------
 arch/powerpc/kernel/process.c | 3 -
 4 files changed, 313 insertions(+), 90 deletions(-)
[...]
-static bool
-dar_range_overlaps(unsigned long dar, int size, struct arch_hw_breakpoint *info)
+static bool dar_user_range_overlaps(unsigned long dar, int size,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct arch_hw_breakpoint *info)
 {
ÂÂÂÂÂ return ((dar <= info->address + info->len - 1) &&
ÂÂÂÂÂÂÂÂÂ (dar + size - 1 >= info->address));
 }
Here and several other places, I think it would be more clear if you could avoid the - 1 :
ÂÂÂÂreturn ((dar < info->address + info->len) &&
ÂÂÂÂÂÂÂ (dar + size > info->address));
+static bool dar_in_hw_range(unsigned long dar, struct arch_hw_breakpoint *info)
+{
+ÂÂÂ unsigned long hw_start_addr, hw_end_addr;
+
+ÂÂÂ hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE);
+ÂÂÂ hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE) - 1;
+
+ÂÂÂ return ((hw_start_addr <= dar) && (hw_end_addr >= dar));
+}
ÂÂÂÂhw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE);
ÂÂÂÂreturn ((hw_start_addr <= dar) && (hw_end_addr > dar));