1/* 2 * Copyright (c) 2022, Netflix, Inc. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Rewritten from the original host_syscall.h Copyright (C) 2014 Nathan Whitehorn 7 */ 8 9#ifndef _HOST_SYSCALL_H 10#define _HOST_SYSCALL_H 11 12#include <stand.h> 13#include <assert.h> 14 15long host_syscall(int number, ...); 16 17/* 18 * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts 19 */ 20typedef uint64_t host_dev_t; 21typedef uint64_t host_ino_t; 22typedef unsigned int host_mode_t; 23typedef unsigned int host_uid_t; 24typedef unsigned int host_gid_t; 25typedef int64_t host_off_t; 26typedef long host_blksize_t; 27typedef int64_t host_blkcnt_t; 28 29#include "stat_arch.h" 30 31/* 32 * stat flags 33 * These are arch independent and match the values in nolib and uapi headers 34 * with HOST_ prepended. 35 */ 36#define HOST_S_IFMT 0170000 37#define HOST_S_IFIFO 0010000 38#define HOST_S_IFCHR 0020000 39#define HOST_S_IFDIR 0040000 40#define HOST_S_IFBLK 0060000 41#define HOST_S_IFREG 0100000 42#define HOST_S_IFLNK 0120000 43#define HOST_S_IFSOCK 0140000 44 45#define HOST_S_ISBLK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFBLK) 46#define HOST_S_ISCHR(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFCHR) 47#define HOST_S_ISDIR(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFDIR) 48#define HOST_S_ISFIFO(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFIFO) 49#define HOST_S_ISLNK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFLNK) 50#define HOST_S_ISREG(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFREG) 51#define HOST_S_ISSOCK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFSOCK) 52 53/* 54 * Constants for open, fcntl, etc 55 * 56 * Note: Some of these are arch dependent on Linux, but are the same for 57 * powerpc, x86, arm*, and riscv. We should be futureproof, though, since these 58 * are the 'generic' values and only older architectures (no longer supported by 59 * FreeBSD) vary. 60 * 61 * These are from tools/include/uapi/asm-generic/fcntl.h and use the octal 62 * notation. Beware, hex is used in other places creating potential confsion. 63 */ 64#define HOST_O_RDONLY 0 65#define HOST_O_WRONLY 1 66#define HOST_O_RDWR 2 67#define HOST_O_CREAT 00100 68#define HOST_O_EXCL 00200 69#define HOST_O_NOCTTY 00400 70#define HOST_O_TRUNC 01000 71#define HOST_O_APPEND 02000 72#define HOST_O_NONBLOCK 04000 73 74#define HOST_AT_FDCWD -100 /* Relative to current directory */ 75 76/* 77 * Data types 78 */ 79struct old_utsname { 80 char sysname[65]; 81 char nodename[65]; 82 char release[65]; 83 char version[65]; 84 char machine[65]; 85}; 86 87struct host_timeval { 88 time_t tv_sec; 89 long tv_usec; 90}; 91 92/* 93 * Must match Linux's values see linux/tools/include/uapi/asm-generic/mman-common.h 94 * and linux/tools/include/linux/mman.h 95 * 96 * And pre-pend HOST_ here. 97 */ 98#define HOST_PROT_READ 0x1 99#define HOST_PROT_WRITE 0x2 100#define HOST_PROT_EXEC 0x4 101 102#define HOST_MAP_SHARED 0x01 103#define HOST_MAP_PRIVATE 0x02 104#define HOST_MAP_FIXED 0x10 105#define HOST_MAP_ANONYMOUS 0x20 106 107#define HOST_MAP_FAILED ((void *)-1) 108 109/* Mount flags from uapi */ 110#define MS_RELATIME (1 << 21) 111 112#define HOST_REBOOT_MAGIC1 0xfee1dead 113#define HOST_REBOOT_MAGIC2 672274793 114#define HOST_REBOOT_CMD_KEXEC 0x45584543 115 116/* 117 * Values from linux/tools/include/uapi/linux/kexec.h 118 */ 119 120/* 121 * Values match ELF architecture types. 122 */ 123#define HOST_KEXEC_ARCH_X86_64 (62 << 16) 124#define HOST_KEXEC_ARCH_PPC64 (21 << 16) 125#define HOST_KEXEC_ARCH_ARM (40 << 16) 126#define HOST_KEXEC_ARCH_AARCH64 (183 << 16) 127#define HOST_KEXEC_ARCH_RISCV (243 << 16) 128 129/* Arbitrary cap on segments */ 130#define HOST_KEXEC_SEGMENT_MAX 16 131 132struct host_kexec_segment { 133 void *buf; 134 int bufsz; 135 void *mem; 136 int memsz; 137}; 138 139struct host_dirent64 { 140 uint64_t d_ino; /* 64-bit inode number */ 141 int64_t d_off; /* 64-bit offset to next structure */ 142 unsigned short d_reclen; /* Size of this dirent */ 143 unsigned char d_type; /* File type */ 144 char d_name[]; /* Filename (null-terminated) */ 145}; 146 147/* d_type values */ 148#define HOST_DT_UNKNOWN 0 149#define HOST_DT_FIFO 1 150#define HOST_DT_CHR 2 151#define HOST_DT_DIR 4 152#define HOST_DT_BLK 6 153#define HOST_DT_REG 8 154#define HOST_DT_LNK 10 155#define HOST_DT_SOCK 12 156#define HOST_DT_WHT 14 157 158/* 159 * System Calls 160 */ 161int host_close(int fd); 162int host_dup(int fd); 163int host_exit(int code); 164int host_fstat(int fd, struct host_kstat *sb); 165int host_getdents64(int fd, void *dirp, int count); 166int host_getpid(void); 167int host_gettimeofday(struct host_timeval *a, void *b); 168int host_ioctl(int fd, unsigned long request, unsigned long arg); 169int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags); 170ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence); 171int host_mkdir(const char *, host_mode_t); 172void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); 173int host_mount(const char *src, const char *target, const char *type, 174 unsigned long flags, void *data); 175int host_munmap(void *addr, size_t len); 176int host_open(const char *path, int flags, int mode); 177ssize_t host_read(int fd, void *buf, size_t nbyte); 178int host_reboot(int, int, int, uintptr_t); 179int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, 180 struct host_timeval *timeout); 181int host_stat(const char *path, struct host_kstat *sb); 182int host_symlink(const char *path1, const char *path2); 183int host_uname(struct old_utsname *); 184ssize_t host_write(int fd, const void *buf, size_t nbyte); 185 186/* 187 * Wrappers / one-liners 188 */ 189#define host_getmem(size) \ 190 host_mmap(0, size, HOST_PROT_READ | HOST_PROT_WRITE, \ 191 HOST_MAP_PRIVATE | HOST_MAP_ANONYMOUS, -1, 0); 192 193/* 194 * Since we have to interface with the 'raw' system call, we have to cope with 195 * Linux's conventions. To run on the most architectures possible, they don't 196 * return errors through some CPU flag, but instead, return a negative value for 197 * an error, and a positive one for success. However, there's some issues since 198 * addresses have to be returned, some of which are also negative, so Linus 199 * declared that no successful result could be -4096 to 0. This implements 200 * that quirk so we can check return values easily. 201 */ 202static __inline bool 203is_linux_error(long e) 204{ 205 return (e < 0 && e >= -4096); 206} 207 208/* 209 * Translate Linux errno to FreeBSD errno. The two system have idenitcal errors 210 * for 1-34. After that, they differ. Linux also has errno that don't map 211 * exactly to FreeBSD's errno, plus the Linux errno are arch dependent > 212 * 34. Since we just need to do this for simple cases, use the simple mapping 213 * function where -1 to -34 are translated to 1 to 34 and all others are EINVAL. 214 * Pass the linux return value, which will be the -errno. Linux returns these 215 * values as a 'long' which has to align to CPU register size, so accept that 216 * size as the error so the assert can catch more values. 217 */ 218static __inline int 219host_to_stand_errno(long e) 220{ 221 assert(is_linux_error(e)); 222 223 return((-e) > 34 ? EINVAL : (-e)); 224} 225#endif 226