diff options
-rw-r--r-- | Documentation/powerpc/ptrace.txt | 16 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 77 |
2 files changed, 6 insertions, 87 deletions
diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt index f2a7a3919772..f4a5499b7bc6 100644 --- a/Documentation/powerpc/ptrace.txt +++ b/Documentation/powerpc/ptrace.txt | |||
@@ -127,22 +127,6 @@ Some examples of using the structure to: | |||
127 | p.addr2 = (uint64_t) end_range; | 127 | p.addr2 = (uint64_t) end_range; |
128 | p.condition_value = 0; | 128 | p.condition_value = 0; |
129 | 129 | ||
130 | - set a watchpoint in server processors (BookS) | ||
131 | |||
132 | p.version = 1; | ||
133 | p.trigger_type = PPC_BREAKPOINT_TRIGGER_RW; | ||
134 | p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE; | ||
135 | or | ||
136 | p.addr_mode = PPC_BREAKPOINT_MODE_EXACT; | ||
137 | |||
138 | p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; | ||
139 | p.addr = (uint64_t) begin_range; | ||
140 | /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where | ||
141 | * addr2 - addr <= 8 Bytes. | ||
142 | */ | ||
143 | p.addr2 = (uint64_t) end_range; | ||
144 | p.condition_value = 0; | ||
145 | |||
146 | 3. PTRACE_DELHWDEBUG | 130 | 3. PTRACE_DELHWDEBUG |
147 | 131 | ||
148 | Takes an integer which identifies an existing breakpoint or watchpoint | 132 | Takes an integer which identifies an existing breakpoint or watchpoint |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8643ac890235..ac3cb008fb31 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -1336,12 +1336,6 @@ static int set_dac_range(struct task_struct *child, | |||
1336 | static long ppc_set_hwdebug(struct task_struct *child, | 1336 | static long ppc_set_hwdebug(struct task_struct *child, |
1337 | struct ppc_hw_breakpoint *bp_info) | 1337 | struct ppc_hw_breakpoint *bp_info) |
1338 | { | 1338 | { |
1339 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
1340 | int len = 0; | ||
1341 | struct thread_struct *thread = &(child->thread); | ||
1342 | struct perf_event *bp; | ||
1343 | struct perf_event_attr attr; | ||
1344 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
1345 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | 1339 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS |
1346 | unsigned long dabr; | 1340 | unsigned long dabr; |
1347 | #endif | 1341 | #endif |
@@ -1385,9 +1379,13 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1385 | */ | 1379 | */ |
1386 | if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || | 1380 | if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || |
1387 | (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || | 1381 | (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || |
1382 | bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT || | ||
1388 | bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) | 1383 | bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) |
1389 | return -EINVAL; | 1384 | return -EINVAL; |
1390 | 1385 | ||
1386 | if (child->thread.dabr) | ||
1387 | return -ENOSPC; | ||
1388 | |||
1391 | if ((unsigned long)bp_info->addr >= TASK_SIZE) | 1389 | if ((unsigned long)bp_info->addr >= TASK_SIZE) |
1392 | return -EIO; | 1390 | return -EIO; |
1393 | 1391 | ||
@@ -1397,63 +1395,15 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1397 | dabr |= DABR_DATA_READ; | 1395 | dabr |= DABR_DATA_READ; |
1398 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | 1396 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) |
1399 | dabr |= DABR_DATA_WRITE; | 1397 | dabr |= DABR_DATA_WRITE; |
1400 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
1401 | if (ptrace_get_breakpoints(child) < 0) | ||
1402 | return -ESRCH; | ||
1403 | |||
1404 | /* | ||
1405 | * Check if the request is for 'range' breakpoints. We can | ||
1406 | * support it if range < 8 bytes. | ||
1407 | */ | ||
1408 | if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) { | ||
1409 | len = bp_info->addr2 - bp_info->addr; | ||
1410 | } else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) { | ||
1411 | ptrace_put_breakpoints(child); | ||
1412 | return -EINVAL; | ||
1413 | } | ||
1414 | bp = thread->ptrace_bps[0]; | ||
1415 | if (bp) { | ||
1416 | ptrace_put_breakpoints(child); | ||
1417 | return -ENOSPC; | ||
1418 | } | ||
1419 | |||
1420 | /* Create a new breakpoint request if one doesn't exist already */ | ||
1421 | hw_breakpoint_init(&attr); | ||
1422 | attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN; | ||
1423 | attr.bp_len = len; | ||
1424 | arch_bp_generic_fields(dabr & (DABR_DATA_WRITE | DABR_DATA_READ), | ||
1425 | &attr.bp_type); | ||
1426 | |||
1427 | thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, | ||
1428 | ptrace_triggered, NULL, child); | ||
1429 | if (IS_ERR(bp)) { | ||
1430 | thread->ptrace_bps[0] = NULL; | ||
1431 | ptrace_put_breakpoints(child); | ||
1432 | return PTR_ERR(bp); | ||
1433 | } | ||
1434 | |||
1435 | ptrace_put_breakpoints(child); | ||
1436 | return 1; | ||
1437 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
1438 | |||
1439 | if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) | ||
1440 | return -EINVAL; | ||
1441 | |||
1442 | if (child->thread.dabr) | ||
1443 | return -ENOSPC; | ||
1444 | 1398 | ||
1445 | child->thread.dabr = dabr; | 1399 | child->thread.dabr = dabr; |
1400 | |||
1446 | return 1; | 1401 | return 1; |
1447 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | 1402 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ |
1448 | } | 1403 | } |
1449 | 1404 | ||
1450 | static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) | 1405 | static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) |
1451 | { | 1406 | { |
1452 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
1453 | int ret = 0; | ||
1454 | struct thread_struct *thread = &(child->thread); | ||
1455 | struct perf_event *bp; | ||
1456 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
1457 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1407 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
1458 | int rc; | 1408 | int rc; |
1459 | 1409 | ||
@@ -1473,25 +1423,10 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) | |||
1473 | #else | 1423 | #else |
1474 | if (data != 1) | 1424 | if (data != 1) |
1475 | return -EINVAL; | 1425 | return -EINVAL; |
1476 | |||
1477 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
1478 | if (ptrace_get_breakpoints(child) < 0) | ||
1479 | return -ESRCH; | ||
1480 | |||
1481 | bp = thread->ptrace_bps[0]; | ||
1482 | if (bp) { | ||
1483 | unregister_hw_breakpoint(bp); | ||
1484 | thread->ptrace_bps[0] = NULL; | ||
1485 | } else | ||
1486 | ret = -ENOENT; | ||
1487 | ptrace_put_breakpoints(child); | ||
1488 | return ret; | ||
1489 | #else /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
1490 | if (child->thread.dabr == 0) | 1426 | if (child->thread.dabr == 0) |
1491 | return -ENOENT; | 1427 | return -ENOENT; |
1492 | 1428 | ||
1493 | child->thread.dabr = 0; | 1429 | child->thread.dabr = 0; |
1494 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
1495 | 1430 | ||
1496 | return 0; | 1431 | return 0; |
1497 | #endif | 1432 | #endif |
@@ -1598,7 +1533,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
1598 | dbginfo.data_bp_alignment = 4; | 1533 | dbginfo.data_bp_alignment = 4; |
1599 | #endif | 1534 | #endif |
1600 | dbginfo.sizeof_condition = 0; | 1535 | dbginfo.sizeof_condition = 0; |
1601 | dbginfo.features = PPC_DEBUG_FEATURE_DATA_BP_RANGE; | 1536 | dbginfo.features = 0; |
1602 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | 1537 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
1603 | 1538 | ||
1604 | if (!access_ok(VERIFY_WRITE, datavp, | 1539 | if (!access_ok(VERIFY_WRITE, datavp, |