Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kernel: add linux compatibility layer #552

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ ifeq ($(CONFIG_USE_FAKE_CLOCK), 1)
libk_c_files += $(kernel_src_dir)/time/fake_clock.c
endif

ifeq ($(CONFIG_LINUX_COMPAT), 1)
KERNEL_CONFIG += -DCONFIG_LINUX_COMPAT
LIBC_CONFIG += -DCONFIG_LINUX_COMPAT
libk_c_files += $(wildcard $(kernel_src_dir)/sys/linux/*.c)
endif

# This file exists in a Docker container because we copy it in `Dockerfile`.
in_docker = $(wildcard /tmp/install-linux-deps)
ifneq ($(in_docker),)
Expand Down Expand Up @@ -435,6 +441,7 @@ what: ## display some information about the current configuration
echo "OS_NAME : $(OS_NAME)"
echo "ARCH : $(ARCH)"
echo ""
echo "CONFIG_LINUX_COMPAT = $(CONFIG_LINUX_COMPAT)"
echo "CONFIG_SEMIHOSTING = $(CONFIG_SEMIHOSTING)"
echo "CONFIG_USE_DLMALLOC = $(CONFIG_USE_DLMALLOC)"
echo "CONFIG_USE_FAKE_CLOCK = $(CONFIG_USE_FAKE_CLOCK)"
Expand Down
2 changes: 2 additions & 0 deletions Makefile-cfg.include
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ LLVM_SUFFIX ?=

# When set to 1, enable the Undefined Behavior SANitizer.
UBSAN ?=
# When set to 1, enable Linux (binary) compatibility.
CONFIG_LINUX_COMPAT ?=
# When set to 1, enable semi-hosting mode (QEMU, mainly).
CONFIG_SEMIHOSTING ?=
# When set to 1, use dlmalloc for malloc/free/realloc (instead of liballoc).
Expand Down
3 changes: 3 additions & 0 deletions data/initrd/etc/hosts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Mainly needed because `KERNEL_CMDLINE` skips arguments with a dot so we
# cannot use `KERNEL_CMDLINE='/bin/busybox ping github.com'` for instance.
140.82.121.4 github
1 change: 1 addition & 0 deletions data/initrd/etc/passwd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
root:x:0:0::/:none
8 changes: 8 additions & 0 deletions include/kernel/proc/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#ifndef PROC_DESCRIPTOR_H
#define PROC_DESCRIPTOR_H

#include <arpa/inet.h>
#include <fs/vfs.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/types.h>

#define STDIN 0
Expand All @@ -23,6 +25,8 @@ typedef struct descriptor
uint32_t type;
uint32_t protocol;
uint16_t port;
struct sockaddr_in addr;
socklen_t addr_len;
} descriptor_t;

/**
Expand Down Expand Up @@ -82,4 +86,8 @@ int descriptor_udp_lookup(uint16_t port);
*/
bool is_protocol_supported(uint32_t type, uint32_t protocol);

void duplicate_descriptor(int oldfd, int newfd);

int descriptor_raw_lookup(uint32_t protocol, in_addr_t src_addr);

#endif
31 changes: 31 additions & 0 deletions include/kernel/sys/k_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
#include <sys/time.h>
#include <sys/types.h>

#ifdef CONFIG_LINUX_COMPAT

#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/utsname.h>

#endif

/**
* Initializes the syscalls management.
*/
Expand Down Expand Up @@ -48,4 +56,27 @@ pid_t k_getpid();
void k_exit(int code);
int k_openat(int dirfd, const char* pathname, int flags);

#ifdef CONFIG_LINUX_COMPAT

int k_poll(struct pollfd* fds, nfds_t nfds, int timeout);
int k_writev(int fd, struct iovec* iov, int iovcnt);
int k_uname(struct utsname* buf);
int k_getsockname(int sockfd,
struct sockaddr* restrict addr,
socklen_t* restrict addrlen);
int k_connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
int k_dup2(int oldfd, int newfd);
int k_ioctl(int fd, int request, void* ptr);
char* k_getcwd(char* buf, size_t size);
void* k_mmap(void* addr,
size_t length,
int prot,
int flags,
int fd,
off_t offset);
uintptr_t k_brk(uintptr_t addr);
int k_arch_prctl(int code, uintptr_t addr);

#endif // CONFIG_LINUX_COMPAT

#endif
115 changes: 115 additions & 0 deletions include/libc/sys/linux_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md
#ifndef SYS_LINUX_COMPAT_H
#define SYS_LINUX_COMPAT_H

#ifdef __x86_64__

#define SYSCALL_READ 0
#define SYSCALL_WRITE 1
#define SYSCALL_OPEN 2
#define SYSCALL_CLOSE 3
#define SYSCALL_FSTAT 5
#define SYSCALL_POLL 7
#define SYSCALL_LSEEK 8
#define SYSCALL_MMAP 9
#define SYSCALL_BRK 12
#define SYSCALL_RT_SIGACTION 13
#define SYSCALL_RT_SIGPROCMASK 14
#define SYSCALL_IOCTL 16
#define SYSCALL_WRITEV 20
#define SYSCALL_DUP2 33
#define SYSCALL_NANOSLEEP 35
#define SYSCALL_GETPID 39
#define SYSCALL_SOCKET 41
#define SYSCALL_CONNECT 42
#define SYSCALL_SENDTO 44
#define SYSCALL_RECVFROM 45
#define SYSCALL_BIND 49
#define SYSCALL_GETSOCKNAME 51
#define SYSCALL_SETSOCKOPT 54
#define SYSCALL_EXECV 59
#define SYSCALL_EXIT 60
#define SYSCALL_UNAME 63
#define SYSCALL_FCNTL 72
#define SYSCALL_GETCWD 79
#define SYSCALL_GETTIMEOFDAY 96
#define SYSCALL_SETUID 105
#define SYSCALL_SETGID 106
#define SYSCALL_GETEUID 107
#define SYSCALL_ARCH_PRCTL 158
#define SYSCALL_REBOOT 169
#define SYSCALL_SET_TID_ADDR 218
#define SYSCALL_EXIT_GROUP 231
#define SYSCALL_OPENAT 257
#define SYSCALL_GETRANDOM 318

#elif __arm__

#define SYSCALL_EXIT 1
#define SYSCALL_READ 3
#define SYSCALL_WRITE 4
#define SYSCALL_OPEN 5
#define SYSCALL_CLOSE 6
#define SYSCALL_EXECV 11
#define SYSCALL_LSEEK 19
#define SYSCALL_GETPID 20
#define SYSCALL_BRK 45
#define SYSCALL_GETEUID 49
#define SYSCALL_IOCTL 54
#define SYSCALL_DUP2 63
#define SYSCALL_GETTIMEOFDAY 78
#define SYSCALL_REBOOT 88
#define SYSCALL_FSTAT 108
#define SYSCALL_WRITEV 146
#define SYSCALL_EXIT_GROUP 248
#define SYSCALL_SET_TID_ADDR 256
#define SYSCALL_SOCKET 281
#define SYSCALL_SENDTO 290
#define SYSCALL_RECVFROM 292
#define SYSCALL_OPENAT 322
#define SYSCALL_GETRANDOM 384

// Not available on AArch32:
//
// - SYSCALL_ARCH_PRCTL

#elif __aarch64__

#define SYSCALL_FCNTL 25
#define SYSCALL_IOCTL 29
#define SYSCALL_OPENAT 56
#define SYSCALL_CLOSE 57
#define SYSCALL_LSEEK 62
#define SYSCALL_READ 63
#define SYSCALL_WRITE 64
#define SYSCALL_WRITEV 66
#define SYSCALL_FSTAT 80
#define SYSCALL_EXIT 93
#define SYSCALL_EXIT_GROUP 94
#define SYSCALL_SET_TID_ADDR 96
#define SYSCALL_REBOOT 142
#define SYSCALL_GETTIMEOFDAY 169
#define SYSCALL_GETPID 172
#define SYSCALL_GETEUID 175
#define SYSCALL_SOCKET 198
#define SYSCALL_SENDTO 206
#define SYSCALL_RECVFROM 207
#define SYSCALL_BRK 214
#define SYSCALL_MUNMAP 215
#define SYSCALL_EXECV 221
#define SYSCALL_MMAP 222
#define SYSCALL_GETRANDOM 278

// Not available on AArch64:
//
// - SYSCALL_OPEN
// - SYSCALL_DUP2
// - SYSCALL_ARCH_PRCTL

#endif

// Not available outside ArvernOS:
#define SYSCALL_TEST 348
#define SYSCALL_GETHOSTBYNAME2 349

#endif
14 changes: 14 additions & 0 deletions include/libc/sys/poll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** @file */
#ifndef SYS_POLL_H
#define SYS_POLL_H

struct pollfd
{
int fd;
short events;
short revents;
};

typedef unsigned int nfds_t;

#endif
8 changes: 8 additions & 0 deletions include/libc/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
#include <sys/time.h>
#include <sys/types.h>

#ifdef CONFIG_LINUX_COMPAT

#include <sys/linux_compat.h>

#else // CONFIG_LINUX_COMPAT

#define SYSCALL_TEST 1
#define SYSCALL_WRITE 2
#define SYSCALL_READ 3
Expand All @@ -29,6 +35,8 @@
#define SYSCALL_EXIT 16
#define SYSCALL_OPENAT 17

#endif // CONFIG_LINUX_COMPAT

#define SYSCALL_SET_ERRNO() \
if (retval < 0) { \
errno = -retval; \
Expand Down
11 changes: 11 additions & 0 deletions include/libc/sys/uio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @file */
#ifndef SYS_UIO_H
#define SYS_UIO_H

struct iovec
{
uintptr_t base;
ssize_t len;
} __attribute__((packed));

#endif
14 changes: 14 additions & 0 deletions include/libc/sys/utsname.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** @file */
#ifndef SYS_UTSNAME_H
#define SYS_UTSNAME_H

struct utsname
{
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
};

#endif
6 changes: 6 additions & 0 deletions src/kernel/arch/aarch32/asm/proc.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifdef CONFIG_LINUX_COMPAT
.global linux_compat_start
linux_compat_start:
mov sp, r1
blx r0
#endif
6 changes: 6 additions & 0 deletions src/kernel/arch/aarch64/asm/proc.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifdef CONFIG_LINUX_COMPAT
.global linux_compat_start
linux_compat_start:
mov sp, x1
blr x0
#endif
2 changes: 1 addition & 1 deletion src/kernel/arch/x86_64/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ QEMU = qemu-system-x86_64
# Options for the different tools
###############################################################################

QEMU_OPTIONS += -m 512M
QEMU_OPTIONS += -m 512M -cpu IvyBridge
QEMU_OPTIONS += -serial file:$(log_file)
QEMU_OPTIONS += -netdev user,id=u1,ipv6=off,dhcpstart=10.0.2.20
QEMU_OPTIONS += -device rtl8139,netdev=u1
Expand Down
28 changes: 27 additions & 1 deletion src/kernel/arch/x86_64/asm/boot.asm
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,37 @@ start:
; load the 64-bit GDT
lgdt [gdt64.pointer]

%ifdef CONFIG_LINUX_COMPAT
call enable_sse

; enable the following instructions: rdfsbase, rdgsbase, wrfsbase, wrgsbase
mov eax, cr4
or eax, 1 << 16
mov cr4, eax
%endif

jmp gdt64.kernel_code:long_mode_start

; Should not be reached.
; should not be reached
hlt

enable_sse:
mov eax, 0x1 ; check for SSE
cpuid
test edx, 1 << 25
jz .no_sse ; after this, SSE can be enabled
mov eax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
ret

.no_sse:
ret

; -----------------------------------------------------------------------------
; make sure the kernel was really loaded by a Multiboot compliant bootloader
%define MULTIBOOT2_MAGIC_VALUE 0x36d76289
Expand Down
Loading