cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

arch-i386.h (10392B)


      1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
      2/*
      3 * i386 specific definitions for NOLIBC
      4 * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
      5 */
      6
      7#ifndef _NOLIBC_ARCH_I386_H
      8#define _NOLIBC_ARCH_I386_H
      9
     10/* O_* macros for fcntl/open are architecture-specific */
     11#define O_RDONLY            0
     12#define O_WRONLY            1
     13#define O_RDWR              2
     14#define O_CREAT          0x40
     15#define O_EXCL           0x80
     16#define O_NOCTTY        0x100
     17#define O_TRUNC         0x200
     18#define O_APPEND        0x400
     19#define O_NONBLOCK      0x800
     20#define O_DIRECTORY   0x10000
     21
     22/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
     23 * exactly 56 bytes (stops before the unused array).
     24 */
     25struct sys_stat_struct {
     26	unsigned long  st_dev;
     27	unsigned long  st_ino;
     28	unsigned short st_mode;
     29	unsigned short st_nlink;
     30	unsigned short st_uid;
     31	unsigned short st_gid;
     32
     33	unsigned long  st_rdev;
     34	unsigned long  st_size;
     35	unsigned long  st_blksize;
     36	unsigned long  st_blocks;
     37
     38	unsigned long  st_atime;
     39	unsigned long  st_atime_nsec;
     40	unsigned long  st_mtime;
     41	unsigned long  st_mtime_nsec;
     42
     43	unsigned long  st_ctime;
     44	unsigned long  st_ctime_nsec;
     45	unsigned long  __unused[2];
     46};
     47
     48/* Syscalls for i386 :
     49 *   - mostly similar to x86_64
     50 *   - registers are 32-bit
     51 *   - syscall number is passed in eax
     52 *   - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
     53 *   - all registers are preserved (except eax of course)
     54 *   - the system call is performed by calling int $0x80
     55 *   - syscall return comes in eax
     56 *   - the arguments are cast to long and assigned into the target registers
     57 *     which are then simply passed as registers to the asm code, so that we
     58 *     don't have to experience issues with register constraints.
     59 *   - the syscall number is always specified last in order to allow to force
     60 *     some registers before (gcc refuses a %-register at the last position).
     61 *
     62 * Also, i386 supports the old_select syscall if newselect is not available
     63 */
     64#define __ARCH_WANT_SYS_OLD_SELECT
     65
     66#define my_syscall0(num)                                                      \
     67({                                                                            \
     68	long _ret;                                                            \
     69	register long _num __asm__ ("eax") = (num);                           \
     70	                                                                      \
     71	__asm__  volatile (                                                   \
     72		"int $0x80\n"                                                 \
     73		: "=a" (_ret)                                                 \
     74		: "0"(_num)                                                   \
     75		: "memory", "cc"                                              \
     76	);                                                                    \
     77	_ret;                                                                 \
     78})
     79
     80#define my_syscall1(num, arg1)                                                \
     81({                                                                            \
     82	long _ret;                                                            \
     83	register long _num __asm__ ("eax") = (num);                           \
     84	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \
     85	                                                                      \
     86	__asm__  volatile (                                                   \
     87		"int $0x80\n"                                                 \
     88		: "=a" (_ret)                                                 \
     89		: "r"(_arg1),                                                 \
     90		  "0"(_num)                                                   \
     91		: "memory", "cc"                                              \
     92	);                                                                    \
     93	_ret;                                                                 \
     94})
     95
     96#define my_syscall2(num, arg1, arg2)                                          \
     97({                                                                            \
     98	long _ret;                                                            \
     99	register long _num __asm__ ("eax") = (num);                           \
    100	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \
    101	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \
    102	                                                                      \
    103	__asm__  volatile (                                                   \
    104		"int $0x80\n"                                                 \
    105		: "=a" (_ret)                                                 \
    106		: "r"(_arg1), "r"(_arg2),                                     \
    107		  "0"(_num)                                                   \
    108		: "memory", "cc"                                              \
    109	);                                                                    \
    110	_ret;                                                                 \
    111})
    112
    113#define my_syscall3(num, arg1, arg2, arg3)                                    \
    114({                                                                            \
    115	long _ret;                                                            \
    116	register long _num __asm__ ("eax") = (num);                           \
    117	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \
    118	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \
    119	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \
    120	                                                                      \
    121	__asm__  volatile (                                                   \
    122		"int $0x80\n"                                                 \
    123		: "=a" (_ret)                                                 \
    124		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \
    125		  "0"(_num)                                                   \
    126		: "memory", "cc"                                              \
    127	);                                                                    \
    128	_ret;                                                                 \
    129})
    130
    131#define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
    132({                                                                            \
    133	long _ret;                                                            \
    134	register long _num __asm__ ("eax") = (num);                           \
    135	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \
    136	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \
    137	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \
    138	register long _arg4 __asm__ ("esi") = (long)(arg4);                   \
    139	                                                                      \
    140	__asm__  volatile (                                                   \
    141		"int $0x80\n"                                                 \
    142		: "=a" (_ret)                                                 \
    143		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \
    144		  "0"(_num)                                                   \
    145		: "memory", "cc"                                              \
    146	);                                                                    \
    147	_ret;                                                                 \
    148})
    149
    150#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
    151({                                                                            \
    152	long _ret;                                                            \
    153	register long _num __asm__ ("eax") = (num);                           \
    154	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \
    155	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \
    156	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \
    157	register long _arg4 __asm__ ("esi") = (long)(arg4);                   \
    158	register long _arg5 __asm__ ("edi") = (long)(arg5);                   \
    159	                                                                      \
    160	__asm__  volatile (                                                   \
    161		"int $0x80\n"                                                 \
    162		: "=a" (_ret)                                                 \
    163		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
    164		  "0"(_num)                                                   \
    165		: "memory", "cc"                                              \
    166	);                                                                    \
    167	_ret;                                                                 \
    168})
    169
    170#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)	\
    171({								\
    172	long _eax  = (long)(num);				\
    173	long _arg6 = (long)(arg6); /* Always in memory */	\
    174	__asm__ volatile (					\
    175		"pushl	%[_arg6]\n\t"				\
    176		"pushl	%%ebp\n\t"				\
    177		"movl	4(%%esp),%%ebp\n\t"			\
    178		"int	$0x80\n\t"				\
    179		"popl	%%ebp\n\t"				\
    180		"addl	$4,%%esp\n\t"				\
    181		: "+a"(_eax)		/* %eax */		\
    182		: "b"(arg1),		/* %ebx */		\
    183		  "c"(arg2),		/* %ecx */		\
    184		  "d"(arg3),		/* %edx */		\
    185		  "S"(arg4),		/* %esi */		\
    186		  "D"(arg5),		/* %edi */		\
    187		  [_arg6]"m"(_arg6)	/* memory */		\
    188		: "memory", "cc"				\
    189	);							\
    190	_eax;							\
    191})
    192
    193/* startup code */
    194/*
    195 * i386 System V ABI mandates:
    196 * 1) last pushed argument must be 16-byte aligned.
    197 * 2) The deepest stack frame should be set to zero
    198 *
    199 */
    200__asm__ (".section .text\n"
    201    ".weak _start\n"
    202    "_start:\n"
    203    "pop %eax\n"                // argc   (first arg, %eax)
    204    "mov %esp, %ebx\n"          // argv[] (second arg, %ebx)
    205    "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
    206    "xor %ebp, %ebp\n"          // zero the stack frame
    207    "and $-16, %esp\n"          // x86 ABI : esp must be 16-byte aligned before
    208    "sub $4, %esp\n"            // the call instruction (args are aligned)
    209    "push %ecx\n"               // push all registers on the stack so that we
    210    "push %ebx\n"               // support both regparm and plain stack modes
    211    "push %eax\n"
    212    "call main\n"               // main() returns the status code in %eax
    213    "mov %eax, %ebx\n"          // retrieve exit code (32-bit int)
    214    "movl $1, %eax\n"           // NR_exit == 1
    215    "int $0x80\n"               // exit now
    216    "hlt\n"                     // ensure it does not
    217    "");
    218
    219#endif // _NOLIBC_ARCH_I386_H