Revision 0f0cb164 exec.c

b/exec.c
2538 2538

  
2539 2539
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2540 2540
                             uint16_t section);
2541
static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section,
2542
                                uint16_t orig_section);
2543
#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2544
                      need_subpage)                                     \
2545
    do {                                                                \
2546
        if (addr > start_addr)                                          \
2547
            start_addr2 = 0;                                            \
2548
        else {                                                          \
2549
            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
2550
            if (start_addr2 > 0)                                        \
2551
                need_subpage = 1;                                       \
2552
        }                                                               \
2553
                                                                        \
2554
        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
2555
            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
2556
        else {                                                          \
2557
            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2558
            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
2559
                need_subpage = 1;                                       \
2560
        }                                                               \
2561
    } while (0)
2562

  
2541
static subpage_t *subpage_init(target_phys_addr_t base);
2563 2542
static void destroy_page_desc(uint16_t section_index)
2564 2543
{
2565 2544
    MemoryRegionSection *section = &phys_sections[section_index];
......
2622 2601
   start_addr and region_offset are rounded down to a page boundary
2623 2602
   before calculating this offset.  This should not be a problem unless
2624 2603
   the low bits of start_addr and region_offset differ.  */
2625
void cpu_register_physical_memory_log(MemoryRegionSection *section,
2626
                                      bool readonly)
2604
static void register_subpage(MemoryRegionSection *section)
2605
{
2606
    subpage_t *subpage;
2607
    target_phys_addr_t base = section->offset_within_address_space
2608
        & TARGET_PAGE_MASK;
2609
    MemoryRegionSection existing = phys_page_find(base >> TARGET_PAGE_BITS);
2610
    MemoryRegionSection subsection = {
2611
        .offset_within_address_space = base,
2612
        .size = TARGET_PAGE_SIZE,
2613
    };
2614
    uint16_t *ptr;
2615
    target_phys_addr_t start, end;
2616

  
2617
    assert(existing.mr->subpage || existing.mr == &io_mem_unassigned);
2618

  
2619
    if (!(existing.mr->subpage)) {
2620
        subpage = subpage_init(base);
2621
        subsection.mr = &subpage->iomem;
2622
        ptr = phys_page_find_alloc(base >> TARGET_PAGE_BITS, 1);
2623
        *ptr = phys_section_add(&subsection);
2624
    } else {
2625
        subpage = container_of(existing.mr, subpage_t, iomem);
2626
    }
2627
    start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
2628
    end = start + section->size;
2629
    subpage_register(subpage, start, end, phys_section_add(section));
2630
}
2631

  
2632

  
2633
static void register_multipage(MemoryRegionSection *section)
2627 2634
{
2628 2635
    target_phys_addr_t start_addr = section->offset_within_address_space;
2629 2636
    ram_addr_t size = section->size;
2630 2637
    target_phys_addr_t addr, end_addr;
2631
    ram_addr_t orig_size = size;
2632
    subpage_t *subpage;
2633 2638
    uint16_t section_index = phys_section_add(section);
2634 2639

  
2635 2640
    assert(size);
2636 2641

  
2637
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2638 2642
    end_addr = start_addr + (target_phys_addr_t)size;
2639 2643

  
2640 2644
    addr = start_addr;
2641 2645
    do {
2642 2646
        uint16_t *p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2643
        uint16_t orig_memory = *p;
2644
        target_phys_addr_t start_addr2, end_addr2;
2645
        int need_subpage = 0;
2646
        MemoryRegion *mr = phys_sections[orig_memory].mr;
2647

  
2648
        CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2649
                      need_subpage);
2650
        if (need_subpage) {
2651
            if (!(mr->subpage)) {
2652
                subpage = subpage_init((addr & TARGET_PAGE_MASK),
2653
                                       p, orig_memory);
2654
            } else {
2655
                subpage = container_of(mr, subpage_t, iomem);
2656
            }
2657
            subpage_register(subpage, start_addr2, end_addr2,
2658
                             section_index);
2659
        } else {
2660
            *p = section_index;
2661
        }
2647
        assert(*p == phys_section_unassigned);
2648
        *p = section_index;
2662 2649
        addr += TARGET_PAGE_SIZE;
2663 2650
    } while (addr != end_addr);
2664 2651
}
2665 2652

  
2653
void cpu_register_physical_memory_log(MemoryRegionSection *section,
2654
                                      bool readonly)
2655
{
2656
    MemoryRegionSection now = *section, remain = *section;
2657

  
2658
    if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
2659
        || (now.size < TARGET_PAGE_SIZE)) {
2660
        now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space)
2661
                       - now.offset_within_address_space,
2662
                       now.size);
2663
        register_subpage(&now);
2664
        remain.size -= now.size;
2665
        remain.offset_within_address_space += now.size;
2666
        remain.offset_within_region += now.size;
2667
    }
2668
    now = remain;
2669
    now.size &= TARGET_PAGE_MASK;
2670
    if (now.size) {
2671
        register_multipage(&now);
2672
        remain.size -= now.size;
2673
        remain.offset_within_address_space += now.size;
2674
        remain.offset_within_region += now.size;
2675
    }
2676
    now = remain;
2677
    if (now.size) {
2678
        register_subpage(&now);
2679
    }
2680
}
2681

  
2682

  
2666 2683
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2667 2684
{
2668 2685
    if (kvm_enabled())
......
3442 3459
    return 0;
3443 3460
}
3444 3461

  
3445
static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind,
3446
                                uint16_t orig_section)
3462
static subpage_t *subpage_init(target_phys_addr_t base)
3447 3463
{
3448 3464
    subpage_t *mmio;
3449
    MemoryRegionSection section = {
3450
        .offset_within_address_space = base,
3451
        .size = TARGET_PAGE_SIZE,
3452
    };
3453 3465

  
3454 3466
    mmio = g_malloc0(sizeof(subpage_t));
3455 3467

  
......
3457 3469
    memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
3458 3470
                          "subpage", TARGET_PAGE_SIZE);
3459 3471
    mmio->iomem.subpage = true;
3460
    section.mr = &mmio->iomem;
3461 3472
#if defined(DEBUG_SUBPAGE)
3462 3473
    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3463 3474
           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
3464 3475
#endif
3465
    *section_ind = phys_section_add(&section);
3466
    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_section);
3476
    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned);
3467 3477

  
3468 3478
    return mmio;
3469 3479
}

Also available in: Unified diff