Revision a1d1bb31 exec.c

b/exec.c
537 537
        cpu_index++;
538 538
    }
539 539
    env->cpu_index = cpu_index;
540
    env->nb_watchpoints = 0;
541 540
    *penv = env;
542 541
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
543 542
    register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
......
1299 1298
#endif
1300 1299

  
1301 1300
/* Add a watchpoint.  */
1302
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
1301
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1302
                          int flags, CPUWatchpoint **watchpoint)
1303 1303
{
1304
    int i;
1304
    CPUWatchpoint *wp;
1305 1305

  
1306
    for (i = 0; i < env->nb_watchpoints; i++) {
1307
        if (addr == env->watchpoint[i].vaddr)
1308
            return 0;
1309
    }
1310
    if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1311
        return -1;
1306
    wp = qemu_malloc(sizeof(*wp));
1307
    if (!wp)
1308
        return -ENOBUFS;
1309

  
1310
    wp->vaddr = addr;
1311
    wp->len_mask = 0;
1312
    wp->flags = flags;
1313

  
1314
    wp->next = env->watchpoints;
1315
    wp->prev = NULL;
1316
    if (wp->next)
1317
        wp->next->prev = wp;
1318
    env->watchpoints = wp;
1312 1319

  
1313
    i = env->nb_watchpoints++;
1314
    env->watchpoint[i].vaddr = addr;
1315
    env->watchpoint[i].type = type;
1316 1320
    tlb_flush_page(env, addr);
1317 1321
    /* FIXME: This flush is needed because of the hack to make memory ops
1318 1322
       terminate the TB.  It can be removed once the proper IO trap and
1319 1323
       re-execute bits are in.  */
1320 1324
    tb_flush(env);
1321
    return i;
1325

  
1326
    if (watchpoint)
1327
        *watchpoint = wp;
1328
    return 0;
1322 1329
}
1323 1330

  
1324
/* Remove a watchpoint.  */
1325
int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1331
/* Remove a specific watchpoint.  */
1332
int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1333
                          int flags)
