Skip to content

Commit 08b2b68

Browse files
committed
Implement epoll emulation
1 parent 5403ebb commit 08b2b68

File tree

1 file changed

+88
-33
lines changed

1 file changed

+88
-33
lines changed

lib/tinykvm/linux/system_calls.cpp

Lines changed: 88 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ void Machine::setup_linux_system_calls()
415415
regs.rax = 0;
416416
SYSPRINT("rt_sigaction(signum=%x, act=0x%lX, oldact=0x%lx) = 0x%llX\n",
417417
sig, g_act, g_oldact, regs.rax);
418-
cpu.set_registers(regs); });
418+
cpu.set_registers(regs);
419+
});
419420
Machine::install_syscall_handler(
420421
SYS_rt_sigprocmask, [](vCPU& cpu)
421422
{
@@ -442,28 +443,28 @@ void Machine::setup_linux_system_calls()
442443
regs.rax = 0;
443444
SYSPRINT("rt_sigprocmask(how=%x, set=0x%lX, oldset=0x%lx, size=%u) = 0x%llX\n",
444445
how, g_set, g_oldset, size, regs.rax);
445-
cpu.set_registers(regs); });
446-
Machine::install_syscall_handler(
446+
cpu.set_registers(regs);
447+
});
448+
Machine::install_syscall_handler( // sigaltstack
447449
SYS_sigaltstack, [](vCPU& cpu)
448450
{
449-
/* SYS sigaltstack */
450451
auto& regs = cpu.registers();
451-
452452
if (regs.rdi != 0x0) {
453453
auto& ss = cpu.machine().signals().per_thread(cpu.machine().threads().gettid()).stack;
454454
cpu.machine().copy_from_guest(&ss, regs.rdi, sizeof(ss));
455455

456456
SYSPRINT("sigaltstack(altstack SP=0x%lX flags=0x%X size=0x%lX)\n",
457457
ss.ss_sp, ss.ss_flags, ss.ss_size);
458458
}
459-
460459
regs.rax = 0;
461460
SYSPRINT("sigaltstack(ss=0x%llX, old_ss=0x%llx) = 0x%llX\n",
462461
regs.rdi, regs.rsi, regs.rax);
463-
cpu.set_registers(regs); });
464-
Machine::install_syscall_handler(
462+
cpu.set_registers(regs);
463+
});
464+
Machine::install_syscall_handler( // ioctl
465465
SYS_ioctl, [](vCPU& cpu) {
466466
auto& regs = cpu.registers();
467+
[[maybe_unused]] const int fd = cpu.machine().fds().translate(regs.rdi);
467468
switch (regs.rsi) {
468469
case 0x5401: /* TCGETS */
469470
if (int(regs.rdi) >= 0 && int(regs.rdi) < 3)
@@ -477,8 +478,8 @@ void Machine::setup_linux_system_calls()
477478
default:
478479
regs.rax = EINVAL;
479480
}
480-
SYSPRINT("ioctl(fd=0x%llX, req=0x%llx) = 0x%llX\n",
481-
regs.rdi, regs.rsi, regs.rax);
481+
SYSPRINT("ioctl(vfd=%lld fd=%d, req=0x%llx) = 0x%llX\n",
482+
regs.rdi, fd, regs.rsi, regs.rax);
482483
cpu.set_registers(regs);
483484
});
484485
Machine::install_syscall_handler(
@@ -705,9 +706,20 @@ void Machine::setup_linux_system_calls()
705706
// int socketpair(int domain, int type, int protocol, int sv[2]);
706707
const uint64_t g_sv = regs.r10;
707708
int sv[2] = { 0, 0 };
708-
cpu.machine().copy_to_guest(g_sv, sv, sizeof(sv));
709-
regs.rax = 0;
710-
SYSPRINT("socketpair(..., 0x%lX) = %lld\n", g_sv, regs.rax);
709+
const int res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
710+
if (res < 0)
711+
{
712+
regs.rax = -errno;
713+
}
714+
else
715+
{
716+
sv[0] = cpu.machine().fds().manage(sv[0], true, true);
717+
sv[1] = cpu.machine().fds().manage(sv[1], true, true);
718+
cpu.machine().copy_to_guest(g_sv, sv, sizeof(sv));
719+
regs.rax = 0;
720+
}
721+
SYSPRINT("socketpair(AF_UNIX, SOCK_STREAM, 0, 0x%lX) = %lld {%d, %d}\n",
722+
g_sv, regs.rax, sv[0], sv[1]);
711723
cpu.set_registers(regs);
712724
});
713725
Machine::install_syscall_handler(
@@ -757,7 +769,7 @@ void Machine::setup_linux_system_calls()
757769
} catch (...) {
758770
regs.rax = -EBADF;
759771
}
760-
SYSPRINT("recvfrom(fd=%lld, buf=0x%llX, size=%llu) = %lld\n",
772+
SYSPRINT("recvfrom(fd=%d, buf=0x%llX, size=%llu) = %lld\n",
761773
vfd, g_buf, bytes, regs.rax);
762774
cpu.set_registers(regs);
763775
});
@@ -792,6 +804,12 @@ void Machine::setup_linux_system_calls()
792804
//const int flags = fcntl(fd, cmd);
793805
regs.rax = 0x1;
794806
}
807+
else if (cmd == F_DUPFD_CLOEXEC)
808+
{
809+
const int new_fd = dup(fd);
810+
const int new_vfd = cpu.machine().fds().manage(new_fd, false, false);
811+
regs.rax = new_vfd;
812+
}
795813
} catch (...) {
796814
regs.rax = -EBADF;
797815
}
@@ -1103,8 +1121,17 @@ void Machine::setup_linux_system_calls()
11031121
{
11041122
/* SYS epoll_create1 */
11051123
auto& regs = cpu.registers();
1106-
regs.rax = 0;
1107-
SYSPRINT("epoll_create1(...) = %lld\n", regs.rax);
1124+
const int fd = epoll_create1(0);
1125+
if (fd < 0)
1126+
{
1127+
regs.rax = -errno;
1128+
}
1129+
else
1130+
{
1131+
const int vfd = cpu.machine().fds().manage(fd, false);
1132+
regs.rax = vfd;
1133+
}
1134+
SYSPRINT("epoll_create1() = %d (%lld)\n", fd, regs.rax);
11081135
cpu.set_registers(regs);
11091136
});
11101137
Machine::install_syscall_handler(
@@ -1116,35 +1143,63 @@ void Machine::setup_linux_system_calls()
11161143
SYSPRINT("nanosleep(...) = %lld\n", regs.rax);
11171144
cpu.set_registers(regs);
11181145
});
1119-
Machine::install_syscall_handler(
1120-
SYS_epoll_ctl, [](vCPU& cpu) // epoll_ctl
1146+
Machine::install_syscall_handler( // epoll_ctl
1147+
SYS_epoll_ctl, [](vCPU& cpu)
11211148
{
11221149
auto& regs = cpu.registers();
1150+
const int epollfd = cpu.machine().fds().translate(regs.rdi);
1151+
const int op = regs.rsi;
1152+
const int fd = cpu.machine().fds().translate(regs.rdx);
11231153
const uint64_t g_event = regs.r10;
11241154
struct epoll_event event;
11251155
cpu.machine().copy_from_guest(&event, g_event, sizeof(event));
1126-
regs.rax = 0;
1127-
SYSPRINT("epoll_ctl(fd=%d op=%d event=0x%llX event u64=0x%llX) = %lld\n",
1128-
int(regs.rdi), int(regs.rsi), event.events, event.data.u64, regs.rax);
1156+
if (epoll_ctl(epollfd, op, fd, &event) < 0) {
1157+
regs.rax = -errno;
1158+
}
1159+
else {
1160+
regs.rax = 0;
1161+
}
1162+
SYSPRINT("epoll_ctl(epollfd=%d (%lld), op=%d, fd=%d (%lld), g_event=0x%lX) = %lld\n",
1163+
epollfd, regs.rdi, op, fd, regs.rdx, g_event, regs.rax);
11291164
cpu.set_registers(regs);
11301165
});
1131-
Machine::install_syscall_handler(
1132-
SYS_epoll_wait, [](vCPU& cpu) // epoll_wait
1166+
Machine::install_syscall_handler( // epoll_wait
1167+
SYS_epoll_wait, [](vCPU& cpu)
11331168
{
11341169
auto& regs = cpu.registers();
11351170
const int vfd = regs.rdi;
11361171
[[maybe_unused]] const uint64_t g_events = regs.rsi;
11371172
[[maybe_unused]] const int maxevents = regs.rdx;
11381173
[[maybe_unused]] const int timeout = regs.r10;
1139-
// Create fake event
1140-
struct epoll_event event;
1141-
event.events = EPOLLIN;
1142-
event.data.fd = 1;
1143-
cpu.machine().copy_to_guest(regs.rsi, &event, sizeof(event));
1144-
regs.rax = 1;
1174+
if (maxevents > 1024)
1175+
{
1176+
regs.rax = -EINVAL;
1177+
SYSPRINT("epoll_wait(fd=%d maxevents=%d timeout=%d) = %lld\n",
1178+
vfd, maxevents, timeout, regs.rax);
1179+
cpu.set_registers(regs);
1180+
return;
1181+
}
1182+
std::array<struct epoll_event, 1024> guest_events;
1183+
const int epollfd = cpu.machine().fds().translate(vfd);
1184+
const int result =
1185+
epoll_wait(epollfd, guest_events.data(), maxevents, timeout);
1186+
// Copy events back to guest
1187+
if (result > 0)
1188+
{
1189+
cpu.machine().copy_to_guest(g_events, guest_events.data(),
1190+
result * sizeof(struct epoll_event));
1191+
} else if (result < 0)
1192+
{
1193+
regs.rax = -errno;
1194+
}
1195+
else
1196+
{
1197+
regs.rax = 0;
1198+
// XXX: This is a giga hack.
1199+
cpu.machine().threads().suspend_and_yield();
1200+
}
11451201
SYSPRINT("epoll_wait(...) = %lld\n", regs.rax);
11461202
cpu.set_registers(regs);
1147-
//cpu.machine().threads().suspend_and_yield();
11481203
});
11491204
Machine::install_syscall_handler(
11501205
SYS_getrlimit, [](vCPU& cpu) { // getrlimit
@@ -1171,7 +1226,7 @@ void Machine::setup_linux_system_calls()
11711226
struct rlimit64 lim{};
11721227
lim.rlim_cur = 4UL << 20;
11731228
lim.rlim_max = 4UL << 20;
1174-
SYSPRINT("prlimit64: current stack limit 0x%llX max 0x%llX\n",
1229+
SYSPRINT("prlimit64: current stack limit 0x%lX max 0x%lX\n",
11751230
lim.rlim_cur, lim.rlim_max);
11761231
cpu.machine().copy_to_guest(oldptr, &lim, sizeof(lim));
11771232
}
@@ -1180,7 +1235,7 @@ void Machine::setup_linux_system_calls()
11801235
#ifdef VERBOSE_SYSCALLS
11811236
struct rlimit64 lim {};
11821237
cpu.machine().copy_from_guest(&lim, newptr, sizeof(lim));
1183-
SYSPRINT("prlimit64: new stack limit 0x%llX max 0x%llX\n",
1238+
SYSPRINT("prlimit64: new stack limit 0x%lX max 0x%lX\n",
11841239
lim.rlim_cur, lim.rlim_max);
11851240
#endif
11861241
}
@@ -1192,7 +1247,7 @@ void Machine::setup_linux_system_calls()
11921247
struct rlimit64 lim{};
11931248
lim.rlim_cur = 4096;
11941249
lim.rlim_max = 4096;
1195-
SYSPRINT("prlimit64: current nofile limit 0x%llX max 0x%llX\n",
1250+
SYSPRINT("prlimit64: current nofile limit 0x%lX max 0x%lX\n",
11961251
lim.rlim_cur, lim.rlim_max);
11971252
cpu.machine().copy_to_guest(oldptr, &lim, sizeof(lim));
11981253
}

0 commit comments

Comments
 (0)