12b7918f1SWarner Losh /* 22b7918f1SWarner Losh * Copyright (c) 2022, Netflix, Inc. 32e3f4988SWarner Losh * 42b7918f1SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 52e3f4988SWarner Losh * 62b7918f1SWarner Losh * Rewritten from the original host_syscall.h Copyright (C) 2014 Nathan Whitehorn 72e3f4988SWarner Losh */ 82e3f4988SWarner Losh 92e3f4988SWarner Losh #ifndef _HOST_SYSCALL_H 102e3f4988SWarner Losh #define _HOST_SYSCALL_H 112e3f4988SWarner Losh 122e3f4988SWarner Losh #include <stand.h> 132e3f4988SWarner Losh #include <assert.h> 142e3f4988SWarner Losh 152e3f4988SWarner Losh long host_syscall(int number, ...); 162e3f4988SWarner Losh 172e3f4988SWarner Losh /* 182e3f4988SWarner Losh * Sizes taken from musl's include/alltypes.h.in and expanded for LP64 hosts 192e3f4988SWarner Losh */ 202e3f4988SWarner Losh typedef uint64_t host_dev_t; 212e3f4988SWarner Losh typedef uint64_t host_ino_t; 222e3f4988SWarner Losh typedef unsigned int host_mode_t; 232e3f4988SWarner Losh typedef unsigned int host_uid_t; 242e3f4988SWarner Losh typedef unsigned int host_gid_t; 252e3f4988SWarner Losh typedef int64_t host_off_t; 262e3f4988SWarner Losh typedef long host_blksize_t; 272e3f4988SWarner Losh typedef int64_t host_blkcnt_t; 282e3f4988SWarner Losh 292e3f4988SWarner Losh #include "stat_arch.h" 302e3f4988SWarner Losh 312e3f4988SWarner Losh /* 322e3f4988SWarner Losh * stat flags 332e3f4988SWarner Losh * These are arch independent and match the values in nolib and uapi headers 342e3f4988SWarner Losh * with HOST_ prepended. 352e3f4988SWarner Losh */ 362e3f4988SWarner Losh #define HOST_S_IFMT 0170000 372e3f4988SWarner Losh #define HOST_S_IFIFO 0010000 382e3f4988SWarner Losh #define HOST_S_IFCHR 0020000 392e3f4988SWarner Losh #define HOST_S_IFDIR 0040000 402e3f4988SWarner Losh #define HOST_S_IFBLK 0060000 412e3f4988SWarner Losh #define HOST_S_IFREG 0100000 422e3f4988SWarner Losh #define HOST_S_IFLNK 0120000 432e3f4988SWarner Losh #define HOST_S_IFSOCK 0140000 442e3f4988SWarner Losh 452e3f4988SWarner Losh #define HOST_S_ISBLK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFBLK) 462e3f4988SWarner Losh #define HOST_S_ISCHR(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFCHR) 472e3f4988SWarner Losh #define HOST_S_ISDIR(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFDIR) 482e3f4988SWarner Losh #define HOST_S_ISFIFO(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFIFO) 492e3f4988SWarner Losh #define HOST_S_ISLNK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFLNK) 502e3f4988SWarner Losh #define HOST_S_ISREG(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFREG) 512e3f4988SWarner Losh #define HOST_S_ISSOCK(mode) (((mode) & HOST_S_IFMT) == HOST_S_IFSOCK) 522e3f4988SWarner Losh 532e3f4988SWarner Losh /* 542e3f4988SWarner Losh * Constants for open, fcntl, etc 552e3f4988SWarner Losh * 562e3f4988SWarner Losh * Note: Some of these are arch dependent on Linux, but are the same for 572e3f4988SWarner Losh * powerpc, x86, arm*, and riscv. We should be futureproof, though, since these 582e3f4988SWarner Losh * are the 'generic' values and only older architectures (no longer supported by 592e3f4988SWarner Losh * FreeBSD) vary. 602e3f4988SWarner Losh * 612e3f4988SWarner Losh * These are from tools/include/uapi/asm-generic/fcntl.h and use the octal 622e3f4988SWarner Losh * notation. Beware, hex is used in other places creating potential confsion. 632e3f4988SWarner Losh */ 642e3f4988SWarner Losh #define HOST_O_RDONLY 0 652e3f4988SWarner Losh #define HOST_O_WRONLY 1 662e3f4988SWarner Losh #define HOST_O_RDWR 2 672e3f4988SWarner Losh #define HOST_O_CREAT 00100 682e3f4988SWarner Losh #define HOST_O_EXCL 00200 692e3f4988SWarner Losh #define HOST_O_NOCTTY 00400 702e3f4988SWarner Losh #define HOST_O_TRUNC 01000 712e3f4988SWarner Losh #define HOST_O_APPEND 02000 722e3f4988SWarner Losh #define HOST_O_NONBLOCK 04000 732e3f4988SWarner Losh 742e3f4988SWarner Losh #define HOST_AT_FDCWD -100 /* Relative to current directory */ 752e3f4988SWarner Losh 762e3f4988SWarner Losh /* 772e3f4988SWarner Losh * Data types 782e3f4988SWarner Losh */ 792e3f4988SWarner Losh struct old_utsname { 802e3f4988SWarner Losh char sysname[65]; 812e3f4988SWarner Losh char nodename[65]; 822e3f4988SWarner Losh char release[65]; 832e3f4988SWarner Losh char version[65]; 842e3f4988SWarner Losh char machine[65]; 852e3f4988SWarner Losh }; 862e3f4988SWarner Losh 872e3f4988SWarner Losh struct host_timeval { 882e3f4988SWarner Losh time_t tv_sec; 892e3f4988SWarner Losh long tv_usec; 902e3f4988SWarner Losh }; 912e3f4988SWarner Losh 922e3f4988SWarner Losh /* 932e3f4988SWarner Losh * Must match Linux's values see linux/tools/include/uapi/asm-generic/mman-common.h 942e3f4988SWarner Losh * and linux/tools/include/linux/mman.h 952e3f4988SWarner Losh * 962e3f4988SWarner Losh * And pre-pend HOST_ here. 972e3f4988SWarner Losh */ 982e3f4988SWarner Losh #define HOST_PROT_READ 0x1 992e3f4988SWarner Losh #define HOST_PROT_WRITE 0x2 1002e3f4988SWarner Losh #define HOST_PROT_EXEC 0x4 1012e3f4988SWarner Losh 1022e3f4988SWarner Losh #define HOST_MAP_SHARED 0x01 1032e3f4988SWarner Losh #define HOST_MAP_PRIVATE 0x02 1042e3f4988SWarner Losh #define HOST_MAP_FIXED 0x10 1052e3f4988SWarner Losh #define HOST_MAP_ANONYMOUS 0x20 1062e3f4988SWarner Losh 1072e3f4988SWarner Losh #define HOST_MAP_FAILED ((void *)-1) 1082e3f4988SWarner Losh 1092e3f4988SWarner Losh /* Mount flags from uapi */ 1102e3f4988SWarner Losh #define MS_RELATIME (1 << 21) 1112e3f4988SWarner Losh 1122e3f4988SWarner Losh #define HOST_REBOOT_MAGIC1 0xfee1dead 1132e3f4988SWarner Losh #define HOST_REBOOT_MAGIC2 672274793 1142e3f4988SWarner Losh #define HOST_REBOOT_CMD_KEXEC 0x45584543 1152e3f4988SWarner Losh 1162e3f4988SWarner Losh /* 1172e3f4988SWarner Losh * Values from linux/tools/include/uapi/linux/kexec.h 1182e3f4988SWarner Losh */ 1192e3f4988SWarner Losh 1202e3f4988SWarner Losh /* 1212e3f4988SWarner Losh * Values match ELF architecture types. 1222e3f4988SWarner Losh */ 1232e3f4988SWarner Losh #define HOST_KEXEC_ARCH_X86_64 (62 << 16) 1242e3f4988SWarner Losh #define HOST_KEXEC_ARCH_PPC64 (21 << 16) 1252e3f4988SWarner Losh #define HOST_KEXEC_ARCH_ARM (40 << 16) 1262e3f4988SWarner Losh #define HOST_KEXEC_ARCH_AARCH64 (183 << 16) 1272e3f4988SWarner Losh #define HOST_KEXEC_ARCH_RISCV (243 << 16) 1282e3f4988SWarner Losh 1292e3f4988SWarner Losh /* Arbitrary cap on segments */ 1302e3f4988SWarner Losh #define HOST_KEXEC_SEGMENT_MAX 16 1312e3f4988SWarner Losh 1322e3f4988SWarner Losh struct host_kexec_segment { 1332e3f4988SWarner Losh void *buf; 1342e3f4988SWarner Losh int bufsz; 1352e3f4988SWarner Losh void *mem; 1362e3f4988SWarner Losh int memsz; 1372e3f4988SWarner Losh }; 1382e3f4988SWarner Losh 1392e3f4988SWarner Losh struct host_dirent64 { 1402e3f4988SWarner Losh uint64_t d_ino; /* 64-bit inode number */ 1412e3f4988SWarner Losh int64_t d_off; /* 64-bit offset to next structure */ 1422e3f4988SWarner Losh unsigned short d_reclen; /* Size of this dirent */ 1432e3f4988SWarner Losh unsigned char d_type; /* File type */ 1442e3f4988SWarner Losh char d_name[]; /* Filename (null-terminated) */ 1452e3f4988SWarner Losh }; 1462e3f4988SWarner Losh 1472e3f4988SWarner Losh /* d_type values */ 1482e3f4988SWarner Losh #define HOST_DT_UNKNOWN 0 1492e3f4988SWarner Losh #define HOST_DT_FIFO 1 1502e3f4988SWarner Losh #define HOST_DT_CHR 2 1512e3f4988SWarner Losh #define HOST_DT_DIR 4 1522e3f4988SWarner Losh #define HOST_DT_BLK 6 1532e3f4988SWarner Losh #define HOST_DT_REG 8 1542e3f4988SWarner Losh #define HOST_DT_LNK 10 1552e3f4988SWarner Losh #define HOST_DT_SOCK 12 1562e3f4988SWarner Losh #define HOST_DT_WHT 14 1572e3f4988SWarner Losh 1582e3f4988SWarner Losh /* 1592e3f4988SWarner Losh * System Calls 1602e3f4988SWarner Losh */ 1612e3f4988SWarner Losh int host_close(int fd); 1622e3f4988SWarner Losh int host_dup(int fd); 1632e3f4988SWarner Losh int host_exit(int code); 1642e3f4988SWarner Losh int host_fstat(int fd, struct host_kstat *sb); 1652e3f4988SWarner Losh int host_getdents64(int fd, void *dirp, int count); 1662e3f4988SWarner Losh int host_getpid(void); 1672e3f4988SWarner Losh int host_gettimeofday(struct host_timeval *a, void *b); 1682e3f4988SWarner Losh int host_ioctl(int fd, unsigned long request, unsigned long arg); 1692e3f4988SWarner Losh int host_kexec_load(unsigned long entry, unsigned long nsegs, struct host_kexec_segment *segs, unsigned long flags); 1702e3f4988SWarner Losh ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence); 1712e3f4988SWarner Losh int host_mkdir(const char *, host_mode_t); 1722e3f4988SWarner Losh void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); 1732e3f4988SWarner Losh int host_mount(const char *src, const char *target, const char *type, 1742e3f4988SWarner Losh unsigned long flags, void *data); 1752e3f4988SWarner Losh int host_munmap(void *addr, size_t len); 1762e3f4988SWarner Losh int host_open(const char *path, int flags, int mode); 1772e3f4988SWarner Losh ssize_t host_read(int fd, void *buf, size_t nbyte); 1782e3f4988SWarner Losh int host_reboot(int, int, int, uintptr_t); 1792e3f4988SWarner Losh int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, 1802e3f4988SWarner Losh struct host_timeval *timeout); 1812e3f4988SWarner Losh int host_stat(const char *path, struct host_kstat *sb); 1822e3f4988SWarner Losh int host_symlink(const char *path1, const char *path2); 1832e3f4988SWarner Losh int host_uname(struct old_utsname *); 1842e3f4988SWarner Losh ssize_t host_write(int fd, const void *buf, size_t nbyte); 1852e3f4988SWarner Losh 1862e3f4988SWarner Losh /* 1872e3f4988SWarner Losh * Wrappers / one-liners 1882e3f4988SWarner Losh */ 1892e3f4988SWarner Losh #define host_getmem(size) \ 1902e3f4988SWarner Losh host_mmap(0, size, HOST_PROT_READ | HOST_PROT_WRITE, \ 1912e3f4988SWarner Losh HOST_MAP_PRIVATE | HOST_MAP_ANONYMOUS, -1, 0); 1922e3f4988SWarner Losh 1932e3f4988SWarner Losh /* 194*3ae18fdfSWarner Losh * Since we have to interface with the 'raw' system call, we have to cope with 195*3ae18fdfSWarner Losh * Linux's conventions. To run on the most architectures possible, they don't 196*3ae18fdfSWarner Losh * return errors through some CPU flag, but instead, return a negative value for 197*3ae18fdfSWarner Losh * an error, and a positive one for success. However, there's some issues since 198*3ae18fdfSWarner Losh * addresses have to be returned, some of which are also negative, so Linus 199*3ae18fdfSWarner Losh * declared that no successful result could be -4096 to 0. This implements 200*3ae18fdfSWarner Losh * that quirk so we can check return values easily. 201*3ae18fdfSWarner Losh */ 202*3ae18fdfSWarner Losh static __inline bool 203*3ae18fdfSWarner Losh is_linux_error(long e) 204*3ae18fdfSWarner Losh { 205*3ae18fdfSWarner Losh return (e < 0 && e >= -4096); 206*3ae18fdfSWarner Losh } 207*3ae18fdfSWarner Losh 208*3ae18fdfSWarner Losh /* 2092e3f4988SWarner Losh * Translate Linux errno to FreeBSD errno. The two system have idenitcal errors 2102e3f4988SWarner Losh * for 1-34. After that, they differ. Linux also has errno that don't map 2112e3f4988SWarner Losh * exactly to FreeBSD's errno, plus the Linux errno are arch dependent > 2122e3f4988SWarner Losh * 34. Since we just need to do this for simple cases, use the simple mapping 2132e3f4988SWarner Losh * function where -1 to -34 are translated to 1 to 34 and all others are EINVAL. 214*3ae18fdfSWarner Losh * Pass the linux return value, which will be the -errno. Linux returns these 215*3ae18fdfSWarner Losh * values as a 'long' which has to align to CPU register size, so accept that 216*3ae18fdfSWarner Losh * size as the error so the assert can catch more values. 2172e3f4988SWarner Losh */ 2182e3f4988SWarner Losh static __inline int 219*3ae18fdfSWarner Losh host_to_stand_errno(long e) 2202e3f4988SWarner Losh { 221*3ae18fdfSWarner Losh assert(is_linux_error(e)); 2222e3f4988SWarner Losh 2232e3f4988SWarner Losh return((-e) > 34 ? EINVAL : (-e)); 2242e3f4988SWarner Losh } 2252e3f4988SWarner Losh #endif 226