Skip to content

Commit 6140db7

Browse files
committed
Track BRK in order to prevent lowering heap
Lowering the heap caused ghosts in the machine and a lot of confusion. Now fixed.
1 parent e0f8d7d commit 6140db7

File tree

7 files changed

+31
-25
lines changed

7 files changed

+31
-25
lines changed

lib/tinykvm/amd64/paging.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,8 @@ static inline bool page_is_zeroed(const uint64_t* page) {
2828
return true;
2929
}
3030

31+
static constexpr inline uint64_t PageMask() {
32+
return vMemory::PageSize() - 1UL;
33+
}
34+
3135
} // tinykvm

lib/tinykvm/linux/system_calls.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ void Machine::setup_linux_system_calls()
244244
} else {
245245
regs.rax = dst;
246246
}
247-
PRINTMMAP("mmap(0x%llX, %llu, prot=%llX, flags=%llX) = 0x%llX\n",
247+
PRINTMMAP("mmap(0x%lX, %lu, prot=%llX, flags=%llX) = 0x%llX\n",
248248
address, length, regs.rdx, regs.r10, regs.rax);
249249
cpu.set_registers(regs);
250250
return;
@@ -300,7 +300,7 @@ void Machine::setup_linux_system_calls()
300300
{
301301
cpu.machine().memzero(regs.rax, length);
302302
}
303-
PRINTMMAP("mmap(0x%llX, %llu, prot=%llX, flags=%llX) = 0x%llX\n",
303+
PRINTMMAP("mmap(0x%lX, %lu, prot=%llX, flags=%llX) = 0x%llX\n",
304304
address, length, regs.rdx, regs.r10, regs.rax);
305305
cpu.set_registers(regs);
306306
});
@@ -331,17 +331,16 @@ void Machine::setup_linux_system_calls()
331331
Machine::install_syscall_handler(
332332
SYS_brk, [](vCPU& cpu) { // BRK
333333
auto& regs = cpu.registers();
334-
if (regs.rdi > cpu.machine().heap_address() + Machine::BRK_MAX)
335-
{
336-
regs.rax = cpu.machine().heap_address() + Machine::BRK_MAX;
337-
}
338-
else if (regs.rdi < cpu.machine().heap_address())
339-
{
340-
regs.rax = cpu.machine().heap_address();
341-
}
342-
else
343-
{
344-
regs.rax = regs.rdi;
334+
const uint64_t old_brk = cpu.machine().brk_address();
335+
uint64_t new_brk = regs.rdi;
336+
if (new_brk < old_brk) {
337+
// brk() to a lower address, keep the old one
338+
// We can only grow the heap, not shrink it.
339+
regs.rax = old_brk;
340+
} else {
341+
// clamp brk() outside to the heap range
342+
new_brk = std::min(new_brk, cpu.machine().brk_end_address());
343+
regs.rax = new_brk;
345344
}
346345
SYSPRINT("brk(0x%llX) = 0x%llX\n", regs.rdi, regs.rax);
347346
cpu.set_registers(regs);
@@ -1049,7 +1048,7 @@ void Machine::setup_linux_system_calls()
10491048
Machine::install_syscall_handler(
10501049
SYS_getrlimit, [](vCPU& cpu) { // getrlimit
10511050
auto& regs = cpu.registers();
1052-
const auto g_rlim = regs.rsi;
1051+
[[maybe_unused]] const auto g_rlim = regs.rsi;
10531052
regs.rax = -ENOSYS;
10541053
SYSPRINT("getrlimit(0x%llX) = %lld\n", g_rlim, regs.rax);
10551054
cpu.set_registers(regs);

lib/tinykvm/machine.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Machine::Machine(const Machine& other, const MachineOptions& options)
6565
m_image_base {other.m_image_base},
6666
m_stack_address {other.m_stack_address},
6767
m_heap_address {other.m_heap_address},
68+
m_brk_address {other.m_brk_address},
6869
m_start_address {other.m_start_address},
6970
m_kernel_end {other.m_kernel_end},
7071
m_mm {other.m_mm},
@@ -158,6 +159,7 @@ void Machine::reset_to(const Machine& other, const MachineOptions& options)
158159
this->m_image_base = other.m_image_base;
159160
this->m_stack_address = other.m_stack_address;
160161
this->m_heap_address = other.m_heap_address;
162+
this->m_brk_address = other.m_brk_address;
161163
this->m_start_address = other.m_start_address;
162164
this->m_kernel_end = other.m_kernel_end;
163165
memory.fork_reset(other.memory, options);

lib/tinykvm/machine.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ struct Machine
158158
address_t kernel_end_address() const noexcept { return m_kernel_end; }
159159
address_t max_address() const noexcept { return memory.physbase + memory.size; }
160160

161-
static constexpr uint64_t BRK_MAX = 0x20000;
161+
static constexpr uint64_t BRK_MAX = 0x22000;
162+
address_t brk_address() const noexcept { return this->m_brk_address; }
163+
address_t brk_end_address() const noexcept { return this->m_heap_address + BRK_MAX; }
164+
void set_brk_address(address_t addr) { this->m_brk_address = addr; }
162165
address_t mmap_start() const noexcept { return this->m_heap_address + BRK_MAX; }
163166
address_t mmap_allocate(size_t bytes);
164167
bool mmap_unmap(uint64_t addr, size_t size);
@@ -271,6 +274,7 @@ struct Machine
271274
address_t m_image_base = 0x0;
272275
address_t m_stack_address;
273276
address_t m_heap_address;
277+
address_t m_brk_address;
274278
address_t m_start_address;
275279
address_t m_kernel_end;
276280

lib/tinykvm/machine_elf.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdexcept>
66
#ifdef TINYKVM_ARCH_AMD64
77
#include "amd64/idt.hpp" // interrupt_header()
8+
#include "amd64/paging.hpp"
89
#endif
910
#include "util/elf.hpp"
1011

@@ -134,18 +135,19 @@ void Machine::elf_loader(std::string_view binary, const MachineOptions& options)
134135
break;
135136
}
136137

137-
uint64_t endm = hdr->p_vaddr + hdr->p_memsz;
138-
endm += vMemory::PageSize()-1; endm &= ~(vMemory::PageSize()-1);
138+
const uint64_t endm = hdr->p_vaddr + hdr->p_memsz;
139139
if (this->m_heap_address < endm)
140140
this->m_heap_address = endm;
141141
}
142142

143143
/* Make sure mmap starts at a sane offset */
144144
this->m_heap_address += this->m_image_base;
145+
this->m_heap_address = (this->m_heap_address + PageMask()) & ~PageMask();
146+
this->m_brk_address = this->m_heap_address;
145147
this->m_mm = this->mmap_start();
146148

147149
/* If there is not enough room for stack, move it */
148-
const uint32_t STACK_SIZE = options.stack_size & ~0xFFFLL;
150+
const uint32_t STACK_SIZE = (options.stack_size + PageMask()) & ~PageMask();
149151
if (this->m_stack_address < STACK_SIZE) {
150152
this->m_stack_address = this->mmap_allocate(STACK_SIZE) + STACK_SIZE;
151153
}
@@ -157,7 +159,8 @@ void Machine::elf_loader(std::string_view binary, const MachineOptions& options)
157159

158160
if (options.verbose_loader) {
159161
printf("* Entry is at %p\n", (void*) m_start_address);
160-
printf("* Stack is at %p\n", (void*) m_stack_address);
162+
printf("* Stack is at %p -> %p\n", (void*) (m_stack_address - STACK_SIZE),
163+
(void*) (m_stack_address));
161164
}
162165
}
163166

lib/tinykvm/machine_utils.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
#include "amd64/paging.hpp"
55

66
namespace tinykvm {
7-
static constexpr uint64_t PageMask() {
8-
return vMemory::PageSize() - 1UL;
9-
}
107

118
void Machine::memzero(address_t addr, size_t len)
129
{

lib/tinykvm/memory.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
namespace tinykvm {
1818
#define USERMODE_FLAGS (0x7 | 1UL << 63) /* USER, READ/WRITE, PRESENT, NX */
19-
static constexpr uint64_t PageMask() {
20-
return vMemory::PageSize() - 1UL;
21-
}
2219

2320
vMemory::vMemory(Machine& m, const MachineOptions& options,
2421
uint64_t ph, uint64_t sf, char* p, size_t s, bool own)

0 commit comments

Comments
 (0)