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(§ion); |
|
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