/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) */ #ifndef __UTILS_H__ #define __UTILS_H__ #include <stdarg.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/time.h> #include <time.h> #include <netinet/in.h> #include <pthread.h> #include <signal.h> /* True/False definitions */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* Host CPU Types */ #define CPU_x86 0 #define CPU_amd64 1 #define CPU_nojit 2 /* Number of host registers available for JIT */ #if JIT_CPU == CPU_x86 #define JIT_HOST_NREG 8 #elif JIT_CPU == CPU_amd64 #define JIT_HOST_NREG 16 #else #define JIT_HOST_NREG 0 #endif /* Endianness */ #define ARCH_BIG_ENDIAN 0x4321 #define ARCH_LITTLE_ENDIAN 0x1234 #if defined(PPC) || defined(__powerpc__) || defined(__ppc__) #define ARCH_BYTE_ORDER ARCH_BIG_ENDIAN #elif defined(__sparc) || defined(__sparc__) #define ARCH_BYTE_ORDER ARCH_BIG_ENDIAN #elif defined(__alpha) || defined(__alpha__) #define ARCH_BYTE_ORDER ARCH_LITTLE_ENDIAN #elif defined(__i386) || defined(__i386__) || defined(i386) #define ARCH_BYTE_ORDER ARCH_LITTLE_ENDIAN #elif defined(__x86_64__) #define ARCH_BYTE_ORDER ARCH_LITTLE_ENDIAN #elif defined(__ia64__) #define ARCH_BYTE_ORDER ARCH_LITTLE_ENDIAN #endif #ifndef ARCH_BYTE_ORDER #error Please define your architecture in utils.h! #endif /* Host to VM (big-endian) conversion functions */ #if ARCH_BYTE_ORDER == ARCH_BIG_ENDIAN #define htovm16(x) (x) #define htovm32(x) (x) #define htovm64(x) (x) #define vmtoh16(x) (x) #define vmtoh32(x) (x) #define vmtoh64(x) (x) #else #define htovm16(x) (htons(x)) #define htovm32(x) (htonl(x)) #define htovm64(x) (swap64(x)) #define vmtoh16(x) (ntohs(x)) #define vmtoh32(x) (ntohl(x)) #define vmtoh64(x) (swap64(x)) #endif /* Useful attributes for functions */ #define asmlinkage __attribute__((regparm(0))) #define fastcall __attribute__((regparm(3))) #if __GNUC__ > 2 #define forced_inline inline __attribute__((always_inline)) #define no_inline __attribute__ ((noinline)) #else #define forced_inline inline #define no_inline #endif #if __GNUC__ > 2 /* http://kerneltrap.org/node/4705 */ #define likely(x) __builtin_expect(!!(x),1) #define unlikely(x) __builtin_expect((x),0) #else #define likely(x) (x) #define unlikely(x) (x) #endif /* Common types */ typedef unsigned char m_uint8_t; typedef signed char m_int8_t; typedef unsigned short m_uint16_t; typedef signed short m_int16_t; typedef unsigned int m_uint32_t; typedef signed int m_int32_t; typedef unsigned long long m_uint64_t; typedef signed long long m_int64_t; typedef unsigned long m_iptr_t; typedef m_uint64_t m_tmcnt_t; /* Forward declarations */ typedef struct cpu_gen cpu_gen_t; typedef struct vm_instance vm_instance_t; typedef struct vm_platform vm_platform_t; typedef struct mips64_jit_tcb mips64_jit_tcb_t; typedef struct ppc32_jit_tcb ppc32_jit_tcb_t; typedef struct jit_op jit_op_t; /* Translated block function pointer */ typedef void (*insn_tblock_fptr)(void); /* Host executable page */ typedef struct insn_exec_page insn_exec_page_t; struct insn_exec_page { u_char *ptr; insn_exec_page_t *next; }; /* MIPS instruction */ typedef m_uint32_t mips_insn_t; /* PowerPC instruction */ typedef m_uint32_t ppc_insn_t; /* Max and min macro */ #define m_max(a,b) (((a) > (b)) ? (a) : (b)) #define m_min(a,b) (((a) < (b)) ? (a) : (b)) /* A simple macro for adjusting pointers */ #define PTR_ADJUST(type,ptr,size) (type)((char *)(ptr) + (size)) /* Size of a field in a structure */ #define SIZEOF(st,field) (sizeof(((st *)NULL)->field)) /* Compute offset of a field in a structure */ #define OFFSET(st,f) ((long)&((st *)(NULL))->f) /* MMAP */ #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif /* List item */ typedef struct m_list m_list_t; struct m_list { void *data; m_list_t *next; }; /* MTS mapping info */ typedef struct { m_uint64_t vaddr; m_uint64_t paddr; m_uint64_t len; m_uint32_t cached; m_uint32_t tlb_index; m_uint32_t offset; }mts_map_t; /* Invalid VTLB entry */ #define MTS_INV_ENTRY_MASK 0x00000001 /* MTS entry flags */ #define MTS_FLAG_DEV 0x000000001 /* Virtual device used */ #define MTS_FLAG_COW 0x000000002 /* Copy-On-Write */ #define MTS_FLAG_EXEC 0x000000004 /* Exec page */ /* Virtual TLB entry (32-bit MMU) */ typedef struct mts32_entry mts32_entry_t; struct mts32_entry { m_uint32_t gvpa; /* Guest Virtual Page Address */ m_uint32_t gppa; /* Guest Physical Page Address */ m_iptr_t hpa; /* Host Page Address */ m_uint32_t flags; /* Flags */ }__attribute__ ((aligned(16))); /* Virtual TLB entry (64-bit MMU) */ typedef struct mts64_entry mts64_entry_t; struct mts64_entry { m_uint64_t gvpa; /* Guest Virtual Page Address */ m_uint64_t gppa; /* Guest Physical Page Address */ m_iptr_t hpa; /* Host Page Address */ m_uint32_t flags; /* Flags */ }__attribute__ ((aligned(16))); /* Host register allocation */ #define HREG_FLAG_ALLOC_LOCKED 1 #define HREG_FLAG_ALLOC_FORCED 2 struct hreg_map { int hreg,vreg; int flags; struct hreg_map *prev,*next; }; /* Global logfile */ extern FILE *log_file; /* Check status of a bit */ static inline int check_bit(u_int old,u_int new,u_int bit) { int mask = 1 << bit; if ((old & mask) && !(new & mask)) return(1); /* bit unset */ if (!(old & mask) && (new & mask)) return(2); /* bit set */ /* no change */ return(0); } /* Sign-extension */ static forced_inline m_int64_t sign_extend(m_int64_t x,int len) { len = 64 - len; return (x << len) >> len; } /* Sign-extension (32-bit) */ static forced_inline m_int32_t sign_extend_32(m_int32_t x,int len) { len = 32 - len; return (x << len) >> len; } /* Extract bits from a 32-bit values */ static inline int bits(m_uint32_t val,int start,int end) { return((val >> start) & ((1 << (end-start+1)) - 1)); } /* Normalize a size */ static inline u_int normalize_size(u_int val,u_int nb,int shift) { return(((val+nb-1) & ~(nb-1)) >> shift); } /* Convert a 16-bit number between little and big endian */ static forced_inline m_uint16_t swap16(m_uint16_t value) { return((value >> 8) | ((value & 0xFF) << 8)); } /* Convert a 32-bit number between little and big endian */ static forced_inline m_uint32_t swap32(m_uint32_t value) { m_uint32_t result; result = value >> 24; result |= ((value >> 16) & 0xff) << 8; result |= ((value >> 8) & 0xff) << 16; result |= (value & 0xff) << 24; return(result); } /* Convert a 64-bit number between little and big endian */ static forced_inline m_uint64_t swap64(m_uint64_t value) { m_uint64_t result; result = (m_uint64_t)swap32(value & 0xffffffff) << 32; result |= swap32(value >> 32); return(result); } /* Get current time in number of msec since epoch */ static inline m_tmcnt_t m_gettime(void) { struct timeval tvp; gettimeofday(&tvp,NULL); return(((m_tmcnt_t)tvp.tv_sec * 1000) + ((m_tmcnt_t)tvp.tv_usec / 1000)); } /* Get current time in number of usec since epoch */ static inline m_tmcnt_t m_gettime_usec(void) { struct timeval tvp; gettimeofday(&tvp,NULL); return(((m_tmcnt_t)tvp.tv_sec * 1000000) + (m_tmcnt_t)tvp.tv_usec); } #ifdef __CYGWIN__ #define GET_TIMEZONE _timezone #else #define GET_TIMEZONE timezone #endif /* Get current time in number of ms (localtime) */ static inline m_tmcnt_t m_gettime_adj(void) { struct timeval tvp; struct tm tmx; time_t gmt_adjust; time_t ct; gettimeofday(&tvp,NULL); ct = tvp.tv_sec; localtime_r(&ct,&tmx); #if defined(__CYGWIN__) || defined(SUNOS) gmt_adjust = -(tmx.tm_isdst ? GET_TIMEZONE - 3600 : GET_TIMEZONE); #else gmt_adjust = tmx.tm_gmtoff; #endif tvp.tv_sec += gmt_adjust; return(((m_tmcnt_t)tvp.tv_sec * 1000) + ((m_tmcnt_t)tvp.tv_usec / 1000)); } /* Get a byte-swapped 16-bit value on a non-aligned area */ static inline m_uint16_t m_ntoh16(m_uint8_t *ptr) { m_uint16_t val = (ptr[0] << 8) | ptr[1]; return(val); } /* Get a byte-swapped 32-bit value on a non-aligned area */ static inline m_uint32_t m_ntoh32(m_uint8_t *ptr) { m_uint32_t val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; return(val); } /* Set a byte-swapped 16-bit value on a non-aligned area */ static inline void m_hton16(m_uint8_t *ptr,m_uint16_t val) { ptr[0] = val >> 8; ptr[1] = val; } /* Set a byte-swapped 32-bit value on a non-aligned area */ static inline void m_hton32(m_uint8_t *ptr,m_uint32_t val) { ptr[0] = val >> 24; ptr[1] = val >> 16; ptr[2] = val >> 8; ptr[3] = val; } /* Add an element to a list */ m_list_t *m_list_add(m_list_t **head,void *data); /* Dynamic sprintf */ char *dyn_sprintf(const char *fmt,...); /* Split a string */ int m_strsplit(char *str,char delim,char **array,int max_count); /* Tokenize a string */ int m_strtok(char *str,char delim,char **array,int max_count); /* Quote a string */ char *m_strquote(char *buffer,size_t buf_len,char *str); /* Ugly function that dumps a structure in hexa and ascii. */ void mem_dump(FILE *f_output,u_char *pkt,u_int len); /* Logging function */ void m_flog(FILE *fd,char *module,char *fmt,va_list ap); /* Logging function */ void m_log(char *module,char *fmt,...); /* Returns a line from specified file (remove trailing '\n') */ char *m_fgets(char *buffer,int size,FILE *fd); /* Read a file and returns it in a buffer */ ssize_t m_read_file(char *filename,u_char **buffer); /* Allocate aligned memory */ void *m_memalign(size_t boundary,size_t size); /* Block specified signal for calling thread */ int m_signal_block(int sig); /* Unblock specified signal for calling thread */ int m_signal_unblock(int sig); /* Set non-blocking mode on a file descriptor */ int m_fd_set_non_block(int fd); /* Map a memory zone from a file */ u_char *memzone_map_file(int fd,size_t len); /* Map a memory zone from a file, with copy-on-write (COW) */ u_char *memzone_map_cow_file(int fd,size_t len); /* Create a file to serve as a memory zone */ int memzone_create_file(char *filename,size_t len,u_char **ptr); /* Open a file to serve as a COW memory zone */ int memzone_open_cow_file(char *filename,size_t len,u_char **ptr); /* Open a file and map it in memory */ int memzone_open_file(char *filename,u_char **ptr,off_t *fsize); /* Compute NVRAM checksum */ m_uint16_t nvram_cksum(m_uint16_t *ptr,size_t count); /* Byte-swap a memory block */ void mem_bswap32(void *ptr,size_t len); /* Reverse a byte */ m_uint8_t m_reverse_u8(m_uint8_t val); #endif