From 3e0eca2f7a7935a6726c43823726d42c4b0d80f9 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Tue, 20 Feb 2018 02:28:12 -0800 Subject: tools/aubdump: Add bitmap to track gtt pages that have been mapped This will allow us to map ranges as they are used, but prevents remapping already mapped regions. By mapping ranges as they are used, we can support pinned pages without having to map all pages of the first 32-bits. v2: * Make bitmap manipulation functions independent from 4k page size. Maybe will be usable also for 1GB pages with PPGTT. Signed-off-by: Jordan Justen Reviewed-by: Scott D Phillips --- tools/aubdump.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/aubdump.c b/tools/aubdump.c index ed181a50..fbd8bf8f 100644 --- a/tools/aubdump.c +++ b/tools/aubdump.c @@ -383,7 +383,7 @@ register_write_out(uint32_t addr, uint32_t value) } static void -gen8_map_ggtt_range(uint64_t start, uint64_t end) +gen8_emit_ggtt_pte_for_range(uint64_t start, uint64_t end) { uint64_t entry_addr; uint64_t page_num; @@ -410,6 +410,100 @@ gen8_map_ggtt_range(uint64_t start, uint64_t end) } while (entry_addr < end); } +/** + * Sets bits `start` through `end` - 1 in the bitmap array. + */ +static void +set_bitmap_range(uint32_t *bitmap, uint32_t start, uint32_t end) +{ + uint32_t pos = start; + while (pos < end) { + const uint32_t bit = 1 << (pos & 0x1f); + if (bit == 1 && (end - pos) > 32) { + bitmap[pos >> 5] = 0xffffffff; + pos += 32; + } else { + bitmap[pos >> 5] |= bit; + pos++; + } + } +} + +/** + * Finds the next `set` (or clear) bit in the bitmap array. + * + * The search starts at `*start` and only checks until `end` - 1. + * + * If found, returns true, and the found bit index in `*start`. + */ +static bool +find_bitmap_bit(uint32_t *bitmap, bool set, uint32_t *start, uint32_t end) +{ + uint32_t pos = *start; + const uint32_t neg_dw = set ? 0 : -1; + while (pos < end) { + const uint32_t dw = bitmap[pos >> 5]; + const uint32_t bit = 1 << (pos & 0x1f); + if (!!(dw & bit) == set) { + *start = pos; + return true; + } else if (bit == 1 && dw == neg_dw) + pos += 32; + else + pos++; + } + return false; +} + +/** + * Finds a range of clear bits within the bitmap array. + * + * The search starts at `*start` and only checks until `*end` - 1. + * + * If found, returns true, and `*start` and `*end` are set for the + * range of clear bits. + */ +static bool +find_bitmap_clear_bit_range(uint32_t *bitmap, uint32_t *start, uint32_t *end) +{ + if (find_bitmap_bit(bitmap, false, start, *end)) { + uint32_t found_end = *start; + if (find_bitmap_bit(bitmap, true, &found_end, *end)) + *end = found_end; + return true; + } + return false; +} + +static void +gen8_map_ggtt_range(uint64_t start, uint64_t end) +{ + uint32_t pos1, pos2, end_pos; + static uint32_t *bitmap = NULL; + if (bitmap == NULL) { + /* 4GiB (32-bits) of 4KiB pages (12-bits) in dwords (5-bits) */ + bitmap = calloc(1 << (32 - 12 - 5), sizeof(*bitmap)); + if (bitmap == NULL) + return; + } + + pos1 = start >> 12; + end_pos = (end + 4096 - 1) >> 12; + while (pos1 < end_pos) { + pos2 = end_pos; + if (!find_bitmap_clear_bit_range(bitmap, &pos1, &pos2)) + break; + + if (verbose) + printf("MAPPING 0x%08lx-0x%08lx\n", + (uint64_t)pos1 << 12, (uint64_t)pos2 << 12); + gen8_emit_ggtt_pte_for_range((uint64_t)pos1 << 12, + (uint64_t)pos2 << 12); + set_bitmap_range(bitmap, (uint64_t)pos1, (uint64_t)pos2); + pos1 = pos2; + } +} + static void gen10_write_header(void) { -- cgit v1.2.3