1326 1334
{
1327
    int i;
1335
    CPUWatchpoint *wp;
1328 1336

  
1329
    for (i = 0; i < env->nb_watchpoints; i++) {
1330
        if (addr == env->watchpoint[i].vaddr) {
1331
            env->nb_watchpoints--;
1332
            env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1333
            tlb_flush_page(env, addr);
1337
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
1338
        if (addr == wp->vaddr && flags == wp->flags) {
1339
            cpu_watchpoint_remove_by_ref(env, wp);
1334 1340
            return 0;
1335 1341
        }
1336 1342
    }
1337
    return -1;
1343
    return -ENOENT;
1338 1344
}
1339 1345

  
1340
/* Remove all watchpoints. */
1341
void cpu_watchpoint_remove_all(CPUState *env) {
1342
    int i;
1346
/* Remove a specific watchpoint by reference.  */
1347
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1348
{
1349
    if (watchpoint->next)
1350
        watchpoint->next->prev = watchpoint->prev;
1351
    if (watchpoint->prev)
1352
        watchpoint->prev->next = watchpoint->next;
1353
    else
1354
        env->watchpoints = watchpoint->next;
1343 1355

  
1344
    for (i = 0; i < env->nb_watchpoints; i++) {
1345
        tlb_flush_page(env, env->watchpoint[i].vaddr);
1346
    }
1347
    env->nb_watchpoints = 0;
1356
    tlb_flush_page(env, watchpoint->vaddr);
1357

  
1358
    qemu_free(watchpoint);
1359
}
1360

  
1361
/* Remove all matching watchpoints.  */
1362
void cpu_watchpoint_remove_all(CPUState *env, int mask)
1363
{
1364
    CPUWatchpoint *wp;
1365

  
1366
    for (wp = env->watchpoints; wp != NULL; wp = wp->next)
1367
        if (wp->flags & mask)
1368
            cpu_watchpoint_remove_by_ref(env, wp);
1348 1369
}
1349 1370

  
1350
/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1351
   breakpoint is reached */
1352
int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
1371
/* Add a breakpoint.  */
1372
int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1373
                          CPUBreakpoint **breakpoint)
1353 1374
{
1354 1375
#if defined(TARGET_HAS_ICE)
1355
    int i;
1376
    CPUBreakpoint *bp;
1356 1377

  
1357
    for(i = 0; i < env->nb_breakpoints; i++) {
1358
        if (env->breakpoints[i] == pc)
1359
            return 0;
1360
    }
1378
    bp = qemu_malloc(sizeof(*bp));
1379
    if (!bp)
1380
        return -ENOBUFS;
1361 1381

  
1362
    if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1363
        return -1;
1364
    env->breakpoints[env->nb_breakpoints++] = pc;
1382
    bp->pc = pc;
1383
    bp->flags = flags;
1384

  
1385
    bp->next = env->breakpoints;
1386
    bp->prev = NULL;
1387
    if (bp->next)
1388
        bp->next->prev = bp;
1389
    env->breakpoints = bp;
1365 1390

  
1366 1391
    breakpoint_invalidate(env, pc);
1392

  
1393
    if (breakpoint)
1394
        *breakpoint = bp;
1367 1395
    return 0;
1368 1396
#else
1369
    return -1;
1397
    return -ENOSYS;
1370 1398
#endif
1371 1399
}
1372 1400

  
1373
/* remove all breakpoints */
1374
void cpu_breakpoint_remove_all(CPUState *env) {
1401
/* Remove a specific breakpoint.  */
1402
int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1403
{
1375 1404
#if defined(TARGET_HAS_ICE)
1376
    int i;
1377
    for(i = 0; i < env->nb_breakpoints; i++) {
1378
        breakpoint_invalidate(env, env->breakpoints[i]);
1405
    CPUBreakpoint *bp;
1406

  
1407
    for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
1408
        if (bp->pc == pc && bp->flags == flags) {
1409
            cpu_breakpoint_remove_by_ref(env, bp);
1410
            return 0;
1411
        }
1379 1412
    }
1380
    env->nb_breakpoints = 0;
1413
    return -ENOENT;
1414
#else
1415
    return -ENOSYS;
1381 1416
#endif
1382 1417
}
1383 1418

  
1384
/* remove a breakpoint */
1385
int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
1419
/* Remove a specific breakpoint by reference.  */
1420
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
1386 1421
{
1387 1422
#if defined(TARGET_HAS_ICE)
1388
    int i;
1389
    for(i = 0; i < env->nb_breakpoints; i++) {
1390
        if (env->breakpoints[i] == pc)
1391
            goto found;
1392
    }
1393
    return -1;
1394
 found:
1395
    env->nb_breakpoints--;
1396
    if (i < env->nb_breakpoints)
1397
      env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
1423
    if (breakpoint->next)
1424
        breakpoint->next->prev = breakpoint->prev;
1425
    if (breakpoint->prev)
1426
        breakpoint->prev->next = breakpoint->next;
1427
    else
1428
        env->breakpoints = breakpoint->next;
1398 1429

  
1399
    breakpoint_invalidate(env, pc);
1400
    return 0;
1401
#else
1402
    return -1;
1430
    breakpoint_invalidate(env, breakpoint->pc);
1431

  
1432
    qemu_free(breakpoint);
1433
#endif
1434
}
1435

  
1436
/* Remove all matching breakpoints. */
1437
void cpu_breakpoint_remove_all(CPUState *env, int mask)
1438
{
1439
#if defined(TARGET_HAS_ICE)
1440
    CPUBreakpoint *bp;
1441

  
1442
    for (bp = env->breakpoints; bp != NULL; bp = bp->next)
1443
        if (bp->flags & mask)
1444
            cpu_breakpoint_remove_by_ref(env, bp);
1403 1445
#endif
1404 1446
}
1405 1447

  
......
1881 1923
    target_phys_addr_t addend;
1882 1924
    int ret;
1883 1925
    CPUTLBEntry *te;
1884
    int i;
1926
    CPUWatchpoint *wp;
1885 1927
    target_phys_addr_t iotlb;
1886 1928

  
1887 1929
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
......
1922 1964
    code_address = address;
1923 1965
    /* Make accesses to pages with watchpoints go via the
1924 1966
       watchpoint trap routines.  */
1925
    for (i = 0; i < env->nb_watchpoints; i++) {
1926
        if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1967
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
1968
        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
1927 1969
            iotlb = io_mem_watch + paddr;
1928 1970
            /* TODO: The memory case can be optimized by not trapping
1929 1971
               reads of pages with a write breakpoint.  */
......
2456 2498
{
2457 2499
    CPUState *env = cpu_single_env;
2458 2500
    target_ulong vaddr;
2459
    int i;
2501
    CPUWatchpoint *wp;
2460 2502

  
2461 2503
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2462
    for (i = 0; i < env->nb_watchpoints; i++) {
2463
        if (vaddr == env->watchpoint[i].vaddr
2464
                && (env->watchpoint[i].type & flags)) {
2465
            env->watchpoint_hit = i + 1;
2504
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
2505
        if (vaddr == wp->vaddr && (wp->flags & flags)) {
2506
            env->watchpoint_hit = wp;
2466 2507
            cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2467 2508
            break;
2468 2509
        }
......
2474 2515
   phys routines.  */
2475 2516
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2476 2517
{
2477
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2518
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2478 2519
    return ldub_phys(addr);
2479 2520
}
2480 2521

  
2481 2522
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2482 2523
{
2483
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2524
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2484 2525
    return lduw_phys(addr);
2485 2526
}
2486 2527

  
2487 2528
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2488 2529
{
2489
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2530
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2490 2531
    return ldl_phys(addr);
2491 2532
}
2492 2533

  
2493 2534
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2494 2535
                             uint32_t val)
2495 2536
{
2496
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2537
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2497 2538
    stb_phys(addr, val);
2498 2539
}
2499 2540

  
2500 2541
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2501 2542
                             uint32_t val)
2502 2543
{
2503
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2544
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2504 2545
    stw_phys(addr, val);
2505 2546
}
2506 2547

  
2507 2548
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2508 2549
                             uint32_t val)
2509 2550
{
2510
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2551
    check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2511 2552
    stl_phys(addr, val);
2512 2553
}
2513 2554

  

Also available in: Unified diff