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 15 long host_syscall(int number, ...); 16 17 /* 18 * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts 19 */ 20 typedef uint64_t host_dev_t; 21 typedef uint64_t host_ino_t; 22 typedef unsigned int host_mode_t; 23 typedef unsigned int host_uid_t; 24 typedef unsigned int host_gid_t; 25 typedef int64_t host_off_t; 26 typedef long host_blksize_t; 27 typedef 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 */ 79 struct old_utsname { 80 char sysname[65]; 81 char nodename[65]; 82 char release[65]; 83 char version[65]; 84 char machine[65]; 85 }; 86 87 struct 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 132 struct host_kexec_segment { 133 void *buf; 134 int bufsz; 135 void *mem; 136 int memsz; 137 }; 138 139 struct 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 */ 161 int host_close(int fd); 162 int host_dup(int fd); 163 int host_exit(int code); 164 int host_fstat(int fd, struct host_kstat *sb); 165 int host_getdents64(int fd, void *dirp, int count); 166 int host_getpid(void); 167 int host_gettimeofday(struct host_timeval *a, void *b); 168 int host_ioctl(int fd, unsigned long request, unsigned long arg); 169 int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags); 170 ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence); 171 int host_mkdir(const char *, host_mode_t); 172 void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); 173 int host_mount(const char *src, const char *target, const char *type, 174 unsigned long flags, void *data); 175 int host_munmap(void *addr, size_t len); 176 int host_open(const char *path, int flags, int mode); 177 ssize_t host_read(int fd, void *buf, size_t nbyte); 178 int host_reboot(int, int, int, uintptr_t); 179 int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, 180 struct host_timeval *timeout); 181 int host_stat(const char *path, struct host_kstat *sb); 182 int host_symlink(const char *path1, const char *path2); 183 int host_uname(struct old_utsname *); 184 ssize_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 */ 202 static __inline bool 203 is_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 */ 218 static __inline int 219 host_to_stand_errno(long e) 220 { 221 assert(is_linux_error(e)); 222 223 return((-e) > 34 ? EINVAL : (-e)); 224 } 225 #endif 226