Skip to content

Commit 2a1795d

Browse files
wkozaczuknyh
authored andcommitted
Move kernel to 0x40200000 address (1 GiB higher) in virtual memory
This patch provides all necessary changes to move OSv kernel by 1 GiB higher in virtual memory space to start at 0x40200000. Most changes involve adding or subtracting 0x40000000 (OSV_KERNEL_VM_SHIFT) in all relevant places. Please note that the kernel is still loaded at 2MiB in physical memory. The motivation for this patch is to make as much space as possible (or just enough) in virtual memory to allow running unmodified Linux non-PIE executables (issue #190). Even though due to the advancement of ASLR more and more applications are PIEs (Position Independent Executables) which are pretty well supported by OSv, there are still many non-PIEs (Position Dependent Executables) that are out. The most prominent one is actualy JVM whose most distributions come with tiny (~20K) bootstrap java non-PIE executable. There are many other examples where small non-PIE executable loads other shared libraries. As issue #1043 explains there are at least 3 possible solutions and this patch implements the 3rd last one described there. Please note that in future with little effort we could provide slightly beter scheme for OSV_KERNEL_VM_SHIFT that would allow us to place the kernel even higher at the end of the 2GiB limit (small memory model) and thus support virtually any non-PIE built using small memory model. Due to its impact this patch has been tested on following hypervisors: - QEMU without KVM - QEMU with KVM - Firecracker - VirtualBox 6 - VMware Player - XEN on EC2 - XEN locally in HVM mode Fixes #1043 Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Message-Id: <20190620040707.23249-1-jwkozaczuk@gmail.com>
1 parent 9e34f42 commit 2a1795d

File tree

10 files changed

+103
-61
lines changed

10 files changed

+103
-61
lines changed

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ gcc-sysroot = $(if $(CROSS_PREFIX), --sysroot external/$(arch)/gcc.bin) \
312312
# To add something that will *not* be part of the main kernel, you can do:
313313
#
314314
# mydir/*.o EXTRA_FLAGS = <MY_STUFF>
315-
EXTRA_FLAGS = -D__OSV_CORE__ -DOSV_KERNEL_BASE=$(kernel_base) -DOSV_LZKERNEL_BASE=$(lzkernel_base)
315+
EXTRA_FLAGS = -D__OSV_CORE__ -DOSV_KERNEL_BASE=$(kernel_base) -DOSV_KERNEL_VM_SHIFT=$(kernel_vm_shift) -DOSV_LZKERNEL_BASE=$(lzkernel_base)
316316
EXTRA_LIBS =
317317
COMMON = $(autodepend) -g -Wall -Wno-pointer-arith $(CFLAGS_WERROR) -Wformat=0 -Wno-format-security \
318318
-D __BSD_VISIBLE=1 -U _FORTIFY_SOURCE -fno-stack-protector $(INCLUDES) \
@@ -421,6 +421,7 @@ ifeq ($(arch),x64)
421421
# lzkernel_base is where the compressed kernel is loaded from disk.
422422
kernel_base := 0x200000
423423
lzkernel_base := 0x100000
424+
kernel_vm_base := 0x40200000
424425

425426
$(out)/arch/x64/boot16.o: $(out)/lzloader.elf
426427
$(out)/boot.bin: arch/x64/boot16.ld $(out)/arch/x64/boot16.o
@@ -480,6 +481,7 @@ endif # x64
480481
ifeq ($(arch),aarch64)
481482

482483
kernel_base := 0x40080000
484+
kernel_vm_base := 0x40080000
483485

484486
include $(libfdt_base)/Makefile.libfdt
485487
libfdt-source := $(patsubst %.c, $(libfdt_base)/%.c, $(LIBFDT_SRCS))
@@ -500,6 +502,8 @@ $(out)/loader.img: $(out)/preboot.bin $(out)/loader-stripped.elf
500502

501503
endif # aarch64
502504

505+
kernel_vm_shift := $(shell printf "0x%X" $(shell expr $$(( $(kernel_vm_base) - $(kernel_base) )) ))
506+
503507
$(out)/bsd/sys/crypto/rijndael/rijndael-api-fst.o: COMMON+=-fno-strict-aliasing
504508
$(out)/bsd/sys/crypto/sha2/sha2.o: COMMON+=-fno-strict-aliasing
505509
$(out)/bsd/sys/net/route.o: COMMON+=-fno-strict-aliasing
@@ -1873,6 +1877,7 @@ stage1: $(stage1_targets) links
18731877

18741878
$(out)/loader.elf: $(stage1_targets) arch/$(arch)/loader.ld $(out)/bootfs.o
18751879
$(call quiet, $(LD) -o $@ --defsym=OSV_KERNEL_BASE=$(kernel_base) \
1880+
--defsym=OSV_KERNEL_VM_BASE=$(kernel_vm_base) --defsym=OSV_KERNEL_VM_SHIFT=$(kernel_vm_shift) \
18761881
-Bdynamic --export-dynamic --eh-frame-hdr --enable-new-dtags \
18771882
$(^:%.ld=-T %.ld) \
18781883
--whole-archive \

arch/x64/arch-setup.cc

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,15 @@ extern boot_time_chart boot_time;
8585
// it by placing address of start32 at the known offset at memory
8686
// as defined by section .start32_address in loader.ld
8787
extern "C" void start32();
88-
void * __attribute__((section (".start32_address"))) start32_address = reinterpret_cast<void*>(&start32);
88+
void * __attribute__((section (".start32_address"))) start32_address =
89+
reinterpret_cast<void*>((long)&start32 - OSV_KERNEL_VM_SHIFT);
8990

9091
void arch_setup_free_memory()
9192
{
92-
static ulong edata;
93+
static ulong edata, edata_phys;
9394
asm ("movl $.edata, %0" : "=rm"(edata));
95+
edata_phys = edata - OSV_KERNEL_VM_SHIFT;
96+
9497
// copy to stack so we don't free it now
9598
auto omb = *osv_multiboot_info;
9699
auto mb = omb.mb;
@@ -129,13 +132,13 @@ void arch_setup_free_memory()
129132
// page tables have been set up, so we can't reference the memory being
130133
// freed.
131134
for_each_e820_entry(e820_buffer, e820_size, [] (e820ent ent) {
132-
// can't free anything below edata, it's core code.
135+
// can't free anything below edata_phys, it's core code.
133136
// can't free anything below kernel at this moment
134-
if (ent.addr + ent.size <= edata) {
137+
if (ent.addr + ent.size <= edata_phys) {
135138
return;
136139
}
137-
if (intersects(ent, edata)) {
138-
ent = truncate_below(ent, edata);
140+
if (intersects(ent, edata_phys)) {
141+
ent = truncate_below(ent, edata_phys);
139142
}
140143
// ignore anything above 1GB, we haven't mapped it yet
141144
if (intersects(ent, initial_map)) {
@@ -149,21 +152,27 @@ void arch_setup_free_memory()
149152
auto base = reinterpret_cast<void*>(get_mem_area_base(area));
150153
mmu::linear_map(base, 0, initial_map, initial_map);
151154
}
152-
// map the core, loaded 1:1 by the boot loader
153-
mmu::phys elf_phys = reinterpret_cast<mmu::phys>(elf_header);
154-
elf_start = reinterpret_cast<void*>(elf_header);
155-
elf_size = edata - elf_phys;
156-
mmu::linear_map(elf_start, elf_phys, elf_size, OSV_KERNEL_BASE);
155+
// Map the core, loaded by the boot loader
156+
// In order to properly setup mapping between virtual
157+
// and physical we need to take into account where kernel
158+
// is loaded in physical memory - elf_phys_start - and
159+
// where it is linked to start in virtual memory - elf_start
160+
static mmu::phys elf_phys_start = reinterpret_cast<mmu::phys>(elf_header);
161+
// There is simple invariant between elf_phys_start and elf_start
162+
// as expressed by the assignment below
163+
elf_start = reinterpret_cast<void*>(elf_phys_start + OSV_KERNEL_VM_SHIFT);
164+
elf_size = edata_phys - elf_phys_start;
165+
mmu::linear_map(elf_start, elf_phys_start, elf_size, OSV_KERNEL_BASE);
157166
// get rid of the command line, before low memory is unmapped
158167
parse_cmdline(mb);
159168
// now that we have some free memory, we can start mapping the rest
160169
mmu::switch_to_runtime_page_tables();
161170
for_each_e820_entry(e820_buffer, e820_size, [] (e820ent ent) {
162171
//
163-
// Free the memory below elf_start which we could not before
164-
if (ent.addr < (u64)elf_start) {
165-
if (ent.addr + ent.size >= (u64)elf_start) {
166-
ent = truncate_above(ent, (u64) elf_start);
172+
// Free the memory below elf_phys_start which we could not before
173+
if (ent.addr < (u64)elf_phys_start) {
174+
if (ent.addr + ent.size >= (u64)elf_phys_start) {
175+
ent = truncate_above(ent, (u64) elf_phys_start);
167176
}
168177
mmu::free_initial_memory_range(ent.addr, ent.size);
169178
return;

arch/x64/boot.S

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,28 @@
2424
.align 4096
2525
.global ident_pt_l4
2626
ident_pt_l4:
27-
.quad ident_pt_l3 + 0x67
27+
# The addresses of the paging tables have to be the physical ones, so we have to
28+
# manually subtract OSV_KERNEL_VM_SHIFT in all relevant places
29+
.quad ident_pt_l3 + 0x67 - OSV_KERNEL_VM_SHIFT
2830
.rept 511
2931
.quad 0
3032
.endr
33+
#if OSV_KERNEL_VM_SHIFT != 0x40000000 && OSV_KERNEL_VM_SHIFT != 0
34+
#error This code only works correctly for OSV_KERNEL_VM_SHIFT = 0x40000000 or 0
35+
#endif
3136
ident_pt_l3:
32-
.quad ident_pt_l2 + 0x67
33-
.rept 511
37+
# Each of the 512 entries in this table maps the very 1st 512 GiB of
38+
# virtual address space 1 GiB at a time
39+
# The very 1st entry maps 1st GiB 1:1 by pointing to ident_pt_l2 table
40+
# that specifies addresses of every one of 512 2MiB slots of physical memory
41+
.quad ident_pt_l2 + 0x67 - OSV_KERNEL_VM_SHIFT
42+
# The 2nd entry maps 2nd GiB to the same 1st GiB of physical memory by pointing
43+
# to the same ident_pt_l2 table as the 1st entry above
44+
# This way we effectively provide correct mapping for the kernel linked
45+
# to start at 1 GiB + 2 MiB (0x40200000) in virtual memory and point to
46+
# 2 MiB address (0x200000) where it starts in physical memory
47+
.quad ident_pt_l2 + 0x67 - OSV_KERNEL_VM_SHIFT
48+
.rept 510
3449
.quad 0
3550
.endr
3651
ident_pt_l2:
@@ -42,7 +57,8 @@ ident_pt_l2:
4257

4358
gdt_desc:
4459
.short gdt_end - gdt - 1
45-
.long gdt
60+
# subtract OSV_KERNEL_VM_SHIFT because when gdt_desc is referenced, the memory is mapped 1:1
61+
.long gdt - OSV_KERNEL_VM_SHIFT
4662

4763
# Set up the 64-bit compatible version of GDT description structure
4864
# that points to the same GDT (Global segments Descriptors Table) and
@@ -53,7 +69,8 @@ gdt_desc:
5369
.align 8
5470
gdt64_desc:
5571
.short gdt_end - gdt - 1
56-
.quad gdt
72+
# subtract OSV_KERNEL_VM_SHIFT because when gdt64_desc is referenced, the memory is mapped 1:1
73+
.quad gdt - OSV_KERNEL_VM_SHIFT
5774

5875
.align 8
5976
gdt = . - 8
@@ -77,10 +94,12 @@ init_stack_top = .
7794
.globl start32
7895
.globl start32_from_64
7996
start32:
97+
# Because the memory is mapped 1:1 at this point, we have to manualy
98+
# subtract OSV_KERNEL_VM_SHIFT from virtual addresses in all relevant places
8099
# boot16.S set %eax to ELF start address, we'll use it later
81100
mov %eax, %ebp
82101
mov $0x0, %edi
83-
lgdt gdt_desc
102+
lgdt gdt_desc-OSV_KERNEL_VM_SHIFT
84103

85104
# Add an address the vmlinux_entry64 will jump to when
86105
# switching from 64-bit to 32-bit mode
@@ -91,7 +110,7 @@ start32_from_64:
91110
mov %eax, %fs
92111
mov %eax, %gs
93112
mov %eax, %ss
94-
ljmp $0x18, $1f
113+
ljmp $0x18, $1f-OSV_KERNEL_VM_SHIFT
95114
1:
96115
and $~7, %esp
97116
# Enable PAE (Physical Address Extension) - ability to address 64GB
@@ -101,6 +120,9 @@ start32_from_64:
101120

102121
# Set root of a page table in cr3
103122
lea ident_pt_l4, %eax
123+
# The address of the root paging table has to be physical
124+
# so substract OSV_KERNEL_VM_SHIFT from ident_pt_l4
125+
sub $OSV_KERNEL_VM_SHIFT, %eax
104126
mov %eax, %cr3
105127

106128
# Set long mode
@@ -128,7 +150,7 @@ start64:
128150
jz start64_continue
129151
call extract_linux_boot_params
130152
mov $0x1000, %rbx
131-
mov $0x200000, %rbp
153+
mov $OSV_KERNEL_BASE, %rbp
132154

133155
start64_continue:
134156
lea .bss, %rdi
@@ -168,6 +190,7 @@ smpboot:
168190
mov smpboot_cr4-smpboot, %eax
169191
mov %eax, %cr4
170192
lea ident_pt_l4, %eax
193+
sub $OSV_KERNEL_VM_SHIFT, %eax
171194
mov %eax, %cr3
172195
mov smpboot_efer-smpboot, %eax
173196
mov smpboot_efer+4-smpboot, %edx
@@ -181,7 +204,7 @@ smpboot:
181204

182205
smpboot_gdt_desc:
183206
.short gdt_end - gdt - 1
184-
.long gdt
207+
.long gdt - OSV_KERNEL_VM_SHIFT
185208
.global smpboot_cr0
186209
smpboot_cr0:
187210
.long 0

arch/x64/entry-xen.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
elfnote_val(XEN_ELFNOTE_ENTRY, xen_start)
2525
elfnote_val(XEN_ELFNOTE_HYPERCALL_PAGE, hypercall_page)
26-
elfnote_val(XEN_ELFNOTE_VIRT_BASE, 0)
26+
elfnote_val(XEN_ELFNOTE_VIRT_BASE, OSV_KERNEL_VM_SHIFT)
2727
elfnote_str(XEN_ELFNOTE_XEN_VERSION, "xen-3.0")
2828
elfnote_str(XEN_ELFNOTE_GUEST_OS, "osv")
2929
elfnote_str(XEN_ELFNOTE_GUEST_VERSION, "?.?")
@@ -50,4 +50,5 @@ xen_start:
5050
mov %rsp, xen_bootstrap_end
5151
mov %rsi, %rdi
5252
call xen_init
53+
mov $0x0, %rdi
5354
jmp start64

arch/x64/loader.ld

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,77 +14,79 @@ SECTIONS
1414
*
1515
* We can't export the ELF header base as a symbol, because ld
1616
* insists on moving stuff around if we do.
17-
*
17+
*/
18+
. = OSV_KERNEL_VM_BASE + 0x800;
19+
/*
1820
* Place address of start32 routine at predefined offset in memory
1921
*/
20-
. = OSV_KERNEL_BASE + 0x800;
21-
.start32_address : {
22+
.start32_address : AT(ADDR(.start32_address) - OSV_KERNEL_VM_SHIFT) {
2223
*(.start32_address)
2324
}
24-
. = OSV_KERNEL_BASE + 0x1000;
25-
.dynamic : { *(.dynamic) } :dynamic :text
26-
.text : {
25+
. = OSV_KERNEL_VM_BASE + 0x1000;
26+
.dynamic : AT(ADDR(.dynamic) - OSV_KERNEL_VM_SHIFT) { *(.dynamic) } :dynamic :text
27+
.text : AT(ADDR(.text) - OSV_KERNEL_VM_SHIFT) {
2728
text_start = .;
2829
*(.text.hot .text.hot.*)
2930
*(.text.unlikely .text.*_unlikely)
3031
*(.text.fixup)
3132
*(.text.startup .text.startup.*)
3233
*(.text .text.*)
3334
text_end = .;
35+
PROVIDE(low_vmlinux_entry64 = vmlinux_entry64 - OSV_KERNEL_VM_SHIFT);
3436
} :text
3537
. = ALIGN(8);
36-
.fixup : {
38+
.fixup : AT(ADDR(.fixup) - OSV_KERNEL_VM_SHIFT) {
3739
fault_fixup_start = .;
3840
*(.fixup)
3941
fault_fixup_end = .;
4042
} :text
4143

4244
. = ALIGN(8);
43-
.memcpy_decode : {
45+
.memcpy_decode : AT(ADDR(.memcpy_decode) - OSV_KERNEL_VM_SHIFT) {
4446
memcpy_decode_start = .;
4547
*(.memcpy_decode)
4648
memcpy_decode_end = .;
4749
} :text
4850

49-
.eh_frame : { *(.eh_frame) } : text
50-
.rodata : { *(.rodata*) } :text
51-
.eh_frame : { *(.eh_frame) } :text
52-
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame
53-
.note : { *(.note*) } :text :note
54-
.gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } : text
55-
.tracepoint_patch_sites ALIGN(8) : {
51+
.eh_frame : AT(ADDR(.eh_frame) - OSV_KERNEL_VM_SHIFT) { *(.eh_frame) } : text
52+
.rodata : AT(ADDR(.rodata) - OSV_KERNEL_VM_SHIFT) { *(.rodata*) } :text
53+
.eh_frame : AT(ADDR(.eh_frame) - OSV_KERNEL_VM_SHIFT) { *(.eh_frame) } :text
54+
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - OSV_KERNEL_VM_SHIFT) { *(.eh_frame_hdr) } :text :eh_frame
55+
.note : AT(ADDR(.note) - OSV_KERNEL_VM_SHIFT) { *(.note*) } :text :note
56+
.gcc_except_table : AT(ADDR(.gcc_except_table) - OSV_KERNEL_VM_SHIFT) { *(.gcc_except_table) *(.gcc_except_table.*) } : text
57+
.tracepoint_patch_sites ALIGN(8) : AT(ADDR(.tracepoint_patch_sites) - OSV_KERNEL_VM_SHIFT) {
5658
__tracepoint_patch_sites_start = .;
5759
*(.tracepoint_patch_sites)
5860
__tracepoint_patch_sites_end = .;
5961
} : text
60-
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } : text
61-
.data : { *(.data) } :text
62+
.data.rel.ro : AT(ADDR(.data.rel.ro) - OSV_KERNEL_VM_SHIFT) { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } : text
63+
.data : AT(ADDR(.data) - OSV_KERNEL_VM_SHIFT) { *(.data) } :text
6264
_init_array_start = .;
63-
.init_array : {
65+
.init_array : AT(ADDR(.init_array) - OSV_KERNEL_VM_SHIFT) {
6466
*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))
6567
*(.init_array .ctors)
6668
} : text
6769
_init_array_end = .;
6870
. = ALIGN(4096);
69-
.percpu : {
71+
.percpu : AT(ADDR(.percpu) - OSV_KERNEL_VM_SHIFT) {
7072
_percpu_start = .;
7173
*(.percpu)
7274
. = ALIGN(4096);
7375
_percpu_end = .;
7476
}
75-
.percpu_workers : {
77+
.percpu_workers : AT(ADDR(.percpu_workers) - OSV_KERNEL_VM_SHIFT) {
7678
_percpu_workers_start = .;
7779
*(.percpu_workers)
7880
_percpu_workers_end = .;
7981
}
8082
. = ALIGN(64);
81-
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :tls :text
82-
.tbss : {
83+
.tdata : AT(ADDR(.tdata) - OSV_KERNEL_VM_SHIFT) { *(.tdata .tdata.* .gnu.linkonce.td.*) } :tls :text
84+
.tbss : AT(ADDR(.tbss) - OSV_KERNEL_VM_SHIFT) {
8385
*(.tbss .tbss.* .gnu.linkonce.tb.*)
8486
. = ALIGN(64);
8587
} :tls :text
8688
.tls_template_size = SIZEOF(.tdata) + SIZEOF(.tbss);
87-
.bss : { *(.bss .bss.*) } :text
89+
.bss : AT(ADDR(.bss) - OSV_KERNEL_VM_SHIFT) { *(.bss .bss.*) } :text
8890
. = ALIGN(64);
8991
tcb0 = .;
9092
. = . + .tls_template_size + 256;
@@ -114,4 +116,4 @@ PHDRS {
114116
eh_frame PT_GNU_EH_FRAME;
115117
note PT_NOTE;
116118
}
117-
ENTRY(vmlinux_entry64);
119+
ENTRY(low_vmlinux_entry64);

arch/x64/vmlinux-boot64.S

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ vmlinux_entry64:
1313
mov %rsi, %rdi
1414

1515
# Load the 64-bit version of the GDT
16-
lgdt gdt64_desc
16+
# Because the memory is mapped 1:1 at this point, we have to manualy
17+
# subtract OSV_KERNEL_VM_SHIFT from the gdt address
18+
lgdt gdt64_desc-OSV_KERNEL_VM_SHIFT
1719

1820
# Setup the stack to switch back to 32-bit mode in order
1921
# to converge with the code that sets up transiton to 64-bit mode later.
@@ -32,6 +34,6 @@ vmlinux_entry64:
3234
# to start32_from_64 which is where the boot process converges.
3335
subq $8, %rsp
3436
movl $0x18, 4(%rsp)
35-
movl $start32_from_64, %eax
37+
movl $start32_from_64-OSV_KERNEL_VM_SHIFT, %eax # Because memory is mapped 1:1 subtract OSV_KERNEL_VM_SHIFT
3638
movl %eax, (%rsp)
3739
lret

arch/x64/xen.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ void xen_init(processor::features_type &features, unsigned base)
172172
// Base + 1 would have given us the version number, it is mostly
173173
// uninteresting for us now
174174
auto x = processor::cpuid(base + 2);
175-
processor::wrmsr(x.b, cast_pointer(&hypercall_page));
175+
processor::wrmsr(x.b, cast_pointer(&hypercall_page) - OSV_KERNEL_VM_SHIFT);
176176

177177
struct xen_feature_info info;
178178
// To fill up the array used by C code
@@ -192,7 +192,7 @@ void xen_init(processor::features_type &features, unsigned base)
192192
map.domid = DOMID_SELF;
193193
map.idx = 0;
194194
map.space = 0;
195-
map.gpfn = cast_pointer(&xen_shared_info) >> 12;
195+
map.gpfn = (cast_pointer(&xen_shared_info) - OSV_KERNEL_VM_SHIFT) >> 12;
196196

197197
// 7 => add to physmap
198198
if (memory_hypercall(XENMEM_add_to_physmap, &map))

core/elf.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,7 +1099,7 @@ void create_main_program()
10991099
program::program(void* addr)
11001100
: _next_alloc(addr)
11011101
{
1102-
_core = std::make_shared<memory_image>(*this, (void*)ELF_IMAGE_START);
1102+
_core = std::make_shared<memory_image>(*this, (void*)(ELF_IMAGE_START + OSV_KERNEL_VM_SHIFT));
11031103
assert(_core->module_index() == core_module_index);
11041104
_core->load_segments();
11051105
set_search_path({"/", "/usr/lib"});

0 commit comments

Comments
 (0)