fix(agc): cache Linux describePages results
This commit is contained in:
parent
2979ae37a3
commit
9f06176334
|
|
@ -423,6 +423,17 @@ struct PageStates {
|
|||
arena.forget(address, bytes);
|
||||
image.forget(address, bytes);
|
||||
}
|
||||
|
||||
void record(std::uintptr_t base, std::uintptr_t regionEnd, bool readable, bool writable, std::uint64_t generation) {
|
||||
for (PageSpan* span : {&arena, &image}) {
|
||||
if (!readable || span->size == 0 || regionEnd <= span->base || base >= span->base + span->size) continue;
|
||||
const std::uint8_t value = PageReadable | (writable ? PageWritable : 0u);
|
||||
const auto first = std::max(base, span->base);
|
||||
const auto last = std::min(regionEnd, span->base + span->size);
|
||||
for (auto at = first; at < last; at += PageBytes) span->store(at, value);
|
||||
if (GuestAllocations::GuestAllocationsGeneration_nid_postfix() != generation) span->forget(first, static_cast<std::size_t>(last - first));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PageStates& Pages() {
|
||||
|
|
@ -533,18 +544,12 @@ bool describePages(std::uintptr_t address, std::size_t bytes, Emit&& emit) {
|
|||
const bool committed = memory.State == MEM_COMMIT && (memory.Protect & (PAGE_GUARD | PAGE_NOACCESS)) == 0;
|
||||
const bool readable = committed && readableProtection(protection);
|
||||
const bool writable = readable && writableProtection(protection);
|
||||
for (PageSpan* span : {&pages.arena, &pages.image}) {
|
||||
if (!readable || span->size == 0 || regionEnd <= span->base || base >= span->base + span->size) continue;
|
||||
const std::uint8_t value = PageReadable | (writable ? PageWritable : 0u);
|
||||
const auto first = std::max(base, span->base);
|
||||
const auto last = std::min(regionEnd, span->base + span->size);
|
||||
for (auto at = first; at < last; at += PageBytes) span->store(at, value);
|
||||
if (GuestAllocations::GuestAllocationsGeneration_nid_postfix() != generation) span->forget(first, static_cast<std::size_t>(last - first));
|
||||
}
|
||||
pages.record(base, regionEnd, readable, writable, generation);
|
||||
const auto next = std::min(end, regionEnd);
|
||||
if (!emit(PageRun{cursor, next, readable, writable})) return true;
|
||||
cursor = next;
|
||||
#else
|
||||
const auto generation = GuestAllocations::GuestAllocationsGeneration_nid_postfix();
|
||||
if (const int fd = HostMapping::QueryFd(); fd >= 0) {
|
||||
procmap_query query{};
|
||||
query.size = sizeof(query);
|
||||
|
|
@ -558,9 +563,13 @@ bool describePages(std::uintptr_t address, std::size_t bytes, Emit&& emit) {
|
|||
cursor = gapEnd;
|
||||
continue;
|
||||
}
|
||||
const auto base = static_cast<std::uintptr_t>(query.vma_start);
|
||||
const auto regionEnd = static_cast<std::uintptr_t>(query.vma_end);
|
||||
const bool readable = (query.vma_flags & PROCMAP_QUERY_VMA_READABLE) != 0;
|
||||
const bool writable = readable && (query.vma_flags & PROCMAP_QUERY_VMA_WRITABLE) != 0;
|
||||
pages.record(base, regionEnd, readable, writable, generation);
|
||||
const auto next = std::min<std::uintptr_t>(end, query.vma_end);
|
||||
if (!emit(PageRun{cursor, next, readable, readable && (query.vma_flags & PROCMAP_QUERY_VMA_WRITABLE) != 0})) return true;
|
||||
if (!emit(PageRun{cursor, next, readable, writable})) return true;
|
||||
cursor = next;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -589,8 +598,11 @@ bool describePages(std::uintptr_t address, std::size_t bytes, Emit&& emit) {
|
|||
found = true;
|
||||
break;
|
||||
}
|
||||
const bool readable = permissions[0] == 'r';
|
||||
const bool writable = readable && permissions[1] == 'w';
|
||||
pages.record(first, last, readable, writable, generation);
|
||||
const auto next = std::min(end, last);
|
||||
if (!emit(PageRun{cursor, next, permissions[0] == 'r', permissions[0] == 'r' && permissions[1] == 'w'})) return true;
|
||||
if (!emit(PageRun{cursor, next, readable, writable})) return true;
|
||||
cursor = next;
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue