11#include < tinykvm/machine.hpp>
22#include < cstring>
33#include < cstdio>
4+ #include < unistd.h>
45#include " assert.hpp"
56#include " load_file.hpp"
67#include " timing.hpp"
78
89#include < tinykvm/rsp_client.hpp>
910#define GUEST_MEMORY 1024UL * 1024 * 1024 /* 1024MB main memory */
1011#define GUEST_WORK_MEM 256UL * 1024 * 1024 /* 256MB working memory */
12+ static const std::string ld_linux_so = " /lib64/ld-linux-x86-64.so.2" ;
1113
1214static double timed_action (std::function<void ()> action)
1315{
@@ -30,9 +32,17 @@ int main(int argc, char** argv)
3032 fprintf (stderr, " %s [guest ELF] [storage ELF]\n " , argv[0 ]);
3133 exit (1 );
3234 }
33- const auto guest_binary = load_file (argv[1 ]);
34- const auto storage_binary = load_file (argv[2 ]);
35- printf (" >>> Guest: %s >>> Storage: %s\n " , argv[1 ], argv[2 ]);
35+ const std::string guest_binary_path = argv[1 ];
36+ auto original_guest_binary = load_file (guest_binary_path);
37+ const std::string storage_binary_path = argv[2 ];
38+ const auto storage_binary = load_file (storage_binary_path);
39+ printf (" >>> Guest: %s >>> Storage: %s\n " , guest_binary_path.c_str (), storage_binary_path.c_str ());
40+ std::string cwd;
41+ {
42+ char buf[PATH_MAX];
43+ if (getcwd (buf, sizeof (buf)) != nullptr )
44+ cwd = buf;
45+ }
3646
3747 tinykvm::Machine::init ();
3848
@@ -54,33 +64,83 @@ int main(int argc, char** argv)
5464 }
5565 });
5666
67+ std::vector<std::string> guest_args;
68+ std::vector<uint8_t > guest_binary;
69+ const tinykvm::DynamicElf guest_dyn_elf = tinykvm::is_dynamic_elf (
70+ std::string_view{(const char *)original_guest_binary.data (), original_guest_binary.size ()});
71+ if (guest_dyn_elf.is_dynamic ) {
72+ // Add ld-linux.so.2 as first argument
73+ guest_binary = load_file (ld_linux_so);
74+ guest_args.push_back (ld_linux_so);
75+ } else {
76+ guest_binary = original_guest_binary;
77+ }
78+ guest_args.push_back (guest_binary_path);
79+ guest_args.push_back (" Hello Main World!" );
80+
5781 /* Setup */
5882 const tinykvm::MachineOptions options {
5983 .max_mem = GUEST_MEMORY,
6084 .max_cow_mem = GUEST_WORK_MEM,
61- .verbose_loader = false
85+ .dylink_address_hint = 0x400000 , // 4MB
86+ .verbose_loader = false ,
87+ .executable_heap = guest_dyn_elf.is_dynamic ,
88+ .mmap_backed_files = true ,
6289 };
6390 tinykvm::Machine master_vm {guest_binary, options};
6491 master_vm.setup_linux (
65- { " main " , " Hello Main World! " } ,
92+ guest_args ,
6693 {" LC_TYPE=C" , " LC_ALL=C" , " USER=root" });
6794 // master_vm.print_pagetables();
95+ master_vm.fds ().set_open_readable_callback (
96+ [] (std::string&) -> bool {
97+ return true ;
98+ });
99+ master_vm.set_verbose_system_calls (getenv (" VERBOSE" ) != nullptr );
100+
101+ std::vector<std::string> storage_args;
102+ storage_args.push_back (storage_binary_path);
103+ storage_args.push_back (" Hello Storage World!" );
68104
69105 /* Create storage VM */
70106 const tinykvm::MachineOptions storage_options {
71107 .max_mem = 256ULL << 20 , // MB
72108 .dylink_address_hint = 0x44000000 , // 1GB + 64MB
73109 .vmem_base_address = 1ULL << 30 , // 1GB
74110 .verbose_loader = false ,
111+ .mmap_backed_files = true ,
75112 };
76113 tinykvm::Machine storage_vm{storage_binary, storage_options};
114+ storage_vm.set_verbose_system_calls (getenv (" VERBOSE" ) != nullptr );
115+ storage_vm.set_verbose_mmap_syscalls (getenv (" VERBOSE" ) != nullptr );
116+ storage_vm.set_verbose_thread_syscalls (getenv (" VERBOSE" ) != nullptr );
117+ storage_vm.fds ().set_open_readable_callback (
118+ [] (std::string&) -> bool {
119+ return true ;
120+ });
121+ storage_vm.fds ().set_current_working_directory (cwd.c_str ());
77122 storage_vm.setup_linux (
78- { " storage " , " Hello Storage World! " } ,
123+ storage_args ,
79124 {" LC_TYPE=C" , " LC_ALL=C" , " USER=root" });
80125 storage_vm.run (5 .0f );
81126
82127 master_vm.remote_connect (storage_vm, false );
83128
129+ static uint64_t callback_address = 0x0 ;
130+ master_vm.install_unhandled_syscall_handler (
131+ [] (tinykvm::vCPU& cpu, unsigned sysnum) {
132+ auto & regs = cpu.registers ();
133+ switch (sysnum) {
134+ case 0x10001 : // Set callback address
135+ callback_address = regs.rdi ;
136+ return ;
137+ default :
138+ printf (" Unhandled master VM syscall: %u\n " , sysnum);
139+ regs.rax = -ENOSYS;
140+ cpu.set_registers (regs);
141+ }
142+ });
143+
84144 auto tdiff = timed_action ([&] {
85145 try {
86146 master_vm.run ();
@@ -107,15 +167,15 @@ int main(int argc, char** argv)
107167 assert (vm.is_remote_connected ());
108168
109169 /* Call 'do_calculation' with 21 as argument */
110- const auto call_addr = vm.address_of (" do_calculation" );
111- if (call_addr == 0 ) {
170+ if (callback_address == 0 ) {
112171 fprintf (stderr, " Error: no do_calculation() in guest\n " );
113172 exit (1 );
114173 }
174+ printf (" Calling do_calculation() @ 0x%lX\n " , callback_address);
115175 for (int i = 0 ; i < 100 ; i++)
116- vm.timed_vmcall (call_addr , 5 .0f , 21 );
176+ vm.timed_vmcall (callback_address , 5 .0f , 21 );
117177 auto fork_tdiff = timed_action ([&] {
118- vm.timed_vmcall (call_addr , 5 .0f , 21 );
178+ vm.timed_vmcall (callback_address , 5 .0f , 21 );
119179 });
120180 printf (" Fork call time: %.2fus Return value: %ld\n " , fork_tdiff*1e6 , vm.return_value ());
121181}
0 commit comments