Skip to content

Commit

Permalink
kernel: add linux compatibility layer
Browse files Browse the repository at this point in the history
  • Loading branch information
willdurand committed Jul 17, 2022
1 parent 4cb7264 commit 2fd5de9
Show file tree
Hide file tree
Showing 40 changed files with 960 additions and 66 deletions.
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

0 comments on commit 2fd5de9

Please sign in to comment.