Index: projects/clang390-import/contrib/ipfilter/opts.h =================================================================== --- projects/clang390-import/contrib/ipfilter/opts.h (revision 304964) +++ projects/clang390-import/contrib/ipfilter/opts.h (revision 304965) @@ -1,69 +1,73 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #ifndef __OPTS_H__ #define __OPTS_H__ #ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #define OPT_REMOVE 0x000001 #define OPT_DEBUG 0x000002 #define OPT_AUTHSTATS 0x000004 #define OPT_RAW 0x000008 #define OPT_LOG 0x000010 #define OPT_SHOWLIST 0x000020 #define OPT_VERBOSE 0x000040 #define OPT_DONOTHING 0x000080 #define OPT_HITS 0x000100 #define OPT_BRIEF 0x000200 #define OPT_ACCNT 0x000400 #define OPT_FRSTATES 0x000800 #define OPT_SHOWLINENO 0x001000 #define OPT_PRINTFR 0x002000 #define OPT_OUTQUE FR_OUTQUE /* 0x4000 */ #define OPT_INQUE FR_INQUE /* 0x8000 */ #define OPT_ZERORULEST 0x010000 #define OPT_SAVEOUT 0x020000 #define OPT_IPSTATES 0x040000 #define OPT_INACTIVE 0x080000 #define OPT_NAT 0x100000 #define OPT_GROUPS 0x200000 #define OPT_STATETOP 0x400000 #define OPT_FLUSH 0x800000 #define OPT_CLEAR 0x1000000 #define OPT_HEX 0x2000000 #define OPT_ASCII 0x4000000 #define OPT_NORESOLVE 0x8000000 #define OPT_DONTOPEN 0x10000000 #define OPT_PURGE 0x20000000 #define OPT_STAT OPT_FRSTATES #define OPT_LIST OPT_SHOWLIST #ifndef __P # ifdef __STDC__ # define __P(x) x # else # define __P(x) () # endif #endif #if defined(sun) && !SOLARIS # define STRERROR(x) sys_errlist[x] extern char *sys_errlist[]; #else # define STRERROR(x) strerror(x) #endif extern int opts; #endif /* __OPTS_H__ */ Index: projects/clang390-import/contrib/ipfilter =================================================================== --- projects/clang390-import/contrib/ipfilter (revision 304964) +++ projects/clang390-import/contrib/ipfilter (revision 304965) Property changes on: projects/clang390-import/contrib/ipfilter ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib/ipfilter:r303250-304964 Index: projects/clang390-import/sys/contrib/ipfilter/netinet/ip_compat.h =================================================================== --- projects/clang390-import/sys/contrib/ipfilter/netinet/ip_compat.h (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter/netinet/ip_compat.h (revision 304965) @@ -1,1495 +1,1497 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 * $FreeBSD$ * Id: ip_compat.h,v 2.142.2.57 2007/10/10 09:51:42 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ #define __IP_COMPAT_H__ #ifndef __P # ifdef __STDC__ # define __P(x) x # else # define __P(x) () # endif #endif #ifndef __STDC__ # undef const # define const #endif #if defined(_KERNEL) || defined(KERNEL) || defined(__KERNEL__) # undef KERNEL # undef _KERNEL # undef __KERNEL__ # define KERNEL # define _KERNEL # define __KERNEL__ #endif -#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) -# define SOLARIS 1 -#else -# define SOLARIS 0 +#ifndef SOLARIS +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #if defined(__SVR4) || defined(__svr4__) || defined(__sgi) # define index strchr # if !defined(_KERNEL) # define bzero(a,b) memset(a,0,b) # define bcmp memcmp # define bcopy(a,b,c) memmove(b,a,c) # endif #endif #ifndef LIFNAMSIZ # ifdef IF_NAMESIZE # define LIFNAMSIZ IF_NAMESIZE # else # ifdef IFNAMSIZ # define LIFNAMSIZ IFNAMSIZ # else # define LIFNAMSIZ 16 # endif # endif #endif #if defined(__sgi) || defined(bsdi) || defined(__hpux) || defined(hpux) struct ether_addr { u_char ether_addr_octet[6]; }; #endif # ifdef __STDC__ # define IPL_EXTERN(ep) ipl##ep # else # define IPL_EXTERN(ep) ipl/**/ep # endif /* * This is a workaround for troubles on FreeBSD and OpenBSD. */ # ifndef _KERNEL # define ADD_KERNEL # define _KERNEL # define KERNEL # endif # include # ifdef ADD_KERNEL # undef _KERNEL # undef KERNEL # endif #define NETBSD_GE_REV(x) (defined(__NetBSD_Version__) && \ (__NetBSD_Version__ >= (x))) #define NETBSD_GT_REV(x) (defined(__NetBSD_Version__) && \ (__NetBSD_Version__ > (x))) #define NETBSD_LT_REV(x) (defined(__NetBSD_Version__) && \ (__NetBSD_Version__ < (x))) #define FREEBSD_GE_REV(x) (defined(__FreeBSD_version) && \ (__FreeBSD_version >= (x))) #define FREEBSD_GT_REV(x) (defined(__FreeBSD_version) && \ (__FreeBSD_version > (x))) #define FREEBSD_LT_REV(x) (defined(__FreeBSD_version) && \ (__FreeBSD_version < (x))) #define BSDOS_GE_REV(x) (defined(_BSDI_VERSION) && \ (_BSDI_VERSION >= (x))) #define BSDOS_GT_REV(x) (defined(_BSDI_VERSION) && \ (_BSDI_VERSION > (x))) #define BSDOS_LT_REV(x) (defined(_BSDI_VERSION) && \ (_BSDI_VERSION < (x))) #define OPENBSD_GE_REV(x) (defined(OpenBSD) && (OpenBSD >= (x))) #define OPENBSD_GT_REV(x) (defined(OpenBSD) && (OpenBSD > (x))) #define OPENBSD_LT_REV(x) (defined(OpenBSD) && (OpenBSD < (x))) #define BSD_GE_YEAR(x) (defined(BSD) && (BSD >= (x))) #define BSD_GT_YEAR(x) (defined(BSD) && (BSD > (x))) #define BSD_LT_YEAR(x) (defined(BSD) && (BSD < (x))) /* ----------------------------------------------------------------------- */ /* F R E E B S D */ /* ----------------------------------------------------------------------- */ # define HAS_SYS_MD5_H 1 # if defined(_KERNEL) # include "opt_bpf.h" # include "opt_inet6.h" # if defined(INET6) && !defined(USE_INET6) # define USE_INET6 # endif # else # if !defined(USE_INET6) && !defined(NOINET6) # define USE_INET6 # endif # endif # if defined(_KERNEL) # include # define p_cred td_ucred # define p_uid td_ucred->cr_ruid /* * When #define'd, the 5.2.1 kernel panics when used with the ftp proxy. * There may be other, safe, kernels but this is not extensively tested yet. */ # define HAVE_M_PULLDOWN # if !defined(IPFILTER_LKM) && (__FreeBSD_version >= 300000) # include "opt_ipfilter.h" # endif # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define NETBSD_PF # else # include # endif /* _KERNEL */ # include # include # include # include # define KRWLOCK_FILL_SZ 56 # define KMUTEX_FILL_SZ 56 # include # define KMUTEX_T struct mtx # define KRWLOCK_T struct rwlock #ifdef _KERNEL # define READ_ENTER(x) rw_rlock(&(x)->ipf_lk) # define WRITE_ENTER(x) rw_wlock(&(x)->ipf_lk) # define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk) # define RWLOCK_INIT(x,y) rw_init(&(x)->ipf_lk, (y)) # define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk) # define RWLOCK_EXIT(x) do { \ if (rw_wowned(&(x)->ipf_lk)) \ rw_wunlock(&(x)->ipf_lk); \ else \ rw_runlock(&(x)->ipf_lk); \ } while (0) # include # define GETKTIME(x) microtime((struct timeval *)x) # include # include # include # define USE_MUTEXES # define MUTEX_ENTER(x) mtx_lock(&(x)->ipf_lk) # define MUTEX_EXIT(x) mtx_unlock(&(x)->ipf_lk) # define MUTEX_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ MTX_DEF) # define MUTEX_DESTROY(x) mtx_destroy(&(x)->ipf_lk) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) /* * Whilst the sx(9) locks on FreeBSD have the right semantics and interface * for what we want to use them for, despite testing showing they work - * with a WITNESS kernel, it generates LOR messages. */ # include # define ATOMIC_INC(x) { mtx_lock(&softc->ipf_rw.ipf_lk); (x)++; \ mtx_unlock(&softc->ipf_rw.ipf_lk); } # define ATOMIC_DEC(x) { mtx_lock(&softc->ipf_rw.ipf_lk); (x)--; \ mtx_unlock(&softc->ipf_rw.ipf_lk); } # define ATOMIC_INCL(x) atomic_add_long(&(x), 1) # define ATOMIC_INC64(x) ATOMIC_INC(x) # define ATOMIC_INC32(x) atomic_add_32((u_int *)&(x), 1) # define ATOMIC_DECL(x) atomic_add_long(&(x), -1) # define ATOMIC_DEC64(x) ATOMIC_DEC(x) # define ATOMIC_DEC32(x) atomic_add_32((u_int *)&(x), -1) # define SPL_X(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # define SPL_SCHED(x) ; # define GET_MINOR dev2unit # define MSGDSIZE(m) mbufchainlen(m) # define M_LEN(m) (m)->m_len # define M_ADJ(m,x) m_adj(m, x) # define M_COPY(x) m_copy((x), 0, M_COPYALL) # define M_DUP(m) m_dup(m, M_NOWAIT) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; #else /* !_KERNEL */ #ifndef _NET_IF_VAR_H_ /* * Userland emulation of struct ifnet. */ struct route; struct mbuf; struct ifnet { char if_xname[IFNAMSIZ]; TAILQ_HEAD(, ifaddr) if_addrlist; int (*if_output)(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); }; #endif /* _NET_IF_VAR_H_ */ #endif /* _KERNEL */ # define IFNAME(x) ((struct ifnet *)x)->if_xname # define COPYIFNAME(v, x, b) \ (void) strncpy(b, \ ((struct ifnet *)x)->if_xname, \ LIFNAMSIZ) typedef u_long ioctlcmd_t; typedef struct uio uio_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 /* ----------------------------------------------------------------------- */ /* G E N E R I C */ /* ----------------------------------------------------------------------- */ /* * For BSD kernels, if bpf is in the kernel, enable ipfilter to use bpf in * filter rules. */ #if !defined(IPFILTER_BPF) # if (defined(NBPF) && (NBPF > 0)) || (defined(DEV_BPF) && (DEV_BPF > 0)) || \ (defined(NBPFILTER) && (NBPFILTER > 0)) # define IPFILTER_BPF # endif #endif /* * Userland locking primitives */ #ifndef _KERNEL #if !defined(KMUTEX_FILL_SZ) # define KMUTEX_FILL_SZ 1 #endif #if !defined(KRWLOCK_FILL_SZ) # define KRWLOCK_FILL_SZ 1 #endif #endif typedef struct { char *eMm_owner; char *eMm_heldin; u_int eMm_magic; int eMm_held; int eMm_heldat; } eMmutex_t; typedef struct { char *eMrw_owner; char *eMrw_heldin; u_int eMrw_magic; short eMrw_read; short eMrw_write; int eMrw_heldat; } eMrwlock_t; typedef union { char _fill[KMUTEX_FILL_SZ]; #ifdef KMUTEX_T struct { KMUTEX_T ipf_slk; const char *ipf_lname; } ipf_lkun_s; #endif eMmutex_t ipf_emu; } ipfmutex_t; typedef union { char _fill[KRWLOCK_FILL_SZ]; #ifdef KRWLOCK_T struct { KRWLOCK_T ipf_slk; const char *ipf_lname; int ipf_sr; int ipf_sw; u_int ipf_magic; } ipf_lkun_s; #endif eMrwlock_t ipf_emu; } ipfrwlock_t; #define ipf_lk ipf_lkun_s.ipf_slk #define ipf_lname ipf_lkun_s.ipf_lname #define ipf_isr ipf_lkun_s.ipf_sr #define ipf_isw ipf_lkun_s.ipf_sw #define ipf_magic ipf_lkun_s.ipf_magic #if !defined(__GNUC__) || \ (defined(__FreeBSD_version) && (__FreeBSD_version >= 503000)) # ifndef INLINE # define INLINE # endif #else # define INLINE __inline__ #endif #if defined(__FreeBSD_version) && defined(_KERNEL) CTASSERT(sizeof(ipfrwlock_t) == KRWLOCK_FILL_SZ); CTASSERT(sizeof(ipfmutex_t) == KMUTEX_FILL_SZ); #endif /* * In a non-kernel environment, there are a lot of macros that need to be * filled in to be null-ops or to point to some compatibility function, * somewhere in userland. */ #ifndef _KERNEL typedef struct mb_s { struct mb_s *mb_next; char *mb_data; void *mb_ifp; int mb_len; int mb_flags; u_long mb_buf[2048]; } mb_t; # undef m_next # define m_next mb_next # undef m_len # define m_len mb_len # undef m_flags # define m_flags mb_flags # undef m_data # define m_data mb_data # undef M_MCAST # define M_MCAST 0x01 # undef M_BCAST # define M_BCAST 0x02 # undef M_MBCAST # define M_MBCAST 0x04 # define MSGDSIZE(m) msgdsize(m) # define M_LEN(m) (m)->mb_len # define M_ADJ(m,x) (m)->mb_len += x # define M_COPY(m) dupmbt(m) # define M_DUP(m) dupmbt(m) # define GETKTIME(x) gettimeofday((struct timeval *)(x), NULL) # define MTOD(m, t) ((t)(m)->mb_data) # define FREE_MB_T(m) freembt(m) # define ALLOC_MB_T(m,l) (m) = allocmbt(l) # define PREP_MB_T(f, m) do { \ (m)->mb_next = *(f)->fin_mp; \ *(fin)->fin_mp = (m); \ (f)->fin_m = (m); \ } while (0) # define SLEEP(x,y) 1; # define WAKEUP(x,y) ; # define POLLWAKEUP(y) ; # define IPF_PANIC(x,y) ; # define PANIC(x,y) ; # define SPL_SCHED(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; # define SPL_X(x) ; # define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) # define KMALLOCS(a,b,c) (a) = (b)malloc(c) # define KFREE(x) free(x) # define KFREES(x,s) free(x) # define GETIFP(x, v) get_unit(x,v) # define GETIFMTU_4(x) 2048 # define GETIFMTU_6(x) 2048 # define COPYIN(a,b,c) bcopywrap((a), (b), (c)) # define COPYOUT(a,b,c) bcopywrap((a), (b), (c)) # define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \ (b), (l)) # define COPYBACK(m, o, l, b) bcopy((b), \ MTOD((mb_t *)m, char *) + (o), \ (l)) # define UIOMOVE(a,b,c,d) ipfuiomove((caddr_t)a,b,c,d) extern void m_copydata __P((mb_t *, int, int, caddr_t)); extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); extern int bcopywrap __P((void *, void *, size_t)); extern mb_t *allocmbt __P((size_t)); extern mb_t *dupmbt __P((mb_t *)); extern void freembt __P((mb_t *)); # define MUTEX_DESTROY(x) eMmutex_destroy(&(x)->ipf_emu, \ __FILE__, __LINE__) # define MUTEX_ENTER(x) eMmutex_enter(&(x)->ipf_emu, \ __FILE__, __LINE__) # define MUTEX_EXIT(x) eMmutex_exit(&(x)->ipf_emu, \ __FILE__, __LINE__) # define MUTEX_INIT(x,y) eMmutex_init(&(x)->ipf_emu, y, \ __FILE__, __LINE__) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) # define MUTEX_DOWNGRADE(x) eMrwlock_downgrade(&(x)->ipf_emu, \ __FILE__, __LINE__) # define READ_ENTER(x) eMrwlock_read_enter(&(x)->ipf_emu, \ __FILE__, __LINE__) # define RWLOCK_INIT(x, y) eMrwlock_init(&(x)->ipf_emu, y) # define RWLOCK_EXIT(x) eMrwlock_exit(&(x)->ipf_emu) # define RW_DESTROY(x) eMrwlock_destroy(&(x)->ipf_emu) # define WRITE_ENTER(x) eMrwlock_write_enter(&(x)->ipf_emu, \ __FILE__, \ __LINE__) # define USE_MUTEXES 1 extern void eMmutex_destroy __P((eMmutex_t *, char *, int)); extern void eMmutex_enter __P((eMmutex_t *, char *, int)); extern void eMmutex_exit __P((eMmutex_t *, char *, int)); extern void eMmutex_init __P((eMmutex_t *, char *, char *, int)); extern void eMrwlock_destroy __P((eMrwlock_t *)); extern void eMrwlock_exit __P((eMrwlock_t *)); extern void eMrwlock_init __P((eMrwlock_t *, char *)); extern void eMrwlock_read_enter __P((eMrwlock_t *, char *, int)); extern void eMrwlock_write_enter __P((eMrwlock_t *, char *, int)); extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int)); #endif extern mb_t *allocmbt(size_t); #define MAX_IPV4HDR ((0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8) #ifndef IP_OFFMASK # define IP_OFFMASK 0x1fff #endif /* * On BSD's use quad_t as a guarantee for getting at least a 64bit sized * object. */ #if !defined(__amd64__) && BSD_GT_YEAR(199306) # define USE_QUAD_T # define U_QUAD_T unsigned long long # define QUAD_T long long #else /* BSD > 199306 */ # if !defined(U_QUAD_T) # define U_QUAD_T u_long # define QUAD_T long # endif #endif /* BSD > 199306 */ #ifdef USE_INET6 # if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ defined(__osf__) || defined(linux) # include # include # if defined(_KERNEL) && !defined(__osf__) # include # endif typedef struct ip6_hdr ip6_t; # endif #endif #ifndef MAX # define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif #if defined(_KERNEL) # if defined(MENTAT) && !defined(INSTANCES) # define COPYDATA mb_copydata # define COPYBACK mb_copyback # else # define COPYDATA m_copydata # define COPYBACK m_copyback # endif # if (defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105180000)) || \ defined(__FreeBSD__) || (defined(OpenBSD) && (OpenBSD < 200206)) || \ defined(_BSDI_VERSION) # include # endif # if !defined(__FreeBSD__) || FREEBSD_GE_REV(300000) # if NETBSD_GE_REV(105180000) || OPENBSD_GE_REV(200111) # include # else # include extern vm_map_t kmem_map; # endif # include # else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD_version >= 300000) */ # include # endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD_version >= 300000) */ # ifdef IPFILTER_M_IPFILTER # include MALLOC_DECLARE(M_IPFILTER); # define _M_IPF M_IPFILTER # else /* IPFILTER_M_IPFILTER */ # ifdef M_PFIL # define _M_IPF M_PFIL # else # ifdef M_IPFILTER # define _M_IPF M_IPFILTER # else # define _M_IPF M_TEMP # endif /* M_IPFILTER */ # endif /* M_PFIL */ # endif /* IPFILTER_M_IPFILTER */ # if !defined(KMALLOC) # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), _M_IPF, M_NOWAIT) # endif # if !defined(KMALLOCS) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT) # endif # if !defined(KFREE) # define KFREE(x) FREE((x), _M_IPF) # endif # if !defined(KFREES) # define KFREES(x,s) FREE((x), _M_IPF) # endif # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,d) # define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) # define WAKEUP(id,x) wakeup(id+x) # if !defined(POLLWAKEUP) # define POLLWAKEUP(x) selwakeup(softc->ipf_selwait+x) # endif # define GETIFP(n, v) ifunit(n) # define GETIFMTU_4(x) ((struct ifnet *)x)->if_mtu # define GETIFMTU_6(x) ((struct ifnet *)x)->if_mtu # if !defined(USE_MUTEXES) && !defined(SPL_NET) # define SPL_IMP(x) x = splimp() # define SPL_NET(x) x = splnet() # if !defined(SPL_SCHED) # define SPL_SCHED(x) x = splsched() # endif # define SPL_X(x) (void) splx(x) # endif /* !USE_MUTEXES */ # ifndef FREE_MB_T # define FREE_MB_T(m) m_freem(m) # endif # ifndef ALLOC_MB_T # ifdef MGETHDR # define ALLOC_MB_T(m,l) do { \ MGETHDR((m), M_NOWAIT, MT_HEADER); \ if ((m) != NULL) { \ (m)->m_len = (l); \ (m)->m_pkthdr.len = (l); \ } \ } while (0) # else # define ALLOC_MB_T(m,l) do { \ MGET((m), M_NOWAIT, MT_HEADER); \ if ((m) != NULL) { \ (m)->m_len = (l); \ (m)->m_pkthdr.len = (l); \ } \ } while (0) # endif # endif # ifndef PREP_MB_T # define PREP_MB_T(f, m) do { \ mb_t *_o = *(f)->fin_mp; \ (m)->m_next = _o; \ *(fin)->fin_mp = (m); \ if (_o->m_flags & M_PKTHDR) { \ (m)->m_pkthdr.len += \ _o->m_pkthdr.len; \ (m)->m_pkthdr.rcvif = \ _o->m_pkthdr.rcvif; \ } \ } while (0) # endif # ifndef M_DUP # ifdef M_COPYALL # define M_DUP(m) m_dup(m, 0, M_COPYALL, 0) # else # define M_DUP(m) m_dup(m) # endif # endif # ifndef MTOD # define MTOD(m,t) mtod(m,t) # endif # ifndef COPYIN # define COPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define COPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # endif # ifndef KMALLOC # define KMALLOC(a,b) (a) = (b)new_kmem_alloc(sizeof(*(a)), \ KMEM_NOSLEEP) # define KMALLOCS(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) # endif # ifndef GET_MINOR # define GET_MINOR(x) dev2unit(x) # endif # define PANIC(x,y) if (x) panic y #endif /* _KERNEL */ #if !defined(IFNAME) && !defined(_KERNEL) # define IFNAME(x) get_ifname((struct ifnet *)x) #endif #ifndef COPYIFNAME # define NEED_FRGETIFNAME extern char *ipf_getifname __P((struct ifnet *, char *)); # define COPYIFNAME(v, x, b) \ ipf_getifname((struct ifnet *)x, b) #endif #ifndef ASSERT # ifdef _KERNEL # define ASSERT(x) # else # define ASSERT(x) do { if (!(x)) abort(); } while (0) # endif #endif #ifndef BCOPYIN # define BCOPYIN(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) #endif /* * Because the ctype(3) posix definition, if used "safely" in code everywhere, * would mean all normal code that walks through strings needed casts. Yuck. */ #define ISALNUM(x) isalnum((u_char)(x)) #define ISALPHA(x) isalpha((u_char)(x)) #define ISDIGIT(x) isdigit((u_char)(x)) #define ISSPACE(x) isspace((u_char)(x)) #define ISUPPER(x) isupper((u_char)(x)) #define ISXDIGIT(x) isxdigit((u_char)(x)) #define ISLOWER(x) islower((u_char)(x)) #define TOUPPER(x) toupper((u_char)(x)) #define TOLOWER(x) tolower((u_char)(x)) /* * If mutexes aren't being used, turn all the mutex functions into null-ops. */ #if !defined(USE_MUTEXES) # define USE_SPL 1 # undef RW_DESTROY # undef MUTEX_INIT # undef MUTEX_NUKE # undef MUTEX_DESTROY # define MUTEX_ENTER(x) ; # define READ_ENTER(x) ; # define WRITE_ENTER(x) ; # define MUTEX_DOWNGRADE(x) ; # define RWLOCK_INIT(x, y) ; # define RWLOCK_EXIT(x) ; # define RW_DESTROY(x) ; # define MUTEX_EXIT(x) ; # define MUTEX_INIT(x,y) ; # define MUTEX_DESTROY(x) ; # define MUTEX_NUKE(x) ; #endif /* !USE_MUTEXES */ #ifndef ATOMIC_INC # define ATOMIC_INC(x) (x)++ # define ATOMIC_DEC(x) (x)-- #endif #if defined(USE_SPL) && defined(_KERNEL) # define SPL_INT(x) int x #else # define SPL_INT(x) #endif /* * If there are no atomic operations for bit sizes defined, define them to all * use a generic one that works for all sizes. */ #ifndef ATOMIC_INCL # define ATOMIC_INCL ATOMIC_INC # define ATOMIC_INC64 ATOMIC_INC # define ATOMIC_INC32 ATOMIC_INC # define ATOMIC_DECL ATOMIC_DEC # define ATOMIC_DEC64 ATOMIC_DEC # define ATOMIC_DEC32 ATOMIC_DEC #endif #ifndef HDR_T_PRIVATE typedef struct tcphdr tcphdr_t; typedef struct udphdr udphdr_t; #endif typedef struct icmp icmphdr_t; typedef struct ip ip_t; typedef struct ether_header ether_header_t; typedef struct tcpiphdr tcpiphdr_t; #ifndef FR_GROUPLEN # define FR_GROUPLEN 16 #endif #ifndef offsetof # define offsetof(t,m) (size_t)((&((t *)0L)->m)) #endif #ifndef stsizeof # define stsizeof(t,m) sizeof(((t *)0L)->m) #endif /* * This set of macros has been brought about because on Tru64 it is not * possible to easily assign or examine values in a structure that are * bit fields. */ #ifndef IP_V # define IP_V(x) (x)->ip_v #endif #ifndef IP_V_A # define IP_V_A(x,y) (x)->ip_v = (y) #endif #ifndef IP_HL # define IP_HL(x) (x)->ip_hl #endif #ifndef IP_HL_A # define IP_HL_A(x,y) (x)->ip_hl = ((y) & 0xf) #endif #ifndef TCP_X2 # define TCP_X2(x) (x)->th_x2 #endif #ifndef TCP_X2_A # define TCP_X2_A(x,y) (x)->th_x2 = (y) #endif #ifndef TCP_OFF # define TCP_OFF(x) (x)->th_off #endif #ifndef TCP_OFF_A # define TCP_OFF_A(x,y) (x)->th_off = (y) #endif #define IPMINLEN(i, h) ((i)->ip_len >= (IP_HL(i) * 4 + sizeof(struct h))) /* * XXX - This is one of those *awful* hacks which nobody likes */ #ifdef ultrix #define A_A #else #define A_A & #endif #define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|\ TH_ECN|TH_CWR) #if BSD_GE_YEAR(199306) && !defined(m_act) # define m_act m_nextpkt #endif /* * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108. * * Basic Option * * 00000001 - (Reserved 4) * 00111101 - Top Secret * 01011010 - Secret * 10010110 - Confidential * 01100110 - (Reserved 3) * 11001100 - (Reserved 2) * 10101011 - Unclassified * 11110001 - (Reserved 1) */ #define IPSO_CLASS_RES4 0x01 #define IPSO_CLASS_TOPS 0x3d #define IPSO_CLASS_SECR 0x5a #define IPSO_CLASS_CONF 0x96 #define IPSO_CLASS_RES3 0x66 #define IPSO_CLASS_RES2 0xcc #define IPSO_CLASS_UNCL 0xab #define IPSO_CLASS_RES1 0xf1 #define IPSO_AUTH_GENSER 0x80 #define IPSO_AUTH_ESI 0x40 #define IPSO_AUTH_SCI 0x20 #define IPSO_AUTH_NSA 0x10 #define IPSO_AUTH_DOE 0x08 #define IPSO_AUTH_UN 0x06 #define IPSO_AUTH_FTE 0x01 /* * IP option #defines */ #undef IPOPT_RR #define IPOPT_RR 7 #undef IPOPT_ZSU #define IPOPT_ZSU 10 /* ZSU */ #undef IPOPT_MTUP #define IPOPT_MTUP 11 /* MTUP */ #undef IPOPT_MTUR #define IPOPT_MTUR 12 /* MTUR */ #undef IPOPT_ENCODE #define IPOPT_ENCODE 15 /* ENCODE */ #undef IPOPT_TS #define IPOPT_TS 68 #undef IPOPT_TR #define IPOPT_TR 82 /* TR */ #undef IPOPT_SECURITY #define IPOPT_SECURITY 130 #undef IPOPT_LSRR #define IPOPT_LSRR 131 #undef IPOPT_E_SEC #define IPOPT_E_SEC 133 /* E-SEC */ #undef IPOPT_CIPSO #define IPOPT_CIPSO 134 /* CIPSO */ #undef IPOPT_SATID #define IPOPT_SATID 136 #ifndef IPOPT_SID # define IPOPT_SID IPOPT_SATID #endif #undef IPOPT_SSRR #define IPOPT_SSRR 137 #undef IPOPT_ADDEXT #define IPOPT_ADDEXT 147 /* ADDEXT */ #undef IPOPT_VISA #define IPOPT_VISA 142 /* VISA */ #undef IPOPT_IMITD #define IPOPT_IMITD 144 /* IMITD */ #undef IPOPT_EIP #define IPOPT_EIP 145 /* EIP */ #undef IPOPT_RTRALRT #define IPOPT_RTRALRT 148 /* RTRALRT */ #undef IPOPT_SDB #define IPOPT_SDB 149 #undef IPOPT_NSAPA #define IPOPT_NSAPA 150 #undef IPOPT_DPS #define IPOPT_DPS 151 #undef IPOPT_UMP #define IPOPT_UMP 152 #undef IPOPT_FINN #define IPOPT_FINN 205 /* FINN */ #undef IPOPT_AH #define IPOPT_AH 256+IPPROTO_AH #ifndef TCPOPT_EOL # define TCPOPT_EOL 0 #endif #ifndef TCPOPT_NOP # define TCPOPT_NOP 1 #endif #ifndef TCPOPT_MAXSEG # define TCPOPT_MAXSEG 2 #endif #ifndef TCPOLEN_MAXSEG # define TCPOLEN_MAXSEG 4 #endif #ifndef TCPOPT_WINDOW # define TCPOPT_WINDOW 3 #endif #ifndef TCPOLEN_WINDOW # define TCPOLEN_WINDOW 3 #endif #ifndef TCPOPT_SACK_PERMITTED # define TCPOPT_SACK_PERMITTED 4 #endif #ifndef TCPOLEN_SACK_PERMITTED # define TCPOLEN_SACK_PERMITTED 2 #endif #ifndef TCPOPT_SACK # define TCPOPT_SACK 5 #endif #ifndef TCPOPT_TIMESTAMP # define TCPOPT_TIMESTAMP 8 #endif #ifndef ICMP_MINLEN # define ICMP_MINLEN 8 #endif #ifndef ICMP_ECHOREPLY # define ICMP_ECHOREPLY 0 #endif #ifndef ICMP_UNREACH # define ICMP_UNREACH 3 #endif #ifndef ICMP_UNREACH_NET # define ICMP_UNREACH_NET 0 #endif #ifndef ICMP_UNREACH_HOST # define ICMP_UNREACH_HOST 1 #endif #ifndef ICMP_UNREACH_PROTOCOL # define ICMP_UNREACH_PROTOCOL 2 #endif #ifndef ICMP_UNREACH_PORT # define ICMP_UNREACH_PORT 3 #endif #ifndef ICMP_UNREACH_NEEDFRAG # define ICMP_UNREACH_NEEDFRAG 4 #endif #ifndef ICMP_UNREACH_SRCFAIL # define ICMP_UNREACH_SRCFAIL 5 #endif #ifndef ICMP_UNREACH_NET_UNKNOWN # define ICMP_UNREACH_NET_UNKNOWN 6 #endif #ifndef ICMP_UNREACH_HOST_UNKNOWN # define ICMP_UNREACH_HOST_UNKNOWN 7 #endif #ifndef ICMP_UNREACH_ISOLATED # define ICMP_UNREACH_ISOLATED 8 #endif #ifndef ICMP_UNREACH_NET_PROHIB # define ICMP_UNREACH_NET_PROHIB 9 #endif #ifndef ICMP_UNREACH_HOST_PROHIB # define ICMP_UNREACH_HOST_PROHIB 10 #endif #ifndef ICMP_UNREACH_TOSNET # define ICMP_UNREACH_TOSNET 11 #endif #ifndef ICMP_UNREACH_TOSHOST # define ICMP_UNREACH_TOSHOST 12 #endif #ifndef ICMP_UNREACH_ADMIN_PROHIBIT # define ICMP_UNREACH_ADMIN_PROHIBIT 13 #endif #ifndef ICMP_UNREACH_FILTER # define ICMP_UNREACH_FILTER 13 #endif #ifndef ICMP_UNREACH_HOST_PRECEDENCE # define ICMP_UNREACH_HOST_PRECEDENCE 14 #endif #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF # define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif #ifndef ICMP_SOURCEQUENCH # define ICMP_SOURCEQUENCH 4 #endif #ifndef ICMP_REDIRECT_NET # define ICMP_REDIRECT_NET 0 #endif #ifndef ICMP_REDIRECT_HOST # define ICMP_REDIRECT_HOST 1 #endif #ifndef ICMP_REDIRECT_TOSNET # define ICMP_REDIRECT_TOSNET 2 #endif #ifndef ICMP_REDIRECT_TOSHOST # define ICMP_REDIRECT_TOSHOST 3 #endif #ifndef ICMP_ALTHOSTADDR # define ICMP_ALTHOSTADDR 6 #endif #ifndef ICMP_TIMXCEED # define ICMP_TIMXCEED 11 #endif #ifndef ICMP_TIMXCEED_INTRANS # define ICMP_TIMXCEED_INTRANS 0 #endif #ifndef ICMP_TIMXCEED_REASS # define ICMP_TIMXCEED_REASS 1 #endif #ifndef ICMP_PARAMPROB # define ICMP_PARAMPROB 12 #endif #ifndef ICMP_PARAMPROB_ERRATPTR # define ICMP_PARAMPROB_ERRATPTR 0 #endif #ifndef ICMP_PARAMPROB_OPTABSENT # define ICMP_PARAMPROB_OPTABSENT 1 #endif #ifndef ICMP_PARAMPROB_LENGTH # define ICMP_PARAMPROB_LENGTH 2 #endif #ifndef ICMP_TSTAMP # define ICMP_TSTAMP 13 #endif #ifndef ICMP_TSTAMPREPLY # define ICMP_TSTAMPREPLY 14 #endif #ifndef ICMP_IREQ # define ICMP_IREQ 15 #endif #ifndef ICMP_IREQREPLY # define ICMP_IREQREPLY 16 #endif #ifndef ICMP_MASKREQ # define ICMP_MASKREQ 17 #endif #ifndef ICMP_MASKREPLY # define ICMP_MASKREPLY 18 #endif #ifndef ICMP_TRACEROUTE # define ICMP_TRACEROUTE 30 #endif #ifndef ICMP_DATACONVERR # define ICMP_DATACONVERR 31 #endif #ifndef ICMP_MOBILE_REDIRECT # define ICMP_MOBILE_REDIRECT 32 #endif #ifndef ICMP_IPV6_WHEREAREYOU # define ICMP_IPV6_WHEREAREYOU 33 #endif #ifndef ICMP_IPV6_IAMHERE # define ICMP_IPV6_IAMHERE 34 #endif #ifndef ICMP_MOBILE_REGREQUEST # define ICMP_MOBILE_REGREQUEST 35 #endif #ifndef ICMP_MOBILE_REGREPLY # define ICMP_MOBILE_REGREPLY 36 #endif #ifndef ICMP_SKIP # define ICMP_SKIP 39 #endif #ifndef ICMP_PHOTURIS # define ICMP_PHOTURIS 40 #endif #ifndef ICMP_PHOTURIS_UNKNOWN_INDEX # define ICMP_PHOTURIS_UNKNOWN_INDEX 1 #endif #ifndef ICMP_PHOTURIS_AUTH_FAILED # define ICMP_PHOTURIS_AUTH_FAILED 2 #endif #ifndef ICMP_PHOTURIS_DECRYPT_FAILED # define ICMP_PHOTURIS_DECRYPT_FAILED 3 #endif #ifndef IPVERSION # define IPVERSION 4 #endif #ifndef IPOPT_MINOFF # define IPOPT_MINOFF 4 #endif #ifndef IPOPT_COPIED # define IPOPT_COPIED(x) ((x)&0x80) #endif #ifndef IPOPT_EOL # define IPOPT_EOL 0 #endif #ifndef IPOPT_NOP # define IPOPT_NOP 1 #endif #ifndef IP_MF # define IP_MF ((u_short)0x2000) #endif #ifndef ETHERTYPE_IP # define ETHERTYPE_IP ((u_short)0x0800) #endif #ifndef TH_FIN # define TH_FIN 0x01 #endif #ifndef TH_SYN # define TH_SYN 0x02 #endif #ifndef TH_RST # define TH_RST 0x04 #endif #ifndef TH_PUSH # define TH_PUSH 0x08 #endif #ifndef TH_ACK # define TH_ACK 0x10 #endif #ifndef TH_URG # define TH_URG 0x20 #endif #undef TH_ACKMASK #define TH_ACKMASK (TH_FIN|TH_SYN|TH_RST|TH_ACK) #ifndef IPOPT_EOL # define IPOPT_EOL 0 #endif #ifndef IPOPT_NOP # define IPOPT_NOP 1 #endif #ifndef IPOPT_RR # define IPOPT_RR 7 #endif #ifndef IPOPT_TS # define IPOPT_TS 68 #endif #ifndef IPOPT_SECURITY # define IPOPT_SECURITY 130 #endif #ifndef IPOPT_LSRR # define IPOPT_LSRR 131 #endif #ifndef IPOPT_SATID # define IPOPT_SATID 136 #endif #ifndef IPOPT_SSRR # define IPOPT_SSRR 137 #endif #ifndef IPOPT_SECUR_UNCLASS # define IPOPT_SECUR_UNCLASS ((u_short)0x0000) #endif #ifndef IPOPT_SECUR_CONFID # define IPOPT_SECUR_CONFID ((u_short)0xf135) #endif #ifndef IPOPT_SECUR_EFTO # define IPOPT_SECUR_EFTO ((u_short)0x789a) #endif #ifndef IPOPT_SECUR_MMMM # define IPOPT_SECUR_MMMM ((u_short)0xbc4d) #endif #ifndef IPOPT_SECUR_RESTR # define IPOPT_SECUR_RESTR ((u_short)0xaf13) #endif #ifndef IPOPT_SECUR_SECRET # define IPOPT_SECUR_SECRET ((u_short)0xd788) #endif #ifndef IPOPT_SECUR_TOPSECRET # define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5) #endif #ifndef IPOPT_OLEN # define IPOPT_OLEN 1 #endif #ifndef IPPROTO_HOPOPTS # define IPPROTO_HOPOPTS 0 #endif #ifndef IPPROTO_IPIP # define IPPROTO_IPIP 4 #endif #ifndef IPPROTO_ENCAP # define IPPROTO_ENCAP 98 #endif #ifndef IPPROTO_IPV6 # define IPPROTO_IPV6 41 #endif #ifndef IPPROTO_ROUTING # define IPPROTO_ROUTING 43 #endif #ifndef IPPROTO_FRAGMENT # define IPPROTO_FRAGMENT 44 #endif #ifndef IPPROTO_GRE # define IPPROTO_GRE 47 /* GRE encaps RFC 1701 */ #endif #ifndef IPPROTO_ESP # define IPPROTO_ESP 50 #endif #ifndef IPPROTO_AH # define IPPROTO_AH 51 #endif #ifndef IPPROTO_ICMPV6 # define IPPROTO_ICMPV6 58 #endif #ifndef IPPROTO_NONE # define IPPROTO_NONE 59 #endif #ifndef IPPROTO_DSTOPTS # define IPPROTO_DSTOPTS 60 #endif #ifndef IPPROTO_MOBILITY # define IPPROTO_MOBILITY 135 #endif #ifndef ICMP_ROUTERADVERT # define ICMP_ROUTERADVERT 9 #endif #ifndef ICMP_ROUTERSOLICIT # define ICMP_ROUTERSOLICIT 10 #endif #ifndef ICMP6_DST_UNREACH # define ICMP6_DST_UNREACH 1 #endif #ifndef ICMP6_PACKET_TOO_BIG # define ICMP6_PACKET_TOO_BIG 2 #endif #ifndef ICMP6_TIME_EXCEEDED # define ICMP6_TIME_EXCEEDED 3 #endif #ifndef ICMP6_PARAM_PROB # define ICMP6_PARAM_PROB 4 #endif #ifndef ICMP6_ECHO_REQUEST # define ICMP6_ECHO_REQUEST 128 #endif #ifndef ICMP6_ECHO_REPLY # define ICMP6_ECHO_REPLY 129 #endif #ifndef ICMP6_MEMBERSHIP_QUERY # define ICMP6_MEMBERSHIP_QUERY 130 #endif #ifndef MLD6_LISTENER_QUERY # define MLD6_LISTENER_QUERY 130 #endif #ifndef ICMP6_MEMBERSHIP_REPORT # define ICMP6_MEMBERSHIP_REPORT 131 #endif #ifndef MLD6_LISTENER_REPORT # define MLD6_LISTENER_REPORT 131 #endif #ifndef ICMP6_MEMBERSHIP_REDUCTION # define ICMP6_MEMBERSHIP_REDUCTION 132 #endif #ifndef MLD6_LISTENER_DONE # define MLD6_LISTENER_DONE 132 #endif #ifndef ND_ROUTER_SOLICIT # define ND_ROUTER_SOLICIT 133 #endif #ifndef ND_ROUTER_ADVERT # define ND_ROUTER_ADVERT 134 #endif #ifndef ND_NEIGHBOR_SOLICIT # define ND_NEIGHBOR_SOLICIT 135 #endif #ifndef ND_NEIGHBOR_ADVERT # define ND_NEIGHBOR_ADVERT 136 #endif #ifndef ND_REDIRECT # define ND_REDIRECT 137 #endif #ifndef ICMP6_ROUTER_RENUMBERING # define ICMP6_ROUTER_RENUMBERING 138 #endif #ifndef ICMP6_WRUREQUEST # define ICMP6_WRUREQUEST 139 #endif #ifndef ICMP6_WRUREPLY # define ICMP6_WRUREPLY 140 #endif #ifndef ICMP6_FQDN_QUERY # define ICMP6_FQDN_QUERY 139 #endif #ifndef ICMP6_FQDN_REPLY # define ICMP6_FQDN_REPLY 140 #endif #ifndef ICMP6_NI_QUERY # define ICMP6_NI_QUERY 139 #endif #ifndef ICMP6_NI_REPLY # define ICMP6_NI_REPLY 140 #endif #ifndef MLD6_MTRACE_RESP # define MLD6_MTRACE_RESP 200 #endif #ifndef MLD6_MTRACE # define MLD6_MTRACE 201 #endif #ifndef ICMP6_HADISCOV_REQUEST # define ICMP6_HADISCOV_REQUEST 202 #endif #ifndef ICMP6_HADISCOV_REPLY # define ICMP6_HADISCOV_REPLY 203 #endif #ifndef ICMP6_MOBILEPREFIX_SOLICIT # define ICMP6_MOBILEPREFIX_SOLICIT 204 #endif #ifndef ICMP6_MOBILEPREFIX_ADVERT # define ICMP6_MOBILEPREFIX_ADVERT 205 #endif #ifndef ICMP6_MAXTYPE # define ICMP6_MAXTYPE 205 #endif #ifndef ICMP6_DST_UNREACH_NOROUTE # define ICMP6_DST_UNREACH_NOROUTE 0 #endif #ifndef ICMP6_DST_UNREACH_ADMIN # define ICMP6_DST_UNREACH_ADMIN 1 #endif #ifndef ICMP6_DST_UNREACH_NOTNEIGHBOR # define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 #endif #ifndef ICMP6_DST_UNREACH_BEYONDSCOPE # define ICMP6_DST_UNREACH_BEYONDSCOPE 2 #endif #ifndef ICMP6_DST_UNREACH_ADDR # define ICMP6_DST_UNREACH_ADDR 3 #endif #ifndef ICMP6_DST_UNREACH_NOPORT # define ICMP6_DST_UNREACH_NOPORT 4 #endif #ifndef ICMP6_TIME_EXCEED_TRANSIT # define ICMP6_TIME_EXCEED_TRANSIT 0 #endif #ifndef ICMP6_TIME_EXCEED_REASSEMBLY # define ICMP6_TIME_EXCEED_REASSEMBLY 1 #endif #ifndef ICMP6_NI_SUCCESS # define ICMP6_NI_SUCCESS 0 #endif #ifndef ICMP6_NI_REFUSED # define ICMP6_NI_REFUSED 1 #endif #ifndef ICMP6_NI_UNKNOWN # define ICMP6_NI_UNKNOWN 2 #endif #ifndef ICMP6_ROUTER_RENUMBERING_COMMAND # define ICMP6_ROUTER_RENUMBERING_COMMAND 0 #endif #ifndef ICMP6_ROUTER_RENUMBERING_RESULT # define ICMP6_ROUTER_RENUMBERING_RESULT 1 #endif #ifndef ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET # define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 #endif #ifndef ICMP6_PARAMPROB_HEADER # define ICMP6_PARAMPROB_HEADER 0 #endif #ifndef ICMP6_PARAMPROB_NEXTHEADER # define ICMP6_PARAMPROB_NEXTHEADER 1 #endif #ifndef ICMP6_PARAMPROB_OPTION # define ICMP6_PARAMPROB_OPTION 2 #endif #ifndef ICMP6_NI_SUBJ_IPV6 # define ICMP6_NI_SUBJ_IPV6 0 #endif #ifndef ICMP6_NI_SUBJ_FQDN # define ICMP6_NI_SUBJ_FQDN 1 #endif #ifndef ICMP6_NI_SUBJ_IPV4 # define ICMP6_NI_SUBJ_IPV4 2 #endif #ifndef MLD_MTRACE_RESP # define MLD_MTRACE_RESP 200 #endif #ifndef MLD_MTRACE # define MLD_MTRACE 201 #endif #ifndef MLD6_MTRACE_RESP # define MLD6_MTRACE_RESP MLD_MTRACE_RESP #endif #ifndef MLD6_MTRACE # define MLD6_MTRACE MLD_MTRACE #endif #if !defined(IPV6_FLOWINFO_MASK) # if (BYTE_ORDER == BIG_ENDIAN) || defined(_BIG_ENDIAN) # define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */ # else # if(BYTE_ORDER == LITTLE_ENDIAN) || !defined(_BIG_ENDIAN) # define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */ # endif /* LITTLE_ENDIAN */ # endif #endif #if !defined(IPV6_FLOWLABEL_MASK) # if (BYTE_ORDER == BIG_ENDIAN) || defined(_BIG_ENDIAN) # define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */ # else # if (BYTE_ORDER == LITTLE_ENDIAN) || !defined(_BIG_ENDIAN) # define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */ # endif /* LITTLE_ENDIAN */ # endif #endif /* * ECN is a new addition to TCP - RFC 2481 */ #ifndef TH_ECN # define TH_ECN 0x40 #endif #ifndef TH_CWR # define TH_CWR 0x80 #endif #define TH_ECNALL (TH_ECN|TH_CWR) /* * TCP States */ #define IPF_TCPS_LISTEN 0 /* listening for connection */ #define IPF_TCPS_SYN_SENT 1 /* active, have sent syn */ #define IPF_TCPS_SYN_RECEIVED 2 /* have send and received syn */ #define IPF_TCPS_HALF_ESTAB 3 /* for connections not fully "up" */ /* states < IPF_TCPS_ESTABLISHED are those where connections not established */ #define IPF_TCPS_ESTABLISHED 4 /* established */ #define IPF_TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ /* states > IPF_TCPS_CLOSE_WAIT are those where user has closed */ #define IPF_TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ #define IPF_TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ #define IPF_TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ /* states > IPF_TCPS_CLOSE_WAIT && < IPF_TCPS_FIN_WAIT_2 await ACK of FIN */ #define IPF_TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ #define IPF_TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ #define IPF_TCPS_CLOSED 11 /* closed */ #define IPF_TCP_NSTATES 12 #define TCP_MSL 120 #undef ICMP_MAX_UNREACH #define ICMP_MAX_UNREACH 14 #undef ICMP_MAXTYPE #define ICMP_MAXTYPE 18 #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif #ifndef LOG_FTP # define LOG_FTP (11<<3) #endif #ifndef LOG_AUTHPRIV # define LOG_AUTHPRIV (10<<3) #endif #ifndef LOG_AUDIT # define LOG_AUDIT (13<<3) #endif #ifndef LOG_NTP # define LOG_NTP (12<<3) #endif #ifndef LOG_SECURITY # define LOG_SECURITY (13<<3) #endif #ifndef LOG_LFMT # define LOG_LFMT (14<<3) #endif #ifndef LOG_CONSOLE # define LOG_CONSOLE (14<<3) #endif /* * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data, * another IP header and then 64 bits of data, totalling 56. Of course, * the last 64 bits is dependent on that being available. */ #define ICMPERR_ICMPHLEN 8 #define ICMPERR_IPICMPHLEN (20 + 8) #define ICMPERR_MINPKTLEN (20 + 8 + 20) #define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) #define ICMP6ERR_MINPKTLEN (40 + 8) #define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) #ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) #endif #ifdef RESCUE # undef IPFILTER_BPF #endif #ifdef IPF_DEBUG # define DPRINT(x) printf x #else # define DPRINT(x) #endif #ifndef AF_INET6 # define AF_INET6 26 #endif #ifdef DTRACE_PROBE # ifdef _KERNEL # define DT(_n) DTRACE_PROBE(_n) # define DT1(_n,_a,_b) DTRACE_PROBE1(_n,_a,_b) # define DT2(_n,_a,_b,_c,_d) DTRACE_PROBE2(_n,_a,_b,_c,_d) # define DT3(_n,_a,_b,_c,_d,_e,_f) \ DTRACE_PROBE3(_n,_a,_b,_c,_d,_e,_f) # define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) \ DTRACE_PROBE4(_n,_a,_b,_c,_d,_e,_f,_g,_h) # else # define DT(_n) # define DT1(_n,_a,_b) # define DT2(_n,_a,_b,_c,_d) # define DT3(_n,_a,_b,_c,_d,_e,_f) # define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) # endif #else # define DT(_n) # define DT1(_n,_a,_b) # define DT2(_n,_a,_b,_c,_d) # define DT3(_n,_a,_b,_c,_d,_e,_f) # define DT4(_n,_a,_b,_c,_d,_e,_f,_g,_h) #endif struct ip6_routing { u_char ip6r_nxt; /* next header */ u_char ip6r_len; /* length in units of 8 octets */ u_char ip6r_type; /* always zero */ u_char ip6r_segleft; /* segments left */ u_32_t ip6r_reserved; /* reserved field */ }; #endif /* __IP_COMPAT_H__ */ Index: projects/clang390-import/sys/contrib/ipfilter/netinet/ip_fil.h =================================================================== --- projects/clang390-import/sys/contrib/ipfilter/netinet/ip_fil.h (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter/netinet/ip_fil.h (revision 304965) @@ -1,1999 +1,2003 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 * $FreeBSD$ * Id: ip_fil.h,v 2.170.2.51 2007/10/10 09:48:03 darrenr Exp $ */ #ifndef __IP_FIL_H__ #define __IP_FIL_H__ #include "netinet/ip_compat.h" #include "netinet/ipf_rb.h" #if NETBSD_GE_REV(104040000) # include #endif #if defined(BSD) && defined(_KERNEL) # if NETBSD_LT_REV(399000000) || defined(__osf__) || FREEBSD_LT_REV(500043) # include # else # include # endif #endif #if !defined(linux) || !defined(_KERNEL) # include #endif #ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #ifndef __P # ifdef __STDC__ # define __P(x) x # else # define __P(x) () # endif #endif #if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCADAFR _IOW('r', 60, struct ipfobj) # define SIOCRMAFR _IOW('r', 61, struct ipfobj) # define SIOCSETFF _IOW('r', 62, u_int) # define SIOCGETFF _IOR('r', 63, u_int) # define SIOCGETFS _IOWR('r', 64, struct ipfobj) # define SIOCIPFFL _IOWR('r', 65, int) # define SIOCIPFFB _IOR('r', 66, int) # define SIOCADIFR _IOW('r', 67, struct ipfobj) # define SIOCRMIFR _IOW('r', 68, struct ipfobj) # define SIOCSWAPA _IOR('r', 69, u_int) # define SIOCINAFR _IOW('r', 70, struct ipfobj) # define SIOCINIFR _IOW('r', 71, struct ipfobj) # define SIOCFRENB _IOW('r', 72, u_int) # define SIOCFRSYN _IOW('r', 73, u_int) # define SIOCFRZST _IOWR('r', 74, struct ipfobj) # define SIOCZRLST _IOWR('r', 75, struct ipfobj) # define SIOCAUTHW _IOWR('r', 76, struct ipfobj) # define SIOCAUTHR _IOWR('r', 77, struct ipfobj) # define SIOCSTAT1 _IOWR('r', 78, struct ipfobj) # define SIOCSTLCK _IOWR('r', 79, u_int) # define SIOCSTPUT _IOWR('r', 80, struct ipfobj) # define SIOCSTGET _IOWR('r', 81, struct ipfobj) # define SIOCSTGSZ _IOWR('r', 82, struct ipfobj) # define SIOCSTAT2 _IOWR('r', 83, struct ipfobj) # define SIOCSETLG _IOWR('r', 84, int) # define SIOCGETLG _IOWR('r', 85, int) # define SIOCFUNCL _IOWR('r', 86, struct ipfunc_resolve) # define SIOCIPFGETNEXT _IOWR('r', 87, struct ipfobj) # define SIOCIPFGET _IOWR('r', 88, struct ipfobj) # define SIOCIPFSET _IOWR('r', 89, struct ipfobj) # define SIOCIPFL6 _IOWR('r', 90, int) # define SIOCIPFITER _IOWR('r', 91, struct ipfobj) # define SIOCGENITER _IOWR('r', 92, struct ipfobj) # define SIOCGTABL _IOWR('r', 93, struct ipfobj) # define SIOCIPFDELTOK _IOWR('r', 94, int) # define SIOCLOOKUPITER _IOWR('r', 95, struct ipfobj) # define SIOCGTQTAB _IOWR('r', 96, struct ipfobj) # define SIOCMATCHFLUSH _IOWR('r', 97, struct ipfobj) # define SIOCIPFINTERROR _IOR('r', 98, int) #else # define SIOCADAFR _IOW(r, 60, struct ipfobj) # define SIOCRMAFR _IOW(r, 61, struct ipfobj) # define SIOCSETFF _IOW(r, 62, u_int) # define SIOCGETFF _IOR(r, 63, u_int) # define SIOCGETFS _IOWR(r, 64, struct ipfobj) # define SIOCIPFFL _IOWR(r, 65, int) # define SIOCIPFFB _IOR(r, 66, int) # define SIOCADIFR _IOW(r, 67, struct ipfobj) # define SIOCRMIFR _IOW(r, 68, struct ipfobj) # define SIOCSWAPA _IOR(r, 69, u_int) # define SIOCINAFR _IOW(r, 70, struct ipfobj) # define SIOCINIFR _IOW(r, 71, struct ipfobj) # define SIOCFRENB _IOW(r, 72, u_int) # define SIOCFRSYN _IOW(r, 73, u_int) # define SIOCFRZST _IOWR(r, 74, struct ipfobj) # define SIOCZRLST _IOWR(r, 75, struct ipfobj) # define SIOCAUTHW _IOWR(r, 76, struct ipfobj) # define SIOCAUTHR _IOWR(r, 77, struct ipfobj) # define SIOCSTAT1 _IOWR(r, 78, struct ipfobj) # define SIOCSTLCK _IOWR(r, 79, u_int) # define SIOCSTPUT _IOWR(r, 80, struct ipfobj) # define SIOCSTGET _IOWR(r, 81, struct ipfobj) # define SIOCSTGSZ _IOWR(r, 82, struct ipfobj) # define SIOCSTAT2 _IOWR(r, 83, struct ipfobj) # define SIOCSETLG _IOWR(r, 84, int) # define SIOCGETLG _IOWR(r, 85, int) # define SIOCFUNCL _IOWR(r, 86, struct ipfunc_resolve) # define SIOCIPFGETNEXT _IOWR(r, 87, struct ipfobj) # define SIOCIPFGET _IOWR(r, 88, struct ipfobj) # define SIOCIPFSET _IOWR(r, 89, struct ipfobj) # define SIOCIPFL6 _IOWR(r, 90, int) # define SIOCIPFITER _IOWR(r, 91, struct ipfobj) # define SIOCGENITER _IOWR(r, 92, struct ipfobj) # define SIOCGTABL _IOWR(r, 93, struct ipfobj) # define SIOCIPFDELTOK _IOWR(r, 94, int) # define SIOCLOOKUPITER _IOWR(r, 95, struct ipfobj) # define SIOCGTQTAB _IOWR(r, 96, struct ipfobj) # define SIOCMATCHFLUSH _IOWR(r, 97, struct ipfobj) # define SIOCIPFINTERROR _IOR(r, 98, int) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR #define SIOCATHST SIOCSTAT1 #define SIOCGFRST SIOCSTAT2 struct ipscan; struct ifnet; struct ipf_main_softc_s; typedef int (* lookupfunc_t) __P((struct ipf_main_softc_s *, void *, int, void *, u_int)); /* * i6addr is used as a container for both IPv4 and IPv6 addresses, as well * as other types of objects, depending on its qualifier. */ #ifdef USE_INET6 typedef union i6addr { u_32_t i6[4]; struct in_addr in4; struct in6_addr in6; void *vptr[2]; lookupfunc_t lptr[2]; struct { u_short type; u_short subtype; int name; } i6un; } i6addr_t; #else typedef union i6addr { u_32_t i6[4]; struct in_addr in4; void *vptr[2]; lookupfunc_t lptr[2]; struct { u_short type; u_short subtype; int name; } i6un; } i6addr_t; #endif #define in4_addr in4.s_addr #define iplookupnum i6[1] #define iplookupname i6un.name #define iplookuptype i6un.type #define iplookupsubtype i6un.subtype /* * NOTE: These DO overlap the above on 64bit systems and this IS recognised. */ #define iplookupptr vptr[0] #define iplookupfunc lptr[1] #define I60(x) (((u_32_t *)(x))[0]) #define I61(x) (((u_32_t *)(x))[1]) #define I62(x) (((u_32_t *)(x))[2]) #define I63(x) (((u_32_t *)(x))[3]) #define HI60(x) ntohl(((u_32_t *)(x))[0]) #define HI61(x) ntohl(((u_32_t *)(x))[1]) #define HI62(x) ntohl(((u_32_t *)(x))[2]) #define HI63(x) ntohl(((u_32_t *)(x))[3]) #define IP6_EQ(a,b) ((I63(a) == I63(b)) && (I62(a) == I62(b)) && \ (I61(a) == I61(b)) && (I60(a) == I60(b))) #define IP6_NEQ(a,b) ((I63(a) != I63(b)) || (I62(a) != I62(b)) || \ (I61(a) != I61(b)) || (I60(a) != I60(b))) #define IP6_ISZERO(a) ((I60(a) | I61(a) | I62(a) | I63(a)) == 0) #define IP6_NOTZERO(a) ((I60(a) | I61(a) | I62(a) | I63(a)) != 0) #define IP6_ISONES(a) ((I63(a) == 0xffffffff) && (I62(a) == 0xffffffff) && \ (I61(a) == 0xffffffff) && (I60(a) == 0xffffffff)) #define IP6_GT(a,b) (ntohl(HI60(a)) > ntohl(HI60(b)) || \ (HI60(a) == HI60(b) && \ (ntohl(HI61(a)) > ntohl(HI61(b)) || \ (HI61(a) == HI61(b) && \ (ntohl(HI62(a)) > ntohl(HI62(b)) || \ (HI62(a) == HI62(b) && \ ntohl(HI63(a)) > ntohl(HI63(b)))))))) #define IP6_LT(a,b) (ntohl(HI60(a)) < ntohl(HI60(b)) || \ (HI60(a) == HI60(b) && \ (ntohl(HI61(a)) < ntohl(HI61(b)) || \ (HI61(a) == HI61(b) && \ (ntohl(HI62(a)) < ntohl(HI62(b)) || \ (HI62(a) == HI62(b) && \ ntohl(HI63(a)) < ntohl(HI63(b)))))))) #define NLADD(n,x) htonl(ntohl(n) + (x)) #define IP6_INC(a) \ do { u_32_t *_i6 = (u_32_t *)(a); \ _i6[3] = NLADD(_i6[3], 1); \ if (_i6[3] == 0) { \ _i6[2] = NLADD(_i6[2], 1); \ if (_i6[2] == 0) { \ _i6[1] = NLADD(_i6[1], 1); \ if (_i6[1] == 0) { \ _i6[0] = NLADD(_i6[0], 1); \ } \ } \ } \ } while (0) #define IP6_ADD(a,x,d) \ do { i6addr_t *_s = (i6addr_t *)(a); \ i6addr_t *_d = (i6addr_t *)(d); \ _d->i6[0] = NLADD(_s->i6[0], x); \ if (ntohl(_d->i6[0]) < ntohl(_s->i6[0])) { \ _d->i6[1] = NLADD(_d->i6[1], 1); \ if (ntohl(_d->i6[1]) < ntohl(_s->i6[1])) { \ _d->i6[2] = NLADD(_d->i6[2], 1); \ if (ntohl(_d->i6[2]) < ntohl(_s->i6[2])) { \ _d->i6[3] = NLADD(_d->i6[3], 1); \ } \ } \ } \ } while (0) #define IP6_AND(a,b,d) do { i6addr_t *_s1 = (i6addr_t *)(a); \ i6addr_t *_s2 = (i6addr_t *)(b); \ i6addr_t *_d = (i6addr_t *)(d); \ _d->i6[0] = _s1->i6[0] & _s2->i6[0]; \ _d->i6[1] = _s1->i6[1] & _s2->i6[1]; \ _d->i6[2] = _s1->i6[2] & _s2->i6[2]; \ _d->i6[3] = _s1->i6[3] & _s2->i6[3]; \ } while (0) #define IP6_ANDASSIGN(a,m) \ do { i6addr_t *_d = (i6addr_t *)(a); \ i6addr_t *_m = (i6addr_t *)(m); \ _d->i6[0] &= _m->i6[0]; \ _d->i6[1] &= _m->i6[1]; \ _d->i6[2] &= _m->i6[2]; \ _d->i6[3] &= _m->i6[3]; \ } while (0) #define IP6_MASKEQ(a,m,b) \ (((I60(a) & I60(m)) == I60(b)) && \ ((I61(a) & I61(m)) == I61(b)) && \ ((I62(a) & I62(m)) == I62(b)) && \ ((I63(a) & I63(m)) == I63(b))) #define IP6_MASKNEQ(a,m,b) \ (((I60(a) & I60(m)) != I60(b)) || \ ((I61(a) & I61(m)) != I61(b)) || \ ((I62(a) & I62(m)) != I62(b)) || \ ((I63(a) & I63(m)) != I63(b))) #define IP6_MERGE(a,b,c) \ do { i6addr_t *_d, *_s1, *_s2; \ _d = (i6addr_t *)(a); \ _s1 = (i6addr_t *)(b); \ _s2 = (i6addr_t *)(c); \ _d->i6[0] |= _s1->i6[0] & ~_s2->i6[0]; \ _d->i6[1] |= _s1->i6[1] & ~_s2->i6[1]; \ _d->i6[2] |= _s1->i6[2] & ~_s2->i6[2]; \ _d->i6[3] |= _s1->i6[3] & ~_s2->i6[3]; \ } while (0) #define IP6_MASK(a,b,c) \ do { i6addr_t *_d, *_s1, *_s2; \ _d = (i6addr_t *)(a); \ _s1 = (i6addr_t *)(b); \ _s2 = (i6addr_t *)(c); \ _d->i6[0] = _s1->i6[0] & ~_s2->i6[0]; \ _d->i6[1] = _s1->i6[1] & ~_s2->i6[1]; \ _d->i6[2] = _s1->i6[2] & ~_s2->i6[2]; \ _d->i6[3] = _s1->i6[3] & ~_s2->i6[3]; \ } while (0) #define IP6_SETONES(a) \ do { i6addr_t *_d = (i6addr_t *)(a); \ _d->i6[0] = 0xffffffff; \ _d->i6[1] = 0xffffffff; \ _d->i6[2] = 0xffffffff; \ _d->i6[3] = 0xffffffff; \ } while (0) typedef union ipso_u { u_short ipso_ripso[2]; u_32_t ipso_doi; } ipso_t; typedef struct fr_ip { u_32_t fi_v:4; /* IP version */ u_32_t fi_xx:4; /* spare */ u_32_t fi_tos:8; /* IP packet TOS */ u_32_t fi_ttl:8; /* IP packet TTL */ u_32_t fi_p:8; /* IP packet protocol */ u_32_t fi_optmsk; /* bitmask composed from IP options */ i6addr_t fi_src; /* source address from packet */ i6addr_t fi_dst; /* destination address from packet */ ipso_t fi_ipso; /* IP security options */ u_32_t fi_flx; /* packet flags */ u_32_t fi_tcpmsk; /* TCP options set/reset */ u_32_t fi_ports[2]; /* TCP ports */ u_char fi_tcpf; /* TCP flags */ u_char fi_sensitivity; u_char fi_xxx[2]; /* pad */ } fr_ip_t; /* * For use in fi_flx */ #define FI_TCPUDP 0x0001 /* TCP/UCP implied comparison*/ #define FI_OPTIONS 0x0002 #define FI_FRAG 0x0004 #define FI_SHORT 0x0008 #define FI_NATED 0x0010 #define FI_MULTICAST 0x0020 #define FI_BROADCAST 0x0040 #define FI_MBCAST 0x0080 #define FI_STATE 0x0100 #define FI_BADNAT 0x0200 #define FI_BAD 0x0400 #define FI_OOW 0x0800 /* Out of state window, else match */ #define FI_ICMPERR 0x1000 #define FI_FRAGBODY 0x2000 #define FI_BADSRC 0x4000 #define FI_LOWTTL 0x8000 #define FI_CMP 0x5cfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */ #define FI_ICMPCMP 0x0003 /* Flags we can check for ICMP error packets */ #define FI_WITH 0x5effe /* Not FI_TCPUDP */ #define FI_V6EXTHDR 0x10000 #define FI_COALESCE 0x20000 #define FI_NEWNAT 0x40000 #define FI_ICMPQUERY 0x80000 #define FI_ENCAP 0x100000 /* encap/decap with NAT */ #define FI_AH 0x200000 /* AH header present */ #define FI_DOCKSUM 0x10000000 /* Proxy wants L4 recalculation */ #define FI_NOCKSUM 0x20000000 /* don't do a L4 checksum validation */ #define FI_NOWILD 0x40000000 /* Do not do wildcard searches */ #define FI_IGNORE 0x80000000 #define fi_secmsk fi_ipso.ipso_ripso[0] #define fi_auth fi_ipso.ipso_ripso[1] #define fi_doi fi_ipso.ipso_doi #define fi_saddr fi_src.in4.s_addr #define fi_daddr fi_dst.in4.s_addr #define fi_srcnum fi_src.iplookupnum #define fi_dstnum fi_dst.iplookupnum #define fi_srcname fi_src.iplookupname #define fi_dstname fi_dst.iplookupname #define fi_srctype fi_src.iplookuptype #define fi_dsttype fi_dst.iplookuptype #define fi_srcsubtype fi_src.iplookupsubtype #define fi_dstsubtype fi_dst.iplookupsubtype #define fi_srcptr fi_src.iplookupptr #define fi_dstptr fi_dst.iplookupptr #define fi_srcfunc fi_src.iplookupfunc #define fi_dstfunc fi_dst.iplookupfunc /* * These are both used by the state and NAT code to indicate that one port or * the other should be treated as a wildcard. * NOTE: When updating, check bit masks in ip_state.h and update there too. */ #define SI_W_SPORT 0x00000100 #define SI_W_DPORT 0x00000200 #define SI_WILDP (SI_W_SPORT|SI_W_DPORT) #define SI_W_SADDR 0x00000400 #define SI_W_DADDR 0x00000800 #define SI_WILDA (SI_W_SADDR|SI_W_DADDR) #define SI_NEWFR 0x00001000 #define SI_CLONE 0x00002000 #define SI_CLONED 0x00004000 #define SI_NEWCLONE 0x00008000 typedef struct { u_short fda_ports[2]; u_char fda_tcpf; /* TCP header flags (SYN, ACK, etc) */ } frdat_t; typedef enum fr_breasons_e { FRB_BLOCKED = 0, FRB_LOGFAIL = 1, FRB_PPSRATE = 2, FRB_JUMBO = 3, FRB_MAKEFRIP = 4, FRB_STATEADD = 5, FRB_UPDATEIPID = 6, FRB_LOGFAIL2 = 7, FRB_DECAPFRIP = 8, FRB_AUTHNEW = 9, FRB_AUTHCAPTURE = 10, FRB_COALESCE = 11, FRB_PULLUP = 12, FRB_AUTHFEEDBACK = 13, FRB_BADFRAG = 14, FRB_NATV4 = 15, FRB_NATV6 = 16, } fr_breason_t; #define FRB_MAX_VALUE 16 typedef enum ipf_cksum_e { FI_CK_BAD = -1, FI_CK_NEEDED = 0, FI_CK_SUMOK = 1, FI_CK_L4PART = 2, FI_CK_L4FULL = 4 } ipf_cksum_t; typedef struct fr_info { void *fin_main_soft; void *fin_ifp; /* interface packet is `on' */ struct frentry *fin_fr; /* last matching rule */ int fin_out; /* in or out ? 1 == out, 0 == in */ fr_ip_t fin_fi; /* IP Packet summary */ frdat_t fin_dat; /* TCP/UDP ports, ICMP code/type */ int fin_dlen; /* length of data portion of packet */ int fin_plen; u_32_t fin_rule; /* rule # last matched */ u_short fin_hlen; /* length of IP header in bytes */ char fin_group[FR_GROUPLEN]; /* group number, -1 for none */ void *fin_dp; /* start of data past IP header */ /* * Fields after fin_dp aren't used for compression of log records. * fin_fi contains the IP version (fin_family) * fin_rule isn't included because adding a new rule can change it but * not change fin_fr. fin_rule is the rule number reported. * It isn't necessary to include fin_crc because that is checked * for explicitly, before calling bcmp. */ u_32_t fin_crc; /* Simple calculation for logging */ int fin_family; /* AF_INET, etc. */ int fin_icode; /* ICMP error to return */ int fin_mtu; /* MTU input for ICMP need-frag */ int fin_rev; /* state only: 1 = reverse */ int fin_ipoff; /* # bytes from buffer start to hdr */ u_32_t fin_id; /* IP packet id field */ u_short fin_l4hlen; /* length of L4 header, if known */ u_short fin_off; int fin_depth; /* Group nesting depth */ int fin_error; /* Error code to return */ ipf_cksum_t fin_cksum; /* -1 = bad, 1 = good, 0 = not done */ fr_breason_t fin_reason; /* why auto blocked */ u_int fin_pktnum; void *fin_nattag; struct frdest *fin_dif; struct frdest *fin_tif; union { ip_t *fip_ip; #ifdef USE_INET6 ip6_t *fip_ip6; #endif } fin_ipu; mb_t **fin_mp; /* pointer to pointer to mbuf */ mb_t *fin_m; /* pointer to mbuf */ #ifdef MENTAT mb_t *fin_qfm; /* pointer to mblk where pkt starts */ void *fin_qpi; char fin_ifname[LIFNAMSIZ]; #endif #ifdef __sgi void *fin_hbuf; #endif void *fin_fraghdr; /* pointer to start of ipv6 frag hdr */ } fr_info_t; #define fin_ip fin_ipu.fip_ip #define fin_ip6 fin_ipu.fip_ip6 #define fin_v fin_fi.fi_v #define fin_p fin_fi.fi_p #define fin_flx fin_fi.fi_flx #define fin_optmsk fin_fi.fi_optmsk #define fin_secmsk fin_fi.fi_secmsk #define fin_doi fin_fi.fi_doi #define fin_auth fin_fi.fi_auth #define fin_src fin_fi.fi_src.in4 #define fin_saddr fin_fi.fi_saddr #define fin_dst fin_fi.fi_dst.in4 #define fin_daddr fin_fi.fi_daddr #define fin_data fin_fi.fi_ports #define fin_sport fin_fi.fi_ports[0] #define fin_dport fin_fi.fi_ports[1] #define fin_tcpf fin_fi.fi_tcpf #define fin_src6 fin_fi.fi_src #define fin_dst6 fin_fi.fi_dst #define fin_srcip6 fin_fi.fi_src.in6 #define fin_dstip6 fin_fi.fi_dst.in6 #define IPF_IN 0 #define IPF_OUT 1 typedef struct frentry *(*ipfunc_t) __P((fr_info_t *, u_32_t *)); typedef int (*ipfuncinit_t) __P((struct ipf_main_softc_s *, struct frentry *)); typedef struct ipfunc_resolve { char ipfu_name[32]; ipfunc_t ipfu_addr; ipfuncinit_t ipfu_init; ipfuncinit_t ipfu_fini; } ipfunc_resolve_t; /* * Size for compares on fr_info structures */ #define FI_CSIZE offsetof(fr_info_t, fin_icode) #define FI_LCSIZE offsetof(fr_info_t, fin_dp) /* * Size for copying cache fr_info structure */ #define FI_COPYSIZE offsetof(fr_info_t, fin_dp) /* * Structure for holding IPFilter's tag information */ #define IPFTAG_LEN 16 typedef struct { union { u_32_t iptu_num[4]; char iptu_tag[IPFTAG_LEN]; } ipt_un; int ipt_not; } ipftag_t; #define ipt_tag ipt_un.iptu_tag #define ipt_num ipt_un.iptu_num /* * Structure to define address for pool lookups. */ typedef struct { u_char adf_len; sa_family_t adf_family; u_char adf_xxx[2]; i6addr_t adf_addr; } addrfamily_t; RBI_LINK(ipf_rb, host_node_s); typedef struct host_node_s { RBI_FIELD(ipf_rb) hn_entry; addrfamily_t hn_addr; int hn_active; } host_node_t; typedef RBI_HEAD(ipf_rb, host_node_s) ipf_rb_head_t; typedef struct host_track_s { ipf_rb_head_t ht_root; int ht_max_nodes; int ht_max_per_node; int ht_netmask; int ht_cur_nodes; } host_track_t; typedef enum fr_dtypes_e { FRD_NORMAL = 0, FRD_DSTLIST } fr_dtypes_t; /* * This structure is used to hold information about the next hop for where * to forward a packet. */ typedef struct frdest { void *fd_ptr; addrfamily_t fd_addr; fr_dtypes_t fd_type; int fd_name; int fd_local; } frdest_t; #define fd_ip6 fd_addr.adf_addr #define fd_ip fd_ip6.in4 typedef enum fr_ctypes_e { FR_NONE = 0, FR_EQUAL, FR_NEQUAL, FR_LESST, FR_GREATERT, FR_LESSTE, FR_GREATERTE, FR_OUTRANGE, FR_INRANGE, FR_INCRANGE } fr_ctypes_t; /* * This structure holds information about a port comparison. */ typedef struct frpcmp { fr_ctypes_t frp_cmp; /* data for port comparisons */ u_32_t frp_port; /* top port for <> and >< */ u_32_t frp_top; /* top port for <> and >< */ } frpcmp_t; /* * Structure containing all the relevant TCP things that can be checked in * a filter rule. */ typedef struct frtuc { u_char ftu_tcpfm; /* tcp flags mask */ u_char ftu_tcpf; /* tcp flags */ frpcmp_t ftu_src; frpcmp_t ftu_dst; } frtuc_t; #define ftu_scmp ftu_src.frp_cmp #define ftu_dcmp ftu_dst.frp_cmp #define ftu_sport ftu_src.frp_port #define ftu_dport ftu_dst.frp_port #define ftu_stop ftu_src.frp_top #define ftu_dtop ftu_dst.frp_top #define FR_TCPFMAX 0x3f typedef enum fr_atypes_e { FRI_NONE = -1, /* For LHS of NAT */ FRI_NORMAL = 0, /* Normal address */ FRI_DYNAMIC, /* dynamic address */ FRI_LOOKUP, /* address is a pool # */ FRI_RANGE, /* address/mask is a range */ FRI_NETWORK, /* network address from if */ FRI_BROADCAST, /* broadcast address from if */ FRI_PEERADDR, /* Peer address for P-to-P */ FRI_NETMASKED, /* network address with netmask from if */ FRI_SPLIT, /* For NAT compatibility */ FRI_INTERFACE /* address is based on interface name */ } fr_atypes_t; /* * This structure makes up what is considered to be the IPFilter specific * matching components of a filter rule, as opposed to the data structures * used to define the result which are in frentry_t and not here. */ typedef struct fripf { fr_ip_t fri_ip; fr_ip_t fri_mip; /* mask structure */ u_short fri_icmpm; /* data for ICMP packets (mask) */ u_short fri_icmp; frtuc_t fri_tuc; fr_atypes_t fri_satype; /* addres type */ fr_atypes_t fri_datype; /* addres type */ int fri_sifpidx; /* doing dynamic addressing */ int fri_difpidx; /* index into fr_ifps[] to use when */ } fripf_t; #define fri_dlookup fri_mip.fi_dst #define fri_slookup fri_mip.fi_src #define fri_dstnum fri_mip.fi_dstnum #define fri_srcnum fri_mip.fi_srcnum #define fri_dstname fri_mip.fi_dstname #define fri_srcname fri_mip.fi_srcname #define fri_dstptr fri_mip.fi_dstptr #define fri_srcptr fri_mip.fi_srcptr typedef enum fr_rtypes_e { FR_T_NONE = 0, FR_T_IPF, /* IPF structures */ FR_T_BPFOPC, /* BPF opcode */ FR_T_CALLFUNC, /* callout to function in fr_func only */ FR_T_COMPIPF, /* compiled C code */ FR_T_IPFEXPR, /* IPF expression */ FR_T_BUILTIN = 0x40000000, /* rule is in kernel space */ FR_T_IPF_BUILTIN, FR_T_BPFOPC_BUILTIN, FR_T_CALLFUNC_BUILTIN, FR_T_COMPIPF_BUILTIN, FR_T_IPFEXPR_BUILTIN } fr_rtypes_t; typedef struct frentry * (* frentfunc_t) __P((fr_info_t *)); typedef struct frentry { ipfmutex_t fr_lock; struct frentry *fr_next; struct frentry **fr_pnext; struct frgroup *fr_grp; struct frgroup *fr_grphead; struct frgroup *fr_icmpgrp; struct ipscan *fr_isc; struct frentry *fr_dnext; /* 2 fr_die linked list pointers */ struct frentry **fr_pdnext; void *fr_ifas[4]; void *fr_ptr; /* for use with fr_arg */ int fr_comment; /* text comment for rule */ int fr_size; /* size of this structure */ int fr_ref; /* reference count */ int fr_statecnt; /* state count - for limit rules */ u_32_t fr_die; /* only used on loading the rule */ u_int fr_cksum; /* checksum on filter rules for performance */ /* * The line number from a file is here because we need to be able to * match the rule generated with ``grep rule ipf.conf | ipf -rf -'' * with the rule loaded using ``ipf -f ipf.conf'' - thus it can't be * on the other side of fr_func. */ int fr_flineno; /* line number from conf file */ /* * These are only incremented when a packet matches this rule and * it is the last match */ U_QUAD_T fr_hits; U_QUAD_T fr_bytes; /* * For PPS rate limiting * fr_lpu is used to always have the same size for this field, * allocating 64bits for seconds and 32bits for milliseconds. */ union { struct timeval frp_lastpkt; char frp_bytes[12]; } fr_lpu; int fr_curpps; union { void *fru_data; char *fru_caddr; fripf_t *fru_ipf; frentfunc_t fru_func; } fr_dun; /* * Fields after this may not change whilst in the kernel. */ ipfunc_t fr_func; /* call this function */ int fr_dsize; int fr_pps; fr_rtypes_t fr_type; u_32_t fr_flags; /* per-rule flags && options (see below) */ u_32_t fr_logtag; /* user defined log tag # */ u_32_t fr_collect; /* collection number */ u_int fr_arg; /* misc. numeric arg for rule */ u_int fr_loglevel; /* syslog log facility + priority */ u_char fr_family; u_char fr_icode; /* return ICMP code */ int fr_group; /* group to which this rule belongs */ int fr_grhead; /* group # which this rule starts */ int fr_ifnames[4]; int fr_isctag; int fr_rpc; /* XID Filtering */ ipftag_t fr_nattag; frdest_t fr_tifs[2]; /* "to"/"reply-to" interface */ frdest_t fr_dif; /* duplicate packet interface */ /* * These are all options related to stateful filtering */ host_track_t fr_srctrack; int fr_nostatelog; int fr_statemax; /* max reference count */ int fr_icmphead; /* ICMP group for state options */ u_int fr_age[2]; /* non-TCP state timeouts */ /* * How big is the name buffer at the end? */ int fr_namelen; char fr_names[1]; } frentry_t; #define fr_lastpkt fr_lpu.frp_lastpkt #define fr_caddr fr_dun.fru_caddr #define fr_data fr_dun.fru_data #define fr_dfunc fr_dun.fru_func #define fr_ipf fr_dun.fru_ipf #define fr_ip fr_ipf->fri_ip #define fr_mip fr_ipf->fri_mip #define fr_icmpm fr_ipf->fri_icmpm #define fr_icmp fr_ipf->fri_icmp #define fr_tuc fr_ipf->fri_tuc #define fr_satype fr_ipf->fri_satype #define fr_datype fr_ipf->fri_datype #define fr_sifpidx fr_ipf->fri_sifpidx #define fr_difpidx fr_ipf->fri_difpidx #define fr_proto fr_ip.fi_p #define fr_mproto fr_mip.fi_p #define fr_ttl fr_ip.fi_ttl #define fr_mttl fr_mip.fi_ttl #define fr_tos fr_ip.fi_tos #define fr_mtos fr_mip.fi_tos #define fr_tcpfm fr_tuc.ftu_tcpfm #define fr_tcpf fr_tuc.ftu_tcpf #define fr_scmp fr_tuc.ftu_scmp #define fr_dcmp fr_tuc.ftu_dcmp #define fr_dport fr_tuc.ftu_dport #define fr_sport fr_tuc.ftu_sport #define fr_stop fr_tuc.ftu_stop #define fr_dtop fr_tuc.ftu_dtop #define fr_dst fr_ip.fi_dst.in4 #define fr_dst6 fr_ip.fi_dst #define fr_daddr fr_ip.fi_dst.in4.s_addr #define fr_src fr_ip.fi_src.in4 #define fr_src6 fr_ip.fi_src #define fr_saddr fr_ip.fi_src.in4.s_addr #define fr_dmsk fr_mip.fi_dst.in4 #define fr_dmsk6 fr_mip.fi_dst #define fr_dmask fr_mip.fi_dst.in4.s_addr #define fr_smsk fr_mip.fi_src.in4 #define fr_smsk6 fr_mip.fi_src #define fr_smask fr_mip.fi_src.in4.s_addr #define fr_dstnum fr_ip.fi_dstnum #define fr_srcnum fr_ip.fi_srcnum #define fr_dlookup fr_ip.fi_dst #define fr_slookup fr_ip.fi_src #define fr_dstname fr_ip.fi_dstname #define fr_srcname fr_ip.fi_srcname #define fr_dsttype fr_ip.fi_dsttype #define fr_srctype fr_ip.fi_srctype #define fr_dstsubtype fr_ip.fi_dstsubtype #define fr_srcsubtype fr_ip.fi_srcsubtype #define fr_dstptr fr_mip.fi_dstptr #define fr_srcptr fr_mip.fi_srcptr #define fr_dstfunc fr_mip.fi_dstfunc #define fr_srcfunc fr_mip.fi_srcfunc #define fr_optbits fr_ip.fi_optmsk #define fr_optmask fr_mip.fi_optmsk #define fr_secbits fr_ip.fi_secmsk #define fr_secmask fr_mip.fi_secmsk #define fr_authbits fr_ip.fi_auth #define fr_authmask fr_mip.fi_auth #define fr_doi fr_ip.fi_doi #define fr_doimask fr_mip.fi_doi #define fr_flx fr_ip.fi_flx #define fr_mflx fr_mip.fi_flx #define fr_ifa fr_ifas[0] #define fr_oifa fr_ifas[2] #define fr_tif fr_tifs[0] #define fr_rif fr_tifs[1] #define FR_NOLOGTAG 0 #define FR_CMPSIZ (sizeof(struct frentry) - \ offsetof(struct frentry, fr_func)) #define FR_NAME(_f, _n) (_f)->fr_names + (_f)->_n /* * fr_flags */ #define FR_BLOCK 0x00001 /* do not allow packet to pass */ #define FR_PASS 0x00002 /* allow packet to pass */ #define FR_AUTH 0x00003 /* use authentication */ #define FR_PREAUTH 0x00004 /* require preauthentication */ #define FR_ACCOUNT 0x00005 /* Accounting rule */ #define FR_SKIP 0x00006 /* skip rule */ #define FR_DECAPSULATE 0x00008 /* decapsulate rule */ #define FR_CALL 0x00009 /* call rule */ #define FR_CMDMASK 0x0000f #define FR_LOG 0x00010 /* Log */ #define FR_LOGB 0x00011 /* Log-fail */ #define FR_LOGP 0x00012 /* Log-pass */ #define FR_LOGMASK (FR_LOG|FR_CMDMASK) #define FR_CALLNOW 0x00020 /* call another function (fr_func) if matches */ #define FR_NOTSRCIP 0x00040 #define FR_NOTDSTIP 0x00080 #define FR_QUICK 0x00100 /* match & stop processing list */ #define FR_KEEPFRAG 0x00200 /* keep fragment information */ #define FR_KEEPSTATE 0x00400 /* keep `connection' state information */ #define FR_FASTROUTE 0x00800 /* bypass normal routing */ #define FR_RETRST 0x01000 /* Return TCP RST packet - reset connection */ #define FR_RETICMP 0x02000 /* Return ICMP unreachable packet */ #define FR_FAKEICMP 0x03000 /* Return ICMP unreachable with fake source */ #define FR_OUTQUE 0x04000 /* outgoing packets */ #define FR_INQUE 0x08000 /* ingoing packets */ #define FR_LOGBODY 0x10000 /* Log the body */ #define FR_LOGFIRST 0x20000 /* Log the first byte if state held */ #define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */ #define FR_STLOOSE 0x80000 /* loose state checking */ #define FR_FRSTRICT 0x100000 /* strict frag. cache */ #define FR_STSTRICT 0x200000 /* strict keep state */ #define FR_NEWISN 0x400000 /* new ISN for outgoing TCP */ #define FR_NOICMPERR 0x800000 /* do not match ICMP errors in state */ #define FR_STATESYNC 0x1000000 /* synchronize state to slave */ #define FR_COPIED 0x2000000 /* copied from user space */ #define FR_INACTIVE 0x4000000 /* only used when flush'ing rules */ #define FR_NOMATCH 0x8000000 /* no match occured */ /* 0x10000000 FF_LOGPASS */ /* 0x20000000 FF_LOGBLOCK */ /* 0x40000000 FF_LOGNOMATCH */ /* 0x80000000 FF_BLOCKNONIP */ #define FR_RETMASK (FR_RETICMP|FR_RETRST|FR_FAKEICMP) #define FR_ISBLOCK(x) (((x) & FR_CMDMASK) == FR_BLOCK) #define FR_ISPASS(x) (((x) & FR_CMDMASK) == FR_PASS) #define FR_ISAUTH(x) (((x) & FR_CMDMASK) == FR_AUTH) #define FR_ISPREAUTH(x) (((x) & FR_CMDMASK) == FR_PREAUTH) #define FR_ISACCOUNT(x) (((x) & FR_CMDMASK) == FR_ACCOUNT) #define FR_ISSKIP(x) (((x) & FR_CMDMASK) == FR_SKIP) #define FR_ISDECAPS(x) (((x) & FR_CMDMASK) == FR_DECAPSULATE) #define FR_ISNOMATCH(x) ((x) & FR_NOMATCH) #define FR_INOUT (FR_INQUE|FR_OUTQUE) /* * recognized flags for SIOCGETFF and SIOCSETFF, and get put in fr_flags */ #define FF_LOGPASS 0x10000000 #define FF_LOGBLOCK 0x20000000 #define FF_LOGNOMATCH 0x40000000 #define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH) #define FF_BLOCKNONIP 0x80000000 /* Solaris2 Only */ /* * Structure that passes information on what/how to flush to the kernel. */ typedef struct ipfflush { int ipflu_how; int ipflu_arg; } ipfflush_t; /* * */ typedef struct ipfgetctl { u_int ipfg_min; /* min value */ u_int ipfg_current; /* current value */ u_int ipfg_max; /* max value */ u_int ipfg_default; /* default value */ u_int ipfg_steps; /* value increments */ char ipfg_name[40]; /* tag name for this control */ } ipfgetctl_t; typedef struct ipfsetctl { int ipfs_which; /* 0 = min 1 = current 2 = max 3 = default */ u_int ipfs_value; /* min value */ char ipfs_name[40]; /* tag name for this control */ } ipfsetctl_t; /* * Some of the statistics below are in their own counters, but most are kept * in this single structure so that they can all easily be collected and * copied back as required. */ typedef struct ipf_statistics { u_long fr_icmp_coalesce; u_long fr_tcp_frag; u_long fr_tcp_pullup; u_long fr_tcp_short; u_long fr_tcp_small; u_long fr_tcp_bad_flags; u_long fr_udp_pullup; u_long fr_ip_freed; u_long fr_v6_ah_bad; u_long fr_v6_bad; u_long fr_v6_badfrag; u_long fr_v6_dst_bad; u_long fr_v6_esp_pullup; u_long fr_v6_ext_short; u_long fr_v6_ext_pullup; u_long fr_v6_ext_hlen; u_long fr_v6_frag_bad; u_long fr_v6_frag_pullup; u_long fr_v6_frag_size; u_long fr_v6_gre_pullup; u_long fr_v6_icmp6_pullup; u_long fr_v6_rh_bad; u_long fr_v6_badttl; /* TTL in packet doesn't reach minimum */ u_long fr_v4_ah_bad; u_long fr_v4_ah_pullup; u_long fr_v4_esp_pullup; u_long fr_v4_cipso_bad; u_long fr_v4_cipso_tlen; u_long fr_v4_gre_frag; u_long fr_v4_gre_pullup; u_long fr_v4_icmp_frag; u_long fr_v4_icmp_pullup; u_long fr_v4_badttl; /* TTL in packet doesn't reach minimum */ u_long fr_v4_badsrc; /* source received doesn't match route */ u_long fr_l4_badcksum; /* layer 4 header checksum failure */ u_long fr_badcoalesces; u_long fr_pass; /* packets allowed */ u_long fr_block; /* packets denied */ u_long fr_nom; /* packets which don't match any rule */ u_long fr_short; /* packets which are short */ u_long fr_ppkl; /* packets allowed and logged */ u_long fr_bpkl; /* packets denied and logged */ u_long fr_npkl; /* packets unmatched and logged */ u_long fr_ret; /* packets for which a return is sent */ u_long fr_acct; /* packets for which counting was performed */ u_long fr_bnfr; /* bad attempts to allocate fragment state */ u_long fr_nfr; /* new fragment state kept */ u_long fr_cfr; /* add new fragment state but complete pkt */ u_long fr_bads; /* bad attempts to allocate packet state */ u_long fr_ads; /* new packet state kept */ u_long fr_chit; /* cached hit */ u_long fr_cmiss; /* cached miss */ u_long fr_tcpbad; /* TCP checksum check failures */ u_long fr_pull[2]; /* good and bad pullup attempts */ u_long fr_bad; /* bad IP packets to the filter */ u_long fr_ipv6; /* IPv6 packets in/out */ u_long fr_ppshit; /* dropped because of pps ceiling */ u_long fr_ipud; /* IP id update failures */ u_long fr_blocked[FRB_MAX_VALUE + 1]; } ipf_statistics_t; /* * Log structure. Each packet header logged is prepended by one of these. * Following this in the log records read from the device will be an ipflog * structure which is then followed by any packet data. */ typedef struct iplog { u_32_t ipl_magic; u_int ipl_count; u_32_t ipl_seqnum; struct timeval ipl_time; size_t ipl_dsize; struct iplog *ipl_next; } iplog_t; #define ipl_sec ipl_time.tv_sec #define ipl_usec ipl_time.tv_usec #define IPL_MAGIC 0x49504c4d /* 'IPLM' */ #define IPL_MAGIC_NAT 0x49504c4e /* 'IPLN' */ #define IPL_MAGIC_STATE 0x49504c53 /* 'IPLS' */ #define IPLOG_SIZE sizeof(iplog_t) typedef struct ipflog { #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ (defined(OpenBSD) && (OpenBSD >= 199603)) #else u_int fl_unit; #endif u_32_t fl_rule; u_32_t fl_flags; u_32_t fl_lflags; u_32_t fl_logtag; ipftag_t fl_nattag; u_short fl_plen; /* extra data after hlen */ u_short fl_loglevel; /* syslog log level */ char fl_group[FR_GROUPLEN]; u_char fl_hlen; /* length of IP headers saved */ u_char fl_dir; u_char fl_breason; /* from fin_reason */ u_char fl_family; /* address family of packet logged */ char fl_ifname[LIFNAMSIZ]; } ipflog_t; #ifndef IPF_LOGGING # define IPF_LOGGING 0 #endif #ifndef IPF_DEFAULT_PASS # define IPF_DEFAULT_PASS FR_PASS #endif #define DEFAULT_IPFLOGSIZE 32768 #ifndef IPFILTER_LOGSIZE # define IPFILTER_LOGSIZE DEFAULT_IPFLOGSIZE #else # if IPFILTER_LOGSIZE < 8192 # error IPFILTER_LOGSIZE too small. Must be >= 8192 # endif #endif #define IPF_OPTCOPY 0x07ff00 /* bit mask of copied options */ /* * Device filenames for reading log information. Use ipf on Solaris2 because * ipl is already a name used by something else. */ #ifndef IPL_NAME # if SOLARIS # define IPL_NAME "/dev/ipf" # else # define IPL_NAME "/dev/ipl" # endif #endif /* * Pathnames for various IP Filter control devices. Used by LKM * and userland, so defined here. */ #define IPNAT_NAME "/dev/ipnat" #define IPSTATE_NAME "/dev/ipstate" #define IPAUTH_NAME "/dev/ipauth" #define IPSYNC_NAME "/dev/ipsync" #define IPSCAN_NAME "/dev/ipscan" #define IPLOOKUP_NAME "/dev/iplookup" #define IPL_LOGIPF 0 /* Minor device #'s for accessing logs */ #define IPL_LOGNAT 1 #define IPL_LOGSTATE 2 #define IPL_LOGAUTH 3 #define IPL_LOGSYNC 4 #define IPL_LOGSCAN 5 #define IPL_LOGLOOKUP 6 #define IPL_LOGCOUNT 7 #define IPL_LOGMAX 7 #define IPL_LOGSIZE IPL_LOGMAX + 1 #define IPL_LOGALL -1 #define IPL_LOGNONE -2 /* * For SIOCGETFS */ typedef struct friostat { ipf_statistics_t f_st[2]; frentry_t *f_ipf[2][2]; frentry_t *f_acct[2][2]; frentry_t *f_auth; struct frgroup *f_groups[IPL_LOGSIZE][2]; u_long f_froute[2]; u_long f_log_ok; u_long f_log_fail; u_long f_rb_no_mem; u_long f_rb_node_max; u_32_t f_ticks; int f_locks[IPL_LOGSIZE]; int f_defpass; /* default pass - from fr_pass */ int f_active; /* 1 or 0 - active rule set */ int f_running; /* 1 if running, else 0 */ int f_logging; /* 1 if enabled, else 0 */ int f_features; char f_version[32]; /* version string */ } friostat_t; #define f_fin f_ipf[0] #define f_fout f_ipf[1] #define f_acctin f_acct[0] #define f_acctout f_acct[1] #define IPF_FEAT_LKM 0x001 #define IPF_FEAT_LOG 0x002 #define IPF_FEAT_LOOKUP 0x004 #define IPF_FEAT_BPF 0x008 #define IPF_FEAT_COMPILED 0x010 #define IPF_FEAT_CKSUM 0x020 #define IPF_FEAT_SYNC 0x040 #define IPF_FEAT_SCAN 0x080 #define IPF_FEAT_IPV6 0x100 typedef struct optlist { u_short ol_val; int ol_bit; } optlist_t; /* * Group list structure. */ typedef struct frgroup { struct frgroup *fg_next; struct frentry *fg_head; struct frentry *fg_start; struct frgroup **fg_set; u_32_t fg_flags; int fg_ref; char fg_name[FR_GROUPLEN]; } frgroup_t; #define FG_NAME(g) (*(g)->fg_name == '\0' ? "" : (g)->fg_name) /* * Used by state and NAT tables */ typedef struct icmpinfo { u_short ici_id; u_short ici_seq; u_char ici_type; } icmpinfo_t; typedef struct udpinfo { u_short us_sport; u_short us_dport; } udpinfo_t; typedef struct tcpdata { u_32_t td_end; u_32_t td_maxend; u_32_t td_maxwin; u_32_t td_winscale; u_32_t td_maxseg; int td_winflags; } tcpdata_t; #define TCP_WSCALE_MAX 14 #define TCP_WSCALE_SEEN 0x00000001 #define TCP_WSCALE_FIRST 0x00000002 #define TCP_SACK_PERMIT 0x00000004 typedef struct tcpinfo { u_32_t ts_sport; u_32_t ts_dport; tcpdata_t ts_data[2]; } tcpinfo_t; /* * Structures to define a GRE header as seen in a packet. */ struct grebits { #if defined(sparc) u_32_t grb_ver:3; u_32_t grb_flags:3; u_32_t grb_A:1; u_32_t grb_recur:1; u_32_t grb_s:1; u_32_t grb_S:1; u_32_t grb_K:1; u_32_t grb_R:1; u_32_t grb_C:1; #else u_32_t grb_C:1; u_32_t grb_R:1; u_32_t grb_K:1; u_32_t grb_S:1; u_32_t grb_s:1; u_32_t grb_recur:1; u_32_t grb_A:1; u_32_t grb_flags:3; u_32_t grb_ver:3; #endif u_short grb_ptype; }; typedef struct grehdr { union { struct grebits gru_bits; u_short gru_flags; } gr_un; u_short gr_len; u_short gr_call; } grehdr_t; #define gr_flags gr_un.gru_flags #define gr_bits gr_un.gru_bits #define gr_ptype gr_bits.grb_ptype #define gr_C gr_bits.grb_C #define gr_R gr_bits.grb_R #define gr_K gr_bits.grb_K #define gr_S gr_bits.grb_S #define gr_s gr_bits.grb_s #define gr_recur gr_bits.grb_recur #define gr_A gr_bits.grb_A #define gr_ver gr_bits.grb_ver /* * GRE information tracked by "keep state" */ typedef struct greinfo { u_short gs_call[2]; u_short gs_flags; u_short gs_ptype; } greinfo_t; #define GRE_REV(x) ((ntohs(x) >> 13) & 7) /* * Format of an Authentication header */ typedef struct authhdr { u_char ah_next; u_char ah_plen; u_short ah_reserved; u_32_t ah_spi; u_32_t ah_seq; /* Following the sequence number field is 0 or more bytes of */ /* authentication data, as specified by ah_plen - RFC 2402. */ } authhdr_t; /* * Timeout tail queue list member */ typedef struct ipftqent { struct ipftqent **tqe_pnext; struct ipftqent *tqe_next; struct ipftq *tqe_ifq; void *tqe_parent; /* pointer back to NAT/state struct */ u_32_t tqe_die; /* when this entriy is to die */ u_32_t tqe_touched; int tqe_flags; int tqe_state[2]; /* current state of this entry */ } ipftqent_t; #define TQE_RULEBASED 0x00000001 #define TQE_DELETE 0x00000002 /* * Timeout tail queue head for IPFilter */ typedef struct ipftq { ipfmutex_t ifq_lock; u_int ifq_ttl; ipftqent_t *ifq_head; ipftqent_t **ifq_tail; struct ipftq *ifq_next; struct ipftq **ifq_pnext; int ifq_ref; u_int ifq_flags; } ipftq_t; #define IFQF_USER 0x01 /* User defined aging */ #define IFQF_DELETE 0x02 /* Marked for deletion */ #define IFQF_PROXY 0x04 /* Timeout queue in use by a proxy */ #define IPFTQ_INIT(x,y,z) do { \ (x)->ifq_ttl = (y); \ (x)->ifq_head = NULL; \ (x)->ifq_ref = 1; \ (x)->ifq_tail = &(x)->ifq_head; \ MUTEX_INIT(&(x)->ifq_lock, (z)); \ } while (0) #define IPF_HZ_MULT 1 #define IPF_HZ_DIVIDE 2 /* How many times a second ipfilter */ /* checks its timeout queues. */ #define IPF_TTLVAL(x) (((x) / IPF_HZ_MULT) * IPF_HZ_DIVIDE) typedef int (*ipftq_delete_fn_t)(struct ipf_main_softc_s *, void *); /* * Object structure description. For passing through in ioctls. */ typedef struct ipfobj { u_32_t ipfo_rev; /* IPFilter version number */ u_32_t ipfo_size; /* size of object at ipfo_ptr */ void *ipfo_ptr; /* pointer to object */ int ipfo_type; /* type of object being pointed to */ int ipfo_offset; /* bytes from ipfo_ptr where to start */ int ipfo_retval; /* return value */ u_char ipfo_xxxpad[28]; /* reserved for future use */ } ipfobj_t; #define IPFOBJ_FRENTRY 0 /* struct frentry */ #define IPFOBJ_IPFSTAT 1 /* struct friostat */ #define IPFOBJ_IPFINFO 2 /* struct fr_info */ #define IPFOBJ_AUTHSTAT 3 /* struct fr_authstat */ #define IPFOBJ_FRAGSTAT 4 /* struct ipfrstat */ #define IPFOBJ_IPNAT 5 /* struct ipnat */ #define IPFOBJ_NATSTAT 6 /* struct natstat */ #define IPFOBJ_STATESAVE 7 /* struct ipstate_save */ #define IPFOBJ_NATSAVE 8 /* struct nat_save */ #define IPFOBJ_NATLOOKUP 9 /* struct natlookup */ #define IPFOBJ_IPSTATE 10 /* struct ipstate */ #define IPFOBJ_STATESTAT 11 /* struct ips_stat */ #define IPFOBJ_FRAUTH 12 /* struct frauth */ #define IPFOBJ_TUNEABLE 13 /* struct ipftune */ #define IPFOBJ_NAT 14 /* struct nat */ #define IPFOBJ_IPFITER 15 /* struct ipfruleiter */ #define IPFOBJ_GENITER 16 /* struct ipfgeniter */ #define IPFOBJ_GTABLE 17 /* struct ipftable */ #define IPFOBJ_LOOKUPITER 18 /* struct ipflookupiter */ #define IPFOBJ_STATETQTAB 19 /* struct ipftq * NSTATES */ #define IPFOBJ_IPFEXPR 20 #define IPFOBJ_PROXYCTL 21 /* strct ap_ctl */ #define IPFOBJ_FRIPF 22 /* structfripf */ #define IPFOBJ_COUNT 23 /* How many #defines are above this? */ typedef union ipftunevalptr { void *ipftp_void; u_long *ipftp_long; u_int *ipftp_int; u_short *ipftp_short; u_char *ipftp_char; u_long ipftp_offset; } ipftunevalptr_t; typedef union ipftuneval { u_long ipftu_long; u_int ipftu_int; u_short ipftu_short; u_char ipftu_char; } ipftuneval_t; struct ipftuneable; typedef int (* ipftunefunc_t) __P((struct ipf_main_softc_s *, struct ipftuneable *, ipftuneval_t *)); typedef struct ipftuneable { ipftunevalptr_t ipft_una; const char *ipft_name; u_long ipft_min; u_long ipft_max; int ipft_sz; int ipft_flags; struct ipftuneable *ipft_next; ipftunefunc_t ipft_func; } ipftuneable_t; #define ipft_addr ipft_una.ipftp_void #define ipft_plong ipft_una.ipftp_long #define ipft_pint ipft_una.ipftp_int #define ipft_pshort ipft_una.ipftp_short #define ipft_pchar ipft_una.ipftp_char #define IPFT_RDONLY 1 /* read-only */ #define IPFT_WRDISABLED 2 /* write when disabled only */ typedef struct ipftune { void *ipft_cookie; ipftuneval_t ipft_un; u_long ipft_min; u_long ipft_max; int ipft_sz; int ipft_flags; char ipft_name[80]; } ipftune_t; #define ipft_vlong ipft_un.ipftu_long #define ipft_vint ipft_un.ipftu_int #define ipft_vshort ipft_un.ipftu_short #define ipft_vchar ipft_un.ipftu_char /* * Hash table header */ #define IPFHASH(x,y) typedef struct { \ ipfrwlock_t ipfh_lock; \ struct x *ipfh_head; \ } y /* ** HPUX Port */ #ifdef __hpux /* HP-UX locking sequence deadlock detection module lock MAJOR ID */ # define IPF_SMAJ 0 /* temp assignment XXX, not critical */ #endif #if !defined(CDEV_MAJOR) && defined (__FreeBSD_version) && \ (__FreeBSD_version >= 220000) # define CDEV_MAJOR 79 #endif /* * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns * on those hooks. We don't need any special mods in non-IP Filter code * with this! */ #if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ (defined(NetBSD1_2) && NetBSD1_2 > 1) || \ (defined(__FreeBSD__) && (__FreeBSD_version >= 500043)) # if (defined(NetBSD) && NetBSD >= 199905) # define PFIL_HOOKS # endif # ifdef PFIL_HOOKS # define NETBSD_PF # endif #endif #ifdef _KERNEL # define FR_VERBOSE(verb_pr) # define FR_DEBUG(verb_pr) #else extern void ipfkdebug __P((char *, ...)); extern void ipfkverbose __P((char *, ...)); # define FR_VERBOSE(verb_pr) ipfkverbose verb_pr # define FR_DEBUG(verb_pr) ipfkdebug verb_pr #endif /* * */ typedef struct ipfruleiter { int iri_inout; char iri_group[FR_GROUPLEN]; int iri_active; int iri_nrules; int iri_v; /* No longer used (compatibility) */ frentry_t *iri_rule; } ipfruleiter_t; /* * Values for iri_inout */ #define F_IN 0 #define F_OUT 1 #define F_ACIN 2 #define F_ACOUT 3 typedef struct ipfgeniter { int igi_type; int igi_nitems; void *igi_data; } ipfgeniter_t; #define IPFGENITER_IPF 0 #define IPFGENITER_NAT 1 #define IPFGENITER_IPNAT 2 #define IPFGENITER_FRAG 3 #define IPFGENITER_AUTH 4 #define IPFGENITER_STATE 5 #define IPFGENITER_NATFRAG 6 #define IPFGENITER_HOSTMAP 7 #define IPFGENITER_LOOKUP 8 typedef struct ipftable { int ita_type; void *ita_table; } ipftable_t; #define IPFTABLE_BUCKETS 1 #define IPFTABLE_BUCKETS_NATIN 2 #define IPFTABLE_BUCKETS_NATOUT 3 typedef struct ipf_v4_masktab_s { u_32_t imt4_active[33]; int imt4_masks[33]; int imt4_max; } ipf_v4_masktab_t; typedef struct ipf_v6_masktab_s { i6addr_t imt6_active[129]; int imt6_masks[129]; int imt6_max; } ipf_v6_masktab_t; /* * */ typedef struct ipftoken { struct ipftoken *ipt_next; struct ipftoken **ipt_pnext; void *ipt_ctx; void *ipt_data; u_long ipt_die; int ipt_type; int ipt_uid; int ipt_subtype; int ipt_ref; int ipt_complete; } ipftoken_t; /* * */ typedef struct ipfexp { int ipfe_cmd; int ipfe_not; int ipfe_narg; int ipfe_size; int ipfe_arg0[1]; } ipfexp_t; /* * Currently support commands (ipfe_cmd) * 32bits is split up follows: * aabbcccc * aa = 0 = packet matching, 1 = meta data matching * bb = IP protocol number * cccc = command */ #define IPF_EXP_IP_PR 0x00000001 #define IPF_EXP_IP_ADDR 0x00000002 #define IPF_EXP_IP_SRCADDR 0x00000003 #define IPF_EXP_IP_DSTADDR 0x00000004 #define IPF_EXP_IP6_ADDR 0x00000005 #define IPF_EXP_IP6_SRCADDR 0x00000006 #define IPF_EXP_IP6_DSTADDR 0x00000007 #define IPF_EXP_TCP_FLAGS 0x00060001 #define IPF_EXP_TCP_PORT 0x00060002 #define IPF_EXP_TCP_SPORT 0x00060003 #define IPF_EXP_TCP_DPORT 0x00060004 #define IPF_EXP_UDP_PORT 0x00110002 #define IPF_EXP_UDP_SPORT 0x00110003 #define IPF_EXP_UDP_DPORT 0x00110004 #define IPF_EXP_IDLE_GT 0x01000001 #define IPF_EXP_TCP_STATE 0x01060002 #define IPF_EXP_END 0xffffffff #define ONE_DAY IPF_TTLVAL(1 * 86400) /* 1 day */ #define FIVE_DAYS (5 * ONE_DAY) typedef struct ipf_main_softc_s { struct ipf_main_softc_s *ipf_next; ipfmutex_t ipf_rw; ipfmutex_t ipf_timeoutlock; ipfrwlock_t ipf_mutex; ipfrwlock_t ipf_frag; ipfrwlock_t ipf_global; ipfrwlock_t ipf_tokens; ipfrwlock_t ipf_state; ipfrwlock_t ipf_nat; ipfrwlock_t ipf_natfrag; ipfrwlock_t ipf_poolrw; int ipf_dynamic_softc; int ipf_refcnt; int ipf_running; int ipf_flags; int ipf_active; int ipf_control_forwarding; int ipf_update_ipid; int ipf_chksrc; /* causes a system crash if enabled */ int ipf_pass; int ipf_minttl; int ipf_icmpminfragmtu; int ipf_interror; /* Should be in a struct that is per */ /* thread or process. Does not belong */ /* here but there's a lot more work */ /* in doing that properly. For now, */ /* it is squatting. */ u_int ipf_tcpidletimeout; u_int ipf_tcpclosewait; u_int ipf_tcplastack; u_int ipf_tcptimewait; u_int ipf_tcptimeout; u_int ipf_tcpsynsent; u_int ipf_tcpsynrecv; u_int ipf_tcpclosed; u_int ipf_tcphalfclosed; u_int ipf_udptimeout; u_int ipf_udpacktimeout; u_int ipf_icmptimeout; u_int ipf_icmpacktimeout; u_int ipf_iptimeout; u_long ipf_ticks; u_long ipf_userifqs; u_long ipf_rb_no_mem; u_long ipf_rb_node_max; u_long ipf_frouteok[2]; ipftuneable_t *ipf_tuners; void *ipf_frag_soft; void *ipf_nat_soft; void *ipf_state_soft; void *ipf_auth_soft; void *ipf_proxy_soft; void *ipf_sync_soft; void *ipf_lookup_soft; void *ipf_log_soft; struct frgroup *ipf_groups[IPL_LOGSIZE][2]; frentry_t *ipf_rules[2][2]; frentry_t *ipf_acct[2][2]; frentry_t *ipf_rule_explist[2]; ipftoken_t *ipf_token_head; ipftoken_t **ipf_token_tail; #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) && \ defined(_KERNEL) struct callout ipf_slow_ch; #endif #if defined(linux) && defined(_KERNEL) struct timer_list ipf_timer; #endif #if NETBSD_GE_REV(104040000) struct callout ipf_slow_ch; #endif #if SOLARIS # if SOLARIS2 >= 7 timeout_id_t ipf_slow_ch; # else int ipf_slow_ch; # endif #endif #if defined(_KERNEL) # if SOLARIS struct pollhead ipf_poll_head[IPL_LOGSIZE]; void *ipf_dip; # if defined(INSTANCES) int ipf_get_loopback; u_long ipf_idnum; net_handle_t ipf_nd_v4; net_handle_t ipf_nd_v6; hook_t *ipf_hk_v4_in; hook_t *ipf_hk_v4_out; hook_t *ipf_hk_v4_nic; hook_t *ipf_hk_v6_in; hook_t *ipf_hk_v6_out; hook_t *ipf_hk_v6_nic; hook_t *ipf_hk_loop_v4_in; hook_t *ipf_hk_loop_v4_out; hook_t *ipf_hk_loop_v6_in; hook_t *ipf_hk_loop_v6_out; # endif # else # if defined(linux) && defined(_KERNEL) struct poll_table_struct ipf_selwait[IPL_LOGSIZE]; wait_queue_head_t iplh_linux[IPL_LOGSIZE]; # else struct selinfo ipf_selwait[IPL_LOGSIZE]; # endif # endif #endif void *ipf_slow; ipf_statistics_t ipf_stats[2]; u_char ipf_iss_secret[32]; u_short ipf_ip_id; } ipf_main_softc_t; #define IPFERROR(_e) do { softc->ipf_interror = (_e); \ DT1(user_error, int, _e); \ } while (0) #ifndef _KERNEL extern int ipf_check __P((void *, struct ip *, int, void *, int, mb_t **)); extern struct ifnet *get_unit __P((char *, int)); extern char *get_ifname __P((struct ifnet *)); extern int ipfioctl __P((ipf_main_softc_t *, int, ioctlcmd_t, caddr_t, int)); extern void m_freem __P((mb_t *)); extern size_t msgdsize __P((mb_t *)); extern int bcopywrap __P((void *, void *, size_t)); extern void ip_fillid(struct ip *); #else /* #ifndef _KERNEL */ # if defined(__NetBSD__) && defined(PFIL_HOOKS) extern void ipfilterattach __P((int)); # endif extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); # ifdef MENTAT extern int ipf_check __P((void *, struct ip *, int, void *, int, void *, mblk_t **)); # if SOLARIS extern void ipf_prependmbt(fr_info_t *, mblk_t *); # if SOLARIS2 >= 7 extern int ipfioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); # else extern int ipfioctl __P((dev_t, int, int *, int, cred_t *, int *)); # endif # endif # ifdef __hpux extern int ipfioctl __P((dev_t, int, caddr_t, int)); extern int ipf_select __P((dev_t, int)); # endif extern int ipf_qout __P((queue_t *, mblk_t *)); # else /* MENTAT */ extern int ipf_check __P((void *, struct ip *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); extern size_t mbufchainlen __P((mb_t *)); # ifdef __sgi # include extern int ipfioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); extern int ipfilter_sgi_attach __P((void)); extern void ipfilter_sgi_detach __P((void)); extern void ipfilter_sgi_intfsync __P((void)); # else # ifdef IPFILTER_LKM extern int ipf_identify __P((char *)); # endif # if BSDOS_GE_REV(199510) || FREEBSD_GE_REV(220000) || \ (defined(NetBSD) && (NetBSD >= 199511)) || defined(__OpenBSD__) # if defined(__NetBSD__) || BSDOS_GE_REV(199701) || \ defined(__OpenBSD__) || FREEBSD_GE_REV(300000) # if (__FreeBSD_version >= 500024) # if (__FreeBSD_version >= 502116) extern int ipfioctl __P((struct cdev*, u_long, caddr_t, int, struct thread *)); # else extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct thread *)); # endif /* __FreeBSD_version >= 502116 */ # else # if NETBSD_GE_REV(499001000) extern int ipfioctl __P((dev_t, u_long, void *, int, struct lwp *)); # else # if NETBSD_GE_REV(399001400) extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct lwp *)); # else extern int ipfioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); # endif # endif # endif /* __FreeBSD_version >= 500024 */ # else extern int ipfioctl __P((dev_t, int, caddr_t, int, struct proc *)); # endif # else # ifdef linux extern int ipfioctl __P((struct inode *, struct file *, u_int, u_long)); # else extern int ipfioctl __P((dev_t, int, caddr_t, int)); # endif # endif /* (_BSDI_VERSION >= 199510) */ # endif /* __ sgi */ # endif /* MENTAT */ # if defined(__FreeBSD_version) extern int ipf_pfil_hook __P((void)); extern int ipf_pfil_unhook __P((void)); extern void ipf_event_reg __P((void)); extern void ipf_event_dereg __P((void)); # endif # if defined(INSTANCES) extern ipf_main_softc_t *ipf_find_softc __P((u_long)); extern int ipf_set_loopback __P((ipf_main_softc_t *, ipftuneable_t *, ipftuneval_t *)); # endif #endif /* #ifndef _KERNEL */ extern char *memstr __P((const char *, char *, size_t, size_t)); extern int count4bits __P((u_32_t)); #ifdef USE_INET6 extern int count6bits __P((u_32_t *)); #endif extern int frrequest __P((ipf_main_softc_t *, int, ioctlcmd_t, caddr_t, int, int)); extern char *getifname __P((struct ifnet *)); extern int ipfattach __P((ipf_main_softc_t *)); extern int ipfdetach __P((ipf_main_softc_t *)); extern u_short ipf_cksum __P((u_short *, int)); extern int copyinptr __P((ipf_main_softc_t *, void *, void *, size_t)); extern int copyoutptr __P((ipf_main_softc_t *, void *, void *, size_t)); extern int ipf_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *)); extern int ipf_inject __P((fr_info_t *, mb_t *)); extern int ipf_inobj __P((ipf_main_softc_t *, void *, ipfobj_t *, void *, int)); extern int ipf_inobjsz __P((ipf_main_softc_t *, void *, void *, int , int)); extern int ipf_ioctlswitch __P((ipf_main_softc_t *, int, void *, ioctlcmd_t, int, int, void *)); extern int ipf_ipf_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); extern int ipf_ipftune __P((ipf_main_softc_t *, ioctlcmd_t, void *)); extern int ipf_matcharray_load __P((ipf_main_softc_t *, caddr_t, ipfobj_t *, int **)); extern int ipf_matcharray_verify __P((int *, int)); extern int ipf_outobj __P((ipf_main_softc_t *, void *, void *, int)); extern int ipf_outobjk __P((ipf_main_softc_t *, ipfobj_t *, void *)); extern int ipf_outobjsz __P((ipf_main_softc_t *, void *, void *, int, int)); extern void *ipf_pullup __P((mb_t *, fr_info_t *, int)); extern int ipf_resolvedest __P((ipf_main_softc_t *, char *, struct frdest *, int)); extern int ipf_resolvefunc __P((ipf_main_softc_t *, void *)); extern void *ipf_resolvenic __P((ipf_main_softc_t *, char *, int)); extern int ipf_send_icmp_err __P((int, fr_info_t *, int)); extern int ipf_send_reset __P((fr_info_t *)); #if (defined(__FreeBSD_version) && (__FreeBSD_version < 501000)) || \ !defined(_KERNEL) || defined(linux) #endif extern void ipf_apply_timeout __P((ipftq_t *, u_int)); extern ipftq_t *ipf_addtimeoutqueue __P((ipf_main_softc_t *, ipftq_t **, u_int)); extern void ipf_deletequeueentry __P((ipftqent_t *)); extern int ipf_deletetimeoutqueue __P((ipftq_t *)); extern void ipf_freetimeoutqueue __P((ipf_main_softc_t *, ipftq_t *)); extern void ipf_movequeue __P((u_long, ipftqent_t *, ipftq_t *, ipftq_t *)); extern void ipf_queueappend __P((u_long, ipftqent_t *, ipftq_t *, void *)); extern void ipf_queueback __P((u_long, ipftqent_t *)); extern int ipf_queueflush __P((ipf_main_softc_t *, ipftq_delete_fn_t, ipftq_t *, ipftq_t *, u_int *, int, int)); extern void ipf_queuefront __P((ipftqent_t *)); extern int ipf_settimeout_tcp __P((ipftuneable_t *, ipftuneval_t *, ipftq_t *)); extern int ipf_checkv4sum __P((fr_info_t *)); extern int ipf_checkl4sum __P((fr_info_t *)); extern int ipf_ifpfillv4addr __P((int, struct sockaddr_in *, struct sockaddr_in *, struct in_addr *, struct in_addr *)); extern int ipf_coalesce __P((fr_info_t *)); #ifdef USE_INET6 extern int ipf_checkv6sum __P((fr_info_t *)); extern int ipf_ifpfillv6addr __P((int, struct sockaddr_in6 *, struct sockaddr_in6 *, i6addr_t *, i6addr_t *)); #endif extern int ipf_tune_add __P((ipf_main_softc_t *, ipftuneable_t *)); extern int ipf_tune_add_array __P((ipf_main_softc_t *, ipftuneable_t *)); extern int ipf_tune_del __P((ipf_main_softc_t *, ipftuneable_t *)); extern int ipf_tune_del_array __P((ipf_main_softc_t *, ipftuneable_t *)); extern int ipf_tune_array_link __P((ipf_main_softc_t *, ipftuneable_t *)); extern int ipf_tune_array_unlink __P((ipf_main_softc_t *, ipftuneable_t *)); extern ipftuneable_t *ipf_tune_array_copy __P((void *, size_t, ipftuneable_t *)); extern int ipf_pr_pullup __P((fr_info_t *, int)); extern int ipf_flush __P((ipf_main_softc_t *, minor_t, int)); extern frgroup_t *ipf_group_add __P((ipf_main_softc_t *, char *, void *, u_32_t, minor_t, int)); extern void ipf_group_del __P((ipf_main_softc_t *, frgroup_t *, frentry_t *)); extern int ipf_derefrule __P((ipf_main_softc_t *, frentry_t **)); extern frgroup_t *ipf_findgroup __P((ipf_main_softc_t *, char *, minor_t, int, frgroup_t ***)); extern int ipf_log_init __P((void)); extern int ipf_log_bytesused __P((ipf_main_softc_t *, int)); extern int ipf_log_canread __P((ipf_main_softc_t *, int)); extern int ipf_log_clear __P((ipf_main_softc_t *, minor_t)); extern u_long ipf_log_failures __P((ipf_main_softc_t *, int)); extern int ipf_log_read __P((ipf_main_softc_t *, minor_t, uio_t *)); extern int ipf_log_items __P((ipf_main_softc_t *, int, fr_info_t *, void **, size_t *, int *, int)); extern u_long ipf_log_logok __P((ipf_main_softc_t *, int)); extern void ipf_log_unload __P((ipf_main_softc_t *)); extern int ipf_log_pkt __P((fr_info_t *, u_int)); extern frentry_t *ipf_acctpkt __P((fr_info_t *, u_32_t *)); extern u_short fr_cksum __P((fr_info_t *, ip_t *, int, void *)); extern void ipf_deinitialise __P((ipf_main_softc_t *)); extern int ipf_deliverlocal __P((ipf_main_softc_t *, int, void *, i6addr_t *)); extern frentry_t *ipf_dstgrpmap __P((fr_info_t *, u_32_t *)); extern void ipf_fixskip __P((frentry_t **, frentry_t *, int)); extern void ipf_forgetifp __P((ipf_main_softc_t *, void *)); extern frentry_t *ipf_getrulen __P((ipf_main_softc_t *, int, char *, u_32_t)); extern int ipf_ifpaddr __P((ipf_main_softc_t *, int, int, void *, i6addr_t *, i6addr_t *)); extern void ipf_inet_mask_add __P((int, ipf_v4_masktab_t *)); extern void ipf_inet_mask_del __P((int, ipf_v4_masktab_t *)); #ifdef USE_INET6 extern void ipf_inet6_mask_add __P((int, i6addr_t *, ipf_v6_masktab_t *)); extern void ipf_inet6_mask_del __P((int, i6addr_t *, ipf_v6_masktab_t *)); #endif extern int ipf_initialise __P((void)); extern int ipf_lock __P((caddr_t, int *)); extern int ipf_makefrip __P((int, ip_t *, fr_info_t *)); extern int ipf_matchtag __P((ipftag_t *, ipftag_t *)); extern int ipf_matchicmpqueryreply __P((int, icmpinfo_t *, struct icmp *, int)); extern u_32_t ipf_newisn __P((fr_info_t *)); extern u_int ipf_pcksum __P((fr_info_t *, int, u_int)); extern void ipf_rule_expire __P((ipf_main_softc_t *)); extern int ipf_scanlist __P((fr_info_t *, u_32_t)); extern frentry_t *ipf_srcgrpmap __P((fr_info_t *, u_32_t *)); extern int ipf_tcpudpchk __P((fr_ip_t *, frtuc_t *)); extern int ipf_verifysrc __P((fr_info_t *fin)); extern int ipf_zerostats __P((ipf_main_softc_t *, char *)); extern int ipf_getnextrule __P((ipf_main_softc_t *, ipftoken_t *, void *)); extern int ipf_sync __P((ipf_main_softc_t *, void *)); extern int ipf_token_deref __P((ipf_main_softc_t *, ipftoken_t *)); extern void ipf_token_expire __P((ipf_main_softc_t *)); extern ipftoken_t *ipf_token_find __P((ipf_main_softc_t *, int, int, void *)); extern int ipf_token_del __P((ipf_main_softc_t *, int, int, void *)); extern void ipf_token_mark_complete __P((ipftoken_t *)); extern int ipf_genericiter __P((ipf_main_softc_t *, void *, int, void *)); #ifdef IPFILTER_LOOKUP extern void *ipf_resolvelookup __P((int, u_int, u_int, lookupfunc_t *)); #endif extern u_32_t ipf_random __P((void)); extern int ipf_main_load __P((void)); extern void *ipf_main_soft_create __P((void *)); extern void ipf_main_soft_destroy __P((ipf_main_softc_t *)); extern int ipf_main_soft_init __P((ipf_main_softc_t *)); extern int ipf_main_soft_fini __P((ipf_main_softc_t *)); extern int ipf_main_unload __P((void)); extern int ipf_load_all __P((void)); extern int ipf_unload_all __P((void)); extern void ipf_destroy_all __P((ipf_main_softc_t *)); extern ipf_main_softc_t *ipf_create_all __P((void *)); extern int ipf_init_all __P((ipf_main_softc_t *)); extern int ipf_fini_all __P((ipf_main_softc_t *)); extern void ipf_log_soft_destroy __P((ipf_main_softc_t *, void *)); extern void *ipf_log_soft_create __P((ipf_main_softc_t *)); extern int ipf_log_soft_init __P((ipf_main_softc_t *, void *)); extern int ipf_log_soft_fini __P((ipf_main_softc_t *, void *)); extern int ipf_log_main_load __P((void)); extern int ipf_log_main_unload __P((void)); extern char ipfilter_version[]; #ifdef USE_INET6 extern int icmptoicmp6types[ICMP_MAXTYPE+1]; extern int icmptoicmp6unreach[ICMP_MAX_UNREACH]; extern int icmpreplytype6[ICMP6_MAXTYPE + 1]; #endif #ifdef IPFILTER_COMPAT extern int ipf_in_compat __P((ipf_main_softc_t *, ipfobj_t *, void *,int)); extern int ipf_out_compat __P((ipf_main_softc_t *, ipfobj_t *, void *)); #endif extern int icmpreplytype4[ICMP_MAXTYPE + 1]; extern int ipf_ht_node_add __P((ipf_main_softc_t *, host_track_t *, int, i6addr_t *)); extern int ipf_ht_node_del __P((host_track_t *, int, i6addr_t *)); extern void ipf_rb_ht_flush __P((host_track_t *)); extern void ipf_rb_ht_freenode __P((host_node_t *, void *)); extern void ipf_rb_ht_init __P((host_track_t *)); #endif /* __IP_FIL_H__ */ Index: projects/clang390-import/sys/contrib/ipfilter/netinet/ip_log.c =================================================================== --- projects/clang390-import/sys/contrib/ipfilter/netinet/ip_log.c (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter/netinet/ip_log.c (revision 304965) @@ -1,951 +1,955 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $FreeBSD$ * Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $ */ #include #if defined(KERNEL) || defined(_KERNEL) # undef KERNEL # undef _KERNEL # define KERNEL 1 # define _KERNEL 1 #endif #if defined(__FreeBSD__) && !defined(_KERNEL) # include #endif #ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #include #include #include #ifndef _KERNEL # include # include # include # include # define _KERNEL # define KERNEL # ifdef __OpenBSD__ struct file; # endif # include # undef _KERNEL # undef KERNEL #endif #if (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) && \ defined(_KERNEL) # include # include #else # include #endif #include #if defined(_KERNEL) # include # if (defined(NetBSD) && (__NetBSD_Version__ >= 104000000)) # include # endif #endif /* _KERNEL */ #if !SOLARIS && !defined(__hpux) && !defined(linux) # if (defined(NetBSD) && (NetBSD > 199609)) || \ (defined(OpenBSD) && (OpenBSD > 199603)) || \ (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) # include # else # include # endif # include # include # if __FreeBSD_version >= 500000 # include # endif #else # if !defined(__hpux) && defined(_KERNEL) # include # include # include # include # include # include # include # include # include # endif /* !__hpux */ #endif /* !SOLARIS && !__hpux */ #if !defined(linux) # include #endif #include #include #ifdef sun # include #endif #if __FreeBSD_version >= 300000 # include #endif #include #ifdef __sgi # include # ifdef IFF_DRVRLOCK /* IRIX6 */ # include # endif #endif #if !defined(__hpux) && !defined(linux) && \ !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ # include #endif #include #include #include #include #include #ifdef USE_INET6 # include #endif #if !defined(linux) # include #endif #ifndef _KERNEL # include #endif #include "netinet/ip_compat.h" #include #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_auth.h" #if (__FreeBSD_version >= 300000) || defined(__NetBSD__) # include #endif /* END OF INCLUDES */ #ifdef IPFILTER_LOG # if defined(IPL_SELECT) # include # include # define READ_COLLISION 0x001 extern int selwait; # endif /* IPL_SELECT */ typedef struct ipf_log_softc_s { ipfmutex_t ipl_mutex[IPL_LOGSIZE]; # if SOLARIS && defined(_KERNEL) kcondvar_t ipl_wait[IPL_LOGSIZE]; # endif # if defined(linux) && defined(_KERNEL) wait_queue_head_t iplh_linux[IPL_LOGSIZE]; # endif # if defined(__hpux) && defined(_KERNEL) iplog_select_t ipl_ss[IPL_LOGSIZE]; # endif iplog_t **iplh[IPL_LOGSIZE]; iplog_t *iplt[IPL_LOGSIZE]; iplog_t *ipll[IPL_LOGSIZE]; u_long ipl_logfail[IPL_LOGSIZE]; u_long ipl_logok[IPL_LOGSIZE]; fr_info_t ipl_crc[IPL_LOGSIZE]; u_32_t ipl_counter[IPL_LOGSIZE]; int ipl_suppress; int ipl_logall; int ipl_log_init; int ipl_logsize; int ipl_used[IPL_LOGSIZE]; int ipl_magic[IPL_LOGSIZE]; ipftuneable_t *ipf_log_tune; int ipl_readers[IPL_LOGSIZE]; } ipf_log_softc_t; static int magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE, IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, IPL_MAGIC }; static ipftuneable_t ipf_log_tuneables[] = { /* log */ { { (void *)offsetof(ipf_log_softc_t, ipl_suppress) }, "log_suppress", 0, 1, stsizeof(ipf_log_softc_t, ipl_suppress), 0, NULL, NULL }, { { (void *)offsetof(ipf_log_softc_t, ipl_logall) }, "log_all", 0, 1, stsizeof(ipf_log_softc_t, ipl_logall), 0, NULL, NULL }, { { (void *)offsetof(ipf_log_softc_t, ipl_logsize) }, "log_size", 0, 0x80000, stsizeof(ipf_log_softc_t, ipl_logsize), 0, NULL, NULL }, { { NULL }, NULL, 0, 0, 0, 0, NULL, NULL } }; int ipf_log_main_load() { return 0; } int ipf_log_main_unload() { return 0; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_soft_create */ /* Returns: void * - NULL = failure, else pointer to log context data */ /* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Initialise log buffers & pointers. Also iniialised the CRC to a local */ /* secret for use in calculating the "last log checksum". */ /* ------------------------------------------------------------------------ */ void * ipf_log_soft_create(softc) ipf_main_softc_t *softc; { ipf_log_softc_t *softl; int i; KMALLOC(softl, ipf_log_softc_t *); if (softl == NULL) return NULL; bzero((char *)softl, sizeof(*softl)); bcopy((char *)magic, (char *)softl->ipl_magic, sizeof(magic)); softl->ipf_log_tune = ipf_tune_array_copy(softl, sizeof(ipf_log_tuneables), ipf_log_tuneables); if (softl->ipf_log_tune == NULL) { ipf_log_soft_destroy(softc, softl); return NULL; } if (ipf_tune_array_link(softc, softl->ipf_log_tune) == -1) { ipf_log_soft_destroy(softc, softl); return NULL; } for (i = IPL_LOGMAX; i >= 0; i--) { MUTEX_INIT(&softl->ipl_mutex[i], "ipf log mutex"); } softl->ipl_suppress = 1; softl->ipl_logall = 0; softl->ipl_log_init = 0; softl->ipl_logsize = IPFILTER_LOGSIZE; return softl; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_soft_init */ /* Returns: int - 0 == success (always returned) */ /* Parameters: softc(I) - pointer to soft context main structure */ /* */ /* Initialise log buffers & pointers. Also iniialised the CRC to a local */ /* secret for use in calculating the "last log checksum". */ /* ------------------------------------------------------------------------ */ int ipf_log_soft_init(softc, arg) ipf_main_softc_t *softc; void *arg; { ipf_log_softc_t *softl = arg; int i; for (i = IPL_LOGMAX; i >= 0; i--) { softl->iplt[i] = NULL; softl->ipll[i] = NULL; softl->iplh[i] = &softl->iplt[i]; bzero((char *)&softl->ipl_crc[i], sizeof(softl->ipl_crc[i])); # ifdef IPL_SELECT softl->iplog_ss[i].read_waiter = 0; softl->iplog_ss[i].state = 0; # endif } softl->ipl_log_init = 1; return 0; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_soft_fini */ /* Parameters: softc(I) - pointer to soft context main structure */ /* arg(I) - pointer to log context structure */ /* */ /* Clean up any log data that has accumulated without being read. */ /* ------------------------------------------------------------------------ */ int ipf_log_soft_fini(softc, arg) ipf_main_softc_t *softc; void *arg; { ipf_log_softc_t *softl = arg; int i; if (softl->ipl_log_init == 0) return 0; softl->ipl_log_init = 0; for (i = IPL_LOGMAX; i >= 0; i--) { (void) ipf_log_clear(softc, i); /* * This is a busy-wait loop so as to avoid yet another lock * to wait on. */ MUTEX_ENTER(&softl->ipl_mutex[i]); while (softl->ipl_readers[i] > 0) { # if SOLARIS && defined(_KERNEL) cv_broadcast(&softl->ipl_wait[i]); MUTEX_EXIT(&softl->ipl_mutex[i]); delay(100); pollwakeup(&softc->ipf_poll_head[i], POLLRDNORM); # else MUTEX_EXIT(&softl->ipl_mutex[i]); WAKEUP(softl->iplh, i); POLLWAKEUP(i); # endif MUTEX_ENTER(&softl->ipl_mutex[i]); } MUTEX_EXIT(&softl->ipl_mutex[i]); } return 0; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_soft_destroy */ /* Parameters: softc(I) - pointer to soft context main structure */ /* arg(I) - pointer to log context structure */ /* */ /* When this function is called, it is expected that there are no longer */ /* any threads active in the reading code path or the logging code path. */ /* ------------------------------------------------------------------------ */ void ipf_log_soft_destroy(softc, arg) ipf_main_softc_t *softc; void *arg; { ipf_log_softc_t *softl = arg; int i; for (i = IPL_LOGMAX; i >= 0; i--) { # if SOLARIS && defined(_KERNEL) cv_destroy(&softl->ipl_wait[i]); # endif MUTEX_DESTROY(&softl->ipl_mutex[i]); } if (softl->ipf_log_tune != NULL) { ipf_tune_array_unlink(softc, softl->ipf_log_tune); KFREES(softl->ipf_log_tune, sizeof(ipf_log_tuneables)); softl->ipf_log_tune = NULL; } KFREE(softl); } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_pkt */ /* Returns: int - 0 == success, -1 == failure */ /* Parameters: fin(I) - pointer to packet information */ /* flags(I) - flags from filter rules */ /* */ /* Create a log record for a packet given that it has been triggered by a */ /* rule (or the default setting). Calculate the transport protocol header */ /* size using predetermined size of a couple of popular protocols and thus */ /* how much data to copy into the log, including part of the data body if */ /* requested. */ /* ------------------------------------------------------------------------ */ int ipf_log_pkt(fin, flags) fr_info_t *fin; u_int flags; { ipf_main_softc_t *softc = fin->fin_main_soft; ipf_log_softc_t *softl = softc->ipf_log_soft; register size_t hlen; int types[2], mlen; size_t sizes[2]; void *ptrs[2]; ipflog_t ipfl; u_char p; mb_t *m; # if (SOLARIS || defined(__hpux)) && defined(_KERNEL) && !defined(FW_HOOKS) qif_t *ifp; # else struct ifnet *ifp; # endif /* SOLARIS || __hpux */ m = fin->fin_m; if (m == NULL) return -1; ipfl.fl_nattag.ipt_num[0] = 0; ifp = fin->fin_ifp; hlen = (char *)fin->fin_dp - (char *)fin->fin_ip; /* * calculate header size. */ if (fin->fin_off == 0) { p = fin->fin_fi.fi_p; if (p == IPPROTO_TCP) hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); else if (p == IPPROTO_UDP) hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); else if (p == IPPROTO_ICMP) { struct icmp *icmp; icmp = (struct icmp *)fin->fin_dp; /* * For ICMP, if the packet is an error packet, also * include the information about the packet which * caused the error. */ switch (icmp->icmp_type) { case ICMP_UNREACH : case ICMP_SOURCEQUENCH : case ICMP_REDIRECT : case ICMP_TIMXCEED : case ICMP_PARAMPROB : hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen); break; default : hlen += MIN(sizeof(struct icmp), fin->fin_dlen); break; } } # ifdef USE_INET6 else if (p == IPPROTO_ICMPV6) { struct icmp6_hdr *icmp; icmp = (struct icmp6_hdr *)fin->fin_dp; /* * For ICMPV6, if the packet is an error packet, also * include the information about the packet which * caused the error. */ if (icmp->icmp6_type < 128) { hlen += MIN(sizeof(struct icmp6_hdr) + 8, fin->fin_dlen); } else { hlen += MIN(sizeof(struct icmp6_hdr), fin->fin_dlen); } } # endif } /* * Get the interface number and name to which this packet is * currently associated. */ # if (SOLARIS || defined(__hpux)) && defined(_KERNEL) # if !defined(FW_HOOKS) ipfl.fl_unit = (u_int)ifp->qf_ppa; # endif COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ OPENBSD_GE_REV(199603) || defined(linux) || FREEBSD_GE_REV(501113) COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname); # else ipfl.fl_unit = (u_int)ifp->if_unit; # if defined(_KERNEL) if ((ipfl.fl_ifname[0] = ifp->if_name[0])) if ((ipfl.fl_ifname[1] = ifp->if_name[1])) if ((ipfl.fl_ifname[2] = ifp->if_name[2])) ipfl.fl_ifname[3] = ifp->if_name[3]; # else (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0'; # endif # endif # endif /* __hpux || SOLARIS */ mlen = fin->fin_plen - hlen; if (!softl->ipl_logall) { mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0; } else if ((flags & FR_LOGBODY) == 0) { mlen = 0; } if (mlen < 0) mlen = 0; ipfl.fl_plen = (u_char)mlen; ipfl.fl_hlen = (u_char)hlen; ipfl.fl_rule = fin->fin_rule; (void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN); if (fin->fin_fr != NULL) { ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; ipfl.fl_logtag = fin->fin_fr->fr_logtag; } else { ipfl.fl_loglevel = 0xffff; ipfl.fl_logtag = FR_NOLOGTAG; } if (fin->fin_nattag != NULL) bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag, sizeof(ipfl.fl_nattag)); ipfl.fl_flags = flags; ipfl.fl_breason = (fin->fin_reason & 0xff); ipfl.fl_dir = fin->fin_out; ipfl.fl_lflags = fin->fin_flx; ipfl.fl_family = fin->fin_family; ptrs[0] = (void *)&ipfl; sizes[0] = sizeof(ipfl); types[0] = 0; # if defined(MENTAT) && defined(_KERNEL) /* * Are we copied from the mblk or an aligned array ? */ if (fin->fin_ip == (ip_t *)m->b_rptr) { ptrs[1] = m; sizes[1] = hlen + mlen; types[1] = 1; } else { ptrs[1] = fin->fin_ip; sizes[1] = hlen + mlen; types[1] = 0; } # else ptrs[1] = m; sizes[1] = hlen + mlen; types[1] = 1; # endif /* MENTAT */ return ipf_log_items(softc, IPL_LOGIPF, fin, ptrs, sizes, types, 2); } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_items */ /* Returns: int - 0 == success, -1 == failure */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* fin(I) - pointer to packet information */ /* items(I) - array of pointers to log data */ /* itemsz(I) - array of size of valid memory pointed to */ /* types(I) - type of data pointed to by items pointers */ /* cnt(I) - number of elements in arrays items/itemsz/types */ /* */ /* Takes an array of parameters and constructs one record to include the */ /* miscellaneous packet information, as well as packet data, for reading */ /* from the log device. */ /* ------------------------------------------------------------------------ */ int ipf_log_items(softc, unit, fin, items, itemsz, types, cnt) ipf_main_softc_t *softc; int unit; fr_info_t *fin; void **items; size_t *itemsz; int *types, cnt; { ipf_log_softc_t *softl = softc->ipf_log_soft; caddr_t buf, ptr; iplog_t *ipl; size_t len; int i; SPL_INT(s); /* * Get the total amount of data to be logged. */ for (i = 0, len = sizeof(iplog_t); i < cnt; i++) len += itemsz[i]; SPL_NET(s); MUTEX_ENTER(&softl->ipl_mutex[unit]); softl->ipl_counter[unit]++; /* * check that we have space to record this information and can * allocate that much. */ if ((softl->ipl_used[unit] + len) > softl->ipl_logsize) { softl->ipl_logfail[unit]++; MUTEX_EXIT(&softl->ipl_mutex[unit]); return -1; } KMALLOCS(buf, caddr_t, len); if (buf == NULL) { softl->ipl_logfail[unit]++; MUTEX_EXIT(&softl->ipl_mutex[unit]); return -1; } ipl = (iplog_t *)buf; ipl->ipl_magic = softl->ipl_magic[unit]; ipl->ipl_count = 1; ipl->ipl_seqnum = softl->ipl_counter[unit]; ipl->ipl_next = NULL; ipl->ipl_dsize = len; #ifdef _KERNEL GETKTIME(&ipl->ipl_sec); #else ipl->ipl_sec = 0; ipl->ipl_usec = 0; #endif /* * Loop through all the items to be logged, copying each one to the * buffer. Use bcopy for normal data or the mb_t copyout routine. */ for (i = 0, ptr = buf + sizeof(*ipl); i < cnt; i++) { if (types[i] == 0) { bcopy(items[i], ptr, itemsz[i]); } else if (types[i] == 1) { COPYDATA(items[i], 0, itemsz[i], ptr); } ptr += itemsz[i]; } /* * Check to see if this log record has a CRC which matches the last * record logged. If it does, just up the count on the previous one * rather than create a new one. */ if (softl->ipl_suppress) { if ((fin != NULL) && (fin->fin_off == 0)) { if ((softl->ipll[unit] != NULL) && (fin->fin_crc == softl->ipl_crc[unit].fin_crc) && bcmp((char *)fin, (char *)&softl->ipl_crc[unit], FI_LCSIZE) == 0) { softl->ipll[unit]->ipl_count++; MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); KFREES(buf, len); return 0; } bcopy((char *)fin, (char *)&softl->ipl_crc[unit], FI_LCSIZE); softl->ipl_crc[unit].fin_crc = fin->fin_crc; } else bzero((char *)&softl->ipl_crc[unit], FI_CSIZE); } /* * advance the log pointer to the next empty record and deduct the * amount of space we're going to use. */ softl->ipl_logok[unit]++; softl->ipll[unit] = ipl; *softl->iplh[unit] = ipl; softl->iplh[unit] = &ipl->ipl_next; softl->ipl_used[unit] += len; /* * Now that the log record has been completed and added to the queue, * wake up any listeners who may want to read it. */ # if SOLARIS && defined(_KERNEL) cv_signal(&softl->ipl_wait[unit]); MUTEX_EXIT(&softl->ipl_mutex[unit]); pollwakeup(&softc->ipf_poll_head[unit], POLLRDNORM); # else MUTEX_EXIT(&softl->ipl_mutex[unit]); WAKEUP(softl->iplh, unit); POLLWAKEUP(unit); # endif SPL_X(s); # ifdef IPL_SELECT iplog_input_ready(unit); # endif return 0; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_read */ /* Returns: int - 0 == success, else error value. */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* uio(O) - pointer to information about where to store data */ /* */ /* Called to handle a read on an IPFilter device. Returns only complete */ /* log messages - will not partially copy a log record out to userland. */ /* */ /* NOTE: This function will block and wait for a signal to return data if */ /* there is none present. Asynchronous I/O is not implemented. */ /* ------------------------------------------------------------------------ */ int ipf_log_read(softc, unit, uio) ipf_main_softc_t *softc; minor_t unit; struct uio *uio; { ipf_log_softc_t *softl = softc->ipf_log_soft; size_t dlen, copied; int error = 0; iplog_t *ipl; SPL_INT(s); if (softl->ipl_log_init == 0) { IPFERROR(40007); return 0; } /* * Sanity checks. Make sure the minor # is valid and we're copying * a valid chunk of data. */ if (IPL_LOGMAX < unit) { IPFERROR(40001); return ENXIO; } if (uio->uio_resid == 0) return 0; if (uio->uio_resid < sizeof(iplog_t)) { IPFERROR(40002); return EINVAL; } if (uio->uio_resid > softl->ipl_logsize) { IPFERROR(40005); return EINVAL; } /* * Lock the log so we can snapshot the variables. Wait for a signal * if the log is empty. */ SPL_NET(s); MUTEX_ENTER(&softl->ipl_mutex[unit]); softl->ipl_readers[unit]++; while (softl->ipl_log_init == 1 && softl->iplt[unit] == NULL) { # if SOLARIS && defined(_KERNEL) if (!cv_wait_sig(&softl->ipl_wait[unit], &softl->ipl_mutex[unit].ipf_lk)) { softl->ipl_readers[unit]--; MUTEX_EXIT(&softl->ipl_mutex[unit]); IPFERROR(40003); return EINTR; } # else # if defined(__hpux) && defined(_KERNEL) lock_t *l; # ifdef IPL_SELECT if (uio->uio_fpflags & (FNBLOCK|FNDELAY)) { /* this is no blocking system call */ softl->ipl_readers[unit]--; MUTEX_EXIT(&softl->ipl_mutex[unit]); return 0; } # endif MUTEX_EXIT(&softl->ipl_mutex[unit]); l = get_sleep_lock(&softl->iplh[unit]); error = sleep(&softl->iplh[unit], PZERO+1); spinunlock(l); # else # if defined(__osf__) && defined(_KERNEL) error = mpsleep(&softl->iplh[unit], PSUSP|PCATCH, "ipfread", 0, &softl->ipl_mutex, MS_LOCK_SIMPLE); # else MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); error = SLEEP(unit + softl->iplh, "ipl sleep"); # endif /* __osf__ */ # endif /* __hpux */ SPL_NET(s); MUTEX_ENTER(&softl->ipl_mutex[unit]); if (error) { softl->ipl_readers[unit]--; MUTEX_EXIT(&softl->ipl_mutex[unit]); IPFERROR(40004); return error; } # endif /* SOLARIS */ } if (softl->ipl_log_init != 1) { softl->ipl_readers[unit]--; MUTEX_EXIT(&softl->ipl_mutex[unit]); IPFERROR(40008); return EIO; } # if (defined(BSD) && (BSD >= 199101)) || defined(__FreeBSD__) || \ defined(__osf__) uio->uio_rw = UIO_READ; # endif for (copied = 0; (ipl = softl->iplt[unit]) != NULL; copied += dlen) { dlen = ipl->ipl_dsize; if (dlen > uio->uio_resid) break; /* * Don't hold the mutex over the uiomove call. */ softl->iplt[unit] = ipl->ipl_next; softl->ipl_used[unit] -= dlen; MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); error = UIOMOVE(ipl, dlen, UIO_READ, uio); if (error) { SPL_NET(s); MUTEX_ENTER(&softl->ipl_mutex[unit]); IPFERROR(40006); ipl->ipl_next = softl->iplt[unit]; softl->iplt[unit] = ipl; softl->ipl_used[unit] += dlen; break; } MUTEX_ENTER(&softl->ipl_mutex[unit]); KFREES((caddr_t)ipl, dlen); SPL_NET(s); } if (!softl->iplt[unit]) { softl->ipl_used[unit] = 0; softl->iplh[unit] = &softl->iplt[unit]; softl->ipll[unit] = NULL; } softl->ipl_readers[unit]--; MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); return error; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_clear */ /* Returns: int - number of log bytes cleared. */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* */ /* Deletes all queued up log records for a given output device. */ /* ------------------------------------------------------------------------ */ int ipf_log_clear(softc, unit) ipf_main_softc_t *softc; minor_t unit; { ipf_log_softc_t *softl = softc->ipf_log_soft; iplog_t *ipl; int used; SPL_INT(s); SPL_NET(s); MUTEX_ENTER(&softl->ipl_mutex[unit]); while ((ipl = softl->iplt[unit]) != NULL) { softl->iplt[unit] = ipl->ipl_next; KFREES((caddr_t)ipl, ipl->ipl_dsize); } softl->iplh[unit] = &softl->iplt[unit]; softl->ipll[unit] = NULL; used = softl->ipl_used[unit]; softl->ipl_used[unit] = 0; bzero((char *)&softl->ipl_crc[unit], FI_CSIZE); MUTEX_EXIT(&softl->ipl_mutex[unit]); SPL_X(s); return used; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_canread */ /* Returns: int - 0 == no data to read, 1 = data present */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* */ /* Returns an indication of whether or not there is data present in the */ /* current buffer for the selected ipf device. */ /* ------------------------------------------------------------------------ */ int ipf_log_canread(softc, unit) ipf_main_softc_t *softc; int unit; { ipf_log_softc_t *softl = softc->ipf_log_soft; return softl->iplt[unit] != NULL; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_canread */ /* Returns: int - 0 == no data to read, 1 = data present */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* */ /* Returns how many bytes are currently held in log buffers for the */ /* selected ipf device. */ /* ------------------------------------------------------------------------ */ int ipf_log_bytesused(softc, unit) ipf_main_softc_t *softc; int unit; { ipf_log_softc_t *softl = softc->ipf_log_soft; if (softl == NULL) return 0; return softl->ipl_used[unit]; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_failures */ /* Returns: U_QUAD_T - number of log failures */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* */ /* Returns how many times we've tried to log a packet but failed to do so */ /* for the selected ipf device. */ /* ------------------------------------------------------------------------ */ u_long ipf_log_failures(softc, unit) ipf_main_softc_t *softc; int unit; { ipf_log_softc_t *softl = softc->ipf_log_soft; if (softl == NULL) return 0; return softl->ipl_logfail[unit]; } /* ------------------------------------------------------------------------ */ /* Function: ipf_log_logok */ /* Returns: U_QUAD_T - number of packets logged */ /* Parameters: softc(I) - pointer to main soft context */ /* unit(I) - device we are reading from */ /* */ /* Returns how many times we've successfully logged a packet for the */ /* selected ipf device. */ /* ------------------------------------------------------------------------ */ u_long ipf_log_logok(softc, unit) ipf_main_softc_t *softc; int unit; { ipf_log_softc_t *softl = softc->ipf_log_soft; if (softl == NULL) return 0; return softl->ipl_logok[unit]; } #endif /* IPFILTER_LOG */ Index: projects/clang390-import/sys/contrib/ipfilter/netinet/ip_nat.h =================================================================== --- projects/clang390-import/sys/contrib/ipfilter/netinet/ip_nat.h (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter/netinet/ip_nat.h (revision 304965) @@ -1,774 +1,778 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 * $FreeBSD$ * Id: ip_nat.h,v 2.90.2.20 2007/09/25 08:27:32 darrenr Exp $ */ #ifndef __IP_NAT_H__ #define __IP_NAT_H__ -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#ifndef SOLARIS +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) #define SIOCADNAT _IOW('r', 60, struct ipfobj) #define SIOCRMNAT _IOW('r', 61, struct ipfobj) #define SIOCGNATS _IOWR('r', 62, struct ipfobj) #define SIOCGNATL _IOWR('r', 63, struct ipfobj) #define SIOCPURGENAT _IOWR('r', 100, struct ipfobj) #else #define SIOCADNAT _IOW(r, 60, struct ipfobj) #define SIOCRMNAT _IOW(r, 61, struct ipfobj) #define SIOCGNATS _IOWR(r, 62, struct ipfobj) #define SIOCGNATL _IOWR(r, 63, struct ipfobj) #define SIOCPURGENAT _IOWR(r, 100, struct ipfobj) #endif #undef LARGE_NAT /* define this if you're setting up a system to NAT * LARGE numbers of networks/hosts - i.e. in the * hundreds or thousands. In such a case, you should * also change the RDR_SIZE and NAT_SIZE below to more * appropriate sizes. The figures below were used for * a setup with 1000-2000 networks to NAT. */ #ifndef NAT_SIZE # ifdef LARGE_NAT # define NAT_SIZE 2047 # else # define NAT_SIZE 127 # endif #endif #ifndef RDR_SIZE # ifdef LARGE_NAT # define RDR_SIZE 2047 # else # define RDR_SIZE 127 # endif #endif #ifndef HOSTMAP_SIZE # ifdef LARGE_NAT # define HOSTMAP_SIZE 8191 # else # define HOSTMAP_SIZE 2047 # endif #endif #ifndef NAT_TABLE_MAX /* * This is newly introduced and for the sake of "least surprise", the numbers * present aren't what we'd normally use for creating a proper hash table. */ # ifdef LARGE_NAT # define NAT_TABLE_MAX 180000 # else # define NAT_TABLE_MAX 30000 # endif #endif #ifndef NAT_TABLE_SZ # ifdef LARGE_NAT # define NAT_TABLE_SZ 16383 # else # define NAT_TABLE_SZ 2047 # endif #endif #ifndef APR_LABELLEN #define APR_LABELLEN 16 #endif #define NAT_HW_CKSUM 0x80000000 #define NAT_HW_CKSUM_PART 0x40000000 #define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */ struct ipstate; struct ap_session; /* * This structure is used in the active NAT table and represents an * active NAT session. */ typedef struct nat { ipfmutex_t nat_lock; struct nat *nat_next; struct nat **nat_pnext; struct nat *nat_hnext[2]; struct nat **nat_phnext[2]; struct hostmap *nat_hm; void *nat_data; struct nat **nat_me; struct ipstate *nat_state; struct ap_session *nat_aps; /* proxy session */ frentry_t *nat_fr; /* filter rule ptr if appropriate */ struct ipnat *nat_ptr; /* pointer back to the rule */ void *nat_ifps[2]; void *nat_sync; ipftqent_t nat_tqe; int nat_mtu[2]; u_32_t nat_flags; u_32_t nat_sumd[2]; /* ip checksum delta for data segment*/ u_32_t nat_ipsumd; /* ip checksum delta for ip header */ u_32_t nat_mssclamp; /* if != zero clamp MSS to this */ i6addr_t nat_odst6; i6addr_t nat_osrc6; i6addr_t nat_ndst6; i6addr_t nat_nsrc6; U_QUAD_T nat_pkts[2]; U_QUAD_T nat_bytes[2]; union { udpinfo_t nat_unu; tcpinfo_t nat_unt; icmpinfo_t nat_uni; greinfo_t nat_ugre; } nat_unold, nat_unnew; int nat_use; int nat_pr[2]; /* protocol for NAT */ int nat_dir; int nat_ref; /* reference count */ u_int nat_hv[2]; char nat_ifnames[2][LIFNAMSIZ]; int nat_rev; /* 0 = forward, 1 = reverse */ int nat_dlocal; int nat_v[2]; /* 0 = old, 1 = new */ u_int nat_redir; /* copy of in_redir */ } nat_t; #define nat_osrcip nat_osrc6.in4 #define nat_odstip nat_odst6.in4 #define nat_nsrcip nat_nsrc6.in4 #define nat_ndstip nat_ndst6.in4 #define nat_osrcaddr nat_osrc6.in4.s_addr #define nat_odstaddr nat_odst6.in4.s_addr #define nat_nsrcaddr nat_nsrc6.in4.s_addr #define nat_ndstaddr nat_ndst6.in4.s_addr #define nat_age nat_tqe.tqe_die #define nat_osport nat_unold.nat_unt.ts_sport #define nat_odport nat_unold.nat_unt.ts_dport #define nat_nsport nat_unnew.nat_unt.ts_sport #define nat_ndport nat_unnew.nat_unt.ts_dport #define nat_oicmpid nat_unold.nat_uni.ici_id #define nat_nicmpid nat_unnew.nat_uni.ici_id #define nat_type nat_unold.nat_uni.ici_type #define nat_oseq nat_unold.nat_uni.ici_seq #define nat_nseq nat_unnew.nat_uni.ici_seq #define nat_tcpstate nat_tqe.tqe_state #define nat_die nat_tqe.tqe_die #define nat_touched nat_tqe.tqe_touched /* * Values for nat_dir */ #define NAT_INBOUND 0 #define NAT_OUTBOUND 1 #define NAT_ENCAPIN 2 #define NAT_ENCAPOUT 3 #define NAT_DIVERTIN 4 #define NAT_DIVERTOUT 5 /* * Definitions for nat_flags */ #define NAT_TCP 0x0001 /* IPN_TCP */ #define NAT_UDP 0x0002 /* IPN_UDP */ #define NAT_ICMPERR 0x0004 /* IPN_ICMPERR */ #define NAT_ICMPQUERY 0x0008 /* IPN_ICMPQUERY */ #define NAT_SEARCH 0x0010 #define NAT_SLAVE 0x0020 /* Slave connection for a proxy */ #define NAT_NOTRULEPORT 0x0040 /* Don't use the port # in the NAT rule */ #define NAT_TCPUDP (NAT_TCP|NAT_UDP) #define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR) #define NAT_TCPUDPICMPQ (NAT_TCP|NAT_UDP|NAT_ICMPQUERY) #define NAT_FROMRULE (NAT_TCP|NAT_UDP) /* 0x0100 reserved for FI_W_SPORT */ /* 0x0200 reserved for FI_W_DPORT */ /* 0x0400 reserved for FI_W_SADDR */ /* 0x0800 reserved for FI_W_DADDR */ /* 0x1000 reserved for FI_W_NEWFR */ /* 0x2000 reserved for SI_CLONE */ /* 0x4000 reserved for SI_CLONED */ /* 0x8000 reserved for SI_IGNOREPKT */ #define NAT_DEBUG 0x800000 typedef struct nat_addr_s { i6addr_t na_addr[2]; i6addr_t na_nextaddr; int na_atype; int na_function; } nat_addr_t; #define na_nextip na_nextaddr.in4.s_addr #define na_nextip6 na_nextaddr.in6 #define na_num na_addr[0].iplookupnum #define na_type na_addr[0].iplookuptype #define na_subtype na_addr[0].iplookupsubtype #define na_ptr na_addr[1].iplookupptr #define na_func na_addr[1].iplookupfunc /* * This structure represents an actual NAT rule, loaded by ipnat. */ typedef struct ipnat { ipfmutex_t in_lock; struct ipnat *in_next; /* NAT rule list next */ struct ipnat **in_pnext; /* prior rdr next ptr */ struct ipnat *in_rnext; /* rdr rule hash next */ struct ipnat **in_prnext; /* prior rdr next ptr */ struct ipnat *in_mnext; /* map rule hash next */ struct ipnat **in_pmnext; /* prior map next ptr */ struct ipftq *in_tqehead[2]; void *in_ifps[2]; void *in_apr; char *in_comment; mb_t *in_divmp; void *in_pconf; U_QUAD_T in_pkts[2]; U_QUAD_T in_bytes[2]; u_long in_space; u_long in_hits; int in_size; int in_use; u_int in_hv[2]; int in_flineno; /* conf. file line number */ int in_stepnext; int in_dlocal; u_short in_dpnext; u_short in_spnext; /* From here to the end is covered by IPN_CMPSIZ */ u_char in_v[2]; /* 0 = old, 1 = new */ u_32_t in_flags; u_32_t in_mssclamp; /* if != 0 clamp MSS to this */ u_int in_age[2]; int in_redir; /* see below for values */ int in_pr[2]; /* protocol. */ nat_addr_t in_ndst; nat_addr_t in_nsrc; nat_addr_t in_osrc; nat_addr_t in_odst; frtuc_t in_tuc; u_short in_ppip; /* ports per IP. */ u_short in_ippip; /* IP #'s per IP# */ u_short in_ndports[2]; u_short in_nsports[2]; int in_ifnames[2]; int in_plabel; /* proxy label. */ int in_pconfig; /* proxy label. */ ipftag_t in_tag; int in_namelen; char in_names[1]; } ipnat_t; /* * MAP-IN MAP-OUT RDR-IN RDR-OUT * osrc X == src == src X * odst X == dst == dst X * nsrc == dst X X == dst * ndst == src X X == src */ #define in_dpmin in_ndports[0] /* Also holds static redir port */ #define in_dpmax in_ndports[1] #define in_spmin in_nsports[0] /* Also holds static redir port */ #define in_spmax in_nsports[1] #define in_ndport in_ndports[0] #define in_nsport in_nsports[0] #define in_dipnext in_ndst.na_nextaddr.in4 #define in_dipnext6 in_ndst.na_nextaddr #define in_dnip in_ndst.na_nextaddr.in4.s_addr #define in_dnip6 in_ndst.na_nextaddr #define in_sipnext in_nsrc.na_nextaddr.in4 #define in_snip in_nsrc.na_nextaddr.in4.s_addr #define in_snip6 in_nsrc.na_nextaddr #define in_odstip in_odst.na_addr[0].in4 #define in_odstip6 in_odst.na_addr[0] #define in_odstaddr in_odst.na_addr[0].in4.s_addr #define in_odstmsk in_odst.na_addr[1].in4.s_addr #define in_odstmsk6 in_odst.na_addr[1] #define in_odstatype in_odst.na_atype #define in_osrcip in_osrc.na_addr[0].in4 #define in_osrcip6 in_osrc.na_addr[0] #define in_osrcaddr in_osrc.na_addr[0].in4.s_addr #define in_osrcmsk in_osrc.na_addr[1].in4.s_addr #define in_osrcmsk6 in_osrc.na_addr[1] #define in_osrcatype in_osrc.na_atype #define in_ndstip in_ndst.na_addr[0].in4 #define in_ndstip6 in_ndst.na_addr[0] #define in_ndstaddr in_ndst.na_addr[0].in4.s_addr #define in_ndstmsk in_ndst.na_addr[1].in4.s_addr #define in_ndstmsk6 in_ndst.na_addr[1] #define in_ndstatype in_ndst.na_atype #define in_ndstafunc in_ndst.na_function #define in_nsrcip in_nsrc.na_addr[0].in4 #define in_nsrcip6 in_nsrc.na_addr[0] #define in_nsrcaddr in_nsrc.na_addr[0].in4.s_addr #define in_nsrcmsk in_nsrc.na_addr[1].in4.s_addr #define in_nsrcmsk6 in_nsrc.na_addr[1] #define in_nsrcatype in_nsrc.na_atype #define in_nsrcafunc in_nsrc.na_function #define in_scmp in_tuc.ftu_scmp #define in_dcmp in_tuc.ftu_dcmp #define in_stop in_tuc.ftu_stop #define in_dtop in_tuc.ftu_dtop #define in_osport in_tuc.ftu_sport #define in_odport in_tuc.ftu_dport #define in_ndstnum in_ndst.na_addr[0].iplookupnum #define in_ndsttype in_ndst.na_addr[0].iplookuptype #define in_ndstptr in_ndst.na_addr[1].iplookupptr #define in_ndstfunc in_ndst.na_addr[1].iplookupfunc #define in_nsrcnum in_nsrc.na_addr[0].iplookupnum #define in_nsrctype in_nsrc.na_addr[0].iplookuptype #define in_nsrcptr in_nsrc.na_addr[1].iplookupptr #define in_nsrcfunc in_nsrc.na_addr[1].iplookupfunc #define in_odstnum in_odst.na_addr[0].iplookupnum #define in_odsttype in_odst.na_addr[0].iplookuptype #define in_odstptr in_odst.na_addr[1].iplookupptr #define in_odstfunc in_odst.na_addr[1].iplookupfunc #define in_osrcnum in_osrc.na_addr[0].iplookupnum #define in_osrctype in_osrc.na_addr[0].iplookuptype #define in_osrcptr in_osrc.na_addr[1].iplookupptr #define in_osrcfunc in_osrc.na_addr[1].iplookupfunc #define in_icmpidmin in_nsports[0] #define in_icmpidmax in_nsports[1] /* * Bit definitions for in_flags */ #define IPN_ANY 0x00000 #define IPN_TCP 0x00001 #define IPN_UDP 0x00002 #define IPN_TCPUDP (IPN_TCP|IPN_UDP) #define IPN_ICMPERR 0x00004 #define IPN_TCPUDPICMP (IPN_TCP|IPN_UDP|IPN_ICMPERR) #define IPN_ICMPQUERY 0x00008 #define IPN_TCPUDPICMPQ (IPN_TCP|IPN_UDP|IPN_ICMPQUERY) #define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR) #define IPN_AUTOPORTMAP 0x00010 #define IPN_FILTER 0x00020 #define IPN_SPLIT 0x00040 #define IPN_ROUNDR 0x00080 #define IPN_SIPRANGE 0x00100 #define IPN_DIPRANGE 0x00200 #define IPN_NOTSRC 0x00400 #define IPN_NOTDST 0x00800 #define IPN_NO 0x01000 #define IPN_DYNSRCIP 0x02000 /* dynamic src IP# */ #define IPN_DYNDSTIP 0x04000 /* dynamic dst IP# */ #define IPN_DELETE 0x08000 #define IPN_STICKY 0x10000 #define IPN_FRAG 0x20000 #define IPN_FIXEDSPORT 0x40000 #define IPN_FIXEDDPORT 0x80000 #define IPN_FINDFORWARD 0x100000 #define IPN_IN 0x200000 #define IPN_SEQUENTIAL 0x400000 #define IPN_PURGE 0x800000 #define IPN_PROXYRULE 0x1000000 #define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_SIPRANGE|IPN_SPLIT|\ IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|IPN_NO|\ IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY|\ IPN_DIPRANGE|IPN_SEQUENTIAL|IPN_PURGE) /* * Values for in_redir */ #define NAT_MAP 0x01 #define NAT_REDIRECT 0x02 #define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) #define NAT_MAPBLK 0x04 #define NAT_REWRITE 0x08 #define NAT_ENCAP 0x10 #define NAT_DIVERTUDP 0x20 #define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */ #define USABLE_PORTS (65536 - MAPBLK_MINPORT) #define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_v)) typedef struct natlookup { i6addr_t nl_inipaddr; i6addr_t nl_outipaddr; i6addr_t nl_realipaddr; int nl_v; int nl_flags; u_short nl_inport; u_short nl_outport; u_short nl_realport; } natlookup_t; #define nl_inip nl_inipaddr.in4 #define nl_outip nl_outipaddr.in4 #define nl_realip nl_realipaddr.in4 #define nl_inip6 nl_inipaddr.in6 #define nl_outip6 nl_outipaddr.in6 #define nl_realip6 nl_realipaddr.in6 typedef struct nat_save { void *ipn_next; struct nat ipn_nat; struct ipnat ipn_ipnat; struct frentry ipn_fr; int ipn_dsize; char ipn_data[4]; } nat_save_t; #define ipn_rule ipn_nat.nat_fr typedef struct natget { void *ng_ptr; int ng_sz; } natget_t; /* * This structure gets used to help NAT sessions keep the same NAT rule (and * thus translation for IP address) when: * (a) round-robin redirects are in use * (b) different IP add */ typedef struct hostmap { struct hostmap *hm_hnext; struct hostmap **hm_phnext; struct hostmap *hm_next; struct hostmap **hm_pnext; struct ipnat *hm_ipnat; i6addr_t hm_osrcip6; i6addr_t hm_odstip6; i6addr_t hm_nsrcip6; i6addr_t hm_ndstip6; u_32_t hm_port; int hm_ref; int hm_hv; int hm_v; } hostmap_t; #define hm_osrcip hm_osrcip6.in4 #define hm_odstip hm_odstip6.in4 #define hm_nsrcip hm_nsrcip6.in4 #define hm_ndstip hm_ndstip6.in4 #define hm_osrc6 hm_osrcip6.in6 #define hm_odst6 hm_odstip6.in6 #define hm_nsrc6 hm_nsrcip6.in6 #define hm_ndst6 hm_ndstip6.in6 /* * Structure used to pass information in to nat_newmap and nat_newrdr. */ typedef struct natinfo { ipnat_t *nai_np; u_32_t nai_sum1; u_32_t nai_sum2; struct in_addr nai_ip; /* In host byte order */ u_short nai_port; u_short nai_nport; u_short nai_sport; u_short nai_dport; } natinfo_t; typedef struct nat_stat_side { u_int *ns_bucketlen; nat_t **ns_table; u_long ns_added; u_long ns_appr_fail; u_long ns_badnat; u_long ns_badnatnew; u_long ns_badnextaddr; u_long ns_bucket_max; u_long ns_clone_nomem; u_long ns_decap_bad; u_long ns_decap_fail; u_long ns_decap_pullup; u_long ns_divert_dup; u_long ns_divert_exist; u_long ns_drop; u_long ns_encap_dup; u_long ns_encap_pullup; u_long ns_exhausted; u_long ns_icmp_address; u_long ns_icmp_basic; u_long ns_icmp_mbuf; u_long ns_icmp_notfound; u_long ns_icmp_rebuild; u_long ns_icmp_short; u_long ns_icmp_size; u_long ns_ifpaddrfail; u_long ns_ignored; u_long ns_insert_fail; u_long ns_inuse; u_long ns_log; u_long ns_lookup_miss; u_long ns_lookup_nowild; u_long ns_new_ifpaddr; u_long ns_memfail; u_long ns_table_max; u_long ns_translated; u_long ns_unfinalised; u_long ns_wrap; u_long ns_xlate_null; u_long ns_xlate_exists; u_long ns_ipf_proxy_fail; u_long ns_uncreate[2]; } nat_stat_side_t; typedef struct natstat { nat_t *ns_instances; ipnat_t *ns_list; hostmap_t *ns_maplist; hostmap_t **ns_maptable; u_int ns_active; u_long ns_addtrpnt; u_long ns_divert_build; u_long ns_expire; u_long ns_flush_all; u_long ns_flush_closing; u_long ns_flush_queue; u_long ns_flush_state; u_long ns_flush_timeout; u_long ns_hm_new; u_long ns_hm_newfail; u_long ns_hm_addref; u_long ns_hm_nullnp; u_long ns_log_ok; u_long ns_log_fail; u_int ns_hostmap_sz; u_int ns_nattab_sz; u_int ns_nattab_max; u_int ns_orphans; u_int ns_rules; u_int ns_rules_map; u_int ns_rules_rdr; u_int ns_rultab_sz; u_int ns_rdrtab_sz; u_32_t ns_ticks; u_int ns_trpntab_sz; u_int ns_wilds; u_long ns_proto[256]; nat_stat_side_t ns_side[2]; #ifdef USE_INET6 nat_stat_side_t ns_side6[2]; #endif } natstat_t; typedef struct natlog { i6addr_t nl_osrcip; i6addr_t nl_odstip; i6addr_t nl_nsrcip; i6addr_t nl_ndstip; u_short nl_osrcport; u_short nl_odstport; u_short nl_nsrcport; u_short nl_ndstport; int nl_action; int nl_type; int nl_rule; U_QUAD_T nl_pkts[2]; U_QUAD_T nl_bytes[2]; u_char nl_p[2]; u_char nl_v[2]; u_char nl_ifnames[2][LIFNAMSIZ]; } natlog_t; #define NL_NEW 0 #define NL_CLONE 1 #define NL_PURGE 0xfffc #define NL_DESTROY 0xfffd #define NL_FLUSH 0xfffe #define NL_EXPIRE 0xffff #define NAT_HASH_FN(_k,_l,_m) (((_k) + ((_k) >> 12) + _l) % (_m)) #define NAT_HASH_FN6(_k,_l,_m) ((((u_32_t *)(_k))[3] \ + (((u_32_t *)(_k))[3] >> 12) \ + (((u_32_t *)(_k))[2]) \ + (((u_32_t *)(_k))[2] >> 12) \ + (((u_32_t *)(_k))[1]) \ + (((u_32_t *)(_k))[1] >> 12) \ + (((u_32_t *)(_k))[0]) \ + (((u_32_t *)(_k))[0] >> 12) \ + _l) % (_m)) #define LONG_SUM(_i) (((_i) & 0xffff) + ((_i) >> 16)) #define LONG_SUM6(_i) (LONG_SUM(ntohl(((u_32_t *)(_i))[0])) + \ LONG_SUM(ntohl(((u_32_t *)(_i))[1])) + \ LONG_SUM(ntohl(((u_32_t *)(_i))[2])) + \ LONG_SUM(ntohl(((u_32_t *)(_i))[3]))) #define CALC_SUMD(s1, s2, sd) { \ (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ /* Do it twice */ \ (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ /* Because ~1 == -2, We really need ~1 == -1 */ \ if ((s1) > (s2)) (s2)--; \ (sd) = (s2) - (s1); \ (sd) = ((sd) & 0xffff) + ((sd) >> 16); } #define NAT_SYSSPACE 0x80000000 #define NAT_LOCKHELD 0x40000000 /* * This is present in ip_nat.h because it needs to be shared between * ip_nat.c and ip_nat6.c */ typedef struct ipf_nat_softc_s { ipfmutex_t ipf_nat_new; ipfmutex_t ipf_nat_io; int ipf_nat_doflush; int ipf_nat_logging; int ipf_nat_lock; int ipf_nat_inited; int ipf_nat_table_wm_high; int ipf_nat_table_wm_low; u_int ipf_nat_table_max; u_int ipf_nat_table_sz; u_int ipf_nat_maprules_sz; u_int ipf_nat_rdrrules_sz; u_int ipf_nat_hostmap_sz; u_int ipf_nat_maxbucket; u_int ipf_nat_last_force_flush; u_int ipf_nat_defage; u_int ipf_nat_defipage; u_int ipf_nat_deficmpage; ipf_v4_masktab_t ipf_nat_map_mask; ipf_v6_masktab_t ipf_nat6_map_mask; ipf_v4_masktab_t ipf_nat_rdr_mask; ipf_v6_masktab_t ipf_nat6_rdr_mask; nat_t **ipf_nat_table[2]; nat_t *ipf_nat_instances; ipnat_t *ipf_nat_list; ipnat_t **ipf_nat_list_tail; ipnat_t **ipf_nat_map_rules; ipnat_t **ipf_nat_rdr_rules; ipftq_t *ipf_nat_utqe; hostmap_t **ipf_hm_maptable ; hostmap_t *ipf_hm_maplist ; ipftuneable_t *ipf_nat_tune; ipftq_t ipf_nat_udptq; ipftq_t ipf_nat_udpacktq; ipftq_t ipf_nat_icmptq; ipftq_t ipf_nat_icmpacktq; ipftq_t ipf_nat_iptq; ipftq_t ipf_nat_pending; ipftq_t ipf_nat_tcptq[IPF_TCP_NSTATES]; natstat_t ipf_nat_stats; } ipf_nat_softc_t ; #define ipf_nat_map_max ipf_nat_map_mask.imt4_max #define ipf_nat_rdr_max ipf_nat_rdr_mask.imt4_max #define ipf_nat6_map_max ipf_nat6_map_mask.imt6_max #define ipf_nat6_rdr_max ipf_nat6_rdr_mask.imt6_max #define ipf_nat_map_active_masks ipf_nat_map_mask.imt4_active #define ipf_nat_rdr_active_masks ipf_nat_rdr_mask.imt4_active #define ipf_nat6_map_active_masks ipf_nat6_map_mask.imt6_active #define ipf_nat6_rdr_active_masks ipf_nat6_rdr_mask.imt6_active extern frentry_t ipfnatblock; extern void ipf_fix_datacksum __P((u_short *, u_32_t)); extern void ipf_fix_incksum __P((int, u_short *, u_32_t, u_32_t)); extern void ipf_fix_outcksum __P((int, u_short *, u_32_t, u_32_t)); extern int ipf_nat_checkin __P((fr_info_t *, u_32_t *)); extern int ipf_nat_checkout __P((fr_info_t *, u_32_t *)); extern void ipf_nat_delete __P((ipf_main_softc_t *, struct nat *, int)); extern void ipf_nat_deref __P((ipf_main_softc_t *, nat_t **)); extern void ipf_nat_expire __P((ipf_main_softc_t *)); extern int ipf_nat_hashtab_add __P((ipf_main_softc_t *, ipf_nat_softc_t *, nat_t *)); extern void ipf_nat_hostmapdel __P((ipf_main_softc_t *, hostmap_t **)); extern int ipf_nat_hostmap_rehash __P((ipf_main_softc_t *, ipftuneable_t *, ipftuneval_t *)); extern nat_t *ipf_nat_icmperrorlookup __P((fr_info_t *, int)); extern nat_t *ipf_nat_icmperror __P((fr_info_t *, u_int *, int)); #if defined(__OpenBSD__) extern void ipf_nat_ifdetach __P((void *)); #endif extern int ipf_nat_init __P((void)); extern nat_t *ipf_nat_inlookup __P((fr_info_t *, u_int, u_int, struct in_addr, struct in_addr)); extern int ipf_nat_in __P((fr_info_t *, nat_t *, int, u_32_t)); extern int ipf_nat_insert __P((ipf_main_softc_t *, ipf_nat_softc_t *, nat_t *)); extern int ipf_nat_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, int, void *)); extern void ipf_nat_log __P((ipf_main_softc_t *, ipf_nat_softc_t *, struct nat *, u_int)); extern nat_t *ipf_nat_lookupredir __P((natlookup_t *)); extern nat_t *ipf_nat_maplookup __P((void *, u_int, struct in_addr, struct in_addr)); extern nat_t *ipf_nat_add __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int)); extern int ipf_nat_out __P((fr_info_t *, nat_t *, int, u_32_t)); extern nat_t *ipf_nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr, struct in_addr)); extern u_short *ipf_nat_proto __P((fr_info_t *, nat_t *, u_int)); extern void ipf_nat_rule_deref __P((ipf_main_softc_t *, ipnat_t **)); extern void ipf_nat_setqueue __P((ipf_main_softc_t *, ipf_nat_softc_t *, nat_t *)); extern void ipf_nat_setpending __P((ipf_main_softc_t *, nat_t *)); extern nat_t *ipf_nat_tnlookup __P((fr_info_t *, int)); extern void ipf_nat_update __P((fr_info_t *, nat_t *)); extern int ipf_nat_rehash __P((ipf_main_softc_t *, ipftuneable_t *, ipftuneval_t *)); extern int ipf_nat_rehash_rules __P((ipf_main_softc_t *, ipftuneable_t *, ipftuneval_t *)); extern int ipf_nat_settimeout __P((struct ipf_main_softc_s *, ipftuneable_t *, ipftuneval_t *)); extern void ipf_nat_sync __P((ipf_main_softc_t *, void *)); extern nat_t *ipf_nat_clone __P((fr_info_t *, nat_t *)); extern void ipf_nat_delmap __P((ipf_nat_softc_t *, ipnat_t *)); extern void ipf_nat_delrdr __P((ipf_nat_softc_t *, ipnat_t *)); extern int ipf_nat_wildok __P((nat_t *, int, int, int, int)); extern void ipf_nat_setlock __P((void *, int)); extern void ipf_nat_load __P((void)); extern void *ipf_nat_soft_create __P((ipf_main_softc_t *)); extern int ipf_nat_soft_init __P((ipf_main_softc_t *, void *)); extern void ipf_nat_soft_destroy __P((ipf_main_softc_t *, void *)); extern int ipf_nat_soft_fini __P((ipf_main_softc_t *, void *)); extern int ipf_nat_main_load __P((void)); extern int ipf_nat_main_unload __P((void)); extern ipftq_t *ipf_nat_add_tq __P((ipf_main_softc_t *, int)); extern void ipf_nat_uncreate __P((fr_info_t *)); #ifdef USE_INET6 extern nat_t *ipf_nat6_add __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int)); extern void ipf_nat6_addrdr __P((ipf_nat_softc_t *, ipnat_t *)); extern void ipf_nat6_addmap __P((ipf_nat_softc_t *, ipnat_t *)); extern void ipf_nat6_addencap __P((ipf_nat_softc_t *, ipnat_t *)); extern int ipf_nat6_checkout __P((fr_info_t *, u_32_t *)); extern int ipf_nat6_checkin __P((fr_info_t *, u_32_t *)); extern void ipf_nat6_delmap __P((ipf_nat_softc_t *, ipnat_t *)); extern void ipf_nat6_delrdr __P((ipf_nat_softc_t *, ipnat_t *)); extern int ipf_nat6_finalise __P((fr_info_t *, nat_t *)); extern nat_t *ipf_nat6_icmperror __P((fr_info_t *, u_int *, int)); extern nat_t *ipf_nat6_icmperrorlookup __P((fr_info_t *, int)); extern nat_t *ipf_nat6_inlookup __P((fr_info_t *, u_int, u_int, struct in6_addr *, struct in6_addr *)); extern u_32_t ipf_nat6_ip6subtract __P((i6addr_t *, i6addr_t *)); extern frentry_t *ipf_nat6_ipfin __P((fr_info_t *, u_32_t *)); extern frentry_t *ipf_nat6_ipfout __P((fr_info_t *, u_32_t *)); extern nat_t *ipf_nat6_lookupredir __P((natlookup_t *)); extern int ipf_nat6_newmap __P((fr_info_t *, nat_t *, natinfo_t *)); extern int ipf_nat6_newrdr __P((fr_info_t *, nat_t *, natinfo_t *)); extern nat_t *ipf_nat6_outlookup __P((fr_info_t *, u_int, u_int, struct in6_addr *, struct in6_addr *)); extern int ipf_nat6_newrewrite __P((fr_info_t *, nat_t *, natinfo_t *)); extern int ipf_nat6_newdivert __P((fr_info_t *, nat_t *, natinfo_t *)); extern int ipf_nat6_ruleaddrinit __P((ipf_main_softc_t *, ipf_nat_softc_t *, ipnat_t *)); #endif #endif /* __IP_NAT_H__ */ Index: projects/clang390-import/sys/contrib/ipfilter/netinet/ip_proxy.h =================================================================== --- projects/clang390-import/sys/contrib/ipfilter/netinet/ip_proxy.h (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter/netinet/ip_proxy.h (revision 304965) @@ -1,463 +1,467 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $FreeBSD$ * Id: ip_proxy.h,v 2.31.2.2 2005/03/12 19:33:48 darrenr Exp */ #ifndef __IP_PROXY_H__ #define __IP_PROXY_H__ -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#ifndef SOLARIS +# if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 +# else +# define SOLARIS 0 +# endif #endif #if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) #define SIOCPROXY _IOWR('r', 64, struct ap_control) #else #define SIOCPROXY _IOWR(r, 64, struct ap_control) #endif #ifndef APR_LABELLEN #define APR_LABELLEN 16 #endif #define AP_SESS_SIZE 53 struct nat; struct ipnat; struct ipstate; typedef struct ap_tcp { u_short apt_sport; /* source port */ u_short apt_dport; /* destination port */ short apt_sel[2]; /* {seq,ack}{off,min} set selector */ short apt_seqoff[2]; /* sequence # difference */ u_32_t apt_seqmin[2]; /* don't change seq-off until after this */ short apt_ackoff[2]; /* sequence # difference */ u_32_t apt_ackmin[2]; /* don't change seq-off until after this */ u_char apt_state[2]; /* connection state */ } ap_tcp_t; typedef struct ap_udp { u_short apu_sport; /* source port */ u_short apu_dport; /* destination port */ } ap_udp_t; typedef struct ap_session { struct aproxy *aps_apr; union { struct ap_tcp apu_tcp; struct ap_udp apu_udp; } aps_un; U_QUAD_T aps_bytes; /* bytes sent */ U_QUAD_T aps_pkts; /* packets sent */ void *aps_nat; /* pointer back to nat struct */ void *aps_data; /* private data */ int aps_psiz; /* size of private data */ struct ap_session *aps_next; } ap_session_t; #define aps_sport aps_un.apu_tcp.apt_sport #define aps_dport aps_un.apu_tcp.apt_dport #define aps_sel aps_un.apu_tcp.apt_sel #define aps_seqoff aps_un.apu_tcp.apt_seqoff #define aps_seqmin aps_un.apu_tcp.apt_seqmin #define aps_state aps_un.apu_tcp.apt_state #define aps_ackoff aps_un.apu_tcp.apt_ackoff #define aps_ackmin aps_un.apu_tcp.apt_ackmin typedef struct ap_control { char apc_label[APR_LABELLEN]; char apc_config[APR_LABELLEN]; u_char apc_p; /* * The following fields are upto the proxy's apr_ctl routine to deal * with. When the proxy gets this in kernel space, apc_data will * point to a malloc'd region of memory of apc_dsize bytes. If the * proxy wants to keep that memory, it must set apc_data to NULL * before it returns. It is expected if this happens that it will * take care to free it in apr_fini or otherwise as appropriate. * apc_cmd is provided as a standard place to put simple commands, * with apc_arg being available to put a simple arg. */ u_long apc_cmd; u_long apc_arg; void *apc_data; size_t apc_dsize; } ap_ctl_t; #define APC_CMD_ADD 0 #define APC_CMD_DEL 1 typedef struct aproxy { struct aproxy *apr_next; struct aproxy *apr_parent; char apr_label[APR_LABELLEN]; /* Proxy label # */ u_char apr_p; /* protocol */ int apr_flags; int apr_ref; int apr_clones; void (* apr_load) __P((void)); void (* apr_unload) __P((void)); void *(* apr_create) __P((ipf_main_softc_t *)); void (* apr_destroy) __P((ipf_main_softc_t *, void *)); int (* apr_init) __P((ipf_main_softc_t *, void *)); void (* apr_fini) __P((ipf_main_softc_t *, void *)); int (* apr_new) __P((void *, fr_info_t *, ap_session_t *, struct nat *)); void (* apr_del) __P((ipf_main_softc_t *, ap_session_t *)); int (* apr_inpkt) __P((void *, fr_info_t *, ap_session_t *, struct nat *)); int (* apr_outpkt) __P((void *, fr_info_t *, ap_session_t *, struct nat *)); int (* apr_match) __P((fr_info_t *, ap_session_t *, struct nat *)); int (* apr_ctl) __P((ipf_main_softc_t *, void *, ap_ctl_t *)); int (* apr_clear) __P((struct aproxy *)); int (* apr_flush) __P((struct aproxy *, int)); void *apr_soft; } aproxy_t; #define APR_DELETE 1 #define APR_ERR(x) ((x) << 16) #define APR_EXIT(x) (((x) >> 16) & 0xffff) #define APR_INC(x) ((x) & 0xffff) #ifdef _KERNEL /* * Generic #define's to cover missing things in the kernel */ # ifndef isdigit # define isdigit(x) ((x) >= '0' && (x) <= '9') # endif # ifndef isupper # define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z')) # endif # ifndef islower # define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z')) # endif # ifndef isalpha # define isalpha(x) (isupper(x) || islower(x)) # endif # ifndef toupper # define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A') # endif # ifndef isspace # define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \ ((x) == '\t') || ((x) == '\b')) # endif #endif /* _KERNEL */ /* * For the ftp proxy. */ #define FTP_BUFSZ 160 #define IPF_FTPBUFSZ 160 typedef struct ftpside { char *ftps_rptr; char *ftps_wptr; void *ftps_ifp; u_32_t ftps_seq[2]; u_32_t ftps_len; int ftps_junk; int ftps_cmds; int ftps_cmd; char ftps_buf[FTP_BUFSZ]; } ftpside_t; typedef struct ftpinfo { int ftp_passok; int ftp_incok; void *ftp_pendstate; nat_t *ftp_pendnat; ftpside_t ftp_side[2]; } ftpinfo_t; /* * IPsec proxy */ typedef u_32_t ipsec_cookie_t[2]; typedef struct ipsec_pxy { ipsec_cookie_t ipsc_icookie; ipsec_cookie_t ipsc_rcookie; int ipsc_rckset; nat_t *ipsc_nat; struct ipstate *ipsc_state; ipnat_t *ipsc_rule; } ipsec_pxy_t; /* * For the irc proxy. */ typedef struct ircinfo { size_t irc_len; char *irc_snick; char *irc_dnick; char *irc_type; char *irc_arg; char *irc_addr; u_32_t irc_ipnum; u_short irc_port; } ircinfo_t; /* * For the DNS "proxy" */ typedef struct dnsinfo { ipfmutex_t dnsi_lock; u_short dnsi_id; char dnsi_buffer[512]; } dnsinfo_t; /* * Real audio proxy structure and #defines */ typedef struct raudio_s { int rap_seenpna; int rap_seenver; int rap_version; int rap_eos; /* End Of Startup */ int rap_gotid; int rap_gotlen; int rap_mode; int rap_sdone; u_short rap_plport; u_short rap_prport; u_short rap_srport; char rap_svr[19]; u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have * been filled */ u_32_t rap_sseq; } raudio_t; #define RA_ID_END 0 #define RA_ID_UDP 1 #define RA_ID_ROBUST 7 #define RAP_M_UDP 1 #define RAP_M_ROBUST 2 #define RAP_M_TCP 4 #define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST) /* * MSN RPC proxy */ typedef struct msnrpcinfo { u_int mri_flags; int mri_cmd[2]; u_int mri_valid; struct in_addr mri_raddr; u_short mri_rport; } msnrpcinfo_t; /* * Sun RPCBIND proxy */ #define RPCB_MAXMSG 888 #define RPCB_RES_PMAP 0 /* Response contains a v2 port. */ #define RPCB_RES_STRING 1 /* " " " v3 (GETADDR) string. */ #define RPCB_RES_LIST 2 /* " " " v4 (GETADDRLIST) list. */ #define RPCB_MAXREQS 32 /* Arbitrary limit on tracked transactions */ #define RPCB_REQMIN 40 #define RPCB_REQMAX 888 #define RPCB_REPMIN 20 #define RPCB_REPMAX 604 /* XXX double check this! */ /* * These macros determine the number of bytes between p and the end of * r->rs_buf relative to l. */ #define RPCB_BUF_END(r) (char *)((r)->rm_msgbuf + (r)->rm_buflen) #define RPCB_BUF_GEQ(r, p, l) \ ((RPCB_BUF_END((r)) > (char *)(p)) && \ ((RPCB_BUF_END((r)) - (char *)(p)) >= (l))) #define RPCB_BUF_EQ(r, p, l) \ (RPCB_BUF_END((r)) == ((char *)(p) + (l))) /* * The following correspond to RPC(B) detailed in RFC183[13]. */ #define RPCB_CALL 0 #define RPCB_REPLY 1 #define RPCB_MSG_VERSION 2 #define RPCB_PROG 100000 #define RPCB_GETPORT 3 #define RPCB_GETADDR 3 #define RPCB_GETADDRLIST 11 #define RPCB_MSG_ACCEPTED 0 #define RPCB_MSG_DENIED 1 /* BEGIN (Generic XDR structures) */ typedef struct xdr_string { u_32_t *xs_len; char *xs_str; } xdr_string_t; typedef struct xdr_auth { /* u_32_t xa_flavor; */ xdr_string_t xa_string; } xdr_auth_t; typedef struct xdr_uaddr { u_32_t xu_ip; u_short xu_port; xdr_string_t xu_str; } xdr_uaddr_t; typedef struct xdr_proto { u_int xp_proto; xdr_string_t xp_str; } xdr_proto_t; #define xu_xslen xu_str.xs_len #define xu_xsstr xu_str.xs_str #define xp_xslen xp_str.xs_len #define xp_xsstr xp_str.xs_str /* END (Generic XDR structures) */ /* BEGIN (RPC call structures) */ typedef struct pmap_args { /* u_32_t pa_prog; */ /* u_32_t pa_vers; */ u_32_t *pa_prot; /* u_32_t pa_port; */ } pmap_args_t; typedef struct rpcb_args { /* u_32_t *ra_prog; */ /* u_32_t *ra_vers; */ xdr_proto_t ra_netid; xdr_uaddr_t ra_maddr; /* xdr_string_t ra_owner; */ } rpcb_args_t; typedef struct rpc_call { /* u_32_t rc_rpcvers; */ /* u_32_t rc_prog; */ u_32_t *rc_vers; u_32_t *rc_proc; xdr_auth_t rc_authcred; xdr_auth_t rc_authverf; union { pmap_args_t ra_pmapargs; rpcb_args_t ra_rpcbargs; } rpcb_args; } rpc_call_t; #define rc_pmapargs rpcb_args.ra_pmapargs #define rc_rpcbargs rpcb_args.ra_rpcbargs /* END (RPC call structures) */ /* BEGIN (RPC reply structures) */ typedef struct rpcb_entry { xdr_uaddr_t re_maddr; xdr_proto_t re_netid; /* u_32_t re_semantics; */ xdr_string_t re_family; xdr_proto_t re_proto; u_32_t *re_more; /* 1 == another entry follows */ } rpcb_entry_t; typedef struct rpcb_listp { u_32_t *rl_list; /* 1 == list follows */ int rl_cnt; rpcb_entry_t rl_entries[2]; /* TCP / UDP only */ } rpcb_listp_t; typedef struct rpc_resp { /* u_32_t rr_acceptdeny; */ /* Omitted 'message denied' fork; we don't care about rejects. */ xdr_auth_t rr_authverf; /* u_32_t *rr_astat; */ union { u_32_t *resp_pmap; xdr_uaddr_t resp_getaddr; rpcb_listp_t resp_getaddrlist; } rpcb_reply; } rpc_resp_t; #define rr_v2 rpcb_reply.resp_pmap #define rr_v3 rpcb_reply.resp_getaddr #define rr_v4 rpcb_reply.resp_getaddrlist /* END (RPC reply structures) */ /* BEGIN (RPC message structure & macros) */ typedef struct rpc_msg { char rm_msgbuf[RPCB_MAXMSG]; /* RPCB data buffer */ u_int rm_buflen; u_32_t *rm_xid; /* u_32_t Call vs Reply */ union { rpc_call_t rb_call; rpc_resp_t rb_resp; } rm_body; } rpc_msg_t; #define rm_call rm_body.rb_call #define rm_resp rm_body.rb_resp /* END (RPC message structure & macros) */ /* * These code paths aren't hot enough to warrant per transaction * mutexes. */ typedef struct rpcb_xact { struct rpcb_xact *rx_next; struct rpcb_xact **rx_pnext; u_32_t rx_xid; /* RPC transmission ID */ u_int rx_type; /* RPCB response type */ u_int rx_ref; /* reference count */ u_int rx_proto; /* transport protocol (v2 only) */ } rpcb_xact_t; typedef struct rpcb_session { ipfmutex_t rs_rxlock; rpcb_xact_t *rs_rxlist; } rpcb_session_t; /* * For an explanation, please see the following: * RFC1832 - Sections 3.11, 4.4, and 4.5. */ #define XDRALIGN(x) ((((x) % 4) != 0) ? ((((x) + 3) / 4) * 4) : (x)) extern int ipf_proxy_add __P((void *, aproxy_t *)); extern int ipf_proxy_check __P((fr_info_t *, struct nat *)); extern int ipf_proxy_ctl __P((ipf_main_softc_t *, void *, ap_ctl_t *)); extern int ipf_proxy_del __P((aproxy_t *)); extern void ipf_proxy_deref __P((aproxy_t *)); extern void ipf_proxy_flush __P((void *, int)); extern int ipf_proxy_init __P((void)); extern int ipf_proxy_ioctl __P((ipf_main_softc_t *, caddr_t, ioctlcmd_t, int, void *)); extern aproxy_t *ipf_proxy_lookup __P((void *, u_int, char *)); extern int ipf_proxy_match __P((fr_info_t *, struct nat *)); extern int ipf_proxy_new __P((fr_info_t *, struct nat *)); extern int ipf_proxy_ok __P((fr_info_t *, tcphdr_t *, struct ipnat *)); extern void ipf_proxy_free __P((ipf_main_softc_t *, ap_session_t *)); extern int ipf_proxy_main_load __P((void)); extern int ipf_proxy_main_unload __P((void)); extern ipnat_t *ipf_proxy_rule_fwd __P((nat_t *)); extern ipnat_t *ipf_proxy_rule_rev __P((nat_t *)); extern void *ipf_proxy_soft_create __P((ipf_main_softc_t *)); extern void ipf_proxy_soft_destroy __P((ipf_main_softc_t *, void *)); extern int ipf_proxy_soft_init __P((ipf_main_softc_t *, void *)); extern int ipf_proxy_soft_fini __P((ipf_main_softc_t *, void *)); #endif /* __IP_PROXY_H__ */ Index: projects/clang390-import/sys/contrib/ipfilter =================================================================== --- projects/clang390-import/sys/contrib/ipfilter (revision 304964) +++ projects/clang390-import/sys/contrib/ipfilter (revision 304965) Property changes on: projects/clang390-import/sys/contrib/ipfilter ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys/contrib/ipfilter:r304955-304964 Index: projects/clang390-import/sys/ddb/db_expr.c =================================================================== --- projects/clang390-import/sys/ddb/db_expr.c (revision 304964) +++ projects/clang390-import/sys/ddb/db_expr.c (revision 304965) @@ -1,371 +1,377 @@ /*- * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include static bool db_add_expr(db_expr_t *valuep); static bool db_mult_expr(db_expr_t *valuep); static bool db_shift_expr(db_expr_t *valuep); static bool db_term(db_expr_t *valuep); static bool db_unary(db_expr_t *valuep); static bool db_logical_or_expr(db_expr_t *valuep); static bool db_logical_and_expr(db_expr_t *valuep); static bool db_logical_relation_expr(db_expr_t *valuep); static bool db_term(db_expr_t *valuep) { int t; t = db_read_token(); if (t == tIDENT) { if (!db_value_of_name(db_tok_string, valuep) && !db_value_of_name_pcpu(db_tok_string, valuep) && !db_value_of_name_vnet(db_tok_string, valuep)) { - db_error("Symbol not found\n"); + db_printf("Symbol '%s' not found\n", db_tok_string); + db_error(NULL); /*NOTREACHED*/ } return (true); } if (t == tNUMBER) { *valuep = (db_expr_t)db_tok_number; return (true); } if (t == tDOT) { *valuep = (db_expr_t)db_dot; return (true); } if (t == tDOTDOT) { *valuep = (db_expr_t)db_prev; return (true); } if (t == tPLUS) { *valuep = (db_expr_t) db_next; return (true); } if (t == tDITTO) { *valuep = (db_expr_t)db_last_addr; return (true); } if (t == tDOLLAR) { if (!db_get_variable(valuep)) return (false); return (true); } if (t == tLPAREN) { if (!db_expression(valuep)) { - db_error("Syntax error\n"); + db_printf("Expression syntax error after '%c'\n", '('); + db_error(NULL); /*NOTREACHED*/ } t = db_read_token(); if (t != tRPAREN) { - db_error("Syntax error\n"); + db_printf("Expression syntax error -- expected '%c'\n", ')'); + db_error(NULL); /*NOTREACHED*/ } return (true); } db_unread_token(t); return (false); } static bool db_unary(db_expr_t *valuep) { int t; t = db_read_token(); if (t == tMINUS) { if (!db_unary(valuep)) { db_printf("Expression syntax error after '%c'\n", '-'); db_error(NULL); /*NOTREACHED*/ } *valuep = -*valuep; return (true); } if (t == tEXCL) { if(!db_unary(valuep)) { db_printf("Expression syntax error after '%c'\n", '!'); db_error(NULL); /* NOTREACHED */ } *valuep = (!(*valuep)); return (true); } if (t == tBIT_NOT) { if(!db_unary(valuep)) { db_printf("Expression syntax error after '%c'\n", '~'); db_error(NULL); /* NOTREACHED */ } *valuep = (~(*valuep)); return (true); } if (t == tSTAR) { /* indirection */ if (!db_unary(valuep)) { db_printf("Expression syntax error after '%c'\n", '*'); db_error(NULL); /*NOTREACHED*/ } *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), false); return (true); } db_unread_token(t); return (db_term(valuep)); } static bool db_mult_expr(db_expr_t *valuep) { db_expr_t lhs, rhs; int t; if (!db_unary(&lhs)) return (false); t = db_read_token(); while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH || t == tBIT_AND ) { if (!db_term(&rhs)) { - db_printf("Expression syntax error after '%c'\n", '!'); + db_printf("Expression syntax error after '%c'\n", + t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' : + t == tHASH ? '#' : '&'); db_error(NULL); /*NOTREACHED*/ } switch(t) { case tSTAR: lhs *= rhs; break; case tBIT_AND: lhs &= rhs; break; default: if (rhs == 0) { - db_error("Divide by 0\n"); + db_error("Division by 0\n"); /*NOTREACHED*/ } if (t == tSLASH) lhs /= rhs; else if (t == tPCT) lhs %= rhs; else lhs = roundup(lhs, rhs); } t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } static bool db_add_expr(db_expr_t *valuep) { db_expr_t lhs, rhs; int t; - char c; if (!db_mult_expr(&lhs)) return (false); t = db_read_token(); while (t == tPLUS || t == tMINUS || t == tBIT_OR) { if (!db_mult_expr(&rhs)) { - c = db_tok_string[0]; - db_printf("Expression syntax error after '%c'\n", c); + db_printf("Expression syntax error after '%c'\n", + t == tPLUS ? '+' : t == tMINUS ? '-' : '|'); db_error(NULL); /*NOTREACHED*/ } switch (t) { case tPLUS: lhs += rhs; break; case tMINUS: lhs -= rhs; break; case tBIT_OR: lhs |= rhs; break; default: __unreachable(); } t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } static bool db_shift_expr(db_expr_t *valuep) { db_expr_t lhs, rhs; int t; if (!db_add_expr(&lhs)) return (false); t = db_read_token(); while (t == tSHIFT_L || t == tSHIFT_R) { if (!db_add_expr(&rhs)) { - db_error("Syntax error\n"); + db_printf("Expression syntax error after '%s'\n", + t == tSHIFT_L ? "<<" : ">>"); + db_error(NULL); /*NOTREACHED*/ } if (rhs < 0) { - db_error("Negative shift amount\n"); + db_printf("Negative shift amount %jd\n", (intmax_t)rhs); + db_error(NULL); /*NOTREACHED*/ } if (t == tSHIFT_L) lhs <<= rhs; else { /* Shift right is unsigned */ lhs = (unsigned) lhs >> rhs; } t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } static bool db_logical_relation_expr( db_expr_t *valuep) { db_expr_t lhs, rhs; int t; - char op[3]; if (!db_shift_expr(&lhs)) return (false); t = db_read_token(); while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER || t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) { - op[0] = db_tok_string[0]; - op[1] = db_tok_string[1]; - op[2] = 0; if (!db_shift_expr(&rhs)) { - db_printf("Expression syntax error after \"%s\"\n", op); + db_printf("Expression syntax error after '%s'\n", + t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" : + t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" : + t == tLESS ? "<" : "<="); db_error(NULL); /*NOTREACHED*/ } switch(t) { case tLOG_EQ: lhs = (lhs == rhs); break; case tLOG_NOT_EQ: lhs = (lhs != rhs); break; case tGREATER: lhs = (lhs > rhs); break; case tGREATER_EQ: lhs = (lhs >= rhs); break; case tLESS: lhs = (lhs < rhs); break; case tLESS_EQ: lhs = (lhs <= rhs); break; default: __unreachable(); } t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } static bool db_logical_and_expr( db_expr_t *valuep) { db_expr_t lhs, rhs; int t; if (!db_logical_relation_expr(&lhs)) return (false); t = db_read_token(); while (t == tLOG_AND) { if (!db_logical_relation_expr(&rhs)) { db_printf("Expression syntax error after '%s'\n", "&&"); db_error(NULL); /*NOTREACHED*/ } lhs = (lhs && rhs); t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } static bool db_logical_or_expr( db_expr_t *valuep) { db_expr_t lhs, rhs; int t; if (!db_logical_and_expr(&lhs)) return(false); t = db_read_token(); while (t == tLOG_OR) { if (!db_logical_and_expr(&rhs)) { db_printf("Expression syntax error after '%s'\n", "||"); db_error(NULL); /*NOTREACHED*/ } lhs = (lhs || rhs); t = db_read_token(); } db_unread_token(t); *valuep = lhs; return (true); } int db_expression(db_expr_t *valuep) { return (db_logical_or_expr(valuep)); } Index: projects/clang390-import/sys/dev/bhnd/bcma/bcma.c =================================================================== --- projects/clang390-import/sys/dev/bhnd/bcma/bcma.c (revision 304964) +++ projects/clang390-import/sys/dev/bhnd/bcma/bcma.c (revision 304965) @@ -1,595 +1,632 @@ /*- * Copyright (c) 2015 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "bcmavar.h" #include "bcma_eromreg.h" #include "bcma_eromvar.h" #include int bcma_probe(device_t dev) { device_set_desc(dev, "BCMA BHND bus"); return (BUS_PROBE_DEFAULT); } int bcma_attach(device_t dev) { struct bcma_devinfo *dinfo; device_t *devs, child; int ndevs; int error; if ((error = device_get_children(dev, &devs, &ndevs))) return (error); /* * Map our children's agent register block. */ for (int i = 0; i < ndevs; i++) { bhnd_addr_t addr; bhnd_size_t size; rman_res_t r_start, r_count, r_end; child = devs[i]; dinfo = device_get_ivars(child); KASSERT(!device_is_suspended(child), ("bcma(4) stateful suspend handling requires that devices " "not be suspended before bcma_attach()")); /* Verify that the agent register block exists and is * mappable */ if (bhnd_get_port_rid(child, BHND_PORT_AGENT, 0, 0) == -1) continue; /* Fetch the address of the agent register block */ error = bhnd_get_region_addr(child, BHND_PORT_AGENT, 0, 0, &addr, &size); if (error) { device_printf(dev, "failed fetching agent register " "block address for core %d\n", i); goto cleanup; } /* Allocate the resource */ r_start = addr; r_count = size; r_end = r_start + r_count - 1; dinfo->rid_agent = i + 1; dinfo->res_agent = BHND_BUS_ALLOC_RESOURCE(dev, dev, SYS_RES_MEMORY, &dinfo->rid_agent, r_start, r_end, r_count, RF_ACTIVE); if (dinfo->res_agent == NULL) { device_printf(dev, "failed allocating agent register " "block for core %d\n", i); error = ENXIO; goto cleanup; } } cleanup: free(devs, M_BHND); if (error) return (error); return (bhnd_generic_attach(dev)); } int bcma_detach(device_t dev) { return (bhnd_generic_detach(dev)); } static int bcma_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) { const struct bcma_devinfo *dinfo; const struct bhnd_core_info *ci; dinfo = device_get_ivars(child); ci = &dinfo->corecfg->core_info; switch (index) { case BHND_IVAR_VENDOR: *result = ci->vendor; return (0); case BHND_IVAR_DEVICE: *result = ci->device; return (0); case BHND_IVAR_HWREV: *result = ci->hwrev; return (0); case BHND_IVAR_DEVICE_CLASS: *result = bhnd_core_class(ci); return (0); case BHND_IVAR_VENDOR_NAME: *result = (uintptr_t) bhnd_vendor_name(ci->vendor); return (0); case BHND_IVAR_DEVICE_NAME: *result = (uintptr_t) bhnd_core_name(ci); return (0); case BHND_IVAR_CORE_INDEX: *result = ci->core_idx; return (0); case BHND_IVAR_CORE_UNIT: *result = ci->unit; return (0); default: return (ENOENT); } } static int bcma_write_ivar(device_t dev, device_t child, int index, uintptr_t value) { switch (index) { case BHND_IVAR_VENDOR: case BHND_IVAR_DEVICE: case BHND_IVAR_HWREV: case BHND_IVAR_DEVICE_CLASS: case BHND_IVAR_VENDOR_NAME: case BHND_IVAR_DEVICE_NAME: case BHND_IVAR_CORE_INDEX: case BHND_IVAR_CORE_UNIT: return (EINVAL); default: return (ENOENT); } } static struct resource_list * bcma_get_resource_list(device_t dev, device_t child) { struct bcma_devinfo *dinfo = device_get_ivars(child); return (&dinfo->resources); } static device_t bcma_find_hostb_device(device_t dev) { struct bcma_softc *sc = device_get_softc(dev); /* This is set (or not) by the concrete bcma driver subclass. */ return (sc->hostb_dev); } static int bcma_reset_core(device_t dev, device_t child, uint16_t flags) { struct bcma_devinfo *dinfo; if (device_get_parent(child) != dev) BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags); dinfo = device_get_ivars(child); /* Can't reset the core without access to the agent registers */ if (dinfo->res_agent == NULL) return (ENODEV); /* Start reset */ bhnd_bus_write_4(dinfo->res_agent, BHND_RESET_CF, BHND_RESET_CF_ENABLE); bhnd_bus_read_4(dinfo->res_agent, BHND_RESET_CF); DELAY(10); /* Disable clock */ bhnd_bus_write_4(dinfo->res_agent, BHND_CF, flags); bhnd_bus_read_4(dinfo->res_agent, BHND_CF); DELAY(10); /* Enable clocks & force clock gating */ bhnd_bus_write_4(dinfo->res_agent, BHND_CF, BHND_CF_CLOCK_EN | BHND_CF_FGC | flags); bhnd_bus_read_4(dinfo->res_agent, BHND_CF); DELAY(10); /* Complete reset */ bhnd_bus_write_4(dinfo->res_agent, BHND_RESET_CF, 0); bhnd_bus_read_4(dinfo->res_agent, BHND_RESET_CF); DELAY(10); /* Release force clock gating */ bhnd_bus_write_4(dinfo->res_agent, BHND_CF, BHND_CF_CLOCK_EN | flags); bhnd_bus_read_4(dinfo->res_agent, BHND_CF); DELAY(10); return (0); } static int bcma_suspend_core(device_t dev, device_t child) { struct bcma_devinfo *dinfo; if (device_get_parent(child) != dev) BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child); dinfo = device_get_ivars(child); /* Can't suspend the core without access to the agent registers */ if (dinfo->res_agent == NULL) return (ENODEV); // TODO - perform suspend return (ENXIO); } static uint32_t bcma_read_config(device_t dev, device_t child, bus_size_t offset, u_int width) { struct bcma_devinfo *dinfo; struct bhnd_resource *r; /* Must be a directly attached child core */ if (device_get_parent(child) != dev) return (UINT32_MAX); /* Fetch the agent registers */ dinfo = device_get_ivars(child); if ((r = dinfo->res_agent) == NULL) return (UINT32_MAX); /* Verify bounds */ if (offset > rman_get_size(r->res)) return (UINT32_MAX); if (rman_get_size(r->res) - offset < width) return (UINT32_MAX); switch (width) { case 1: return (bhnd_bus_read_1(r, offset)); case 2: return (bhnd_bus_read_2(r, offset)); case 4: return (bhnd_bus_read_4(r, offset)); default: return (UINT32_MAX); } } static void bcma_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val, u_int width) { struct bcma_devinfo *dinfo; struct bhnd_resource *r; /* Must be a directly attached child core */ if (device_get_parent(child) != dev) return; /* Fetch the agent registers */ dinfo = device_get_ivars(child); if ((r = dinfo->res_agent) == NULL) return; /* Verify bounds */ if (offset > rman_get_size(r->res)) return; if (rman_get_size(r->res) - offset < width) return; switch (width) { case 1: bhnd_bus_write_1(r, offset, val); break; case 2: bhnd_bus_write_2(r, offset, val); break; case 4: bhnd_bus_write_4(r, offset, val); break; default: break; } } static u_int bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type) { struct bcma_devinfo *dinfo; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, type)); dinfo = device_get_ivars(child); switch (type) { case BHND_PORT_DEVICE: return (dinfo->corecfg->num_dev_ports); case BHND_PORT_BRIDGE: return (dinfo->corecfg->num_bridge_ports); case BHND_PORT_AGENT: return (dinfo->corecfg->num_wrapper_ports); default: device_printf(dev, "%s: unknown type (%d)\n", __func__, type); return (0); } } static u_int bcma_get_region_count(device_t dev, device_t child, bhnd_port_type type, u_int port_num) { struct bcma_devinfo *dinfo; struct bcma_sport_list *ports; struct bcma_sport *port; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, type, port_num)); dinfo = device_get_ivars(child); ports = bcma_corecfg_get_port_list(dinfo->corecfg, type); STAILQ_FOREACH(port, ports, sp_link) { if (port->sp_num == port_num) return (port->sp_num_maps); } /* not found */ return (0); } static int bcma_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, u_int port_num, u_int region_num) { struct bcma_devinfo *dinfo; struct bcma_map *map; struct bcma_sport_list *ports; struct bcma_sport *port; dinfo = device_get_ivars(child); ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); STAILQ_FOREACH(port, ports, sp_link) { if (port->sp_num != port_num) continue; STAILQ_FOREACH(map, &port->sp_maps, m_link) if (map->m_region_num == region_num) return map->m_rid; } return -1; } static int bcma_decode_port_rid(device_t dev, device_t child, int type, int rid, bhnd_port_type *port_type, u_int *port_num, u_int *region_num) { struct bcma_devinfo *dinfo; struct bcma_map *map; struct bcma_sport_list *ports; struct bcma_sport *port; dinfo = device_get_ivars(child); /* Ports are always memory mapped */ if (type != SYS_RES_MEMORY) return (EINVAL); /* Starting with the most likely device list, search all three port * lists */ bhnd_port_type types[] = { BHND_PORT_DEVICE, BHND_PORT_AGENT, BHND_PORT_BRIDGE }; for (int i = 0; i < nitems(types); i++) { ports = bcma_corecfg_get_port_list(dinfo->corecfg, types[i]); STAILQ_FOREACH(port, ports, sp_link) { STAILQ_FOREACH(map, &port->sp_maps, m_link) { if (map->m_rid != rid) continue; *port_type = port->sp_type; *port_num = port->sp_num; *region_num = map->m_region_num; return (0); } } } return (ENOENT); } static int bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) { struct bcma_devinfo *dinfo; struct bcma_map *map; struct bcma_sport_list *ports; struct bcma_sport *port; dinfo = device_get_ivars(child); ports = bcma_corecfg_get_port_list(dinfo->corecfg, port_type); /* Search the port list */ STAILQ_FOREACH(port, ports, sp_link) { if (port->sp_num != port_num) continue; STAILQ_FOREACH(map, &port->sp_maps, m_link) { if (map->m_region_num != region_num) continue; /* Found! */ *addr = map->m_base; *size = map->m_size; return (0); } } return (ENOENT); } static struct bhnd_devinfo * bcma_alloc_bhnd_dinfo(device_t dev) { struct bcma_devinfo *dinfo = bcma_alloc_dinfo(dev); return ((struct bhnd_devinfo *)dinfo); } static void bcma_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo) { bcma_free_dinfo(dev, (struct bcma_devinfo *)dinfo); } + +static int +bcma_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores, + u_int *num_cores) +{ + struct bcma_softc *sc; + struct bcma_erom erom; + const struct bhnd_chipid *cid; + struct resource *r; + int error; + int rid; + + sc = device_get_softc(dev); + + /* Map the EROM table. */ + cid = BHND_BUS_GET_CHIPID(dev, dev); + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr, + cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE, + RF_ACTIVE); + if (r == NULL) { + device_printf(dev, "failed to allocate EROM resource\n"); + return (ENXIO); + } + + /* Enumerate all declared cores */ + if ((error = bcma_erom_open(&erom, r, BCMA_EROM_TABLE_START))) + goto cleanup; + + error = bcma_erom_get_core_info(&erom, cores, num_cores); + +cleanup: + bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + return (error); +} + /** * Scan a device enumeration ROM table, adding all valid discovered cores to * the bus. * * @param bus The bcma bus. * @param erom_res An active resource mapping the EROM core. * @param erom_offset Base offset of the EROM core's register mapping. */ int bcma_add_children(device_t bus, struct resource *erom_res, bus_size_t erom_offset) { struct bcma_erom erom; struct bcma_corecfg *corecfg; struct bcma_devinfo *dinfo; device_t child; int error; corecfg = NULL; /* Initialize our reader */ error = bcma_erom_open(&erom, erom_res, erom_offset); if (error) return (error); /* Add all cores. */ while (!error) { /* Parse next core */ error = bcma_erom_parse_corecfg(&erom, &corecfg); if (error && error == ENOENT) { return (0); } else if (error) { goto failed; } /* Add the child device */ child = BUS_ADD_CHILD(bus, 0, NULL, -1); if (child == NULL) { error = ENXIO; goto failed; } /* Initialize device ivars */ dinfo = device_get_ivars(child); if ((error = bcma_init_dinfo(bus, dinfo, corecfg))) goto failed; /* The dinfo instance now owns the corecfg value */ corecfg = NULL; /* If pins are floating or the hardware is otherwise * unpopulated, the device shouldn't be used. */ if (bhnd_is_hw_disabled(child)) device_disable(child); /* Issue bus callback for fully initialized child. */ BHND_BUS_CHILD_ADDED(bus, child); } /* Hit EOF parsing cores? */ if (error == ENOENT) return (0); failed: if (corecfg != NULL) bcma_free_corecfg(corecfg); return (error); } static device_method_t bcma_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcma_probe), DEVMETHOD(device_attach, bcma_attach), DEVMETHOD(device_detach, bcma_detach), /* Bus interface */ DEVMETHOD(bus_read_ivar, bcma_read_ivar), DEVMETHOD(bus_write_ivar, bcma_write_ivar), DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), /* BHND interface */ DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device), DEVMETHOD(bhnd_bus_alloc_devinfo, bcma_alloc_bhnd_dinfo), DEVMETHOD(bhnd_bus_free_devinfo, bcma_free_bhnd_dinfo), + DEVMETHOD(bhnd_bus_get_core_table, bcma_get_core_table), DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core), DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core), DEVMETHOD(bhnd_bus_read_config, bcma_read_config), DEVMETHOD(bhnd_bus_write_config, bcma_write_config), DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count), DEVMETHOD(bhnd_bus_get_region_count, bcma_get_region_count), DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid), DEVMETHOD(bhnd_bus_decode_port_rid, bcma_decode_port_rid), DEVMETHOD(bhnd_bus_get_region_addr, bcma_get_region_addr), DEVMETHOD_END }; DEFINE_CLASS_1(bhnd, bcma_driver, bcma_methods, sizeof(struct bcma_softc), bhnd_driver); MODULE_VERSION(bcma, 1); MODULE_DEPEND(bcma, bhnd, 1, 1, 1); Index: projects/clang390-import/sys/dev/bhnd/bhnd.h =================================================================== --- projects/clang390-import/sys/dev/bhnd/bhnd.h (revision 304964) +++ projects/clang390-import/sys/dev/bhnd/bhnd.h (revision 304965) @@ -1,1199 +1,1225 @@ /*- * Copyright (c) 2015 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #ifndef _BHND_BHND_H_ #define _BHND_BHND_H_ #include #include #include #include "bhnd_ids.h" #include "bhnd_types.h" #include "bhnd_debug.h" #include "bhnd_bus_if.h" #include "bhnd_match.h" #include "nvram/bhnd_nvram.h" extern devclass_t bhnd_devclass; extern devclass_t bhnd_hostb_devclass; extern devclass_t bhnd_nvram_devclass; #define BHND_CHIPID_MAX_NAMELEN 32 /**< maximum buffer required for a bhnd_format_chip_id() */ /** * bhnd child instance variables */ enum bhnd_device_vars { BHND_IVAR_VENDOR, /**< Designer's JEP-106 manufacturer ID. */ BHND_IVAR_DEVICE, /**< Part number */ BHND_IVAR_HWREV, /**< Core revision */ BHND_IVAR_DEVICE_CLASS, /**< Core class (@sa bhnd_devclass_t) */ BHND_IVAR_VENDOR_NAME, /**< Core vendor name */ BHND_IVAR_DEVICE_NAME, /**< Core name */ BHND_IVAR_CORE_INDEX, /**< Bus-assigned core number */ BHND_IVAR_CORE_UNIT, /**< Bus-assigned core unit number, assigned sequentially (starting at 0) for each vendor/device pair. */ }; /** * bhnd device probe priority bands. */ enum { BHND_PROBE_ROOT = 0, /**< Nexus or host bridge */ BHND_PROBE_BUS = 1000, /**< Busses and bridges */ BHND_PROBE_CPU = 2000, /**< CPU devices */ BHND_PROBE_INTERRUPT = 3000, /**< Interrupt controllers. */ BHND_PROBE_TIMER = 4000, /**< Timers and clocks. */ BHND_PROBE_RESOURCE = 5000, /**< Resource discovery (including NVRAM/SPROM) */ BHND_PROBE_DEFAULT = 6000, /**< Default device priority */ }; /** * Constants defining fine grained ordering within a BHND_PROBE_* priority band. * * Example: * @code * BHND_PROBE_BUS + BHND_PROBE_ORDER_FIRST * @endcode */ enum { BHND_PROBE_ORDER_FIRST = 0, BHND_PROBE_ORDER_EARLY = 25, BHND_PROBE_ORDER_MIDDLE = 50, BHND_PROBE_ORDER_LATE = 75, BHND_PROBE_ORDER_LAST = 100 }; /* * Simplified accessors for bhnd device ivars */ #define BHND_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(bhnd, var, BHND, ivar, type) BHND_ACCESSOR(vendor, VENDOR, uint16_t); BHND_ACCESSOR(device, DEVICE, uint16_t); BHND_ACCESSOR(hwrev, HWREV, uint8_t); BHND_ACCESSOR(class, DEVICE_CLASS, bhnd_devclass_t); BHND_ACCESSOR(vendor_name, VENDOR_NAME, const char *); BHND_ACCESSOR(device_name, DEVICE_NAME, const char *); BHND_ACCESSOR(core_index, CORE_INDEX, u_int); BHND_ACCESSOR(core_unit, CORE_UNIT, int); #undef BHND_ACCESSOR /** * A bhnd(4) board descriptor. */ struct bhnd_board_info { uint16_t board_vendor; /**< PCI-SIG vendor ID (even on non-PCI * devices). * * On PCI devices, this will generally * be the subsystem vendor ID, but the * value may be overridden in device * NVRAM. */ uint16_t board_type; /**< Board type (See BHND_BOARD_*) * * On PCI devices, this will generally * be the subsystem device ID, but the * value may be overridden in device * NVRAM. */ uint16_t board_rev; /**< Board revision. */ uint8_t board_srom_rev; /**< Board SROM format revision */ uint32_t board_flags; /**< Board flags (see BHND_BFL_*) */ uint32_t board_flags2; /**< Board flags 2 (see BHND_BFL2_*) */ uint32_t board_flags3; /**< Board flags 3 (see BHND_BFL3_*) */ }; /** * Chip Identification * * This is read from the ChipCommon ID register; on earlier bhnd(4) devices * where ChipCommon is unavailable, known values must be supplied. */ struct bhnd_chipid { uint16_t chip_id; /**< chip id (BHND_CHIPID_*) */ uint8_t chip_rev; /**< chip revision */ uint8_t chip_pkg; /**< chip package (BHND_PKGID_*) */ uint8_t chip_type; /**< chip type (BHND_CHIPTYPE_*) */ bhnd_addr_t enum_addr; /**< chip_type-specific enumeration * address; either the siba(4) base * core register block, or the bcma(4) * EROM core address. */ uint8_t ncores; /**< number of cores, if known. 0 if * not available. */ }; /** * A bhnd(4) core descriptor. */ struct bhnd_core_info { uint16_t vendor; /**< JEP-106 vendor (BHND_MFGID_*) */ uint16_t device; /**< device */ uint16_t hwrev; /**< hardware revision */ u_int core_idx; /**< bus-assigned core index */ int unit; /**< bus-assigned core unit */ }; /** * A bhnd(4) bus resource. * * This provides an abstract interface to per-core resources that may require * bus-level remapping of address windows prior to access. */ struct bhnd_resource { struct resource *res; /**< the system resource. */ bool direct; /**< false if the resource requires * bus window remapping before it * is MMIO accessible. */ }; /** * Device quirk table descriptor. */ struct bhnd_device_quirk { struct bhnd_device_match desc; /**< device match descriptor */ uint32_t quirks; /**< quirk flags */ }; #define BHND_CORE_QUIRK(_rev, _flags) \ {{ BHND_MATCH_CORE_REV(_rev) }, (_flags) } #define BHND_CHIP_QUIRK(_chip, _rev, _flags) \ {{ BHND_CHIP_IR(BCM ## _chip, _rev) }, (_flags) } #define BHND_PKG_QUIRK(_chip, _pkg, _flags) \ {{ BHND_CHIP_IP(BCM ## _chip, BCM ## _chip ## _pkg) }, (_flags) } #define BHND_BOARD_QUIRK(_board, _flags) \ {{ BHND_MATCH_BOARD_TYPE(_board) }, \ (_flags) } #define BHND_DEVICE_QUIRK_END { { BHND_MATCH_ANY }, 0 } #define BHND_DEVICE_QUIRK_IS_END(_q) \ (((_q)->desc.m.match_flags == 0) && (_q)->quirks == 0) enum { BHND_DF_ANY = 0, BHND_DF_HOSTB = (1<<0), /**< core is serving as the bus' host * bridge. implies BHND_DF_ADAPTER */ BHND_DF_SOC = (1<<1), /**< core is attached to a native bus (BHND_ATTACH_NATIVE) */ BHND_DF_ADAPTER = (1<<2), /**< core is attached to a bridged * adapter (BHND_ATTACH_ADAPTER) */ }; /** Device probe table descriptor */ struct bhnd_device { const struct bhnd_device_match core; /**< core match descriptor */ const char *desc; /**< device description, or NULL. */ const struct bhnd_device_quirk *quirks_table; /**< quirks table for this device, or NULL */ uint32_t device_flags; /**< required BHND_DF_* flags */ }; #define _BHND_DEVICE(_vendor, _device, _desc, _quirks, \ _flags, ...) \ { { BHND_MATCH_CORE(BHND_MFGID_ ## _vendor, \ BHND_COREID_ ## _device) }, _desc, _quirks, \ _flags } #define BHND_DEVICE(_vendor, _device, _desc, _quirks, ...) \ _BHND_DEVICE(_vendor, _device, _desc, _quirks, \ ## __VA_ARGS__, 0) #define BHND_DEVICE_END { { BHND_MATCH_ANY }, NULL, NULL, 0 } #define BHND_DEVICE_IS_END(_d) \ (BHND_MATCH_IS_ANY(&(_d)->core) && (_d)->desc == NULL) const char *bhnd_vendor_name(uint16_t vendor); const char *bhnd_port_type_name(bhnd_port_type port_type); const char *bhnd_nvram_src_name(bhnd_nvram_src nvram_src); const char *bhnd_find_core_name(uint16_t vendor, uint16_t device); bhnd_devclass_t bhnd_find_core_class(uint16_t vendor, uint16_t device); const char *bhnd_core_name(const struct bhnd_core_info *ci); bhnd_devclass_t bhnd_core_class(const struct bhnd_core_info *ci); int bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id); device_t bhnd_match_child(device_t dev, const struct bhnd_core_match *desc); device_t bhnd_find_child(device_t dev, bhnd_devclass_t class, int unit); device_t bhnd_find_bridge_root(device_t dev, devclass_t bus_class); const struct bhnd_core_info *bhnd_match_core( const struct bhnd_core_info *cores, u_int num_cores, const struct bhnd_core_match *desc); const struct bhnd_core_info *bhnd_find_core( const struct bhnd_core_info *cores, u_int num_cores, bhnd_devclass_t class); bool bhnd_core_matches( const struct bhnd_core_info *core, const struct bhnd_core_match *desc); bool bhnd_chip_matches( const struct bhnd_chipid *chipid, const struct bhnd_chip_match *desc); bool bhnd_board_matches( const struct bhnd_board_info *info, const struct bhnd_board_match *desc); bool bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc); bool bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc); const struct bhnd_device *bhnd_device_lookup(device_t dev, const struct bhnd_device *table, size_t entry_size); uint32_t bhnd_device_quirks(device_t dev, const struct bhnd_device *table, size_t entry_size); struct bhnd_core_info bhnd_get_core_info(device_t dev); int bhnd_alloc_resources(device_t dev, struct resource_spec *rs, struct bhnd_resource **res); void bhnd_release_resources(device_t dev, const struct resource_spec *rs, struct bhnd_resource **res); struct bhnd_chipid bhnd_parse_chipid(uint32_t idreg, bhnd_addr_t enum_addr); int bhnd_read_chipid(device_t dev, struct resource_spec *rs, bus_size_t chipc_offset, struct bhnd_chipid *result); void bhnd_set_custom_core_desc(device_t dev, const char *name); void bhnd_set_default_core_desc(device_t dev); void bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id); int bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len, size_t *rlen); int bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width); int bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value); int bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value); int bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value); int bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width); int bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value); int bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value); int bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value); int bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t count, bhnd_nvram_type type); bool bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child); bool bhnd_bus_generic_is_region_valid(device_t dev, device_t child, bhnd_port_type type, u_int port, u_int region); int bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size, bhnd_nvram_type type); const struct bhnd_chipid *bhnd_bus_generic_get_chipid(device_t dev, device_t child); int bhnd_bus_generic_read_board_info(device_t dev, device_t child, struct bhnd_board_info *info); struct bhnd_resource *bhnd_bus_generic_alloc_resource (device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); int bhnd_bus_generic_release_resource (device_t dev, device_t child, int type, int rid, struct bhnd_resource *r); int bhnd_bus_generic_activate_resource (device_t dev, device_t child, int type, int rid, struct bhnd_resource *r); int bhnd_bus_generic_deactivate_resource (device_t dev, device_t child, int type, int rid, struct bhnd_resource *r); bhnd_attach_type bhnd_bus_generic_get_attach_type(device_t dev, device_t child); /** * Return the active host bridge core for the bhnd bus, if any, or NULL if * not found. * * @param dev A bhnd bus device. */ static inline device_t bhnd_find_hostb_device(device_t dev) { return (BHND_BUS_FIND_HOSTB_DEVICE(dev)); } /** * Return true if the hardware components required by @p dev are known to be * unpopulated or otherwise unusable. * * In some cases, enumerated devices may have pins that are left floating, or * the hardware may otherwise be non-functional; this method allows a parent * device to explicitly specify if a successfully enumerated @p dev should * be disabled. * * @param dev A bhnd bus child device. */ static inline bool bhnd_is_hw_disabled(device_t dev) { return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), dev)); } /** * Return the BHND chip identification info for the bhnd bus. * * @param dev A bhnd bus child device. */ static inline const struct bhnd_chipid * bhnd_get_chipid(device_t dev) { return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev)); }; /** + * Get a list of all cores discoverable on the bhnd bus. + * + * Enumerates all cores discoverable on @p dev, returning the list in + * @p cores and the count in @p num_cores. + * + * The memory allocated for the list should be freed using + * `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed + * when an error is returned. + * + * @param dev A bhnd bus child device. + * @param[out] cores The table of core descriptors. + * @param[out] num_cores The number of core descriptors in @p cores. + * + * @retval 0 success + * @retval non-zero if an error occurs enumerating @p dev, a regular UNIX + * error code should be returned. + */ +static inline int +bhnd_get_core_table(device_t dev, struct bhnd_core_info **cores, + u_int *num_cores) +{ + return (BHND_BUS_GET_CORE_TABLE(device_get_parent(dev), dev, cores, + num_cores)); +} + +/** * If supported by the chipset, return the clock source for the given clock. * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev A bhnd bus child device. * @param clock The clock for which a clock source will be returned. * * @retval bhnd_clksrc The clock source for @p clock. * @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its * clock source is not known to the bus. */ static inline bhnd_clksrc bhnd_pwrctl_get_clksrc(device_t dev, bhnd_clock clock) { return (BHND_BUS_PWRCTL_GET_CLKSRC(device_get_parent(dev), dev, clock)); } /** * If supported by the chipset, gate @p clock * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev A bhnd bus child device. * @param clock The clock to be disabled. * * @retval 0 success * @retval ENODEV If bus-level clock source management is not supported. * @retval ENXIO If bus-level management of @p clock is not supported. */ static inline int bhnd_pwrctl_gate_clock(device_t dev, bhnd_clock clock) { return (BHND_BUS_PWRCTL_GATE_CLOCK(device_get_parent(dev), dev, clock)); } /** * If supported by the chipset, ungate @p clock * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev A bhnd bus child device. * @param clock The clock to be enabled. * * @retval 0 success * @retval ENODEV If bus-level clock source management is not supported. * @retval ENXIO If bus-level management of @p clock is not supported. */ static inline int bhnd_pwrctl_ungate_clock(device_t dev, bhnd_clock clock) { return (BHND_BUS_PWRCTL_UNGATE_CLOCK(device_get_parent(dev), dev, clock)); } /** * Return the BHND attachment type of the parent bhnd bus. * * @param dev A bhnd bus child device. * * @retval BHND_ATTACH_ADAPTER if the bus is resident on a bridged adapter, * such as a WiFi chipset. * @retval BHND_ATTACH_NATIVE if the bus provides hardware services (clock, * CPU, etc) to a directly attached native host. */ static inline bhnd_attach_type bhnd_get_attach_type (device_t dev) { return (BHND_BUS_GET_ATTACH_TYPE(device_get_parent(dev), dev)); } /** * Attempt to read the BHND board identification from the bhnd bus. * * This relies on NVRAM access, and will fail if a valid NVRAM device cannot * be found, or is not yet attached. * * @param dev The parent of @p child. * @param child The bhnd device requesting board info. * @param[out] info On success, will be populated with the bhnd(4) device's * board information. * * @retval 0 success * @retval ENODEV No valid NVRAM source could be found. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ static inline int bhnd_read_board_info(device_t dev, struct bhnd_board_info *info) { return (BHND_BUS_READ_BOARD_INFO(device_get_parent(dev), dev, info)); } /** * Allocate and enable per-core PMU request handling for @p child. * * The region containing the core's PMU register block (if any) must be * allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before * calling bhnd_alloc_pmu(), and must not be released until after * calling bhnd_release_pmu(). * * @param dev The parent of @p child. * @param child The requesting bhnd device. * * @retval 0 success * @retval non-zero If allocating PMU request state otherwise fails, a * regular unix error code will be returned. */ static inline int bhnd_alloc_pmu(device_t dev) { return (BHND_BUS_ALLOC_PMU(device_get_parent(dev), dev)); } /** * Release any per-core PMU resources allocated for @p child. Any outstanding * PMU requests are are discarded. * * @param dev The parent of @p child. * @param child The requesting bhnd device. * * @retval 0 success * @retval non-zero If releasing PMU request state otherwise fails, a * regular unix error code will be returned, and * the core state will be left unmodified. */ static inline int bhnd_release_pmu(device_t dev) { return (BHND_BUS_RELEASE_PMU(device_get_parent(dev), dev)); } /** * Request that @p clock (or faster) be routed to @p dev. * * A driver must ask the bhnd bus to allocate clock request state * via bhnd_alloc_pmu() before it can request clock resources. * * Request multiplexing is managed by the bus. * * @param dev The bhnd(4) device to which @p clock should be routed. * @param clock The requested clock source. * * @retval 0 success * @retval ENODEV If an unsupported clock was requested. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ static inline int bhnd_request_clock(device_t dev, bhnd_clock clock) { return (BHND_BUS_REQUEST_CLOCK(device_get_parent(dev), dev, clock)); } /** * Request that @p clocks be powered on behalf of @p dev. * * This will power any clock sources (e.g. XTAL, PLL, etc) required for * @p clocks and wait until they are ready, discarding any previous * requests by @p dev. * * Request multiplexing is managed by the bus. * * A driver must ask the bhnd bus to allocate clock request state * via bhnd_alloc_pmu() before it can request clock resources. * * @param dev The requesting bhnd(4) device. * @param clocks The clock(s) to be enabled. * * @retval 0 success * @retval ENODEV If an unsupported clock was requested. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ static inline int bhnd_enable_clocks(device_t dev, uint32_t clocks) { return (BHND_BUS_ENABLE_CLOCKS(device_get_parent(dev), dev, clocks)); } /** * Power up an external PMU-managed resource assigned to @p dev. * * A driver must ask the bhnd bus to allocate PMU request state * via bhnd_alloc_pmu() before it can request PMU resources. * * @param dev The requesting bhnd(4) device. * @param rsrc The core-specific external resource identifier. * * @retval 0 success * @retval ENODEV If the PMU does not support @p rsrc. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ static inline int bhnd_request_ext_rsrc(device_t dev, u_int rsrc) { return (BHND_BUS_REQUEST_EXT_RSRC(device_get_parent(dev), dev, rsrc)); } /** * Power down an external PMU-managed resource assigned to @p dev. * * A driver must ask the bhnd bus to allocate PMU request state * via bhnd_alloc_pmu() before it can request PMU resources. * * @param dev The requesting bhnd(4) device. * @param rsrc The core-specific external resource identifier. * * @retval 0 success * @retval ENODEV If the PMU does not support @p rsrc. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ static inline int bhnd_release_ext_rsrc(device_t dev, u_int rsrc) { return (BHND_BUS_RELEASE_EXT_RSRC(device_get_parent(dev), dev, rsrc)); } /** * Read @p width bytes at @p offset from the bus-specific agent/config * space of @p dev. * * @param dev The bhnd device for which @p offset should be read. * @param offset The offset to be read. * @param width The size of the access. Must be 1, 2 or 4 bytes. * * The exact behavior of this method is bus-specific. In the case of * bcma(4), this method provides access to the first agent port of @p child. * * @note Device drivers should only use this API for functionality * that is not available via another bhnd(4) function. */ static inline uint32_t bhnd_read_config(device_t dev, bus_size_t offset, u_int width) { return (BHND_BUS_READ_CONFIG(device_get_parent(dev), dev, offset, width)); } /** * Read @p width bytes at @p offset from the bus-specific agent/config * space of @p dev. * * @param dev The bhnd device for which @p offset should be read. * @param offset The offset to be written. * @param width The size of the access. Must be 1, 2 or 4 bytes. * * The exact behavior of this method is bus-specific. In the case of * bcma(4), this method provides access to the first agent port of @p child. * * @note Device drivers should only use this API for functionality * that is not available via another bhnd(4) function. */ static inline void bhnd_write_config(device_t dev, bus_size_t offset, uint32_t val, u_int width) { BHND_BUS_WRITE_CONFIG(device_get_parent(dev), dev, offset, val, width); } /** * Read an NVRAM variable, coerced to the requested @p type. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] buf A buffer large enough to hold @p len bytes. On * success, the requested value will be written to * this buffer. This argment may be NULL if * the value is not desired. * @param[in,out] len The maximum capacity of @p buf. On success, * will be set to the actual size of the requested * value. * @param type The desired data representation to be written * to @p buf. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval ENOMEM If a buffer of @p size is too small to hold the * requested value. * @retval EOPNOTSUPP If the value cannot be coerced to @p type. * @retval ERANGE If value coercion would overflow @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ static inline int bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len, bhnd_nvram_type type) { return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf, len, type)); } /** * Allocate a resource from a device's parent bhnd(4) bus. * * @param dev The device requesting resource ownership. * @param type The type of resource to allocate. This may be any type supported * by the standard bus APIs. * @param rid The bus-specific handle identifying the resource being allocated. * @param start The start address of the resource. * @param end The end address of the resource. * @param count The size of the resource. * @param flags The flags for the resource to be allocated. These may be any * values supported by the standard bus APIs. * * To request the resource's default addresses, pass @p start and * @p end values of @c 0 and @c ~0, respectively, and * a @p count of @c 1. * * @retval NULL The resource could not be allocated. * @retval resource The allocated resource. */ static inline struct bhnd_resource * bhnd_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { return BHND_BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, type, rid, start, end, count, flags); } /** * Allocate a resource from a device's parent bhnd(4) bus, using the * resource's default start, end, and count values. * * @param dev The device requesting resource ownership. * @param type The type of resource to allocate. This may be any type supported * by the standard bus APIs. * @param rid The bus-specific handle identifying the resource being allocated. * @param flags The flags for the resource to be allocated. These may be any * values supported by the standard bus APIs. * * @retval NULL The resource could not be allocated. * @retval resource The allocated resource. */ static inline struct bhnd_resource * bhnd_alloc_resource_any(device_t dev, int type, int *rid, u_int flags) { return bhnd_alloc_resource(dev, type, rid, 0, ~0, 1, flags); } /** * Activate a previously allocated bhnd resource. * * @param dev The device holding ownership of the allocated resource. * @param type The type of the resource. * @param rid The bus-specific handle identifying the resource. * @param r A pointer to the resource returned by bhnd_alloc_resource or * BHND_BUS_ALLOC_RESOURCE. * * @retval 0 success * @retval non-zero an error occurred while activating the resource. */ static inline int bhnd_activate_resource(device_t dev, int type, int rid, struct bhnd_resource *r) { return BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), dev, type, rid, r); } /** * Deactivate a previously activated bhnd resource. * * @param dev The device holding ownership of the activated resource. * @param type The type of the resource. * @param rid The bus-specific handle identifying the resource. * @param r A pointer to the resource returned by bhnd_alloc_resource or * BHND_BUS_ALLOC_RESOURCE. * * @retval 0 success * @retval non-zero an error occurred while activating the resource. */ static inline int bhnd_deactivate_resource(device_t dev, int type, int rid, struct bhnd_resource *r) { return BHND_BUS_DEACTIVATE_RESOURCE(device_get_parent(dev), dev, type, rid, r); } /** * Free a resource allocated by bhnd_alloc_resource(). * * @param dev The device holding ownership of the resource. * @param type The type of the resource. * @param rid The bus-specific handle identifying the resource. * @param r A pointer to the resource returned by bhnd_alloc_resource or * BHND_ALLOC_RESOURCE. * * @retval 0 success * @retval non-zero an error occurred while activating the resource. */ static inline int bhnd_release_resource(device_t dev, int type, int rid, struct bhnd_resource *r) { return BHND_BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type, rid, r); } /** * Return true if @p region_num is a valid region on @p port_num of * @p type attached to @p dev. * * @param dev A bhnd bus child device. * @param type The port type being queried. * @param port_num The port number being queried. * @param region_num The region number being queried. */ static inline bool bhnd_is_region_valid(device_t dev, bhnd_port_type type, u_int port_num, u_int region_num) { return (BHND_BUS_IS_REGION_VALID(device_get_parent(dev), dev, type, port_num, region_num)); } /** * Return the number of ports of type @p type attached to @p def. * * @param dev A bhnd bus child device. * @param type The port type being queried. */ static inline u_int bhnd_get_port_count(device_t dev, bhnd_port_type type) { return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), dev, type)); } /** * Return the number of memory regions mapped to @p child @p port of * type @p type. * * @param dev A bhnd bus child device. * @param port The port number being queried. * @param type The port type being queried. */ static inline u_int bhnd_get_region_count(device_t dev, bhnd_port_type type, u_int port) { return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), dev, type, port)); } /** * Return the resource-ID for a memory region on the given device port. * * @param dev A bhnd bus child device. * @param type The port type. * @param port The port identifier. * @param region The identifier of the memory region on @p port. * * @retval int The RID for the given @p port and @p region on @p device. * @retval -1 No such port/region found. */ static inline int bhnd_get_port_rid(device_t dev, bhnd_port_type type, u_int port, u_int region) { return BHND_BUS_GET_PORT_RID(device_get_parent(dev), dev, type, port, region); } /** * Decode a port / region pair on @p dev defined by @p rid. * * @param dev A bhnd bus child device. * @param type The resource type. * @param rid The resource identifier. * @param[out] port_type The decoded port type. * @param[out] port The decoded port identifier. * @param[out] region The decoded region identifier. * * @retval 0 success * @retval non-zero No matching port/region found. */ static inline int bhnd_decode_port_rid(device_t dev, int type, int rid, bhnd_port_type *port_type, u_int *port, u_int *region) { return BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), dev, type, rid, port_type, port, region); } /** * Get the address and size of @p region on @p port. * * @param dev A bhnd bus child device. * @param port_type The port type. * @param port The port identifier. * @param region The identifier of the memory region on @p port. * @param[out] region_addr The region's base address. * @param[out] region_size The region's size. * * @retval 0 success * @retval non-zero No matching port/region found. */ static inline int bhnd_get_region_addr(device_t dev, bhnd_port_type port_type, u_int port, u_int region, bhnd_addr_t *region_addr, bhnd_size_t *region_size) { return BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), dev, port_type, port, region, region_addr, region_size); } /* * bhnd bus-level equivalents of the bus_(read|write|set|barrier|...) * macros (compatible with bhnd_resource). * * Generated with bhnd/tools/bus_macro.sh */ #define bhnd_bus_barrier(r, o, l, f) \ ((r)->direct) ? \ bus_barrier((r)->res, (o), (l), (f)) : \ BHND_BUS_BARRIER( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (l), (f)) #define bhnd_bus_read_1(r, o) \ ((r)->direct) ? \ bus_read_1((r)->res, (o)) : \ BHND_BUS_READ_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_1(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_1((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_1(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_1((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_1(r, o, v) \ ((r)->direct) ? \ bus_write_1((r)->res, (o), (v)) : \ BHND_BUS_WRITE_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_1(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_1((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_1(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_1((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_stream_1(r, o) \ ((r)->direct) ? \ bus_read_stream_1((r)->res, (o)) : \ BHND_BUS_READ_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_stream_1(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_stream_1((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_stream_1(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_stream_1((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_stream_1(r, o, v) \ ((r)->direct) ? \ bus_write_stream_1((r)->res, (o), (v)) : \ BHND_BUS_WRITE_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_stream_1(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_stream_1((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_stream_1(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_stream_1((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_STREAM_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_set_multi_1(r, o, v, c) \ ((r)->direct) ? \ bus_set_multi_1((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_MULTI_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #define bhnd_bus_set_region_1(r, o, v, c) \ ((r)->direct) ? \ bus_set_region_1((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_REGION_1( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #define bhnd_bus_read_2(r, o) \ ((r)->direct) ? \ bus_read_2((r)->res, (o)) : \ BHND_BUS_READ_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_2(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_2((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_2(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_2((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_2(r, o, v) \ ((r)->direct) ? \ bus_write_2((r)->res, (o), (v)) : \ BHND_BUS_WRITE_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_2(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_2((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_2(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_2((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_stream_2(r, o) \ ((r)->direct) ? \ bus_read_stream_2((r)->res, (o)) : \ BHND_BUS_READ_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_stream_2(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_stream_2((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_stream_2(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_stream_2((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_stream_2(r, o, v) \ ((r)->direct) ? \ bus_write_stream_2((r)->res, (o), (v)) : \ BHND_BUS_WRITE_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_stream_2(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_stream_2((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_stream_2(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_stream_2((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_STREAM_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_set_multi_2(r, o, v, c) \ ((r)->direct) ? \ bus_set_multi_2((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_MULTI_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #define bhnd_bus_set_region_2(r, o, v, c) \ ((r)->direct) ? \ bus_set_region_2((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_REGION_2( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #define bhnd_bus_read_4(r, o) \ ((r)->direct) ? \ bus_read_4((r)->res, (o)) : \ BHND_BUS_READ_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_4(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_4((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_4(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_4((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_4(r, o, v) \ ((r)->direct) ? \ bus_write_4((r)->res, (o), (v)) : \ BHND_BUS_WRITE_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_4(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_4((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_4(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_4((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_stream_4(r, o) \ ((r)->direct) ? \ bus_read_stream_4((r)->res, (o)) : \ BHND_BUS_READ_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) #define bhnd_bus_read_multi_stream_4(r, o, d, c) \ ((r)->direct) ? \ bus_read_multi_stream_4((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_MULTI_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_region_stream_4(r, o, d, c) \ ((r)->direct) ? \ bus_read_region_stream_4((r)->res, (o), (d), (c)) : \ BHND_BUS_READ_REGION_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_stream_4(r, o, v) \ ((r)->direct) ? \ bus_write_stream_4((r)->res, (o), (v)) : \ BHND_BUS_WRITE_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) #define bhnd_bus_write_multi_stream_4(r, o, d, c) \ ((r)->direct) ? \ bus_write_multi_stream_4((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_MULTI_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_region_stream_4(r, o, d, c) \ ((r)->direct) ? \ bus_write_region_stream_4((r)->res, (o), (d), (c)) : \ BHND_BUS_WRITE_REGION_STREAM_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_set_multi_4(r, o, v, c) \ ((r)->direct) ? \ bus_set_multi_4((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_MULTI_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #define bhnd_bus_set_region_4(r, o, v, c) \ ((r)->direct) ? \ bus_set_region_4((r)->res, (o), (v), (c)) : \ BHND_BUS_SET_REGION_4( \ device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v), (c)) #endif /* _BHND_BHND_H_ */ Index: projects/clang390-import/sys/dev/bhnd/bhnd_bus_if.m =================================================================== --- projects/clang390-import/sys/dev/bhnd/bhnd_bus_if.m (revision 304964) +++ projects/clang390-import/sys/dev/bhnd/bhnd_bus_if.m (revision 304965) @@ -1,1238 +1,1271 @@ #- # Copyright (c) 2015 Landon Fuller # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # $FreeBSD$ #include #include #include #include INTERFACE bhnd_bus; # # bhnd(4) bus interface # HEADER { /* forward declarations */ struct bhnd_board_info; struct bhnd_core_info; struct bhnd_chipid; struct bhnd_devinfo; struct bhnd_resource; } CODE { #include #include static struct bhnd_chipid * bhnd_bus_null_get_chipid(device_t dev, device_t child) { panic("bhnd_bus_get_chipid unimplemented"); } + static int + bhnd_bus_null_get_core_table(device_t dev, device_t child, + struct bhnd_core_info **cores, u_int *num_cores) + { + panic("bhnd_bus_get_core_table unimplemented"); + } + static bhnd_attach_type bhnd_bus_null_get_attach_type(device_t dev, device_t child) { panic("bhnd_bus_get_attach_type unimplemented"); } static bhnd_clksrc bhnd_bus_null_pwrctl_get_clksrc(device_t dev, device_t child, bhnd_clock clock) { return (BHND_CLKSRC_UNKNOWN); } static int bhnd_bus_null_pwrctl_gate_clock(device_t dev, device_t child, bhnd_clock clock) { return (ENODEV); } static int bhnd_bus_null_pwrctl_ungate_clock(device_t dev, device_t child, bhnd_clock clock) { return (ENODEV); } static int bhnd_bus_null_read_board_info(device_t dev, device_t child, struct bhnd_board_info *info) { panic("bhnd_bus_read_boardinfo unimplemented"); } static void bhnd_bus_null_child_added(device_t dev, device_t child) { } static int bhnd_bus_null_alloc_pmu(device_t dev, device_t child) { panic("bhnd_bus_alloc_pmu unimplemented"); } static int bhnd_bus_null_release_pmu(device_t dev, device_t child) { panic("bhnd_bus_release_pmu unimplemented"); } static int bhnd_bus_null_request_clock(device_t dev, device_t child, bhnd_clock clock) { panic("bhnd_bus_request_clock unimplemented"); } static int bhnd_bus_null_enable_clocks(device_t dev, device_t child, uint32_t clocks) { panic("bhnd_bus_enable_clocks unimplemented"); } static int bhnd_bus_null_request_ext_rsrc(device_t dev, device_t child, u_int rsrc) { panic("bhnd_bus_request_ext_rsrc unimplemented"); } static int bhnd_bus_null_release_ext_rsrc(device_t dev, device_t child, u_int rsrc) { panic("bhnd_bus_release_ext_rsrc unimplemented"); } static uint32_t bhnd_bus_null_read_config(device_t dev, device_t child, bus_size_t offset, u_int width) { panic("bhnd_bus_null_read_config unimplemented"); } static void bhnd_bus_null_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val, u_int width) { panic("bhnd_bus_null_write_config unimplemented"); } static device_t bhnd_bus_null_find_hostb_device(device_t dev) { panic("bhnd_bus_find_hostb_device unimplemented"); } static bool bhnd_bus_null_is_hw_disabled(device_t dev, device_t child) { panic("bhnd_bus_is_hw_disabled unimplemented"); } static int bhnd_bus_null_get_probe_order(device_t dev, device_t child) { panic("bhnd_bus_get_probe_order unimplemented"); } static int bhnd_bus_null_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, u_int port, u_int region) { return (-1); } static int bhnd_bus_null_decode_port_rid(device_t dev, device_t child, int type, int rid, bhnd_port_type *port_type, u_int *port, u_int *region) { return (ENOENT); } static int bhnd_bus_null_get_region_addr(device_t dev, device_t child, bhnd_port_type type, u_int port, u_int region, bhnd_addr_t *addr, bhnd_size_t *size) { return (ENOENT); } static int bhnd_bus_null_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size, bhnd_nvram_type type) { return (ENODEV); } } /** * Return the active host bridge core for the bhnd bus, if any. * * @param dev The bhnd bus device. * * @retval device_t if a hostb device exists * @retval NULL if no hostb device is found. */ METHOD device_t find_hostb_device { device_t dev; } DEFAULT bhnd_bus_null_find_hostb_device; /** * Return true if the hardware components required by @p child are unpopulated * or otherwise unusable. * * In some cases, enumerated devices may have pins that are left floating, or * the hardware may otherwise be non-functional; this method allows a parent * device to explicitly specify if a successfully enumerated @p child should * be disabled. * * @param dev The device whose child is being examined. * @param child The child device. */ METHOD bool is_hw_disabled { device_t dev; device_t child; } DEFAULT bhnd_bus_null_is_hw_disabled; /** * Return the probe (and attach) order for @p child. * * All devices on the bhnd(4) bus will be probed, attached, or resumed in * ascending order; they will be suspended, shutdown, and detached in * descending order. * * The following device methods will be dispatched in ascending probe order * by the bus: * * - DEVICE_PROBE() * - DEVICE_ATTACH() * - DEVICE_RESUME() * * The following device methods will be dispatched in descending probe order * by the bus: * * - DEVICE_SHUTDOWN() * - DEVICE_DETACH() * - DEVICE_SUSPEND() * * @param dev The device whose child is being examined. * @param child The child device. * * Refer to BHND_PROBE_* and BHND_PROBE_ORDER_* for the standard set of * priorities. */ METHOD int get_probe_order { device_t dev; device_t child; } DEFAULT bhnd_bus_null_get_probe_order; /** * Return the BHND chip identification for the parent bus. * * @param dev The device whose child is being examined. * @param child The child device. */ METHOD const struct bhnd_chipid * get_chipid { device_t dev; device_t child; } DEFAULT bhnd_bus_null_get_chipid; + +/** + * Get a list of all cores discoverable on @p dev. + * + * Enumerates all cores discoverable on @p dev, returning the list in + * @p cores and the count in @p num_cores. + * + * The memory allocated for the list should be freed using + * `free(*cores, M_BHND)`. @p cores and @p num_cores are not changed + * when an error is returned. + * + * @param dev The bhnd bus device. + * @param child The requesting bhnd bus child. + * @param[out] cores The table of core descriptors. + * @param[out] num_cores The number of core descriptors in @p cores. + * + * @retval 0 success + * @retval non-zero if an error occurs enumerating @p dev, a regular UNIX + * error code should be returned. + */ +METHOD int get_core_table { + device_t dev; + device_t child; + struct bhnd_core_info **cores; + u_int *num_cores; +} DEFAULT bhnd_bus_null_get_core_table; /** * Return the BHND attachment type of the parent bus. * * @param dev The device whose child is being examined. * @param child The child device. * * @retval BHND_ATTACH_ADAPTER if the bus is resident on a bridged adapter, * such as a WiFi chipset. * @retval BHND_ATTACH_NATIVE if the bus provides hardware services (clock, * CPU, etc) to a directly attached native host. */ METHOD bhnd_attach_type get_attach_type { device_t dev; device_t child; } DEFAULT bhnd_bus_null_get_attach_type; /** * Attempt to read the BHND board identification from the parent bus. * * This relies on NVRAM access, and will fail if a valid NVRAM device cannot * be found, or is not yet attached. * * @param dev The parent of @p child. * @param child The bhnd device requesting board info. * @param[out] info On success, will be populated with the bhnd(4) device's * board information. * * @retval 0 success * @retval ENODEV No valid NVRAM source could be found. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ METHOD int read_board_info { device_t dev; device_t child; struct bhnd_board_info *info; } DEFAULT bhnd_bus_null_read_board_info; /** * Allocate and zero-initialize a buffer suitably sized and aligned for a * bhnd_devinfo structure. * * @param dev The bhnd bus device. * * @retval non-NULL success * @retval NULL allocation failed */ METHOD struct bhnd_devinfo * alloc_devinfo { device_t dev; }; /** * Release memory previously allocated for @p devinfo. * * @param dev The bhnd bus device. * @param dinfo A devinfo buffer previously allocated via * BHND_BUS_ALLOC_DEVINFO(). */ METHOD void free_devinfo { device_t dev; struct bhnd_devinfo *dinfo; }; /** * Notify a bhnd bus that a child was added. * * This method must be called by concrete bhnd(4) driver impementations * after @p child's bus state is fully initialized. * * @param dev The bhnd bus whose child is being added. * @param child The child added to @p dev. */ METHOD void child_added { device_t dev; device_t child; } DEFAULT bhnd_bus_null_child_added; /** * Reset the device's hardware core. * * @param dev The parent of @p child. * @param child The device to be reset. * @param flags Device-specific core flags to be supplied on reset. * * @retval 0 success * @retval non-zero error */ METHOD int reset_core { device_t dev; device_t child; uint16_t flags; } /** * Suspend a device hardware core. * * @param dev The parent of @p child. * @param child The device to be reset. * * @retval 0 success * @retval non-zero error */ METHOD int suspend_core { device_t dev; device_t child; } /** * If supported by the chipset, return the clock source for the given clock. * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev The parent of @p child. * @param child The bhnd device requesting a clock source. * @param clock The clock for which a clock source will be returned. * * @retval bhnd_clksrc The clock source for @p clock. * @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its * clock source is not known to the bus. */ METHOD bhnd_clksrc pwrctl_get_clksrc { device_t dev; device_t child; bhnd_clock clock; } DEFAULT bhnd_bus_null_pwrctl_get_clksrc; /** * If supported by the chipset, gate the clock source for @p clock * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev The parent of @p child. * @param child The bhnd device requesting clock gating. * @param clock The clock to be disabled. * * @retval 0 success * @retval ENODEV If bus-level clock source management is not supported. * @retval ENXIO If bus-level management of @p clock is not supported. */ METHOD int pwrctl_gate_clock { device_t dev; device_t child; bhnd_clock clock; } DEFAULT bhnd_bus_null_pwrctl_gate_clock; /** * If supported by the chipset, ungate the clock source for @p clock * * This function is only supported on early PWRCTL-equipped chipsets * that expose clock management via their host bridge interface. Currently, * this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9. * * @param dev The parent of @p child. * @param child The bhnd device requesting clock gating. * @param clock The clock to be enabled. * * @retval 0 success * @retval ENODEV If bus-level clock source management is not supported. * @retval ENXIO If bus-level management of @p clock is not supported. */ METHOD int pwrctl_ungate_clock { device_t dev; device_t child; bhnd_clock clock; } DEFAULT bhnd_bus_null_pwrctl_ungate_clock; /** * Allocate and enable per-core PMU request handling for @p child. * * The region containing the core's PMU register block (if any) must be * allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before * calling BHND_BUS_ALLOC_PMU(), and must not be released until after * calling BHND_BUS_RELEASE_PMU(). * * @param dev The parent of @p child. * @param child The requesting bhnd device. */ METHOD int alloc_pmu { device_t dev; device_t child; } DEFAULT bhnd_bus_null_alloc_pmu; /** * Release per-core PMU resources allocated for @p child. Any * outstanding PMU requests are discarded. * * @param dev The parent of @p child. * @param child The requesting bhnd device. */ METHOD int release_pmu { device_t dev; device_t child; } DEFAULT bhnd_bus_null_release_pmu; /** * Request that @p clock (or faster) be routed to @p child. * * A driver must ask the bhnd bus to allocate PMU request state * via BHND_BUS_ALLOC_PMU() before it can request clock resources. * * Request multiplexing is managed by the bus. * * @param dev The parent of @p child. * @param child The bhnd device requesting @p clock. * @param clock The requested clock source. * * @retval 0 success * @retval ENODEV If an unsupported clock was requested. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ METHOD int request_clock { device_t dev; device_t child; bhnd_clock clock; } DEFAULT bhnd_bus_null_request_clock; /** * Request that @p clocks be powered on behalf of @p child. * * This will power on clock sources (e.g. XTAL, PLL, etc) required for * @p clocks and wait until they are ready, discarding any previous * requests by @p child. * * Request multiplexing is managed by the bus. * * A driver must ask the bhnd bus to allocate PMU request state * via BHND_BUS_ALLOC_PMU() before it can request clock resources. * * @param dev The parent of @p child. * @param child The bhnd device requesting @p clock. * @param clock The requested clock source. * * @retval 0 success * @retval ENODEV If an unsupported clock was requested. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ METHOD int enable_clocks { device_t dev; device_t child; uint32_t clocks; } DEFAULT bhnd_bus_null_enable_clocks; /** * Power up an external PMU-managed resource assigned to @p child. * * A driver must ask the bhnd bus to allocate PMU request state * via BHND_BUS_ALLOC_PMU() before it can request PMU resources. * * @param dev The parent of @p child. * @param child The bhnd device requesting @p rsrc. * @param rsrc The core-specific external resource identifier. * * @retval 0 success * @retval ENODEV If the PMU does not support @p rsrc. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ METHOD int request_ext_rsrc { device_t dev; device_t child; u_int rsrc; } DEFAULT bhnd_bus_null_request_ext_rsrc; /** * Power down an external PMU-managed resource assigned to @p child. * * A driver must ask the bhnd bus to allocate PMU request state * via BHND_BUS_ALLOC_PMU() before it can request PMU resources. * * @param dev The parent of @p child. * @param child The bhnd device requesting @p rsrc. * @param rsrc The core-specific external resource number. * * @retval 0 success * @retval ENODEV If the PMU does not support @p rsrc. * @retval ENXIO If the PMU has not been initialized or is otherwise unvailable. */ METHOD int release_ext_rsrc { device_t dev; device_t child; u_int rsrc; } DEFAULT bhnd_bus_null_release_ext_rsrc; /** * Read @p width bytes at @p offset from the bus-specific agent/config * space of @p child. * * @param dev The parent of @p child. * @param child The bhnd device for which @p offset should be read. * @param offset The offset to be read. * @param width The size of the access. Must be 1, 2 or 4 bytes. * * The exact behavior of this method is bus-specific. On a bcma(4) bus, this * method provides access to the first agent port of @p child; on a siba(4) bus, * this method provides access to the core's CFG0 register block. * * @note Device drivers should only use this API for functionality * that is not available via another bhnd(4) function. */ METHOD uint32_t read_config { device_t dev; device_t child; bus_size_t offset; u_int width; } DEFAULT bhnd_bus_null_read_config; /** * Read @p width bytes at @p offset from the bus-specific agent/config * space of @p child. * * @param dev The parent of @p child. * @param child The bhnd device for which @p offset should be read. * @param offset The offset to be written. * @param width The size of the access. Must be 1, 2 or 4 bytes. * * The exact behavior of this method is bus-specific. In the case of * bcma(4), this method provides access to the first agent port of @p child. * * @note Device drivers should only use this API for functionality * that is not available via another bhnd(4) function. */ METHOD void write_config { device_t dev; device_t child; bus_size_t offset; uint32_t val; u_int width; } DEFAULT bhnd_bus_null_write_config; /** * Allocate a bhnd resource. * * This method's semantics are functionally identical to the bus API of the same * name; refer to BUS_ALLOC_RESOURCE for complete documentation. */ METHOD struct bhnd_resource * alloc_resource { device_t dev; device_t child; int type; int *rid; rman_res_t start; rman_res_t end; rman_res_t count; u_int flags; } DEFAULT bhnd_bus_generic_alloc_resource; /** * Release a bhnd resource. * * This method's semantics are functionally identical to the bus API of the same * name; refer to BUS_RELEASE_RESOURCE for complete documentation. */ METHOD int release_resource { device_t dev; device_t child; int type; int rid; struct bhnd_resource *res; } DEFAULT bhnd_bus_generic_release_resource; /** * Activate a bhnd resource. * * This method's semantics are functionally identical to the bus API of the same * name; refer to BUS_ACTIVATE_RESOURCE for complete documentation. */ METHOD int activate_resource { device_t dev; device_t child; int type; int rid; struct bhnd_resource *r; } DEFAULT bhnd_bus_generic_activate_resource; /** * Deactivate a bhnd resource. * * This method's semantics are functionally identical to the bus API of the same * name; refer to BUS_DEACTIVATE_RESOURCE for complete documentation. */ METHOD int deactivate_resource { device_t dev; device_t child; int type; int rid; struct bhnd_resource *r; } DEFAULT bhnd_bus_generic_deactivate_resource; /** * Return true if @p region_num is a valid region on @p port_num of * @p type attached to @p child. * * @param dev The device whose child is being examined. * @param child The child device. * @param type The port type being queried. * @param port_num The port number being queried. * @param region_num The region number being queried. */ METHOD bool is_region_valid { device_t dev; device_t child; bhnd_port_type type; u_int port_num; u_int region_num; }; /** * Return the number of ports of type @p type attached to @p child. * * @param dev The device whose child is being examined. * @param child The child device. * @param type The port type being queried. */ METHOD u_int get_port_count { device_t dev; device_t child; bhnd_port_type type; }; /** * Return the number of memory regions mapped to @p child @p port of * type @p type. * * @param dev The device whose child is being examined. * @param child The child device. * @param port The port number being queried. * @param type The port type being queried. */ METHOD u_int get_region_count { device_t dev; device_t child; bhnd_port_type type; u_int port; }; /** * Return the SYS_RES_MEMORY resource-ID for a port/region pair attached to * @p child. * * @param dev The bus device. * @param child The bhnd child. * @param port_type The port type. * @param port_num The index of the child interconnect port. * @param region_num The index of the port-mapped address region. * * @retval -1 No such port/region found. */ METHOD int get_port_rid { device_t dev; device_t child; bhnd_port_type port_type; u_int port_num; u_int region_num; } DEFAULT bhnd_bus_null_get_port_rid; /** * Decode a port / region pair on @p child defined by @p type and @p rid. * * @param dev The bus device. * @param child The bhnd child. * @param type The resource type. * @param rid The resource ID. * @param[out] port_type The port's type. * @param[out] port The port identifier. * @param[out] region The identifier of the memory region on @p port. * * @retval 0 success * @retval non-zero No matching type/rid found. */ METHOD int decode_port_rid { device_t dev; device_t child; int type; int rid; bhnd_port_type *port_type; u_int *port; u_int *region; } DEFAULT bhnd_bus_null_decode_port_rid; /** * Get the address and size of @p region on @p port. * * @param dev The bus device. * @param child The bhnd child. * @param port_type The port type. * @param port The port identifier. * @param region The identifier of the memory region on @p port. * @param[out] region_addr The region's base address. * @param[out] region_size The region's size. * * @retval 0 success * @retval non-zero No matching port/region found. */ METHOD int get_region_addr { device_t dev; device_t child; bhnd_port_type port_type; u_int port; u_int region; bhnd_addr_t *region_addr; bhnd_size_t *region_size; } DEFAULT bhnd_bus_null_get_region_addr; /** * Read an NVRAM variable. * * It is the responsibility of the bus to delegate this request to * the appropriate NVRAM child device, or to a parent bus implementation. * * @param dev The bus device. * @param child The requesting device. * @param name The NVRAM variable name. * @param[out] buf On success, the requested value will be written * to this buffer. This argment may be NULL if * the value is not desired. * @param[in,out] size The capacity of @p buf. On success, will be set * to the actual size of the requested value. * @param type The data type to be written to @p buf. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too * small to hold the requested value. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the @p name's data type cannot be coerced to @p type. * @retval ERANGE If value coercion would overflow @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ METHOD int get_nvram_var { device_t dev; device_t child; const char *name; void *buf; size_t *size; bhnd_nvram_type type; } DEFAULT bhnd_bus_null_get_nvram_var; /** An implementation of bus_read_1() compatible with bhnd_resource */ METHOD uint8_t read_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_read_2() compatible with bhnd_resource */ METHOD uint16_t read_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_read_4() compatible with bhnd_resource */ METHOD uint32_t read_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_write_1() compatible with bhnd_resource */ METHOD void write_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t value; } /** An implementation of bus_write_2() compatible with bhnd_resource */ METHOD void write_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t value; } /** An implementation of bus_write_4() compatible with bhnd_resource */ METHOD void write_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t value; } /** An implementation of bus_read_stream_1() compatible with bhnd_resource */ METHOD uint8_t read_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_read_stream_2() compatible with bhnd_resource */ METHOD uint16_t read_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_read_stream_4() compatible with bhnd_resource */ METHOD uint32_t read_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; } /** An implementation of bus_write_stream_1() compatible with bhnd_resource */ METHOD void write_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t value; } /** An implementation of bus_write_stream_2() compatible with bhnd_resource */ METHOD void write_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t value; } /** An implementation of bus_write_stream_4() compatible with bhnd_resource */ METHOD void write_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t value; } /** An implementation of bus_read_multi_1() compatible with bhnd_resource */ METHOD void read_multi_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_read_multi_2() compatible with bhnd_resource */ METHOD void read_multi_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_read_multi_4() compatible with bhnd_resource */ METHOD void read_multi_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_1() compatible with bhnd_resource */ METHOD void write_multi_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_2() compatible with bhnd_resource */ METHOD void write_multi_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_4() compatible with bhnd_resource */ METHOD void write_multi_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_read_multi_stream_1() compatible * bhnd_resource */ METHOD void read_multi_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_read_multi_stream_2() compatible * bhnd_resource */ METHOD void read_multi_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_read_multi_stream_4() compatible * bhnd_resource */ METHOD void read_multi_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_stream_1() compatible * bhnd_resource */ METHOD void write_multi_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_stream_2() compatible with * bhnd_resource */ METHOD void write_multi_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_write_multi_stream_4() compatible with * bhnd_resource */ METHOD void write_multi_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_set_multi_1() compatible with bhnd_resource */ METHOD void set_multi_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t value; bus_size_t count; } /** An implementation of bus_set_multi_2() compatible with bhnd_resource */ METHOD void set_multi_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t value; bus_size_t count; } /** An implementation of bus_set_multi_4() compatible with bhnd_resource */ METHOD void set_multi_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t value; bus_size_t count; } /** An implementation of bus_set_region_1() compatible with bhnd_resource */ METHOD void set_region_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t value; bus_size_t count; } /** An implementation of bus_set_region_2() compatible with bhnd_resource */ METHOD void set_region_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t value; bus_size_t count; } /** An implementation of bus_set_region_4() compatible with bhnd_resource */ METHOD void set_region_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t value; bus_size_t count; } /** An implementation of bus_read_region_1() compatible with bhnd_resource */ METHOD void read_region_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_read_region_2() compatible with bhnd_resource */ METHOD void read_region_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_read_region_4() compatible with bhnd_resource */ METHOD void read_region_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_read_region_stream_1() compatible with * bhnd_resource */ METHOD void read_region_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_read_region_stream_2() compatible with * bhnd_resource */ METHOD void read_region_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_read_region_stream_4() compatible with * bhnd_resource */ METHOD void read_region_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_write_region_1() compatible with bhnd_resource */ METHOD void write_region_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_write_region_2() compatible with bhnd_resource */ METHOD void write_region_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_write_region_4() compatible with bhnd_resource */ METHOD void write_region_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_write_region_stream_1() compatible with * bhnd_resource */ METHOD void write_region_stream_1 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint8_t *datap; bus_size_t count; } /** An implementation of bus_write_region_stream_2() compatible with * bhnd_resource */ METHOD void write_region_stream_2 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint16_t *datap; bus_size_t count; } /** An implementation of bus_write_region_stream_4() compatible with * bhnd_resource */ METHOD void write_region_stream_4 { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; uint32_t *datap; bus_size_t count; } /** An implementation of bus_barrier() compatible with bhnd_resource */ METHOD void barrier { device_t dev; device_t child; struct bhnd_resource *r; bus_size_t offset; bus_size_t length; int flags; } Index: projects/clang390-import/sys/dev/bhnd/siba/siba.c =================================================================== --- projects/clang390-import/sys/dev/bhnd/siba/siba.c (revision 304964) +++ projects/clang390-import/sys/dev/bhnd/siba/siba.c (revision 304965) @@ -1,717 +1,788 @@ /*- * Copyright (c) 2015 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "sibareg.h" #include "sibavar.h" int siba_probe(device_t dev) { device_set_desc(dev, "SIBA BHND bus"); return (BUS_PROBE_DEFAULT); } int siba_attach(device_t dev) { struct siba_devinfo *dinfo; struct siba_softc *sc; device_t *devs; int ndevs; int error; sc = device_get_softc(dev); sc->dev = dev; /* Fetch references to the siba SIBA_CFG* blocks for all * registered devices */ if ((error = device_get_children(dev, &devs, &ndevs))) return (error); for (int i = 0; i < ndevs; i++) { struct siba_addrspace *addrspace; dinfo = device_get_ivars(devs[i]); KASSERT(!device_is_suspended(devs[i]), ("siba(4) stateful suspend handling requires that devices " "not be suspended before siba_attach()")); /* Fetch the core register address space */ addrspace = siba_find_addrspace(dinfo, BHND_PORT_DEVICE, 0, 0); if (addrspace == NULL) { device_printf(dev, "missing device registers for core %d\n", i); error = ENXIO; goto cleanup; } /* * Map the per-core configuration blocks */ KASSERT(dinfo->core_id.num_cfg_blocks <= SIBA_MAX_CFG, ("config block count %u out of range", dinfo->core_id.num_cfg_blocks)); for (u_int cfgidx = 0; cfgidx < dinfo->core_id.num_cfg_blocks; cfgidx++) { rman_res_t r_start, r_count, r_end; /* Determine the config block's address range; configuration * blocks are allocated starting at SIBA_CFG0_OFFSET, * growing downwards. */ r_start = addrspace->sa_base + SIBA_CFG0_OFFSET; r_start -= cfgidx * SIBA_CFG_SIZE; r_count = SIBA_CFG_SIZE; r_end = r_start + r_count - 1; /* Allocate the config resource */ dinfo->cfg_rid[cfgidx] = 0; dinfo->cfg[cfgidx] = BHND_BUS_ALLOC_RESOURCE(dev, dev, SYS_RES_MEMORY, &dinfo->cfg_rid[cfgidx], r_start, r_end, r_count, RF_ACTIVE); if (dinfo->cfg[cfgidx] == NULL) { device_printf(dev, "failed allocating CFG_%u for " "core %d\n", cfgidx, i); error = ENXIO; goto cleanup; } } } cleanup: free(devs, M_BHND); if (error) return (error); /* Delegate remainder to standard bhnd method implementation */ return (bhnd_generic_attach(dev)); } int siba_detach(device_t dev) { return (bhnd_generic_detach(dev)); } int siba_resume(device_t dev) { return (bhnd_generic_resume(dev)); } int siba_suspend(device_t dev) { return (bhnd_generic_suspend(dev)); } static int siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) { const struct siba_devinfo *dinfo; const struct bhnd_core_info *cfg; dinfo = device_get_ivars(child); cfg = &dinfo->core_id.core_info; switch (index) { case BHND_IVAR_VENDOR: *result = cfg->vendor; return (0); case BHND_IVAR_DEVICE: *result = cfg->device; return (0); case BHND_IVAR_HWREV: *result = cfg->hwrev; return (0); case BHND_IVAR_DEVICE_CLASS: *result = bhnd_core_class(cfg); return (0); case BHND_IVAR_VENDOR_NAME: *result = (uintptr_t) bhnd_vendor_name(cfg->vendor); return (0); case BHND_IVAR_DEVICE_NAME: *result = (uintptr_t) bhnd_core_name(cfg); return (0); case BHND_IVAR_CORE_INDEX: *result = cfg->core_idx; return (0); case BHND_IVAR_CORE_UNIT: *result = cfg->unit; return (0); default: return (ENOENT); } } static int siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value) { switch (index) { case BHND_IVAR_VENDOR: case BHND_IVAR_DEVICE: case BHND_IVAR_HWREV: case BHND_IVAR_DEVICE_CLASS: case BHND_IVAR_VENDOR_NAME: case BHND_IVAR_DEVICE_NAME: case BHND_IVAR_CORE_INDEX: case BHND_IVAR_CORE_UNIT: return (EINVAL); default: return (ENOENT); } } static struct resource_list * siba_get_resource_list(device_t dev, device_t child) { struct siba_devinfo *dinfo = device_get_ivars(child); return (&dinfo->resources); } static device_t siba_find_hostb_device(device_t dev) { struct siba_softc *sc = device_get_softc(dev); /* This is set (or not) by the concrete siba driver subclass. */ return (sc->hostb_dev); } static int siba_reset_core(device_t dev, device_t child, uint16_t flags) { struct siba_devinfo *dinfo; if (device_get_parent(child) != dev) BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags); dinfo = device_get_ivars(child); /* Can't reset the core without access to the CFG0 registers */ if (dinfo->cfg[0] == NULL) return (ENODEV); // TODO - perform reset return (ENXIO); } static int siba_suspend_core(device_t dev, device_t child) { struct siba_devinfo *dinfo; if (device_get_parent(child) != dev) BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child); dinfo = device_get_ivars(child); /* Can't suspend the core without access to the CFG0 registers */ if (dinfo->cfg[0] == NULL) return (ENODEV); // TODO - perform suspend return (ENXIO); } static uint32_t siba_read_config(device_t dev, device_t child, bus_size_t offset, u_int width) { struct siba_devinfo *dinfo; rman_res_t r_size; /* Must be directly attached */ if (device_get_parent(child) != dev) return (UINT32_MAX); /* CFG0 registers must be available */ dinfo = device_get_ivars(child); if (dinfo->cfg[0] == NULL) return (UINT32_MAX); /* Offset must fall within CFG0 */ r_size = rman_get_size(dinfo->cfg[0]->res); if (r_size < offset || r_size - offset < width) return (UINT32_MAX); switch (width) { case 1: return (bhnd_bus_read_1(dinfo->cfg[0], offset)); case 2: return (bhnd_bus_read_2(dinfo->cfg[0], offset)); case 4: return (bhnd_bus_read_4(dinfo->cfg[0], offset)); } /* Unsuported */ return (UINT32_MAX); } static void siba_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val, u_int width) { struct siba_devinfo *dinfo; rman_res_t r_size; /* Must be directly attached */ if (device_get_parent(child) != dev) return; /* CFG0 registers must be available */ dinfo = device_get_ivars(child); if (dinfo->cfg[0] == NULL) return; /* Offset must fall within CFG0 */ r_size = rman_get_size(dinfo->cfg[0]->res); if (r_size < offset || r_size - offset < width) return; switch (width) { case 1: bhnd_bus_write_1(dinfo->cfg[0], offset, val); case 2: bhnd_bus_write_2(dinfo->cfg[0], offset, val); case 4: bhnd_bus_write_4(dinfo->cfg[0], offset, val); } } static u_int siba_get_port_count(device_t dev, device_t child, bhnd_port_type type) { struct siba_devinfo *dinfo; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child, type)); dinfo = device_get_ivars(child); return (siba_addrspace_port_count(dinfo)); } static u_int siba_get_region_count(device_t dev, device_t child, bhnd_port_type type, u_int port) { struct siba_devinfo *dinfo; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child, type, port)); dinfo = device_get_ivars(child); if (!siba_is_port_valid(dinfo, type, port)) return (0); return (siba_addrspace_region_count(dinfo, port)); } static int siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type, u_int port_num, u_int region_num) { struct siba_devinfo *dinfo; struct siba_addrspace *addrspace; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child, port_type, port_num, region_num)); dinfo = device_get_ivars(child); addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num); if (addrspace == NULL) return (-1); return (addrspace->sa_rid); } static int siba_decode_port_rid(device_t dev, device_t child, int type, int rid, bhnd_port_type *port_type, u_int *port_num, u_int *region_num) { struct siba_devinfo *dinfo; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child, type, rid, port_type, port_num, region_num)); dinfo = device_get_ivars(child); /* Ports are always memory mapped */ if (type != SYS_RES_MEMORY) return (EINVAL); for (int i = 0; i < dinfo->core_id.num_addrspace; i++) { if (dinfo->addrspace[i].sa_rid != rid) continue; *port_type = BHND_PORT_DEVICE; *port_num = siba_addrspace_port(i); *region_num = siba_addrspace_region(i); return (0); } /* Not found */ return (ENOENT); } static int siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size) { struct siba_devinfo *dinfo; struct siba_addrspace *addrspace; /* delegate non-bus-attached devices to our parent */ if (device_get_parent(child) != dev) { return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child, port_type, port_num, region_num, addr, size)); } dinfo = device_get_ivars(child); addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num); if (addrspace == NULL) return (ENOENT); *addr = addrspace->sa_base; *size = addrspace->sa_size - addrspace->sa_bus_reserved; return (0); } /** * Register all address space mappings for @p di. * * @param dev The siba bus device. * @param di The device info instance on which to register all address * space entries. * @param r A resource mapping the enumeration table block for @p di. */ static int siba_register_addrspaces(device_t dev, struct siba_devinfo *di, struct resource *r) { struct siba_core_id *cid; uint32_t addr; uint32_t size; int error; cid = &di->core_id; /* Register the device address space entries */ for (uint8_t i = 0; i < di->core_id.num_addrspace; i++) { uint32_t adm; u_int adm_offset; uint32_t bus_reserved; /* Determine the register offset */ adm_offset = siba_admatch_offset(i); if (adm_offset == 0) { device_printf(dev, "addrspace %hhu is unsupported", i); return (ENODEV); } /* Fetch the address match register value */ adm = bus_read_4(r, adm_offset); /* Parse the value */ if ((error = siba_parse_admatch(adm, &addr, &size))) { device_printf(dev, "failed to decode address " " match register value 0x%x\n", adm); return (error); } /* If this is the device's core/enumeration addrespace, * reserve the Sonics configuration register blocks for the * use of our bus. */ bus_reserved = 0; if (i == SIBA_CORE_ADDRSPACE) bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE; /* Append the region info */ error = siba_append_dinfo_region(di, i, addr, size, bus_reserved); if (error) return (error); } return (0); } static struct bhnd_devinfo * siba_alloc_bhnd_dinfo(device_t dev) { struct siba_devinfo *dinfo = siba_alloc_dinfo(dev); return ((struct bhnd_devinfo *)dinfo); } static void siba_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo) { siba_free_dinfo(dev, (struct siba_devinfo *)dinfo); } + +static int +siba_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores, + u_int *num_cores) +{ + const struct bhnd_chipid *chipid; + struct bhnd_core_info *table; + struct bhnd_resource *r; + int error; + int rid; + + /* Fetch the core count from our chip identification */ + chipid = BHND_BUS_GET_CHIPID(dev, dev); + + /* Allocate our local core table */ + table = malloc(sizeof(*table) * chipid->ncores, M_BHND, M_NOWAIT); + if (table == NULL) + return (ENOMEM); + + /* Enumerate all cores. */ + for (u_int i = 0; i < chipid->ncores; i++) { + struct siba_core_id cid; + uint32_t idhigh, idlow; + + /* Map the core's register block */ + rid = 0; + r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, + SIBA_CORE_ADDR(i), SIBA_CORE_ADDR(i) + SIBA_CORE_SIZE - 1, + SIBA_CORE_SIZE, RF_ACTIVE); + if (r == NULL) { + error = ENXIO; + goto failed; + } + + /* Read the core info */ + idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); + idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); + + cid = siba_parse_core_id(idhigh, idlow, i, 0); + table[i] = cid.core_info; + + /* Determine unit number */ + for (u_int j = 0; j < i; j++) { + if (table[j].vendor == table[i].vendor && + table[j].device == table[i].device) + table[i].unit++; + } + + /* Release our resource */ + bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); + r = NULL; + } + + /* Provide the result values (performed last to avoid modifying + * cores/num_cores if enumeration failed). */ + *cores = table; + *num_cores = chipid->ncores; + + return (0); + +failed: + if (table != NULL) + free(table, M_BHND); + + if (r != NULL) + bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r); + + return (error); +} + /** * Scan the core table and add all valid discovered cores to * the bus. * * @param dev The siba bus device. * @param chipid The chip identifier, if the device does not provide a * ChipCommon core. Should o NULL otherwise. */ int siba_add_children(device_t dev, const struct bhnd_chipid *chipid) { struct bhnd_chipid ccid; struct bhnd_core_info *cores; struct siba_devinfo *dinfo; struct resource *r; int rid; int error; dinfo = NULL; cores = NULL; r = NULL; /* * Try to determine the number of device cores via the ChipCommon * identification registers. * * A small number of very early devices do not include a ChipCommon * core, in which case our caller must supply the chip identification * information via a non-NULL chipid parameter. */ if (chipid == NULL) { uint32_t idhigh, ccreg; uint16_t vendor, device; uint8_t ccrev; /* Map the first core's register block. If the ChipCommon core * exists, it will always be the first core. */ rid = 0; r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1, RF_ACTIVE); /* Identify the core */ idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); vendor = SIBA_REG_GET(idhigh, IDH_VENDOR); device = SIBA_REG_GET(idhigh, IDH_DEVICE); ccrev = SIBA_IDH_CORE_REV(idhigh); if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) { device_printf(dev, "cannot identify device: no chipcommon core " "found\n"); error = ENXIO; goto cleanup; } /* Identify the chipset */ ccreg = bus_read_4(r, CHIPC_ID); ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR); if (!CHIPC_NCORES_MIN_HWREV(ccrev)) { switch (ccid.chip_id) { case BHND_CHIPID_BCM4306: ccid.ncores = 6; break; case BHND_CHIPID_BCM4704: ccid.ncores = 9; break; case BHND_CHIPID_BCM5365: /* * BCM5365 does support ID_NUMCORE in at least * some of its revisions, but for unknown * reasons, Broadcom's drivers always exclude * the ChipCommon revision (0x5) used by BCM5365 * from the set of revisions supporting * ID_NUMCORE, and instead supply a fixed value. * * Presumably, at least some of these devices * shipped with a broken ID_NUMCORE value. */ ccid.ncores = 7; break; default: device_printf(dev, "unable to determine core " "count for unrecognized chipset 0x%hx\n", ccid.chip_id); error = ENXIO; goto cleanup; } } chipid = &ccid; bus_release_resource(dev, SYS_RES_MEMORY, rid, r); } /* Allocate our temporary core table and enumerate all cores */ cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT); if (cores == NULL) return (ENOMEM); /* Add all cores. */ for (u_int i = 0; i < chipid->ncores; i++) { struct siba_core_id cid; device_t child; uint32_t idhigh, idlow; rman_res_t r_count, r_end, r_start; /* Map the core's register block */ rid = 0; r_start = SIBA_CORE_ADDR(i); r_count = SIBA_CORE_SIZE; r_end = r_start + SIBA_CORE_SIZE - 1; r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start, r_end, r_count, RF_ACTIVE); if (r == NULL) { error = ENXIO; goto cleanup; } /* Add the child device */ child = BUS_ADD_CHILD(dev, 0, NULL, -1); if (child == NULL) { error = ENXIO; goto cleanup; } /* Read the core info */ idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW)); cid = siba_parse_core_id(idhigh, idlow, i, 0); cores[i] = cid.core_info; /* Determine unit number */ for (u_int j = 0; j < i; j++) { if (cores[j].vendor == cores[i].vendor && cores[j].device == cores[i].device) cores[i].unit++; } /* Initialize per-device bus info */ if ((dinfo = device_get_ivars(child)) == NULL) { error = ENXIO; goto cleanup; } if ((error = siba_init_dinfo(dev, dinfo, &cid))) goto cleanup; /* Register the core's address space(s). */ if ((error = siba_register_addrspaces(dev, dinfo, r))) goto cleanup; /* If pins are floating or the hardware is otherwise * unpopulated, the device shouldn't be used. */ if (bhnd_is_hw_disabled(child)) device_disable(child); /* Release our resource */ bus_release_resource(dev, SYS_RES_MEMORY, rid, r); r = NULL; /* Issue bus callback for fully initialized child. */ BHND_BUS_CHILD_ADDED(dev, child); } cleanup: if (cores != NULL) free(cores, M_BHND); if (r != NULL) bus_release_resource(dev, SYS_RES_MEMORY, rid, r); return (error); } static device_method_t siba_methods[] = { /* Device interface */ DEVMETHOD(device_probe, siba_probe), DEVMETHOD(device_attach, siba_attach), DEVMETHOD(device_detach, siba_detach), DEVMETHOD(device_resume, siba_resume), DEVMETHOD(device_suspend, siba_suspend), /* Bus interface */ DEVMETHOD(bus_read_ivar, siba_read_ivar), DEVMETHOD(bus_write_ivar, siba_write_ivar), DEVMETHOD(bus_get_resource_list, siba_get_resource_list), /* BHND interface */ DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), + DEVMETHOD(bhnd_bus_get_core_table, siba_get_core_table), DEVMETHOD(bhnd_bus_alloc_devinfo, siba_alloc_bhnd_dinfo), DEVMETHOD(bhnd_bus_free_devinfo, siba_free_bhnd_dinfo), DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), DEVMETHOD(bhnd_bus_read_config, siba_read_config), DEVMETHOD(bhnd_bus_write_config, siba_write_config), DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), DEVMETHOD(bhnd_bus_get_region_count, siba_get_region_count), DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid), DEVMETHOD(bhnd_bus_decode_port_rid, siba_decode_port_rid), DEVMETHOD(bhnd_bus_get_region_addr, siba_get_region_addr), DEVMETHOD_END }; DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver); MODULE_VERSION(siba, 1); MODULE_DEPEND(siba, bhnd, 1, 1, 1); Index: projects/clang390-import/sys/i386/i386/machdep.c =================================================================== --- projects/clang390-import/sys/i386/i386/machdep.c (revision 304964) +++ projects/clang390-import/sys/i386/i386/machdep.c (revision 304965) @@ -1,3402 +1,3409 @@ /*- * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 */ #include __FBSDID("$FreeBSD$"); #include "opt_apic.h" #include "opt_atpic.h" #include "opt_compat.h" #include "opt_cpu.h" #include "opt_ddb.h" #include "opt_inet.h" #include "opt_isa.h" #include "opt_kstack_pages.h" #include "opt_maxmem.h" #include "opt_mp_watchdog.h" #include "opt_npx.h" #include "opt_perfmon.h" #include "opt_platform.h" #include "opt_xbox.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SMP #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DDB #ifndef KDB #error KDB must be enabled in order for DDB to work! #endif #include #include #endif #ifdef PC98 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PERFMON #include #endif #ifdef SMP #include #endif #ifdef FDT #include #endif #ifdef DEV_APIC #include #endif #ifdef DEV_ISA #include #endif #ifdef XBOX #include int arch_i386_is_xbox = 0; uint32_t arch_i386_xbox_memsize = 0; #endif /* Sanity check for __curthread() */ CTASSERT(offsetof(struct pcpu, pc_curthread) == 0); extern register_t init386(int first); extern void dblfault_handler(void); #if !defined(CPU_DISABLE_SSE) && defined(I686_CPU) #define CPU_ENABLE_SSE #endif static void cpu_startup(void *); static void fpstate_drop(struct thread *td); static void get_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpusave, size_t xfpusave_len); static int set_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpustate, size_t xfpustate_len); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); /* Intel ICH registers */ #define ICH_PMBASE 0x400 #define ICH_SMI_EN ICH_PMBASE + 0x30 int _udatasel, _ucodesel; u_int basemem; #ifdef PC98 int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */ int need_post_dma_flush; /* If 1, use invd after DMA transfer. */ static int ispc98 = 1; SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, ""); #endif int cold = 1; #ifdef COMPAT_43 static void osendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask); #endif #ifdef COMPAT_FREEBSD4 static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask); #endif long Maxmem = 0; long realmem = 0; #ifdef PAE FEATURE(pae, "Physical Address Extensions"); #endif /* * The number of PHYSMAP entries must be one less than the number of * PHYSSEG entries because the PHYSMAP entry that spans the largest * physical address that is accessible by ISA DMA is split into two * PHYSSEG entries. */ #define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; /* must be 2 less so 0 0 can signal end of chunks */ #define PHYS_AVAIL_ARRAY_END (nitems(phys_avail) - 2) #define DUMP_AVAIL_ARRAY_END (nitems(dump_avail) - 2) struct kva_md_info kmi; static struct trapframe proc0_tf; struct pcpu __pcpu[MAXCPU]; struct mtx icu_lock; struct mem_range_softc mem_range_softc; /* Default init_ops implementation. */ struct init_ops init_ops = { .early_clock_source_init = i8254_init, .early_delay = i8254_delay, #ifdef DEV_APIC .msi_init = msi_init, #endif }; static void cpu_startup(dummy) void *dummy; { uintmax_t memsize; char *sysenv; #ifndef PC98 /* * On MacBooks, we need to disallow the legacy USB circuit to * generate an SMI# because this can cause several problems, * namely: incorrect CPU frequency detection and failure to * start the APs. * We do this by disabling a bit in the SMI_EN (SMI Control and * Enable register) of the Intel ICH LPC Interface Bridge. */ sysenv = kern_getenv("smbios.system.product"); if (sysenv != NULL) { if (strncmp(sysenv, "MacBook1,1", 10) == 0 || strncmp(sysenv, "MacBook3,1", 10) == 0 || strncmp(sysenv, "MacBook4,1", 10) == 0 || strncmp(sysenv, "MacBookPro1,1", 13) == 0 || strncmp(sysenv, "MacBookPro1,2", 13) == 0 || strncmp(sysenv, "MacBookPro3,1", 13) == 0 || strncmp(sysenv, "MacBookPro4,1", 13) == 0 || strncmp(sysenv, "Macmini1,1", 10) == 0) { if (bootverbose) printf("Disabling LEGACY_USB_EN bit on " "Intel ICH.\n"); outl(ICH_SMI_EN, inl(ICH_SMI_EN) & ~0x8); } freeenv(sysenv); } #endif /* !PC98 */ /* * Good {morning,afternoon,evening,night}. */ startrtclock(); printcpuinfo(); panicifcpuunsupported(); #ifdef PERFMON perfmon_init(); #endif /* * Display physical memory if SMBIOS reports reasonable amount. */ memsize = 0; sysenv = kern_getenv("smbios.memory.enabled"); if (sysenv != NULL) { memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10) << 10; freeenv(sysenv); } if (memsize < ptoa((uintmax_t)vm_cnt.v_free_count)) memsize = ptoa((uintmax_t)Maxmem); printf("real memory = %ju (%ju MB)\n", memsize, memsize >> 20); realmem = atop(memsize); /* * Display any holes after the first chunk of extended memory. */ if (bootverbose) { int indx; printf("Physical memory chunk(s):\n"); for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { vm_paddr_t size; size = phys_avail[indx + 1] - phys_avail[indx]; printf( "0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n", (uintmax_t)phys_avail[indx], (uintmax_t)phys_avail[indx + 1] - 1, (uintmax_t)size, (uintmax_t)size / PAGE_SIZE); } } vm_ksubmap_init(&kmi); printf("avail memory = %ju (%ju MB)\n", ptoa((uintmax_t)vm_cnt.v_free_count), ptoa((uintmax_t)vm_cnt.v_free_count) / 1048576); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); vm_pager_bufferinit(); cpu_setregs(); } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * at top to call routine, followed by call * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ #ifdef COMPAT_43 static void osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct osigframe sf, *fp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); /* Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct osigframe *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct osigframe)); #if defined(COMPAT_43) td->td_sigstk.ss_flags |= SS_ONSTACK; #endif } else fp = (struct osigframe *)regs->tf_esp - 1; /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo)); if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; sf.sf_siginfo.si_code = ksi->ksi_code; sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher; sf.sf_addr = 0; } else { /* Old FreeBSD-style arguments. */ sf.sf_arg2 = ksi->ksi_code; sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* Save most if not all of trap frame. */ sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax; sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx; sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx; sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx; sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi; sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi; sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; sf.sf_siginfo.si_sc.sc_es = regs->tf_es; sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; sf.sf_siginfo.si_sc.sc_gs = rgs(); sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp; /* Build the signal context to be used by osigreturn(). */ sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp; sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp; sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip; sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags; sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; sf.sf_siginfo.si_sc.sc_err = regs->tf_err; /* * If we're a vm86 process, we want to save the segment registers. * We also change eflags to be our emulated eflags, not the actual * eflags. */ if (regs->tf_eflags & PSL_VM) { /* XXX confusing names: `tf' isn't a trapframe; `regs' is. */ struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs; sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs; sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es; sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds; if (vm86->vm86_has_vme == 0) sf.sf_siginfo.si_sc.sc_ps = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); /* See sendsig() for comments. */ tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); } /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, fp, sizeof(*fp)) != 0) { #ifdef DEBUG printf("process %ld has trashed its stack\n", (long)p->p_pid); #endif PROC_LOCK(p); sigexit(td, SIGILL); } regs->tf_esp = (int)fp; if (p->p_sysent->sv_sigcode_base != 0) { regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode - szosigcode; } else { /* a.out sysentvec does not use shared page */ regs->tf_eip = p->p_sysent->sv_psstrings - szosigcode; } regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; load_gs(_udatasel); regs->tf_ss = _udatasel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct sigframe4 sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); /* Save user context. */ bzero(&sf, sizeof(sf)); sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = td->td_sigstk; sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; sf.sf_uc.uc_mcontext.mc_gs = rgs(); bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); bzero(sf.sf_uc.uc_mcontext.mc_fpregs, sizeof(sf.sf_uc.uc_mcontext.mc_fpregs)); bzero(sf.sf_uc.uc_mcontext.__spare__, sizeof(sf.sf_uc.uc_mcontext.__spare__)); bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); /* Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { sfp = (struct sigframe4 *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct sigframe4)); #if defined(COMPAT_43) td->td_sigstk.ss_flags |= SS_ONSTACK; #endif } else sfp = (struct sigframe4 *)regs->tf_esp - 1; /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; bzero(&sf.sf_si, sizeof(sf.sf_si)); if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; /* Fill in POSIX parts */ sf.sf_si.si_signo = sig; sf.sf_si.si_code = ksi->ksi_code; sf.sf_si.si_addr = ksi->ksi_addr; } else { /* Old FreeBSD-style arguments. */ sf.sf_siginfo = ksi->ksi_code; sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* * If we're a vm86 process, we want to save the segment registers. * We also change eflags to be our emulated eflags, not the actual * eflags. */ if (regs->tf_eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; if (vm86->vm86_has_vme == 0) sf.sf_uc.uc_mcontext.mc_eflags = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); /* * Clear PSL_NT to inhibit T_TSSFLT faults on return from * syscalls made by the signal handler. This just avoids * wasting time for our lazy fixup of such faults. PSL_NT * does nothing in vm86 mode, but vm86 programs can set it * almost legitimately in probes for old cpu types. */ tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); } /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { #ifdef DEBUG printf("process %ld has trashed its stack\n", (long)p->p_pid); #endif PROC_LOCK(p); sigexit(td, SIGILL); } regs->tf_esp = (int)sfp; regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode - szfreebsd4_sigcode; regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_FREEBSD4 */ void sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct sigframe sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; char *sp; struct trapframe *regs; struct segment_descriptor *sdp; char *xfpusave; size_t xfpusave_len; int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_sendsig(catcher, ksi, mask); return; } #endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { osendsig(catcher, ksi, mask); return; } #endif regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); #ifdef CPU_ENABLE_SSE if (cpu_max_ext_state_size > sizeof(union savefpu) && use_xsave) { xfpusave_len = cpu_max_ext_state_size - sizeof(union savefpu); xfpusave = __builtin_alloca(xfpusave_len); } else { #else { #endif xfpusave_len = 0; xfpusave = NULL; } /* Save user context. */ bzero(&sf, sizeof(sf)); sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = td->td_sigstk; sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; sf.sf_uc.uc_mcontext.mc_gs = rgs(); bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len); fpstate_drop(td); /* * Unconditionally fill the fsbase and gsbase into the mcontext. */ sdp = &td->td_pcb->pcb_fsd; sf.sf_uc.uc_mcontext.mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase; sdp = &td->td_pcb->pcb_gsd; sf.sf_uc.uc_mcontext.mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase; bzero(sf.sf_uc.uc_mcontext.mc_spare2, sizeof(sf.sf_uc.uc_mcontext.mc_spare2)); bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); /* Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; #if defined(COMPAT_43) td->td_sigstk.ss_flags |= SS_ONSTACK; #endif } else sp = (char *)regs->tf_esp - 128; if (xfpusave != NULL) { sp -= xfpusave_len; sp = (char *)((unsigned int)sp & ~0x3F); sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp; } sp -= sizeof(struct sigframe); /* Align to 16 bytes. */ sfp = (struct sigframe *)((unsigned int)sp & ~0xF); /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; bzero(&sf.sf_si, sizeof(sf.sf_si)); if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; /* Fill in POSIX parts */ sf.sf_si = ksi->ksi_info; sf.sf_si.si_signo = sig; /* maybe a translated signal */ } else { /* Old FreeBSD-style arguments. */ sf.sf_siginfo = ksi->ksi_code; sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* * If we're a vm86 process, we want to save the segment registers. * We also change eflags to be our emulated eflags, not the actual * eflags. */ if (regs->tf_eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; if (vm86->vm86_has_vme == 0) sf.sf_uc.uc_mcontext.mc_eflags = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); /* * Clear PSL_NT to inhibit T_TSSFLT faults on return from * syscalls made by the signal handler. This just avoids * wasting time for our lazy fixup of such faults. PSL_NT * does nothing in vm86 mode, but vm86 programs can set it * almost legitimately in probes for old cpu types. */ tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); } /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, sfp, sizeof(*sfp)) != 0 || (xfpusave != NULL && copyout(xfpusave, (void *)sf.sf_uc.uc_mcontext.mc_xfpustate, xfpusave_len) != 0)) { #ifdef DEBUG printf("process %ld has trashed its stack\n", (long)p->p_pid); #endif PROC_LOCK(p); sigexit(td, SIGILL); } regs->tf_esp = (int)sfp; regs->tf_eip = p->p_sysent->sv_sigcode_base; if (regs->tf_eip == 0) regs->tf_eip = p->p_sysent->sv_psstrings - szsigcode; regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * state to gain improper privileges. * * MPSAFE */ #ifdef COMPAT_43 int osigreturn(td, uap) struct thread *td; struct osigreturn_args /* { struct osigcontext *sigcntxp; } */ *uap; { struct osigcontext sc; struct trapframe *regs; struct osigcontext *scp; int eflags, error; ksiginfo_t ksi; regs = td->td_frame; error = copyin(uap->sigcntxp, &sc, sizeof(sc)); if (error != 0) return (error); scp = ≻ eflags = scp->sc_ps; if (eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86; /* * if pcb_ext == 0 or vm86_inited == 0, the user hasn't * set up the vm86 area, and we can't enter vm86 mode. */ if (td->td_pcb->pcb_ext == 0) return (EINVAL); vm86 = &td->td_pcb->pcb_ext->ext_vm86; if (vm86->vm86_inited == 0) return (EINVAL); /* Go back to user mode if both flags are set. */ if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; } else { vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } tf->tf_vm86_ds = scp->sc_ds; tf->tf_vm86_es = scp->sc_es; tf->tf_vm86_fs = scp->sc_fs; tf->tf_vm86_gs = scp->sc_gs; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; tf->tf_fs = _udatasel; } else { /* * Don't allow users to change privileged or reserved flags. */ if (!EFL_SECURE(eflags, regs->tf_eflags)) { return (EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ if (!CS_SECURE(scp->sc_cs)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); return (EINVAL); } regs->tf_ds = scp->sc_ds; regs->tf_es = scp->sc_es; regs->tf_fs = scp->sc_fs; } /* Restore remaining registers. */ regs->tf_eax = scp->sc_eax; regs->tf_ebx = scp->sc_ebx; regs->tf_ecx = scp->sc_ecx; regs->tf_edx = scp->sc_edx; regs->tf_esi = scp->sc_esi; regs->tf_edi = scp->sc_edi; regs->tf_cs = scp->sc_cs; regs->tf_ss = scp->sc_ss; regs->tf_isp = scp->sc_isp; regs->tf_ebp = scp->sc_fp; regs->tf_esp = scp->sc_sp; regs->tf_eip = scp->sc_pc; regs->tf_eflags = eflags; #if defined(COMPAT_43) if (scp->sc_onstack & 1) td->td_sigstk.ss_flags |= SS_ONSTACK; else td->td_sigstk.ss_flags &= ~SS_ONSTACK; #endif kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, SIGPROCMASK_OLD); return (EJUSTRETURN); } #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 /* * MPSAFE */ int freebsd4_sigreturn(td, uap) struct thread *td; struct freebsd4_sigreturn_args /* { const ucontext4 *sigcntxp; } */ *uap; { struct ucontext4 uc; struct trapframe *regs; struct ucontext4 *ucp; int cs, eflags, error; ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) return (error); ucp = &uc; regs = td->td_frame; eflags = ucp->uc_mcontext.mc_eflags; if (eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86; /* * if pcb_ext == 0 or vm86_inited == 0, the user hasn't * set up the vm86 area, and we can't enter vm86 mode. */ if (td->td_pcb->pcb_ext == 0) return (EINVAL); vm86 = &td->td_pcb->pcb_ext->ext_vm86; if (vm86->vm86_inited == 0) return (EINVAL); /* Go back to user mode if both flags are set. */ if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; } else { vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); tf->tf_eflags = eflags; tf->tf_vm86_ds = tf->tf_ds; tf->tf_vm86_es = tf->tf_es; tf->tf_vm86_fs = tf->tf_fs; tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; tf->tf_fs = _udatasel; } else { /* * Don't allow users to change privileged or reserved flags. */ if (!EFL_SECURE(eflags, regs->tf_eflags)) { uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n", td->td_proc->p_pid, td->td_name, eflags); return (EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", td->td_proc->p_pid, td->td_name, cs); ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); return (EINVAL); } bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); } #if defined(COMPAT_43) if (ucp->uc_mcontext.mc_onstack & 1) td->td_sigstk.ss_flags |= SS_ONSTACK; else td->td_sigstk.ss_flags &= ~SS_ONSTACK; #endif kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); return (EJUSTRETURN); } #endif /* COMPAT_FREEBSD4 */ /* * MPSAFE */ int sys_sigreturn(td, uap) struct thread *td; struct sigreturn_args /* { const struct __ucontext *sigcntxp; } */ *uap; { ucontext_t uc; struct proc *p; struct trapframe *regs; ucontext_t *ucp; char *xfpustate; size_t xfpustate_len; int cs, eflags, error, ret; ksiginfo_t ksi; p = td->td_proc; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) return (error); ucp = &uc; if ((ucp->uc_mcontext.mc_flags & ~_MC_FLAG_MASK) != 0) { uprintf("pid %d (%s): sigreturn mc_flags %x\n", p->p_pid, td->td_name, ucp->uc_mcontext.mc_flags); return (EINVAL); } regs = td->td_frame; eflags = ucp->uc_mcontext.mc_eflags; if (eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86; /* * if pcb_ext == 0 or vm86_inited == 0, the user hasn't * set up the vm86 area, and we can't enter vm86 mode. */ if (td->td_pcb->pcb_ext == 0) return (EINVAL); vm86 = &td->td_pcb->pcb_ext->ext_vm86; if (vm86->vm86_inited == 0) return (EINVAL); /* Go back to user mode if both flags are set. */ if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; } else { vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); tf->tf_eflags = eflags; tf->tf_vm86_ds = tf->tf_ds; tf->tf_vm86_es = tf->tf_es; tf->tf_vm86_fs = tf->tf_fs; tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; tf->tf_fs = _udatasel; } else { /* * Don't allow users to change privileged or reserved flags. */ if (!EFL_SECURE(eflags, regs->tf_eflags)) { uprintf("pid %d (%s): sigreturn eflags = 0x%x\n", td->td_proc->p_pid, td->td_name, eflags); return (EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { uprintf("pid %d (%s): sigreturn cs = 0x%x\n", td->td_proc->p_pid, td->td_name, cs); ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_eip; trapsignal(td, &ksi); return (EINVAL); } if ((uc.uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) { xfpustate_len = uc.uc_mcontext.mc_xfpustate_len; if (xfpustate_len > cpu_max_ext_state_size - sizeof(union savefpu)) { uprintf( "pid %d (%s): sigreturn xfpusave_len = 0x%zx\n", p->p_pid, td->td_name, xfpustate_len); return (EINVAL); } xfpustate = __builtin_alloca(xfpustate_len); error = copyin((const void *)uc.uc_mcontext.mc_xfpustate, xfpustate, xfpustate_len); if (error != 0) { uprintf( "pid %d (%s): sigreturn copying xfpustate failed\n", p->p_pid, td->td_name); return (error); } } else { xfpustate = NULL; xfpustate_len = 0; } ret = set_fpcontext(td, &ucp->uc_mcontext, xfpustate, xfpustate_len); if (ret != 0) return (ret); bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); } #if defined(COMPAT_43) if (ucp->uc_mcontext.mc_onstack & 1) td->td_sigstk.ss_flags |= SS_ONSTACK; else td->td_sigstk.ss_flags &= ~SS_ONSTACK; #endif kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); return (EJUSTRETURN); } /* * Reset registers to default values on exec. */ void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; /* Reset pc->pcb_gs and %gs before possibly invalidating it. */ pcb->pcb_gs = _udatasel; load_gs(_udatasel); mtx_lock_spin(&dt_lock); if (td->td_proc->p_md.md_ldt) user_ldt_free(td); else mtx_unlock_spin(&dt_lock); bzero((char *)regs, sizeof(struct trapframe)); regs->tf_eip = imgp->entry_addr; regs->tf_esp = stack; regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); regs->tf_ss = _udatasel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_cs = _ucodesel; /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ regs->tf_ebx = imgp->ps_strings; /* * Reset the hardware debug registers if they were in use. * They won't have any meaning for the newly exec'd process. */ if (pcb->pcb_flags & PCB_DBREGS) { pcb->pcb_dr0 = 0; pcb->pcb_dr1 = 0; pcb->pcb_dr2 = 0; pcb->pcb_dr3 = 0; pcb->pcb_dr6 = 0; pcb->pcb_dr7 = 0; if (pcb == curpcb) { /* * Clear the debug registers on the running * CPU, otherwise they will end up affecting * the next process we switch to. */ reset_dbregs(); } pcb->pcb_flags &= ~PCB_DBREGS; } pcb->pcb_initial_npxcw = __INITIAL_NPXCW__; /* * Drop the FP state if we hold it, so that the process gets a * clean FP state if it uses the FPU again. */ fpstate_drop(td); /* * XXX - Linux emulator * Make sure sure edx is 0x0 on entry. Linux binaries depend * on it. */ td->td_retval[1] = 0; } void cpu_setregs(void) { unsigned int cr0; cr0 = rcr0(); /* * CR0_MP, CR0_NE and CR0_TS are set for NPX (FPU) support: * * Prepare to trap all ESC (i.e., NPX) instructions and all WAIT * instructions. We must set the CR0_MP bit and use the CR0_TS * bit to control the trap, because setting the CR0_EM bit does * not cause WAIT instructions to trap. It's important to trap * WAIT instructions - otherwise the "wait" variants of no-wait * control instructions would degenerate to the "no-wait" variants * after FP context switches but work correctly otherwise. It's * particularly important to trap WAITs when there is no NPX - * otherwise the "wait" variants would always degenerate. * * Try setting CR0_NE to get correct error reporting on 486DX's. * Setting it should fail or do nothing on lesser processors. */ cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM; load_cr0(cr0); load_gs(_udatasel); } u_long bootdev; /* not a struct cdev *- encoding is different */ SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev, CTLFLAG_RD, &bootdev, 0, "Maybe the Boot device (not in struct cdev *format)"); static char bootmethod[16] = "BIOS"; SYSCTL_STRING(_machdep, OID_AUTO, bootmethod, CTLFLAG_RD, bootmethod, 0, "System firmware boot method"); /* * Initialize 386 and configure to run kernel */ /* * Initialize segments & interrupt table */ int _default_ldt; union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */ union descriptor ldt[NLDT]; /* local descriptor table */ static struct gate_descriptor idt0[NIDT]; struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */ struct region_descriptor r_gdt, r_idt; /* table descriptors */ struct mtx dt_lock; /* lock for GDT and LDT */ static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; extern vm_offset_t proc0kstack; /* * software prototypes -- in more palatable form. * * GCODE_SEL through GUDATA_SEL must be in this order for syscall/sysret * GUFS_SEL and GUGS_SEL must be in this order (swtch.s knows it) */ struct soft_segment_descriptor gdt_segs[] = { /* GNULL_SEL 0 Null Descriptor */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = SEL_KPL, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_KPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GUFS_SEL 2 %fs Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GUGS_SEL 3 %gs Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GCODE_SEL 4 Code Descriptor for kernel */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMERA, .ssd_dpl = SEL_KPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GDATA_SEL 5 Data Descriptor for kernel */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_KPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GUCODE_SEL 6 Code Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMERA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GUDATA_SEL 7 Data Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */ { .ssd_base = 0x400, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_KPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GPROC0_SEL 9 Proc 0 Tss Descriptor */ { .ssd_base = 0x0, .ssd_limit = sizeof(struct i386tss)-1, .ssd_type = SDT_SYS386TSS, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* GLDT_SEL 10 LDT Descriptor */ { .ssd_base = (int) ldt, .ssd_limit = sizeof(ldt)-1, .ssd_type = SDT_SYSLDT, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* GUSERLDT_SEL 11 User LDT Descriptor per process */ { .ssd_base = (int) ldt, .ssd_limit = (512 * sizeof(union descriptor)-1), .ssd_type = SDT_SYSLDT, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* GPANIC_SEL 12 Panic Tss Descriptor */ { .ssd_base = (int) &dblfault_tss, .ssd_limit = sizeof(struct i386tss)-1, .ssd_type = SDT_SYS386TSS, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */ { .ssd_base = 0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMERA, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 1 }, /* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */ { .ssd_base = 0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMERA, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 1 }, /* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */ { .ssd_base = 0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */ { .ssd_base = 0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 1 }, /* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */ { .ssd_base = 0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = 0, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 1 }, /* GNDIS_SEL 18 NDIS Descriptor */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = 0, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, }; static struct soft_segment_descriptor ldt_segs[] = { /* Null Descriptor - overwritten by call gate */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = 0, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* Null Descriptor - overwritten by call gate */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = 0, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* Null Descriptor - overwritten by call gate */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = 0, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* Code Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMERA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, /* Null Descriptor - overwritten by call gate */ { .ssd_base = 0x0, .ssd_limit = 0x0, .ssd_type = 0, .ssd_dpl = 0, .ssd_p = 0, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 0, .ssd_gran = 0 }, /* Data Descriptor for user */ { .ssd_base = 0x0, .ssd_limit = 0xfffff, .ssd_type = SDT_MEMRWA, .ssd_dpl = SEL_UPL, .ssd_p = 1, .ssd_xx = 0, .ssd_xx1 = 0, .ssd_def32 = 1, .ssd_gran = 1 }, }; void setidt(idx, func, typ, dpl, selec) int idx; inthand_t *func; int typ; int dpl; int selec; { struct gate_descriptor *ip; ip = idt + idx; ip->gd_looffset = (int)func; ip->gd_selector = selec; ip->gd_stkcpy = 0; ip->gd_xx = 0; ip->gd_type = typ; ip->gd_dpl = dpl; ip->gd_p = 1; ip->gd_hioffset = ((int)func)>>16 ; } extern inthand_t IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(xmm), #ifdef KDTRACE_HOOKS IDTVEC(dtrace_ret), #endif #ifdef XENHVM IDTVEC(xen_intr_upcall), #endif IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall); #ifdef DDB /* * Display the index and function name of any IDT entries that don't use * the default 'rsvd' entry point. */ DB_SHOW_COMMAND(idt, db_show_idt) { struct gate_descriptor *ip; int idx; uintptr_t func; ip = idt; for (idx = 0; idx < NIDT && !db_pager_quit; idx++) { func = (ip->gd_hioffset << 16 | ip->gd_looffset); if (func != (uintptr_t)&IDTVEC(rsvd)) { db_printf("%3d\t", idx); db_printsym(func, DB_STGY_PROC); db_printf("\n"); } ip++; } } /* Show privileged registers. */ DB_SHOW_COMMAND(sysregs, db_show_sysregs) { uint64_t idtr, gdtr; idtr = ridt(); db_printf("idtr\t0x%08x/%04x\n", (u_int)(idtr >> 16), (u_int)idtr & 0xffff); gdtr = rgdt(); db_printf("gdtr\t0x%08x/%04x\n", (u_int)(gdtr >> 16), (u_int)gdtr & 0xffff); db_printf("ldtr\t0x%04x\n", rldt()); db_printf("tr\t0x%04x\n", rtr()); db_printf("cr0\t0x%08x\n", rcr0()); db_printf("cr2\t0x%08x\n", rcr2()); db_printf("cr3\t0x%08x\n", rcr3()); db_printf("cr4\t0x%08x\n", rcr4()); if (rcr4() & CR4_XSAVE) db_printf("xcr0\t0x%016llx\n", rxcr(0)); if (amd_feature & (AMDID_NX | AMDID_LM)) db_printf("EFER\t0x%016llx\n", rdmsr(MSR_EFER)); if (cpu_feature2 & (CPUID2_VMX | CPUID2_SMX)) db_printf("FEATURES_CTL\t0x%016llx\n", rdmsr(MSR_IA32_FEATURE_CONTROL)); if ((cpu_vendor_id == CPU_VENDOR_INTEL || cpu_vendor_id == CPU_VENDOR_AMD) && CPUID_TO_FAMILY(cpu_id) >= 6) db_printf("DEBUG_CTL\t0x%016llx\n", rdmsr(MSR_DEBUGCTLMSR)); if (cpu_feature & CPUID_PAT) db_printf("PAT\t0x%016llx\n", rdmsr(MSR_PAT)); } DB_SHOW_COMMAND(dbregs, db_show_dbregs) { db_printf("dr0\t0x%08x\n", rdr0()); db_printf("dr1\t0x%08x\n", rdr1()); db_printf("dr2\t0x%08x\n", rdr2()); db_printf("dr3\t0x%08x\n", rdr3()); db_printf("dr6\t0x%08x\n", rdr6()); db_printf("dr7\t0x%08x\n", rdr7()); } #endif void sdtossd(sd, ssd) struct segment_descriptor *sd; struct soft_segment_descriptor *ssd; { ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; ssd->ssd_type = sd->sd_type; ssd->ssd_dpl = sd->sd_dpl; ssd->ssd_p = sd->sd_p; ssd->ssd_def32 = sd->sd_def32; ssd->ssd_gran = sd->sd_gran; } #if !defined(PC98) static int add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap, int *physmap_idxp) { int i, insert_idx, physmap_idx; physmap_idx = *physmap_idxp; if (length == 0) return (1); #ifndef PAE if (base > 0xffffffff) { printf("%uK of memory above 4GB ignored\n", (u_int)(length / 1024)); return (1); } #endif /* * Find insertion point while checking for overlap. Start off by * assuming the new entry will be added to the end. */ insert_idx = physmap_idx + 2; for (i = 0; i <= physmap_idx; i += 2) { if (base < physmap[i + 1]) { if (base + length <= physmap[i]) { insert_idx = i; break; } if (boothowto & RB_VERBOSE) printf( "Overlapping memory regions, ignoring second region\n"); return (1); } } /* See if we can prepend to the next entry. */ if (insert_idx <= physmap_idx && base + length == physmap[insert_idx]) { physmap[insert_idx] = base; return (1); } /* See if we can append to the previous entry. */ if (insert_idx > 0 && base == physmap[insert_idx - 1]) { physmap[insert_idx - 1] += length; return (1); } physmap_idx += 2; *physmap_idxp = physmap_idx; if (physmap_idx == PHYSMAP_SIZE) { printf( "Too many segments in the physical address map, giving up\n"); return (0); } /* * Move the last 'N' entries down to make room for the new * entry if needed. */ for (i = physmap_idx; i > insert_idx; i -= 2) { physmap[i] = physmap[i - 2]; physmap[i + 1] = physmap[i - 1]; } /* Insert the new entry. */ physmap[insert_idx] = base; physmap[insert_idx + 1] = base + length; return (1); } static int add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) { if (boothowto & RB_VERBOSE) printf("SMAP type=%02x base=%016llx len=%016llx\n", smap->type, smap->base, smap->length); if (smap->type != SMAP_TYPE_MEMORY) return (1); return (add_physmap_entry(smap->base, smap->length, physmap, physmap_idxp)); } static void add_smap_entries(struct bios_smap *smapbase, vm_paddr_t *physmap, int *physmap_idxp) { struct bios_smap *smap, *smapend; u_int32_t smapsize; /* * Memory map from INT 15:E820. * * subr_module.c says: * "Consumer may safely assume that size value precedes data." * ie: an int32_t immediately precedes SMAP. */ smapsize = *((u_int32_t *)smapbase - 1); smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize); for (smap = smapbase; smap < smapend; smap++) if (!add_smap_entry(smap, physmap, physmap_idxp)) break; } #endif /* !PC98 */ static void basemem_setup(void) { vm_paddr_t pa; pt_entry_t *pte; int i; if (basemem > 640) { printf("Preposterous BIOS basemem of %uK, truncating to 640K\n", basemem); basemem = 640; } /* * XXX if biosbasemem is now < 640, there is a `hole' * between the end of base memory and the start of * ISA memory. The hole may be empty or it may * contain BIOS code or data. Map it read/write so * that the BIOS can write to it. (Memory from 0 to * the physical end of the kernel is mapped read-only * to begin with and then parts of it are remapped. * The parts that aren't remapped form holes that * remain read-only and are unused by the kernel. * The base memory area is below the physical end of * the kernel and right now forms a read-only hole. * The part of it from PAGE_SIZE to * (trunc_page(biosbasemem * 1024) - 1) will be * remapped and used by the kernel later.) * * This code is similar to the code used in * pmap_mapdev, but since no memory needs to be * allocated we simply change the mapping. */ for (pa = trunc_page(basemem * 1024); pa < ISA_HOLE_START; pa += PAGE_SIZE) pmap_kenter(KERNBASE + pa, pa); /* * Map pages between basemem and ISA_HOLE_START, if any, r/w into * the vm86 page table so that vm86 can scribble on them using * the vm86 map too. XXX: why 2 ways for this and only 1 way for * page 0, at least as initialized here? */ pte = (pt_entry_t *)vm86paddr; for (i = basemem / 4; i < 160; i++) pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U; } /* * Populate the (physmap) array with base/bound pairs describing the * available physical memory in the system, then test this memory and * build the phys_avail array describing the actually-available memory. * * If we cannot accurately determine the physical memory map, then use * value from the 0xE801 call, and failing that, the RTC. * * Total memory size may be set by the kernel environment variable * hw.physmem or the compile-time define MAXMEM. * * XXX first should be vm_paddr_t. */ #ifdef PC98 static void getmemsize(int first) { int off, physmap_idx, pa_indx, da_indx; u_long physmem_tunable, memtest; vm_paddr_t physmap[PHYSMAP_SIZE]; pt_entry_t *pte; quad_t dcons_addr, dcons_size; int i; int pg_n; u_int extmem; u_int under16; vm_paddr_t pa; bzero(physmap, sizeof(physmap)); /* XXX - some of EPSON machines can't use PG_N */ pg_n = PG_N; if (pc98_machine_type & M_EPSON_PC98) { switch (epson_machine_id) { #ifdef WB_CACHE default: #endif case EPSON_PC486_HX: case EPSON_PC486_HG: case EPSON_PC486_HA: pg_n = 0; break; } } under16 = pc98_getmemsize(&basemem, &extmem); basemem_setup(); physmap[0] = 0; physmap[1] = basemem * 1024; physmap_idx = 2; physmap[physmap_idx] = 0x100000; physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024; /* * Now, physmap contains a map of physical memory. */ #ifdef SMP /* make hole for AP bootstrap code */ physmap[1] = mp_bootaddress(physmap[1]); #endif /* * Maxmem isn't the "maximum memory", it's one larger than the * highest page of the physical address space. It should be * called something like "Maxphyspage". We may adjust this * based on ``hw.physmem'' and the results of the memory test. */ Maxmem = atop(physmap[physmap_idx + 1]); #ifdef MAXMEM Maxmem = MAXMEM / 4; #endif if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable)) Maxmem = atop(physmem_tunable); /* * By default keep the memtest enabled. Use a general name so that * one could eventually do more with the code than just disable it. */ memtest = 1; TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest); if (atop(physmap[physmap_idx + 1]) != Maxmem && (boothowto & RB_VERBOSE)) printf("Physical memory use set to %ldK\n", Maxmem * 4); /* * If Maxmem has been increased beyond what the system has detected, * extend the last memory segment to the new limit. */ if (atop(physmap[physmap_idx + 1]) < Maxmem) physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem); /* * We need to divide chunk if Maxmem is larger than 16MB and * under 16MB area is not full of memory. * (1) system area (15-16MB region) is cut off * (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY") */ if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) { /* 15M - 16M region is cut off, so need to divide chunk */ physmap[physmap_idx + 1] = under16 * 1024; physmap_idx += 2; physmap[physmap_idx] = 0x1000000; physmap[physmap_idx + 1] = physmap[2] + extmem * 1024; } /* call pmap initialization to make new kernel address space */ pmap_bootstrap(first); /* * Size up each available chunk of physical memory. */ physmap[0] = PAGE_SIZE; /* mask off page 0 */ pa_indx = 0; da_indx = 1; phys_avail[pa_indx++] = physmap[0]; phys_avail[pa_indx] = physmap[0]; dump_avail[da_indx] = physmap[0]; pte = CMAP3; /* * Get dcons buffer address */ if (getenv_quad("dcons.addr", &dcons_addr) == 0 || getenv_quad("dcons.size", &dcons_size) == 0) dcons_addr = 0; /* * physmap is in bytes, so when converting to page boundaries, * round up the start address and round down the end address. */ for (i = 0; i <= physmap_idx; i += 2) { vm_paddr_t end; end = ptoa((vm_paddr_t)Maxmem); if (physmap[i + 1] < end) end = trunc_page(physmap[i + 1]); for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) { int tmp, page_bad, full; int *ptr = (int *)CADDR3; full = FALSE; /* * block out kernel memory as not available. */ if (pa >= KERNLOAD && pa < first) goto do_dump_avail; /* * block out dcons buffer */ if (dcons_addr > 0 && pa >= trunc_page(dcons_addr) && pa < dcons_addr + dcons_size) goto do_dump_avail; page_bad = FALSE; if (memtest == 0) goto skip_memtest; /* * map page into kernel: valid, read/write,non-cacheable */ *pte = pa | PG_V | PG_RW | pg_n; invltlb(); tmp = *(int *)ptr; /* * Test for alternating 1's and 0's */ *(volatile int *)ptr = 0xaaaaaaaa; if (*(volatile int *)ptr != 0xaaaaaaaa) page_bad = TRUE; /* * Test for alternating 0's and 1's */ *(volatile int *)ptr = 0x55555555; if (*(volatile int *)ptr != 0x55555555) page_bad = TRUE; /* * Test for all 1's */ *(volatile int *)ptr = 0xffffffff; if (*(volatile int *)ptr != 0xffffffff) page_bad = TRUE; /* * Test for all 0's */ *(volatile int *)ptr = 0x0; if (*(volatile int *)ptr != 0x0) page_bad = TRUE; /* * Restore original value. */ *(int *)ptr = tmp; skip_memtest: /* * Adjust array of valid/good pages. */ if (page_bad == TRUE) continue; /* * If this good page is a continuation of the * previous set of good pages, then just increase * the end pointer. Otherwise start a new chunk. * Note that "end" points one higher than end, * making the range >= start and < end. * If we're also doing a speculative memory * test and we at or past the end, bump up Maxmem * so that we keep going. The first bad page * will terminate the loop. */ if (phys_avail[pa_indx] == pa) { phys_avail[pa_indx] += PAGE_SIZE; } else { pa_indx++; if (pa_indx == PHYS_AVAIL_ARRAY_END) { printf( "Too many holes in the physical address space, giving up\n"); pa_indx--; full = TRUE; goto do_dump_avail; } phys_avail[pa_indx++] = pa; /* start */ phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */ } physmem++; do_dump_avail: if (dump_avail[da_indx] == pa) { dump_avail[da_indx] += PAGE_SIZE; } else { da_indx++; if (da_indx == DUMP_AVAIL_ARRAY_END) { da_indx--; goto do_next; } dump_avail[da_indx++] = pa; /* start */ dump_avail[da_indx] = pa + PAGE_SIZE; /* end */ } do_next: if (full) break; } } *pte = 0; invltlb(); /* * XXX * The last chunk must contain at least one page plus the message * buffer to avoid complicating other code (message buffer address * calculation, etc.). */ while (phys_avail[pa_indx - 1] + PAGE_SIZE + round_page(msgbufsize) >= phys_avail[pa_indx]) { physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); phys_avail[pa_indx--] = 0; phys_avail[pa_indx--] = 0; } Maxmem = atop(phys_avail[pa_indx]); /* Trim off space for the message buffer. */ phys_avail[pa_indx] -= round_page(msgbufsize); /* Map the message buffer. */ for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE) pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] + off); } #else /* PC98 */ static void getmemsize(int first) { int has_smap, off, physmap_idx, pa_indx, da_indx; u_long memtest; vm_paddr_t physmap[PHYSMAP_SIZE]; pt_entry_t *pte; quad_t dcons_addr, dcons_size, physmem_tunable; int hasbrokenint12, i, res; u_int extmem; struct vm86frame vmf; struct vm86context vmc; vm_paddr_t pa; struct bios_smap *smap, *smapbase; caddr_t kmdp; has_smap = 0; #ifdef XBOX if (arch_i386_is_xbox) { /* * We queried the memory size before, so chop off 4MB for * the framebuffer and inform the OS of this. */ physmap[0] = 0; physmap[1] = (arch_i386_xbox_memsize * 1024 * 1024) - XBOX_FB_SIZE; physmap_idx = 0; goto physmap_done; } #endif bzero(&vmf, sizeof(vmf)); bzero(physmap, sizeof(physmap)); basemem = 0; /* * Check if the loader supplied an SMAP memory map. If so, * use that and do not make any VM86 calls. */ physmap_idx = 0; smapbase = NULL; kmdp = preload_search_by_type("elf kernel"); if (kmdp == NULL) kmdp = preload_search_by_type("elf32 kernel"); smapbase = (struct bios_smap *)preload_search_info(kmdp, MODINFO_METADATA | MODINFOMD_SMAP); if (smapbase != NULL) { add_smap_entries(smapbase, physmap, &physmap_idx); has_smap = 1; goto have_smap; } /* * Some newer BIOSes have a broken INT 12H implementation * which causes a kernel panic immediately. In this case, we * need use the SMAP to determine the base memory size. */ hasbrokenint12 = 0; TUNABLE_INT_FETCH("hw.hasbrokenint12", &hasbrokenint12); if (hasbrokenint12 == 0) { /* Use INT12 to determine base memory size. */ vm86_intcall(0x12, &vmf); basemem = vmf.vmf_ax; basemem_setup(); } /* * Fetch the memory map with INT 15:E820. Map page 1 R/W into * the kernel page table so we can use it as a buffer. The * kernel will unmap this page later. */ pmap_kenter(KERNBASE + (1 << PAGE_SHIFT), 1 << PAGE_SHIFT); vmc.npages = 0; smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT)); res = vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di); KASSERT(res != 0, ("vm86_getptr() failed: address not found")); vmf.vmf_ebx = 0; do { vmf.vmf_eax = 0xE820; vmf.vmf_edx = SMAP_SIG; vmf.vmf_ecx = sizeof(struct bios_smap); i = vm86_datacall(0x15, &vmf, &vmc); if (i || vmf.vmf_eax != SMAP_SIG) break; has_smap = 1; if (!add_smap_entry(smap, physmap, &physmap_idx)) break; } while (vmf.vmf_ebx != 0); have_smap: /* * If we didn't fetch the "base memory" size from INT12, * figure it out from the SMAP (or just guess). */ if (basemem == 0) { for (i = 0; i <= physmap_idx; i += 2) { if (physmap[i] == 0x00000000) { basemem = physmap[i + 1] / 1024; break; } } /* XXX: If we couldn't find basemem from SMAP, just guess. */ if (basemem == 0) basemem = 640; basemem_setup(); } if (physmap[1] != 0) goto physmap_done; /* * If we failed to find an SMAP, figure out the extended * memory size. We will then build a simple memory map with * two segments, one for "base memory" and the second for * "extended memory". Note that "extended memory" starts at a * physical address of 1MB and that both basemem and extmem * are in units of 1KB. * * First, try to fetch the extended memory size via INT 15:E801. */ vmf.vmf_ax = 0xE801; if (vm86_intcall(0x15, &vmf) == 0) { extmem = vmf.vmf_cx + vmf.vmf_dx * 64; } else { /* * If INT15:E801 fails, this is our last ditch effort * to determine the extended memory size. Currently * we prefer the RTC value over INT15:88. */ #if 0 vmf.vmf_ah = 0x88; vm86_intcall(0x15, &vmf); extmem = vmf.vmf_ax; #else extmem = rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI) << 8); #endif } /* * Special hack for chipsets that still remap the 384k hole when * there's 16MB of memory - this really confuses people that * are trying to use bus mastering ISA controllers with the * "16MB limit"; they only have 16MB, but the remapping puts * them beyond the limit. * * If extended memory is between 15-16MB (16-17MB phys address range), * chop it to 15MB. */ if ((extmem > 15 * 1024) && (extmem < 16 * 1024)) extmem = 15 * 1024; physmap[0] = 0; physmap[1] = basemem * 1024; physmap_idx = 2; physmap[physmap_idx] = 0x100000; physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024; physmap_done: /* * Now, physmap contains a map of physical memory. */ #ifdef SMP /* make hole for AP bootstrap code */ physmap[1] = mp_bootaddress(physmap[1]); #endif /* * Maxmem isn't the "maximum memory", it's one larger than the * highest page of the physical address space. It should be * called something like "Maxphyspage". We may adjust this * based on ``hw.physmem'' and the results of the memory test. */ Maxmem = atop(physmap[physmap_idx + 1]); #ifdef MAXMEM Maxmem = MAXMEM / 4; #endif if (TUNABLE_QUAD_FETCH("hw.physmem", &physmem_tunable)) Maxmem = atop(physmem_tunable); /* * If we have an SMAP, don't allow MAXMEM or hw.physmem to extend * the amount of memory in the system. */ if (has_smap && Maxmem > atop(physmap[physmap_idx + 1])) Maxmem = atop(physmap[physmap_idx + 1]); /* * By default enable the memory test on real hardware, and disable * it if we appear to be running in a VM. This avoids touching all * pages unnecessarily, which doesn't matter on real hardware but is * bad for shared VM hosts. Use a general name so that * one could eventually do more with the code than just disable it. */ memtest = (vm_guest > VM_GUEST_NO) ? 0 : 1; TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest); if (atop(physmap[physmap_idx + 1]) != Maxmem && (boothowto & RB_VERBOSE)) printf("Physical memory use set to %ldK\n", Maxmem * 4); /* * If Maxmem has been increased beyond what the system has detected, * extend the last memory segment to the new limit. */ if (atop(physmap[physmap_idx + 1]) < Maxmem) physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem); /* call pmap initialization to make new kernel address space */ pmap_bootstrap(first); /* * Size up each available chunk of physical memory. */ physmap[0] = PAGE_SIZE; /* mask off page 0 */ pa_indx = 0; da_indx = 1; phys_avail[pa_indx++] = physmap[0]; phys_avail[pa_indx] = physmap[0]; dump_avail[da_indx] = physmap[0]; pte = CMAP3; /* * Get dcons buffer address */ if (getenv_quad("dcons.addr", &dcons_addr) == 0 || getenv_quad("dcons.size", &dcons_size) == 0) dcons_addr = 0; /* * physmap is in bytes, so when converting to page boundaries, * round up the start address and round down the end address. */ for (i = 0; i <= physmap_idx; i += 2) { vm_paddr_t end; end = ptoa((vm_paddr_t)Maxmem); if (physmap[i + 1] < end) end = trunc_page(physmap[i + 1]); for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) { int tmp, page_bad, full; int *ptr = (int *)CADDR3; full = FALSE; /* * block out kernel memory as not available. */ if (pa >= KERNLOAD && pa < first) goto do_dump_avail; /* * block out dcons buffer */ if (dcons_addr > 0 && pa >= trunc_page(dcons_addr) && pa < dcons_addr + dcons_size) goto do_dump_avail; page_bad = FALSE; if (memtest == 0) goto skip_memtest; /* * map page into kernel: valid, read/write,non-cacheable */ *pte = pa | PG_V | PG_RW | PG_N; invltlb(); tmp = *(int *)ptr; /* * Test for alternating 1's and 0's */ *(volatile int *)ptr = 0xaaaaaaaa; if (*(volatile int *)ptr != 0xaaaaaaaa) page_bad = TRUE; /* * Test for alternating 0's and 1's */ *(volatile int *)ptr = 0x55555555; if (*(volatile int *)ptr != 0x55555555) page_bad = TRUE; /* * Test for all 1's */ *(volatile int *)ptr = 0xffffffff; if (*(volatile int *)ptr != 0xffffffff) page_bad = TRUE; /* * Test for all 0's */ *(volatile int *)ptr = 0x0; if (*(volatile int *)ptr != 0x0) page_bad = TRUE; /* * Restore original value. */ *(int *)ptr = tmp; skip_memtest: /* * Adjust array of valid/good pages. */ if (page_bad == TRUE) continue; /* * If this good page is a continuation of the * previous set of good pages, then just increase * the end pointer. Otherwise start a new chunk. * Note that "end" points one higher than end, * making the range >= start and < end. * If we're also doing a speculative memory * test and we at or past the end, bump up Maxmem * so that we keep going. The first bad page * will terminate the loop. */ if (phys_avail[pa_indx] == pa) { phys_avail[pa_indx] += PAGE_SIZE; } else { pa_indx++; if (pa_indx == PHYS_AVAIL_ARRAY_END) { printf( "Too many holes in the physical address space, giving up\n"); pa_indx--; full = TRUE; goto do_dump_avail; } phys_avail[pa_indx++] = pa; /* start */ phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */ } physmem++; do_dump_avail: if (dump_avail[da_indx] == pa) { dump_avail[da_indx] += PAGE_SIZE; } else { da_indx++; if (da_indx == DUMP_AVAIL_ARRAY_END) { da_indx--; goto do_next; } dump_avail[da_indx++] = pa; /* start */ dump_avail[da_indx] = pa + PAGE_SIZE; /* end */ } do_next: if (full) break; } } *pte = 0; invltlb(); /* * XXX * The last chunk must contain at least one page plus the message * buffer to avoid complicating other code (message buffer address * calculation, etc.). */ while (phys_avail[pa_indx - 1] + PAGE_SIZE + round_page(msgbufsize) >= phys_avail[pa_indx]) { physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); phys_avail[pa_indx--] = 0; phys_avail[pa_indx--] = 0; } Maxmem = atop(phys_avail[pa_indx]); /* Trim off space for the message buffer. */ phys_avail[pa_indx] -= round_page(msgbufsize); /* Map the message buffer. */ for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE) pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] + off); } #endif /* PC98 */ register_t init386(first) int first; { struct gate_descriptor *gdp; int gsel_tss, metadata_missing, x, pa; struct pcpu *pc; #ifdef CPU_ENABLE_SSE struct xstate_hdr *xhdr; #endif thread0.td_kstack = proc0kstack; thread0.td_kstack_pages = TD0_KSTACK_PAGES; /* * This may be done better later if it gets more high level * components in it. If so just link td->td_proc here. */ proc_linkup0(&proc0, &thread0); #ifdef PC98 /* * Initialize DMAC */ pc98_init_dmac(); #endif metadata_missing = 0; if (bootinfo.bi_modulep) { preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE; preload_bootstrap_relocate(KERNBASE); } else { metadata_missing = 1; } if (bootinfo.bi_envp != 0) init_static_kenv((char *)bootinfo.bi_envp + KERNBASE, 0); else init_static_kenv(NULL, 0); /* Init basic tunables, hz etc */ init_param1(); /* * Make gdt memory segments. All segments cover the full 4GB * of address space and permissions are enforced at page level. */ gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1); gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1); gdt_segs[GUCODE_SEL].ssd_limit = atop(0 - 1); gdt_segs[GUDATA_SEL].ssd_limit = atop(0 - 1); gdt_segs[GUFS_SEL].ssd_limit = atop(0 - 1); gdt_segs[GUGS_SEL].ssd_limit = atop(0 - 1); pc = &__pcpu[0]; gdt_segs[GPRIV_SEL].ssd_limit = atop(0 - 1); gdt_segs[GPRIV_SEL].ssd_base = (int) pc; gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss; for (x = 0; x < NGDT; x++) ssdtosd(&gdt_segs[x], &gdt[x].sd); r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; r_gdt.rd_base = (int) gdt; mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN); lgdt(&r_gdt); pcpu_init(pc, 0, sizeof(struct pcpu)); for (pa = first; pa < first + DPCPU_SIZE; pa += PAGE_SIZE) pmap_kenter(pa + KERNBASE, pa); dpcpu_init((void *)(first + KERNBASE), 0); first += DPCPU_SIZE; PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); /* * Initialize mutexes. * * icu_lock: in order to allow an interrupt to occur in a critical * section, to set pcpu->ipending (etc...) properly, we * must be able to get the icu lock, so it can't be * under witness. */ mutex_init(); mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS | MTX_NOPROFILE); /* make ldt memory segments */ ldt_segs[LUCODE_SEL].ssd_limit = atop(0 - 1); ldt_segs[LUDATA_SEL].ssd_limit = atop(0 - 1); for (x = 0; x < nitems(ldt_segs); x++) ssdtosd(&ldt_segs[x], &ldt[x].sd); _default_ldt = GSEL(GLDT_SEL, SEL_KPL); lldt(_default_ldt); PCPU_SET(currentldt, _default_ldt); /* exceptions */ for (x = 0; x < NIDT; x++) setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_DE, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_DB, &IDTVEC(dbg), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_BP, &IDTVEC(bpt), SDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_OF, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_BR, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_NM, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL , GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_DF, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL)); setidt(IDT_FPUGP, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_TS, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_NP, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_SS, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_PF, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_MF, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_AC, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_MC, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_XF, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); #ifdef KDTRACE_HOOKS setidt(IDT_DTRACE_RET, &IDTVEC(dtrace_ret), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); #endif #ifdef XENHVM setidt(IDT_EVTCHN, &IDTVEC(xen_intr_upcall), SDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); #endif r_idt.rd_limit = sizeof(idt0) - 1; r_idt.rd_base = (int) idt; lidt(&r_idt); #ifdef XBOX /* * The following code queries the PCI ID of 0:0:0. For the XBOX, * This should be 0x10de / 0x02a5. * * This is exactly what Linux does. */ outl(0xcf8, 0x80000000); if (inl(0xcfc) == 0x02a510de) { arch_i386_is_xbox = 1; pic16l_setled(XBOX_LED_GREEN); /* * We are an XBOX, but we may have either 64MB or 128MB of * memory. The PCI host bridge should be programmed for this, * so we just query it. */ outl(0xcf8, 0x80000084); arch_i386_xbox_memsize = (inl(0xcfc) == 0x7FFFFFF) ? 128 : 64; } #endif /* XBOX */ /* * Initialize the clock before the console so that console * initialization can use DELAY(). */ clock_init(); finishidentcpu(); /* Final stage of CPU initialization */ setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); initializecpu(); /* Initialize CPU registers */ initializecpucache(); /* pointer to selector slot for %fs/%gs */ PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd); dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 = dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)]; dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 = dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL); #if defined(PAE) || defined(PAE_TABLES) dblfault_tss.tss_cr3 = (int)IdlePDPT; #else dblfault_tss.tss_cr3 = (int)IdlePTD; #endif dblfault_tss.tss_eip = (int)dblfault_handler; dblfault_tss.tss_eflags = PSL_KERNEL; dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL); dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL); dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); - vm86_initialize(); - getmemsize(first); - init_param2(physmem); + /* Initialize the tss (except for the final esp0) early for vm86. */ + PCPU_SET(common_tss.tss_esp0, thread0.td_kstack + + thread0.td_kstack_pages * PAGE_SIZE - 16); + PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); + gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); + PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd); + PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); + PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); + ltr(gsel_tss); - /* now running on new page tables, configured,and u/iom is accessible */ - - /* - * Initialize the console before we print anything out. - */ - cninit(); - - if (metadata_missing) - printf("WARNING: loader(8) metadata is missing!\n"); - + /* Initialize the PIC early for vm86 calls. */ #ifdef DEV_ISA #ifdef DEV_ATPIC #ifndef PC98 elcr_probe(); #endif atpic_startup(); #else /* Reset and mask the atpics and leave them shut down. */ atpic_reset(); /* * Point the ICU spurious interrupt vectors at the APIC spurious * interrupt handler. */ setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #endif #endif + vm86_initialize(); + getmemsize(first); + init_param2(physmem); + + /* now running on new page tables, configured,and u/iom is accessible */ + + /* + * Initialize the console before we print anything out. + */ + cninit(); + + if (metadata_missing) + printf("WARNING: loader(8) metadata is missing!\n"); + #ifdef DDB db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab); #endif kdb_init(); #ifdef KDB if (boothowto & RB_KDB) kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); #endif msgbufinit(msgbufp, msgbufsize); #ifdef DEV_NPX npxinit(true); #endif /* * Set up thread0 pcb after npxinit calculated pcb + fpu save * area size. Zero out the extended state header in fpu save * area. */ thread0.td_pcb = get_pcb_td(&thread0); bzero(get_pcb_user_save_td(&thread0), cpu_max_ext_state_size); #ifdef CPU_ENABLE_SSE if (use_xsave) { xhdr = (struct xstate_hdr *)(get_pcb_user_save_td(&thread0) + 1); xhdr->xstate_bv = xsave_mask; } #endif PCPU_SET(curpcb, thread0.td_pcb); - /* make an initial tss so cpu can get interrupt stack on syscall! */ + /* Move esp0 in the tss to its final place. */ /* Note: -16 is so we can grow the trapframe if we came from vm86 */ PCPU_SET(common_tss.tss_esp0, (vm_offset_t)thread0.td_pcb - 16); - PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); - gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); - PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd); - PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); - PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); + gdt[GPROC0_SEL].sd.sd_type = SDT_SYS386TSS; /* clear busy bit */ ltr(gsel_tss); /* make a call gate to reenter kernel with */ gdp = &ldt[LSYS5CALLS_SEL].gd; x = (int) &IDTVEC(lcall_syscall); gdp->gd_looffset = x; gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); gdp->gd_stkcpy = 1; gdp->gd_type = SDT_SYS386CGT; gdp->gd_dpl = SEL_UPL; gdp->gd_p = 1; gdp->gd_hioffset = x >> 16; /* XXX does this work? */ /* XXX yes! */ ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL]; ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL]; /* transfer to user mode */ _ucodesel = GSEL(GUCODE_SEL, SEL_UPL); _udatasel = GSEL(GUDATA_SEL, SEL_UPL); /* setup proc 0's pcb */ thread0.td_pcb->pcb_flags = 0; #if defined(PAE) || defined(PAE_TABLES) thread0.td_pcb->pcb_cr3 = (int)IdlePDPT; #else thread0.td_pcb->pcb_cr3 = (int)IdlePTD; #endif thread0.td_pcb->pcb_ext = 0; thread0.td_frame = &proc0_tf; cpu_probe_amdc1e(); #ifdef FDT x86_init_fdt(); #endif /* Location of kernel stack for locore */ return ((register_t)thread0.td_pcb); } void cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) { pcpu->pc_acpi_id = 0xffffffff; } #ifndef PC98 static int smap_sysctl_handler(SYSCTL_HANDLER_ARGS) { struct bios_smap *smapbase; struct bios_smap_xattr smap; caddr_t kmdp; uint32_t *smapattr; int count, error, i; /* Retrieve the system memory map from the loader. */ kmdp = preload_search_by_type("elf kernel"); if (kmdp == NULL) kmdp = preload_search_by_type("elf32 kernel"); smapbase = (struct bios_smap *)preload_search_info(kmdp, MODINFO_METADATA | MODINFOMD_SMAP); if (smapbase == NULL) return (0); smapattr = (uint32_t *)preload_search_info(kmdp, MODINFO_METADATA | MODINFOMD_SMAP_XATTR); count = *((u_int32_t *)smapbase - 1) / sizeof(*smapbase); error = 0; for (i = 0; i < count; i++) { smap.base = smapbase[i].base; smap.length = smapbase[i].length; smap.type = smapbase[i].type; if (smapattr != NULL) smap.xattr = smapattr[i]; else smap.xattr = 0; error = SYSCTL_OUT(req, &smap, sizeof(smap)); } return (error); } SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0, smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data"); #endif /* !PC98 */ void spinlock_enter(void) { struct thread *td; register_t flags; td = curthread; if (td->td_md.md_spinlock_count == 0) { flags = intr_disable(); td->td_md.md_spinlock_count = 1; td->td_md.md_saved_flags = flags; } else td->td_md.md_spinlock_count++; critical_enter(); } void spinlock_exit(void) { struct thread *td; register_t flags; td = curthread; critical_exit(); flags = td->td_md.md_saved_flags; td->td_md.md_spinlock_count--; if (td->td_md.md_spinlock_count == 0) intr_restore(flags); } #if defined(I586_CPU) && !defined(NO_F00F_HACK) static void f00f_hack(void *unused); SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL); static void f00f_hack(void *unused) { struct gate_descriptor *new_idt; vm_offset_t tmp; if (!has_f00f_bug) return; GIANT_REQUIRED; printf("Intel Pentium detected, installing workaround for F00F bug\n"); tmp = kmem_malloc(kernel_arena, PAGE_SIZE * 2, M_WAITOK | M_ZERO); if (tmp == 0) panic("kmem_malloc returned 0"); /* Put the problematic entry (#6) at the end of the lower page. */ new_idt = (struct gate_descriptor*) (tmp + PAGE_SIZE - 7 * sizeof(struct gate_descriptor)); bcopy(idt, new_idt, sizeof(idt0)); r_idt.rd_base = (u_int)new_idt; lidt(&r_idt); idt = new_idt; pmap_protect(kernel_pmap, tmp, tmp + PAGE_SIZE, VM_PROT_READ); } #endif /* defined(I586_CPU) && !NO_F00F_HACK */ /* * Construct a PCB from a trapframe. This is called from kdb_trap() where * we want to start a backtrace from the function that caused us to enter * the debugger. We have the context in the trapframe, but base the trace * on the PCB. The PCB doesn't have to be perfect, as long as it contains * enough for a backtrace. */ void makectx(struct trapframe *tf, struct pcb *pcb) { pcb->pcb_edi = tf->tf_edi; pcb->pcb_esi = tf->tf_esi; pcb->pcb_ebp = tf->tf_ebp; pcb->pcb_ebx = tf->tf_ebx; pcb->pcb_eip = tf->tf_eip; pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8; pcb->pcb_gs = rgs(); } int ptrace_set_pc(struct thread *td, u_long addr) { td->td_frame->tf_eip = addr; return (0); } int ptrace_single_step(struct thread *td) { td->td_frame->tf_eflags |= PSL_T; return (0); } int ptrace_clear_single_step(struct thread *td) { td->td_frame->tf_eflags &= ~PSL_T; return (0); } int fill_regs(struct thread *td, struct reg *regs) { struct pcb *pcb; struct trapframe *tp; tp = td->td_frame; pcb = td->td_pcb; regs->r_gs = pcb->pcb_gs; return (fill_frame_regs(tp, regs)); } int fill_frame_regs(struct trapframe *tp, struct reg *regs) { regs->r_fs = tp->tf_fs; regs->r_es = tp->tf_es; regs->r_ds = tp->tf_ds; regs->r_edi = tp->tf_edi; regs->r_esi = tp->tf_esi; regs->r_ebp = tp->tf_ebp; regs->r_ebx = tp->tf_ebx; regs->r_edx = tp->tf_edx; regs->r_ecx = tp->tf_ecx; regs->r_eax = tp->tf_eax; regs->r_eip = tp->tf_eip; regs->r_cs = tp->tf_cs; regs->r_eflags = tp->tf_eflags; regs->r_esp = tp->tf_esp; regs->r_ss = tp->tf_ss; return (0); } int set_regs(struct thread *td, struct reg *regs) { struct pcb *pcb; struct trapframe *tp; tp = td->td_frame; if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); pcb = td->td_pcb; tp->tf_fs = regs->r_fs; tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; tp->tf_edi = regs->r_edi; tp->tf_esi = regs->r_esi; tp->tf_ebp = regs->r_ebp; tp->tf_ebx = regs->r_ebx; tp->tf_edx = regs->r_edx; tp->tf_ecx = regs->r_ecx; tp->tf_eax = regs->r_eax; tp->tf_eip = regs->r_eip; tp->tf_cs = regs->r_cs; tp->tf_eflags = regs->r_eflags; tp->tf_esp = regs->r_esp; tp->tf_ss = regs->r_ss; pcb->pcb_gs = regs->r_gs; return (0); } int fill_fpregs(struct thread *td, struct fpreg *fpregs) { KASSERT(td == curthread || TD_IS_SUSPENDED(td) || P_SHOULDSTOP(td->td_proc), ("not suspended thread %p", td)); #ifdef DEV_NPX npxgetregs(td); #else bzero(fpregs, sizeof(*fpregs)); #endif #ifdef CPU_ENABLE_SSE if (cpu_fxsr) npx_fill_fpregs_xmm(&get_pcb_user_save_td(td)->sv_xmm, (struct save87 *)fpregs); else #endif /* CPU_ENABLE_SSE */ bcopy(&get_pcb_user_save_td(td)->sv_87, fpregs, sizeof(*fpregs)); return (0); } int set_fpregs(struct thread *td, struct fpreg *fpregs) { #ifdef CPU_ENABLE_SSE if (cpu_fxsr) npx_set_fpregs_xmm((struct save87 *)fpregs, &get_pcb_user_save_td(td)->sv_xmm); else #endif /* CPU_ENABLE_SSE */ bcopy(fpregs, &get_pcb_user_save_td(td)->sv_87, sizeof(*fpregs)); #ifdef DEV_NPX npxuserinited(td); #endif return (0); } /* * Get machine context. */ int get_mcontext(struct thread *td, mcontext_t *mcp, int flags) { struct trapframe *tp; struct segment_descriptor *sdp; tp = td->td_frame; PROC_LOCK(curthread->td_proc); mcp->mc_onstack = sigonstack(tp->tf_esp); PROC_UNLOCK(curthread->td_proc); mcp->mc_gs = td->td_pcb->pcb_gs; mcp->mc_fs = tp->tf_fs; mcp->mc_es = tp->tf_es; mcp->mc_ds = tp->tf_ds; mcp->mc_edi = tp->tf_edi; mcp->mc_esi = tp->tf_esi; mcp->mc_ebp = tp->tf_ebp; mcp->mc_isp = tp->tf_isp; mcp->mc_eflags = tp->tf_eflags; if (flags & GET_MC_CLEAR_RET) { mcp->mc_eax = 0; mcp->mc_edx = 0; mcp->mc_eflags &= ~PSL_C; } else { mcp->mc_eax = tp->tf_eax; mcp->mc_edx = tp->tf_edx; } mcp->mc_ebx = tp->tf_ebx; mcp->mc_ecx = tp->tf_ecx; mcp->mc_eip = tp->tf_eip; mcp->mc_cs = tp->tf_cs; mcp->mc_esp = tp->tf_esp; mcp->mc_ss = tp->tf_ss; mcp->mc_len = sizeof(*mcp); get_fpcontext(td, mcp, NULL, 0); sdp = &td->td_pcb->pcb_fsd; mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase; sdp = &td->td_pcb->pcb_gsd; mcp->mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase; mcp->mc_flags = 0; mcp->mc_xfpustate = 0; mcp->mc_xfpustate_len = 0; bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2)); return (0); } /* * Set machine context. * * However, we don't set any but the user modifiable flags, and we won't * touch the cs selector. */ int set_mcontext(struct thread *td, mcontext_t *mcp) { struct trapframe *tp; char *xfpustate; int eflags, ret; tp = td->td_frame; if (mcp->mc_len != sizeof(*mcp) || (mcp->mc_flags & ~_MC_FLAG_MASK) != 0) return (EINVAL); eflags = (mcp->mc_eflags & PSL_USERCHANGE) | (tp->tf_eflags & ~PSL_USERCHANGE); if (mcp->mc_flags & _MC_HASFPXSTATE) { if (mcp->mc_xfpustate_len > cpu_max_ext_state_size - sizeof(union savefpu)) return (EINVAL); xfpustate = __builtin_alloca(mcp->mc_xfpustate_len); ret = copyin((void *)mcp->mc_xfpustate, xfpustate, mcp->mc_xfpustate_len); if (ret != 0) return (ret); } else xfpustate = NULL; ret = set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); if (ret != 0) return (ret); tp->tf_fs = mcp->mc_fs; tp->tf_es = mcp->mc_es; tp->tf_ds = mcp->mc_ds; tp->tf_edi = mcp->mc_edi; tp->tf_esi = mcp->mc_esi; tp->tf_ebp = mcp->mc_ebp; tp->tf_ebx = mcp->mc_ebx; tp->tf_edx = mcp->mc_edx; tp->tf_ecx = mcp->mc_ecx; tp->tf_eax = mcp->mc_eax; tp->tf_eip = mcp->mc_eip; tp->tf_eflags = eflags; tp->tf_esp = mcp->mc_esp; tp->tf_ss = mcp->mc_ss; td->td_pcb->pcb_gs = mcp->mc_gs; return (0); } static void get_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpusave, size_t xfpusave_len) { #ifdef CPU_ENABLE_SSE size_t max_len, len; #endif #ifndef DEV_NPX mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; bzero(mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); #else mcp->mc_ownedfp = npxgetregs(td); bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0], sizeof(mcp->mc_fpstate)); mcp->mc_fpformat = npxformat(); #ifdef CPU_ENABLE_SSE if (!use_xsave || xfpusave_len == 0) return; max_len = cpu_max_ext_state_size - sizeof(union savefpu); len = xfpusave_len; if (len > max_len) { len = max_len; bzero(xfpusave + max_len, len - max_len); } mcp->mc_flags |= _MC_HASFPXSTATE; mcp->mc_xfpustate_len = len; bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len); #endif #endif } static int set_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpustate, size_t xfpustate_len) { union savefpu *fpstate; int error; if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); else if (mcp->mc_fpformat != _MC_FPFMT_387 && mcp->mc_fpformat != _MC_FPFMT_XMM) return (EINVAL); else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) { /* We don't care what state is left in the FPU or PCB. */ fpstate_drop(td); error = 0; } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || mcp->mc_ownedfp == _MC_FPOWNED_PCB) { #ifdef DEV_NPX fpstate = (union savefpu *)&mcp->mc_fpstate; #ifdef CPU_ENABLE_SSE if (cpu_fxsr) fpstate->sv_xmm.sv_env.en_mxcsr &= cpu_mxcsr_mask; #endif error = npxsetregs(td, fpstate, xfpustate, xfpustate_len); #else error = EINVAL; #endif } else return (EINVAL); return (error); } static void fpstate_drop(struct thread *td) { KASSERT(PCB_USER_FPU(td->td_pcb), ("fpstate_drop: kernel-owned fpu")); critical_enter(); #ifdef DEV_NPX if (PCPU_GET(fpcurthread) == td) npxdrop(); #endif /* * XXX force a full drop of the npx. The above only drops it if we * owned it. npxgetregs() has the same bug in the !cpu_fxsr case. * * XXX I don't much like npxgetregs()'s semantics of doing a full * drop. Dropping only to the pcb matches fnsave's behaviour. * We only need to drop to !PCB_INITDONE in sendsig(). But * sendsig() is the only caller of npxgetregs()... perhaps we just * have too many layers. */ curthread->td_pcb->pcb_flags &= ~(PCB_NPXINITDONE | PCB_NPXUSERINITDONE); critical_exit(); } int fill_dbregs(struct thread *td, struct dbreg *dbregs) { struct pcb *pcb; if (td == NULL) { dbregs->dr[0] = rdr0(); dbregs->dr[1] = rdr1(); dbregs->dr[2] = rdr2(); dbregs->dr[3] = rdr3(); dbregs->dr[4] = rdr4(); dbregs->dr[5] = rdr5(); dbregs->dr[6] = rdr6(); dbregs->dr[7] = rdr7(); } else { pcb = td->td_pcb; dbregs->dr[0] = pcb->pcb_dr0; dbregs->dr[1] = pcb->pcb_dr1; dbregs->dr[2] = pcb->pcb_dr2; dbregs->dr[3] = pcb->pcb_dr3; dbregs->dr[4] = 0; dbregs->dr[5] = 0; dbregs->dr[6] = pcb->pcb_dr6; dbregs->dr[7] = pcb->pcb_dr7; } return (0); } int set_dbregs(struct thread *td, struct dbreg *dbregs) { struct pcb *pcb; int i; if (td == NULL) { load_dr0(dbregs->dr[0]); load_dr1(dbregs->dr[1]); load_dr2(dbregs->dr[2]); load_dr3(dbregs->dr[3]); load_dr4(dbregs->dr[4]); load_dr5(dbregs->dr[5]); load_dr6(dbregs->dr[6]); load_dr7(dbregs->dr[7]); } else { /* * Don't let an illegal value for dr7 get set. Specifically, * check for undefined settings. Setting these bit patterns * result in undefined behaviour and can lead to an unexpected * TRCTRAP. */ for (i = 0; i < 4; i++) { if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02) return (EINVAL); if (DBREG_DR7_LEN(dbregs->dr[7], i) == 0x02) return (EINVAL); } pcb = td->td_pcb; /* * Don't let a process set a breakpoint that is not within the * process's address space. If a process could do this, it * could halt the system by setting a breakpoint in the kernel * (if ddb was enabled). Thus, we need to check to make sure * that no breakpoints are being enabled for addresses outside * process's address space. * * XXX - what about when the watched area of the user's * address space is written into from within the kernel * ... wouldn't that still cause a breakpoint to be generated * from within kernel mode? */ if (DBREG_DR7_ENABLED(dbregs->dr[7], 0)) { /* dr0 is enabled */ if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS) return (EINVAL); } if (DBREG_DR7_ENABLED(dbregs->dr[7], 1)) { /* dr1 is enabled */ if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS) return (EINVAL); } if (DBREG_DR7_ENABLED(dbregs->dr[7], 2)) { /* dr2 is enabled */ if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS) return (EINVAL); } if (DBREG_DR7_ENABLED(dbregs->dr[7], 3)) { /* dr3 is enabled */ if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS) return (EINVAL); } pcb->pcb_dr0 = dbregs->dr[0]; pcb->pcb_dr1 = dbregs->dr[1]; pcb->pcb_dr2 = dbregs->dr[2]; pcb->pcb_dr3 = dbregs->dr[3]; pcb->pcb_dr6 = dbregs->dr[6]; pcb->pcb_dr7 = dbregs->dr[7]; pcb->pcb_flags |= PCB_DBREGS; } return (0); } /* * Return > 0 if a hardware breakpoint has been hit, and the * breakpoint was in user space. Return 0, otherwise. */ int user_dbreg_trap(void) { u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */ u_int32_t bp; /* breakpoint bits extracted from dr6 */ int nbp; /* number of breakpoints that triggered */ caddr_t addr[4]; /* breakpoint addresses */ int i; dr7 = rdr7(); if ((dr7 & 0x000000ff) == 0) { /* * all GE and LE bits in the dr7 register are zero, * thus the trap couldn't have been caused by the * hardware debug registers */ return 0; } nbp = 0; dr6 = rdr6(); bp = dr6 & 0x0000000f; if (!bp) { /* * None of the breakpoint bits are set meaning this * trap was not caused by any of the debug registers */ return 0; } /* * at least one of the breakpoints were hit, check to see * which ones and if any of them are user space addresses */ if (bp & 0x01) { addr[nbp++] = (caddr_t)rdr0(); } if (bp & 0x02) { addr[nbp++] = (caddr_t)rdr1(); } if (bp & 0x04) { addr[nbp++] = (caddr_t)rdr2(); } if (bp & 0x08) { addr[nbp++] = (caddr_t)rdr3(); } for (i = 0; i < nbp; i++) { if (addr[i] < (caddr_t)VM_MAXUSER_ADDRESS) { /* * addr[i] is in user space */ return nbp; } } /* * None of the breakpoints are in user space. */ return 0; } #ifdef KDB /* * Provide inb() and outb() as functions. They are normally only available as * inline functions, thus cannot be called from the debugger. */ /* silence compiler warnings */ u_char inb_(u_short); void outb_(u_short, u_char); u_char inb_(u_short port) { return inb(port); } void outb_(u_short port, u_char data) { outb(port, data); } #endif /* KDB */ Index: projects/clang390-import/sys/modules/Makefile =================================================================== --- projects/clang390-import/sys/modules/Makefile (revision 304964) +++ projects/clang390-import/sys/modules/Makefile (revision 304965) @@ -1,798 +1,798 @@ # $FreeBSD$ SYSDIR?=${.CURDIR}/.. .include "${SYSDIR}/conf/kern.opts.mk" SUBDIR_PARALLEL= # Modules that include binary-only blobs of microcode should be selectable by # MK_SOURCELESS_UCODE option (see below). .if defined(MODULES_OVERRIDE) && !defined(ALL_MODULES) SUBDIR=${MODULES_OVERRIDE} .else SUBDIR= \ ${_3dfx} \ ${_3dfx_linux} \ ${_aac} \ ${_aacraid} \ accf_data \ accf_dns \ accf_http \ acl_nfs4 \ acl_posix1e \ ${_acpi} \ ae \ ${_aesni} \ age \ ${_agp} \ aha \ ${_ahb} \ ahci \ ${_aic} \ aic7xxx \ alc \ ale \ alq \ ${_amdsbwd} \ ${_amdtemp} \ amr \ ${_an} \ ${_aout} \ ${_apm} \ ${_arcmsr} \ ${_arcnet} \ ${_asmc} \ ata \ ath \ ath_pci \ ${_autofs} \ ${_auxio} \ ${_bce} \ bfe \ bhnd \ bge \ bhnd \ ${_bxe} \ ${_bios} \ ${_bktr} \ ${_bm} \ bridgestp \ bwi \ bwn \ bwn_pci \ cam \ ${_canbepm} \ ${_canbus} \ ${_cardbus} \ ${_carp} \ cas \ ${_cbb} \ cc \ cd9660 \ cd9660_iconv \ ${_ce} \ ${_cfi} \ ${_ciss} \ cloudabi \ ${_cloudabi32} \ ${_cloudabi64} \ ${_cm} \ ${_cmx} \ ${_coff} \ ${_coretemp} \ ${_cp} \ ${_cpsw} \ ${_cpuctl} \ ${_cpufreq} \ ${_crypto} \ ${_cryptodev} \ ${_cs} \ ${_ct} \ ${_ctau} \ ctl \ ${_cxgb} \ ${_cxgbe} \ dc \ dcons \ dcons_crom \ de \ ${_dpms} \ ${_dpt} \ ${_drm} \ ${_drm2} \ dummynet \ ${_ed} \ ${_elink} \ ${_em} \ en \ ${_ep} \ ${_epic} \ esp \ ${_et} \ ${_ex} \ ${_exca} \ ext2fs \ ${_fatm} \ fdc \ fdescfs \ ${_fe} \ filemon \ firewire \ firmware \ fuse \ ${_fxp} \ gem \ geom \ ${_glxiic} \ ${_glxsb} \ gpio \ hatm \ hifn \ hme \ ${_hpt27xx} \ ${_hptiop} \ ${_hptmv} \ ${_hptnr} \ ${_hptrr} \ hwpmc \ ${_hyperv} \ i2c \ ${_ibcore} \ ${_ibcs2} \ ${_ichwd} \ ${_ida} \ if_bridge \ if_disc \ if_edsc \ ${_if_enc} \ if_epair \ ${_if_gif} \ ${_if_gre} \ ${_if_me} \ if_lagg \ ${_if_ndis} \ ${_if_stf} \ if_tap \ if_tun \ if_vlan \ if_vxlan \ ${_igb} \ ${_iir} \ imgact_binmisc \ ${_io} \ ${_ioat} \ ${_ipoib} \ ${_ipdivert} \ ${_ipfilter} \ ${_ipfw} \ ipfw_nat \ ${_ipfw_nat64} \ ${_ipfw_nptv6} \ ${_ipmi} \ ip6_mroute_mod \ ip_mroute_mod \ ${_ips} \ ${_ipw} \ ${_ipwfw} \ ${_isci} \ ${_iser} \ isp \ ${_ispfw} \ ${_iwi} \ ${_iwifw} \ ${_iwm} \ ${_iwmfw} \ ${_iwn} \ ${_iwnfw} \ ${_ix} \ ${_ixv} \ ${_ixgb} \ ${_ixl} \ ${_ixlv} \ jme \ joy \ kbdmux \ kgssapi \ kgssapi_krb5 \ khelp \ krpc \ ksyms \ le \ lge \ libalias \ libiconv \ libmbpool \ libmchain \ ${_linprocfs} \ ${_linsysfs} \ ${_linux} \ ${_linux_common} \ ${_linux64} \ linuxkpi \ lmc \ lpt \ mac_biba \ mac_bsdextended \ mac_ifoff \ mac_lomac \ mac_mls \ mac_none \ mac_partition \ mac_portacl \ mac_seeotheruids \ mac_stub \ mac_test \ malo \ md \ mdio \ mem \ mfi \ mii \ mlx \ ${_mlx4} \ ${_mlx4ib} \ ${_mlxen} \ ${_mlx5} \ ${_mlx5en} \ ${_mly} \ mmc \ mmcsd \ mpr \ mps \ mpt \ mqueue \ mrsas \ msdosfs \ msdosfs_iconv \ ${_mse} \ msk \ ${_mthca} \ mvs \ mwl \ ${_mwlfw} \ mxge \ my \ ${_nandfs} \ ${_nandsim} \ ${_ncr} \ ${_nctgpio} \ ${_ncv} \ ${_ndis} \ netfpga10g \ ${_netgraph} \ ${_nfe} \ nfscl \ nfscommon \ nfsd \ nfslock \ nfslockd \ nfssvc \ nge \ nmdm \ ${_nsp} \ nullfs \ ${_ntb} \ ${_nvd} \ ${_nvme} \ ${_nvram} \ ${_nxge} \ oce \ otus \ ${_otusfw} \ ow \ ${_padlock} \ ${_padlock_rng} \ patm \ ${_pccard} \ ${_pcfclock} \ pcn \ ${_pf} \ ${_pflog} \ ${_pfsync} \ plip \ ${_pmc} \ ${_pms} \ ppbus \ ppc \ ppi \ pps \ procfs \ proto \ pseudofs \ ${_pst} \ pty \ puc \ ${_qlxge} \ ${_qlxgb} \ ${_qlxgbe} \ ral \ ${_ralfw} \ ${_random_fortuna} \ ${_random_yarrow} \ ${_random_other} \ rc4 \ ${_rdma} \ ${_rdrand_rng} \ re \ rl \ rtwn \ ${_rtwnfw} \ ${_s3} \ ${_safe} \ ${_sbni} \ scc \ ${_scsi_low} \ sdhci \ sdhci_pci \ sem \ send \ ${_sf} \ ${_sfxge} \ sge \ siba_bwn \ siftr \ siis \ sis \ sk \ smbfs \ sn \ ${_snc} \ snp \ sound \ ${_speaker} \ ${_splash} \ ${_sppp} \ ste \ ${_stg} \ stge \ ${_streams} \ ${_svr4} \ ${_sym} \ ${_syscons} \ sysvipc \ ${_ti} \ ${_tcp_fastpath} \ tests/framework \ tests/callout_test \ tl \ tmpfs \ ${_toecore} \ ${_tpm} \ trm \ ${_twa} \ twe \ tws \ tx \ ${_txp} \ uart \ ubsec \ udf \ udf_iconv \ ufs \ unionfs \ urtwn \ ${_urtwnfw} \ usb \ utopia \ ${_vesa} \ ${_virtio} \ vge \ ${_viawd} \ videomode \ vkbd \ ${_vmm} \ ${_vmware} \ ${_vpo} \ vr \ vte \ vx \ ${_vxge} \ wb \ ${_wbwd} \ ${_wi} \ wlan \ wlan_acl \ wlan_amrr \ wlan_ccmp \ wlan_rssadapt \ wlan_tkip \ wlan_wep \ wlan_xauth \ ${_wpi} \ ${_wpifw} \ ${_x86bios} \ ${_xe} \ xl \ zlib .if ${MK_AUTOFS} != "no" || defined(ALL_MODULES) _autofs= autofs .endif .if ${MK_CDDL} != "no" || defined(ALL_MODULES) .if (${MACHINE_CPUARCH} != "arm" || ${MACHINE_ARCH:Marmv6*} != "") && \ ${MACHINE_CPUARCH} != "mips" && \ ${MACHINE_CPUARCH} != "sparc64" SUBDIR+= dtrace .endif SUBDIR+= opensolaris .endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${.CURDIR}/../opencrypto) _crypto= crypto _cryptodev= cryptodev _random_fortuna=random_fortuna _random_yarrow= random_yarrow _random_other= random_other .endif .endif .if ${MK_CUSE} != "no" || defined(ALL_MODULES) SUBDIR+= cuse .endif .if ${MK_EXTRA_TCP_STACKS} != "no" || defined(ALL_MODULES) _tcp_fastpath= tcp/fastpath .endif .if (${MK_INET_SUPPORT} != "no" || ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _carp= carp _toecore= toecore _if_enc= if_enc _if_gif= if_gif _if_gre= if_gre .endif .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _if_stf= if_stf .endif .if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES) _if_me= if_me _ipdivert= ipdivert _ipfw= ipfw .if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) _ipfw_nat64= ipfw_nat64 .endif .endif .if ${MK_INET6_SUPPORT} != "no" || defined(ALL_MODULES) _ipfw_nptv6= ipfw_nptv6 .endif .if ${MK_IPFILTER} != "no" || defined(ALL_MODULES) _ipfilter= ipfilter .endif .if ${MK_ISCSI} != "no" || defined(ALL_MODULES) SUBDIR+= iscsi SUBDIR+= iscsi_initiator .endif .if ${MK_NAND} != "no" || defined(ALL_MODULES) _nandfs= nandfs _nandsim= nandsim .endif .if ${MK_NETGRAPH} != "no" || defined(ALL_MODULES) _netgraph= netgraph .endif .if (${MK_PF} != "no" && (${MK_INET_SUPPORT} != "no" || \ ${MK_INET6_SUPPORT} != "no")) || defined(ALL_MODULES) _pf= pf _pflog= pflog .if ${MK_INET_SUPPORT} != "no" _pfsync= pfsync .endif .endif .if ${MK_SOURCELESS_UCODE} != "no" _bce= bce _fatm= fatm _fxp= fxp _ispfw= ispfw _mwlfw= mwlfw _otusfw= otusfw _ralfw= ralfw _rtwnfw= rtwnfw _urtwnfw= urtwnfw _sf= sf _ti= ti _txp= txp .endif .if ${MK_SOURCELESS_UCODE} != "no" && ${MACHINE_CPUARCH} != "arm" && \ ${MACHINE_CPUARCH} != "mips" && \ ${MACHINE_ARCH} != "powerpc" && ${MACHINE_CPUARCH} != "riscv" _cxgbe= cxgbe .endif .if ${MK_ZFS} != "no" || defined(ALL_MODULES) SUBDIR+= zfs .endif .if ${MACHINE_CPUARCH} != "aarch64" && ${MACHINE_CPUARCH} != "arm" && \ ${MACHINE_CPUARCH} != "mips" && ${MACHINE_CPUARCH} != "powerpc" && \ ${MACHINE_CPUARCH} != "riscv" _syscons= syscons _vpo= vpo .endif .if ${MACHINE_CPUARCH} != "mips" # no BUS_SPACE_UNSPECIFIED # No barrier instruction support (specific to this driver) _sym= sym # intr_disable() is a macro, causes problems .if ${MK_SOURCELESS_UCODE} != "no" _cxgb= cxgb .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" _em= em _igb= igb .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _agp= agp _an= an _aout= aout _bktr= bktr _bxe= bxe _cardbus= cardbus _cbb= cbb _cpuctl= cpuctl _cpufreq= cpufreq _cs= cs _dpms= dpms _drm= drm _drm2= drm2 _ed= ed _em= em _ep= ep _et= et _exca= exca _fe= fe .if ${MK_OFED} != "no" || defined(ALL_MODULES) _ibcore= ibcore .endif _if_ndis= if_ndis _igb= igb _io= io .if ${MK_OFED} != "no" || defined(ALL_MODULES) _ipoib= ipoib _iser= iser .endif _ix= ix _ixv= ixv _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux _nctgpio= nctgpio _ndis= ndis _pccard= pccard .if ${MK_OFED} != "no" || defined(ALL_MODULES) _rdma= rdma .endif _safe= safe _scsi_low= scsi_low _speaker= speaker _splash= splash _sppp= sppp _vmware= vmware _vxge= vxge _wbwd= wbwd _wi= wi _xe= xe .if ${MACHINE} != "pc98" _aac= aac _aacraid= aacraid _acpi= acpi .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _aesni= aesni .endif _amdsbwd= amdsbwd _amdtemp= amdtemp _arcmsr= arcmsr _asmc= asmc _ciss= ciss _cmx= cmx _coretemp= coretemp .if ${MK_SOURCELESS_HOST} != "no" _hpt27xx= hpt27xx .endif _hptiop= hptiop .if ${MK_SOURCELESS_HOST} != "no" _hptmv= hptmv _hptnr= hptnr _hptrr= hptrr .endif _hyperv= hyperv _ichwd= ichwd _ida= ida _iir= iir _ipmi= ipmi _ips= ips _isci= isci _ipw= ipw _iwi= iwi _iwm= iwm _iwn= iwn _ixgb= ixgb .if ${MK_SOURCELESS_UCODE} != "no" _ipwfw= ipwfw _iwifw= iwifw _iwmfw= iwmfw _iwnfw= iwnfw .endif .if ${MK_OFED} != "no" || defined(ALL_MODULES) _mlx4= mlx4 _mlx4ib= mlx4ib _mlxen= mlxen .endif _mlx5= mlx5 .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _mlx5en= mlx5en .endif _mly= mly .if ${MK_OFED} != "no" || defined(ALL_MODULES) _mthca= mthca .endif _nfe= nfe _nvd= nvd _nvme= nvme _nvram= nvram _nxge= nxge .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _padlock= padlock _padlock_rng= padlock_rng _rdrand_rng= rdrand_rng .endif _s3= s3 _tpm= tpm _twa= twa _vesa= vesa _viawd= viawd _virtio= virtio _wpi= wpi .if ${MK_SOURCELESS_UCODE} != "no" _wpifw= wpifw .endif _x86bios= x86bios .endif .endif .if ${MACHINE_CPUARCH} == "amd64" _ioat= ioat _ixl= ixl _ixlv= ixlv _linux64= linux64 _linux_common= linux_common _ntb= ntb _pms= pms _qlxge= qlxge _qlxgb= qlxgb _qlxgbe= qlxgbe _sfxge= sfxge .if ${MK_BHYVE} != "no" || defined(ALL_MODULES) _vmm= vmm .endif .endif .if ${MACHINE_CPUARCH} == "i386" # XXX some of these can move to the general case when de-i386'ed # XXX some of these can move now, but are untested on other architectures. _3dfx= 3dfx _3dfx_linux= 3dfx_linux _aic= aic _apm= apm _arcnet= arcnet .if ${MK_SOURCELESS_UCODE} != "no" _ce= ce .endif _coff= coff .if ${MK_SOURCELESS_UCODE} != "no" _cp= cp .endif _elink= elink _glxiic= glxiic _glxsb= glxsb #_ibcs2= ibcs2 _mse= mse _ncr= ncr _ncv= ncv _nsp= nsp _pcfclock= pcfclock _pst= pst _sbni= sbni _streams= streams _stg= stg _svr4= svr4 .if ${MACHINE} == "i386" .if ${MK_EISA} != "no" _ahb= ahb .endif _bios= bios _cm= cm .if ${MK_SOURCELESS_UCODE} != "no" _ctau= ctau .endif _dpt= dpt _ex= ex .elif ${MACHINE} == "pc98" _canbepm= canbepm _canbus= canbus _ct= ct _pmc= pmc _snc= snc .endif .endif .if ${MACHINE_CPUARCH} == "arm" _cfi= cfi _cpsw= cpsw .endif .if ${MACHINE_CPUARCH} == "powerpc" _agp= agp _an= an _bm= bm _cardbus= cardbus _cbb= cbb _cfi= cfi _cpufreq= cpufreq _drm= drm _exca= exca _nvram= powermac_nvram _pccard= pccard _wi= wi .endif .if ${MACHINE_ARCH} == "powerpc64" _drm2= drm2 .endif .if ${MACHINE_CPUARCH} == "sparc64" _auxio= auxio _em= em _epic= epic _igb= igb .endif -.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE} == "i386" +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" _cloudabi32= cloudabi32 .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" _cloudabi64= cloudabi64 .endif .endif SUBDIR+=${MODULES_EXTRA} .for reject in ${WITHOUT_MODULES} SUBDIR:= ${SUBDIR:N${reject}} .endfor # Calling kldxref(8) for each module is expensive. .if !defined(NO_XREF) .MAKEFLAGS+= -DNO_XREF afterinstall: .PHONY @if type kldxref >/dev/null 2>&1; then \ ${ECHO} kldxref ${DESTDIR}${KMODDIR}; \ kldxref ${DESTDIR}${KMODDIR}; \ fi .endif .include "${SYSDIR}/conf/config.mk" SUBDIR:= ${SUBDIR:u:O} .include Index: projects/clang390-import =================================================================== --- projects/clang390-import (revision 304964) +++ projects/clang390-import (revision 304965) Property changes on: projects/clang390-import ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r304955-304964