Skip to content

Commit bd0fa02

Browse files
committed
Allow blacking out parts of the address space
1 parent 7d3edde commit bd0fa02

File tree

6 files changed

+43
-28
lines changed

6 files changed

+43
-28
lines changed

lib/tinykvm/amd64/paging.cpp

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ static void add_remappings(vMemory& memory,
6666
throw MachineException("Invalid remapping address", remapping.virt);
6767
if (remapping.size % vMemory::PageSize() != 0)
6868
throw MachineException("Invalid remapping size", remapping.size);
69-
const auto virt_tera_page = (remapping.virt >> 39UL) & 511;
70-
const auto virt_giga_page = (remapping.virt >> 30UL) & 511;
69+
const auto virt_tera_page = (remapping.virt >> 39U) & 511;
70+
auto virt_giga_page = (remapping.virt >> 30U) & 511;
7171

7272
uint64_t paddr_base = remapping.phys;
73-
if (paddr_base == 0x0) {
73+
// Blackout remappings are used to reserve/create unmapped virtual memory space
74+
if (paddr_base == 0x0 && !remapping.blackout) {
7475
constexpr auto PD_ALIGN_MASK = (1ULL << 21U) - 1;
7576
// Over-allocate rounding up to nearest 2MB
7677
paddr_base = memory.machine.mmap_allocate(remapping.size + PD_ALIGN_MASK);
@@ -89,25 +90,33 @@ static void add_remappings(vMemory& memory,
8990
auto pdpt_addr = pml4[virt_tera_page] & PDE64_ADDR_MASK;
9091
auto* pdpt = memory.page_at(pdpt_addr);
9192

92-
// Allocate the gigapage with 512x 2MB entries
93-
if (pdpt[virt_giga_page] == 0) {
94-
const auto giga_page = free_page;
95-
free_page += 0x1000;
96-
pdpt[virt_giga_page] = PDE64_PRESENT | PDE64_USER | PDE64_RW | giga_page;
97-
}
93+
constexpr auto PDPT_ALIGN_MASK = (1ULL << 30U) - 1;
94+
const auto n_pd_pages = ((remapping.size + PDPT_ALIGN_MASK) >> 30UL) & 511;
95+
for (uint64_t n_pd = 0; n_pd < n_pd_pages; n_pd++)
96+
{
97+
// Allocate the gigapage with 512x 2MB entries
98+
if (pdpt[virt_giga_page] == 0) {
99+
const auto giga_page = free_page;
100+
free_page += 0x1000;
101+
pdpt[virt_giga_page] = PDE64_PRESENT | PDE64_USER | PDE64_RW | giga_page;
102+
}
98103

99-
auto pd_addr = pdpt[virt_giga_page] & PDE64_ADDR_MASK;
100-
auto* pd = memory.page_at(pd_addr);
104+
auto pd_addr = pdpt[virt_giga_page] & PDE64_ADDR_MASK;
105+
auto* pd = memory.page_at(pd_addr);
101106

102-
// Create 2MB entries for remapping size
103-
const auto n_2mb_pages = (remapping.size >> 21UL) & 511;
104-
for (uint64_t i = 0; i < 512; i++)
105-
{
106-
const auto paddr = paddr_base + (i << 21UL);
107-
if (i < n_2mb_pages)
108-
pd[i] = PDE64_PRESENT | flags | PDE64_PS | paddr;
109-
else
110-
pd[i] = 0;
107+
// Create 2MB entries for remapping size
108+
constexpr auto PD_ALIGN_MASK = (1ULL << 21U) - 1;
109+
const auto n_2mb_pages = ((remapping.size + PD_ALIGN_MASK) >> 21UL) & 511;
110+
for (uint64_t i = 0; i < 512; i++)
111+
{
112+
if (i < n_2mb_pages && !remapping.blackout) {
113+
const auto paddr = paddr_base + (i << 21UL);
114+
pd[i] = PDE64_PRESENT | flags | PDE64_PS | paddr;
115+
}
116+
else pd[i] = 0; // Unmapped 2MB page (remainder or blackout)
117+
}
118+
119+
virt_giga_page++; // Next gigapage
111120
}
112121

113122
// Track the first seen executable mapping, allowing mmap to use it for
@@ -306,6 +315,11 @@ uint64_t setup_amd64_paging(vMemory& memory,
306315
uint64_t flags = PDE64_USER | PDE64_NX;
307316
if (vmem.writable) flags |= PDE64_RW;
308317
if (vmem.executable) flags &= ~PDE64_NX;
318+
if (vmem.blackout) flags = 0;
319+
if constexpr (true) {
320+
printf("* Remapping 0x%lX -> 0x%lX size 0x%lX write=%d exec=%d blackout=%d\n",
321+
vmem.virt, vmem.phys, vmem.size, vmem.writable, vmem.executable, vmem.blackout);
322+
}
309323
add_remappings(memory, vmem, pml4, flags, free_page);
310324
}
311325

lib/tinykvm/common.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace tinykvm
2727
size_t size;
2828
bool writable = false;
2929
bool executable = false;
30+
bool blackout = false; /* Unmapped virtual area */
3031
};
3132

3233
struct MachineOptions {
@@ -51,8 +52,8 @@ namespace tinykvm
5152
/* When enabled, reset_to() will accept a different
5253
master VM than the original, but at a steep cost. */
5354
bool allow_reset_to_new_master = false;
54-
/* Allow fixed addresses with mmap(). */
55-
bool allow_fixed_mmap = false;
55+
/* Force-relocate fixed addresses with mmap(). */
56+
bool relocate_fixed_mmap = true;
5657
/* Make heap executable, to support JIT. */
5758
bool executable_heap = false;
5859
};

lib/tinykvm/machine.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ __attribute__ ((cold))
2929
Machine::Machine(std::string_view binary, const MachineOptions& options)
3030
: m_forked {false},
3131
m_just_reset {false},
32-
m_allow_fixed_mmap {options.allow_fixed_mmap},
32+
m_relocate_fixed_mmap {options.relocate_fixed_mmap},
3333
memory { vMemory::New(*this, options,
3434
options.vmem_base_address, options.vmem_base_address + 0x100000, options.max_mem)
3535
},
@@ -59,7 +59,7 @@ Machine::Machine(const Machine& other, const MachineOptions& options)
5959
: m_prepped {false},
6060
m_forked {true},
6161
m_just_reset {true},
62-
m_allow_fixed_mmap {options.allow_fixed_mmap},
62+
m_relocate_fixed_mmap {options.relocate_fixed_mmap},
6363
m_binary {options.binary.empty() ? other.m_binary : options.binary},
6464
memory {*this, options, other.memory},
6565
m_image_base {other.m_image_base},

lib/tinykvm/machine.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ struct Machine
147147
address_t mmap_start() const noexcept { return this->m_heap_address + BRK_MAX; }
148148
address_t mmap_allocate(size_t bytes);
149149
bool mmap_unmap(uint64_t addr, size_t size);
150-
bool allow_fixed_mmap() const noexcept { return m_allow_fixed_mmap; }
150+
bool relocate_fixed_mmap() const noexcept { return m_relocate_fixed_mmap; }
151151
bool mmap_relax(uint64_t addr, size_t size, size_t new_size);
152152
auto& mmap_cache() noexcept { return m_mmap_cache; }
153153

@@ -239,7 +239,7 @@ struct Machine
239239
bool m_prepped = false;
240240
bool m_forked = false;
241241
bool m_just_reset = false;
242-
bool m_allow_fixed_mmap = false;
242+
bool m_relocate_fixed_mmap = false;
243243
void* m_userdata = nullptr;
244244

245245
std::string_view m_binary;

src/functions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ void setup_kvm_system_calls()
134134
} else {
135135
regs.rax = ~0LL; /* MAP_FAILED */
136136
}
137-
} else if (regs.rdi != 0x0 && cpu.machine().allow_fixed_mmap()) {
137+
} else if (regs.rdi != 0x0 && !cpu.machine().relocate_fixed_mmap()) {
138138
regs.rax = regs.rdi;
139139
} else if (regs.rdi != 0x0 && regs.rdi >= cpu.machine().heap_address() && regs.rdi < cpu.machine().mmap_start()) {
140140
// Existing range already mmap'ed

src/simple.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ int main(int argc, char** argv)
6868
.remappings {remappings},
6969
.verbose_loader = (getenv("VERBOSE") != nullptr),
7070
.hugepages = (getenv("HUGE") != nullptr),
71-
.allow_fixed_mmap = (getenv("GO") != nullptr),
71+
.relocate_fixed_mmap = (getenv("GO") == nullptr),
7272
};
7373
tinykvm::Machine master_vm {binary, options};
7474
//master_vm.print_pagetables();

0 commit comments

Comments
 (0)