From 905c80cf7114db560fe45eaddc09be28b92aded2 Mon Sep 17 00:00:00 2001 From: ngie Date: Tue, 29 Dec 2015 20:17:40 +0000 Subject: [PATCH 01/55] Fix getopt(3) argument after r290180; I forgot to change -r to -R by accident MFC after: 3 days Pointyhat to: ngie Reported by: vangyzen Sponsored by: EMC / Isilon Storage Division --- usr.sbin/makefs/makefs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c index 79cffed5f316..a7ca75195b41 100644 --- a/usr.sbin/makefs/makefs.c +++ b/usr.sbin/makefs/makefs.c @@ -116,7 +116,7 @@ main(int argc, char *argv[]) start_time.tv_sec = start.tv_sec; start_time.tv_nsec = start.tv_usec * 1000; - while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:pr:s:S:t:xZ")) != -1) { + while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:pR:s:S:t:xZ")) != -1) { switch (ch) { case 'B': From d5b4026ea636cfe11667663b94ad58f07a9698d3 Mon Sep 17 00:00:00 2001 From: jilles Date: Tue, 29 Dec 2015 20:51:29 +0000 Subject: [PATCH 02/55] sh: Split subevalvar() in #/##/%/%% and =/? parts. --- bin/sh/expand.c | 73 ++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 621798275bb1..c876abb8028b 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -101,7 +101,8 @@ static char *argstr(char *, int); static char *exptilde(char *, int); static char *expari(char *); static void expbackq(union node *, int, int); -static int subevalvar(char *, char *, int, int, int, int, int); +static int subevalvar_trim(char *, int, int, int, int); +static int subevalvar_misc(char *, const char *, int, int, int); static char *evalvar(char *, int); static int varisset(const char *, int); static void strtodest(const char *, int, int, int); @@ -521,42 +522,23 @@ recordleft(const char *str, const char *loc, char *startp) } static int -subevalvar(char *p, char *str, int strloc, int subtype, int startloc, - int varflags, int quotes) +subevalvar_trim(char *p, int strloc, int subtype, int startloc, int quotes) { char *startp; char *loc = NULL; char *q; + char *str; int c = 0; struct nodelist *saveargbackq = argbackq; int amount; - argstr(p, (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX || - subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX ? - EXP_CASE : 0) | EXP_TILDE); + argstr(p, EXP_CASE | EXP_TILDE); STACKSTRNUL(expdest); argbackq = saveargbackq; startp = stackblock() + startloc; - if (str == NULL) - str = stackblock() + strloc; + str = stackblock() + strloc; switch (subtype) { - case VSASSIGN: - setvar(str, startp, 0); - amount = startp - expdest; - STADJUST(amount, expdest); - varflags &= ~VSNUL; - return 1; - - case VSQUESTION: - if (*p != CTLENDVAR) { - outfmt(out2, "%s\n", startp); - error((char *)NULL); - } - error("%.*s: parameter %snot set", (int)(p - str - 1), - str, (varflags & VSNUL) ? "null or " : ""); - return 0; - case VSTRIMLEFT: for (loc = startp; loc < str; loc++) { c = *loc; @@ -630,6 +612,41 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, } +static int +subevalvar_misc(char *p, const char *var, int subtype, int startloc, + int varflags) +{ + char *startp; + struct nodelist *saveargbackq = argbackq; + int amount; + + argstr(p, EXP_TILDE); + STACKSTRNUL(expdest); + argbackq = saveargbackq; + startp = stackblock() + startloc; + + switch (subtype) { + case VSASSIGN: + setvar(var, startp, 0); + amount = startp - expdest; + STADJUST(amount, expdest); + return 1; + + case VSQUESTION: + if (*p != CTLENDVAR) { + outfmt(out2, "%s\n", startp); + error((char *)NULL); + } + error("%.*s: parameter %snot set", (int)(p - var - 1), + var, (varflags & VSNUL) ? "null or " : ""); + return 0; + + default: + abort(); + } +} + + /* * Expand a variable, and return a pointer to the next character in the * input string. @@ -760,8 +777,8 @@ again: /* jump here after setting a variable with ${var=text} */ */ STPUTC('\0', expdest); patloc = expdest - stackblock(); - if (subevalvar(p, NULL, patloc, subtype, - startloc, varflags, quotes) == 0) { + if (subevalvar_trim(p, patloc, subtype, + startloc, quotes) == 0) { int amount = (expdest - stackblock() - patloc) + 1; STADJUST(-amount, expdest); } @@ -773,8 +790,8 @@ again: /* jump here after setting a variable with ${var=text} */ case VSASSIGN: case VSQUESTION: if (!set) { - if (subevalvar(p, var, 0, subtype, startloc, varflags, - quotes)) { + if (subevalvar_misc(p, var, subtype, startloc, + varflags)) { varflags &= ~VSNUL; /* * Remove any recorded regions beyond From db615833324a17b469dc05ddf53af4a41f2f3636 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 29 Dec 2015 21:29:05 +0000 Subject: [PATCH 03/55] Fix the error checking for the ubenv command. This moves the check for an empty ldvar (which amounts to the varname string starting with '=') into the if block that manipulates ldvar, which avoids later referencing ldvar when it was never initialized. Submitted by: Thomas Skibo Pointy hat: ian --- sys/boot/uboot/common/main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c index 3071426b05c4..6c7b8932d10a 100644 --- a/sys/boot/uboot/common/main.c +++ b/sys/boot/uboot/common/main.c @@ -585,6 +585,10 @@ handle_uboot_env_var(enum ubenv_action action, const char * var) */ if (action == UBENV_IMPORT) { len = strcspn(var, "="); + if (len == 0) { + printf("name cannot start with '=': '%s'\n", var); + return; + } if (var[len] == 0) { strcpy(ldvar, "uboot."); strncat(ldvar, var, sizeof(ldvar) - 7); @@ -604,9 +608,11 @@ handle_uboot_env_var(enum ubenv_action action, const char * var) var = &var[6]; } - /* If ldvar is malformed or there's no variable name left, punt. */ - if (ldvar[0] == 0 || var[0] == 0) + /* If there is no variable name left, punt. */ + if (var[0] == 0) { + printf("empty variable name\n"); return; + } val = ub_env_get(var); if (action == UBENV_SHOW) { From 65cfa1c59dc578a57326c37542b1993012394bbb Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 29 Dec 2015 22:14:21 +0000 Subject: [PATCH 04/55] Add standard extended feature bit 6 from the Intel SDM rev. 57, which indicates that data-pointer in the saved x87 FPU state is only updated on FPU exceptions. Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/x86/include/specialreg.h | 1 + sys/x86/x86/identcpu.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h index b5274b29ca3c..5f2c01057ddb 100644 --- a/sys/x86/include/specialreg.h +++ b/sys/x86/include/specialreg.h @@ -335,6 +335,7 @@ #define CPUID_STDEXT_BMI1 0x00000008 #define CPUID_STDEXT_HLE 0x00000010 #define CPUID_STDEXT_AVX2 0x00000020 +#define CPUID_STDEXT_FDP_EXC 0x00000040 #define CPUID_STDEXT_SMEP 0x00000080 #define CPUID_STDEXT_BMI2 0x00000100 #define CPUID_STDEXT_ERMS 0x00000200 diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c index 902af6b3d279..38c1c6617c12 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -932,6 +932,8 @@ printcpuinfo(void) "\005HLE" /* Advanced Vector Instructions 2 */ "\006AVX2" + /* FDP_EXCPTN_ONLY */ + "\007FDPEXC" /* Supervisor Mode Execution Prot. */ "\010SMEP" /* Bit Manipulation Instructions */ From a09b08770e93d15916c00c18e2f08878531c7ffc Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 29 Dec 2015 22:18:35 +0000 Subject: [PATCH 05/55] Bring some of the recent locore-v4.S improvements into locore-V6... - Map all 4GB as VA=PA so that args passed in from a bootloader can be accessed regardless of where they are. - Figure out the kernel load address by directly masking the PC rather then by doing pc-relative math on the _start symbol. - For EARLY_PRINTF support, map device memory as uncacheable (no-op for ARM_NEW_PMAP because all TEX types resolve to uncacheable). --- sys/arm/arm/locore-v6.S | 67 ++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index ac1990614025..b66b60183c61 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -153,46 +153,49 @@ ASENTRY_NP(_start) * Build page table from scratch. */ - /* Calculate the physical address of the startup pagetable. */ + /* + * Figure out the physical address we're loaded at by assuming this + * entry point code is in the first L1 section and so if we clear the + * offset bits of the pc that will give us the section-aligned load + * address, which remains in r5 throughout all the following code. + */ + ldr r2, =(L1_S_OFFSET) + bic r5, pc, r2 + + /* Find the delta between VA and PA, result stays in r0 throughout. */ adr r0, Lpagetable bl translate_va_to_pa - /* Clear boot page table */ - mov r1, r0 - mov r2, L1_TABLE_SIZE - mov r3,#0 -1: str r3, [r1], #4 - subs r2, #4 - bgt 1b - - /* - * Map PA == VA + /* + * First map the entire 4GB address space as VA=PA. It's mapped as + * normal (cached) memory because it's for things like accessing the + * parameters passed in from the bootloader, which might be at any + * physical address, different for every platform. + */ + mov r1, #0 + mov r2, #0 + mov r3, #4096 + bl build_pagetables + + /* + * Next we do 64MiB starting at the physical load address, mapped to + * the VA the kernel is linked for. */ - /* Find the start kernels load address */ - adr r5, _start - ldr r2, =(PTE1_OFFSET) - bic r5, r2 mov r1, r5 - mov r2, r5 - /* Map 64MiB, preserved over calls to build_pagetables */ + ldr r2, =(KERNVIRTADDR) mov r3, #64 bl build_pagetables - /* Create the kernel map to jump to */ - mov r1, r5 - ldr r2, =(KERNVIRTADDR) - bl build_pagetables - + /* Create a device mapping for early_printf if specified. */ #if defined(SOCDEV_PA) && defined(SOCDEV_VA) - /* Create the custom map (1MB) used for early_printf(). */ ldr r1, =SOCDEV_PA ldr r2, =SOCDEV_VA mov r3, #1 - bl build_pagetables + bl build_device_pagetables #endif bl init_mmu - /* Switch to virtual addresses. */ + /* Transition the PC from physical to virtual addressing. */ ldr pc, =1f 1: @@ -394,6 +397,15 @@ END(reinit_mmu) * * Addresses must be 1MiB aligned */ +build_device_pagetables: +#if defined(ARM_NEW_PMAP) + ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 +#elif defined(SMP) + ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED) +#else + ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)) +#endif + b 1f build_pagetables: /* Set the required page attributed */ #if defined(ARM_NEW_PMAP) @@ -403,18 +415,19 @@ build_pagetables: #else ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) #endif +1: orr r1, r4 /* Move the virtual address to the correct bit location */ lsr r2, #(PTE1_SHIFT - 2) mov r4, r3 -1: +2: str r1, [r0, r2] add r2, r2, #4 add r1, r1, #(PTE1_SIZE) adds r4, r4, #-1 - bhi 1b + bhi 2b mov pc, lr From 79ec12eeb6f427ceaaaa94ca98073316d8c24e47 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 29 Dec 2015 23:16:20 +0000 Subject: [PATCH 06/55] Call kern_thr_exit() instead of duplicating it. This code is missing the racct_subr() call from kern_thr_exit() and would require further code duplication in future changes. Reviewed by: kib MFC after: 1 week --- sys/kern/kern_thread.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index ac96ca504539..66b6120e194f 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -942,7 +943,6 @@ thread_suspend_check(int return_instead) */ if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) { PROC_UNLOCK(p); - tidhash_remove(td); /* * Allow Linux emulation layer to do some work @@ -950,13 +950,8 @@ thread_suspend_check(int return_instead) */ if (__predict_false(p->p_sysent->sv_thread_detach != NULL)) (p->p_sysent->sv_thread_detach)(td); - - PROC_LOCK(p); - tdsigcleanup(td); - umtx_thread_exit(td); - PROC_SLOCK(p); - thread_stopped(p); - thread_exit(); + kern_thr_exit(td); + panic("stopped thread did not exit"); } PROC_SLOCK(p); From fb5720f7be0d2eab3253696e244c058a229b5473 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 29 Dec 2015 23:25:26 +0000 Subject: [PATCH 07/55] Add ptrace(2) reporting for LWP events. Add two new LWPINFO flags: PL_FLAG_BORN and PL_FLAG_EXITED for reporting thread creation and destruction. Newly created threads will stop to report PL_FLAG_BORN before returning to userland and exiting threads will stop to report PL_FLAG_EXIT before exiting completely. Both of these events are only enabled and reported if PT_LWP_EVENTS is enabled on a process. --- sys/kern/kern_fork.c | 7 +- sys/kern/kern_sig.c | 7 +- sys/kern/kern_thr.c | 65 ++++++++---- sys/kern/sys_process.c | 15 +++ sys/sys/proc.h | 4 + sys/sys/ptrace.h | 3 + tests/sys/kern/ptrace_test.c | 193 +++++++++++++++++++++++++++++++++-- 7 files changed, 264 insertions(+), 30 deletions(-) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index a395fdd2b00d..e7d727619be0 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1066,7 +1066,7 @@ fork_return(struct thread *td, struct trapframe *frame) cv_broadcast(&p->p_dbgwait); } PROC_UNLOCK(p); - } else if (p->p_flag & P_TRACED) { + } else if (p->p_flag & P_TRACED || td->td_dbgflags & TDB_BORN) { /* * This is the start of a new thread in a traced * process. Report a system call exit event. @@ -1074,9 +1074,10 @@ fork_return(struct thread *td, struct trapframe *frame) PROC_LOCK(p); td->td_dbgflags |= TDB_SCX; _STOPEVENT(p, S_SCX, td->td_dbg_sc_code); - if ((p->p_stops & S_PT_SCX) != 0) + if ((p->p_stops & S_PT_SCX) != 0 || + (td->td_dbgflags & TDB_BORN) != 0) ptracestop(td, SIGTRAP); - td->td_dbgflags &= ~TDB_SCX; + td->td_dbgflags &= ~(TDB_SCX | TDB_BORN); PROC_UNLOCK(p); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 510b9205a581..75a125934204 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2501,7 +2501,12 @@ ptracestop(struct thread *td, int sig) td->td_tid, p->p_pid, td->td_dbgflags, sig); PROC_SLOCK(p); while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) { - if (p->p_flag & P_SINGLE_EXIT) { + if (p->p_flag & P_SINGLE_EXIT && + !(td->td_dbgflags & TDB_EXIT)) { + /* + * Ignore ptrace stops except for thread exit + * events when the process exits. + */ td->td_dbgflags &= ~TDB_XSIG; PROC_SUNLOCK(p); return (sig); diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 9e878d8dd7cb..1b226dd13cf3 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -253,6 +253,8 @@ thread_create(struct thread *td, struct rtprio *rtp, thread_unlock(td); if (P_SHOULDSTOP(p)) newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; + if (p->p_flag2 & P2_LWP_EVENTS) + newtd->td_dbgflags |= TDB_BORN; /* * Copy the existing thread VM policy into the new thread. @@ -322,29 +324,54 @@ kern_thr_exit(struct thread *td) p = td->td_proc; - rw_wlock(&tidhash_lock); + /* + * If all of the threads in a process call this routine to + * exit (e.g. all threads call pthread_exit()), exactly one + * thread should return to the caller to terminate the process + * instead of the thread. + * + * Checking p_numthreads alone is not sufficient since threads + * might be committed to terminating while the PROC_LOCK is + * dropped in either ptracestop() or while removing this thread + * from the tidhash. Instead, the p_pendingexits field holds + * the count of threads in either of those states and a thread + * is considered the "last" thread if all of the other threads + * in a process are already terminating. + */ PROC_LOCK(p); - - if (p->p_numthreads != 1) { - racct_sub(p, RACCT_NTHR, 1); - LIST_REMOVE(td, td_hash); - rw_wunlock(&tidhash_lock); - tdsigcleanup(td); - umtx_thread_exit(td); - PROC_SLOCK(p); - thread_stopped(p); - thread_exit(); - /* NOTREACHED */ + if (p->p_numthreads == p->p_pendingexits + 1) { + /* + * Ignore attempts to shut down last thread in the + * proc. This will actually call _exit(2) in the + * usermode trampoline when it returns. + */ + PROC_UNLOCK(p); + return (0); } - /* - * Ignore attempts to shut down last thread in the proc. This - * will actually call _exit(2) in the usermode trampoline when - * it returns. - */ + p->p_pendingexits++; + td->td_dbgflags |= TDB_EXIT; + if (p->p_flag & P_TRACED && p->p_flag2 & P2_LWP_EVENTS) + ptracestop(td, SIGTRAP); PROC_UNLOCK(p); - rw_wunlock(&tidhash_lock); - return (0); + tidhash_remove(td); + PROC_LOCK(p); + p->p_pendingexits--; + + /* + * The check above should prevent all other threads from this + * process from exiting while the PROC_LOCK is dropped, so + * there must be at least one other thread other than the + * current thread. + */ + KASSERT(p->p_numthreads > 1, ("too few threads")); + racct_sub(p, RACCT_NTHR, 1); + tdsigcleanup(td); + umtx_thread_exit(td); + PROC_SLOCK(p); + thread_stopped(p); + thread_exit(); + /* NOTREACHED */ } int diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 732d754469ce..a6037e38c72a 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -710,6 +710,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) case PT_TO_SCX: case PT_SYSCALL: case PT_FOLLOW_FORK: + case PT_LWP_EVENTS: case PT_DETACH: sx_xlock(&proctree_lock); proctree_locked = 1; @@ -948,6 +949,16 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) p->p_flag &= ~P_FOLLOWFORK; break; + case PT_LWP_EVENTS: + CTR3(KTR_PTRACE, "PT_LWP_EVENTS: pid %d %s -> %s", p->p_pid, + p->p_flag2 & P2_LWP_EVENTS ? "enabled" : "disabled", + data ? "enabled" : "disabled"); + if (data) + p->p_flag2 |= P2_LWP_EVENTS; + else + p->p_flag2 &= ~P2_LWP_EVENTS; + break; + case PT_STEP: case PT_CONTINUE: case PT_TO_SCE: @@ -1252,6 +1263,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) } if (td2->td_dbgflags & TDB_CHILD) pl->pl_flags |= PL_FLAG_CHILD; + if (td2->td_dbgflags & TDB_BORN) + pl->pl_flags |= PL_FLAG_BORN; + if (td2->td_dbgflags & TDB_EXIT) + pl->pl_flags |= PL_FLAG_EXITED; pl->pl_sigmask = td2->td_sigmask; pl->pl_siglist = td2->td_siglist; strcpy(pl->pl_tdname, td2->td_name); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index cb9431803422..fc5c90db2b4e 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -412,6 +412,8 @@ do { \ #define TDB_STOPATFORK 0x00000080 /* Stop at the return from fork (child only) */ #define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */ +#define TDB_BORN 0x00000200 /* New LWP indicator for ptrace() */ +#define TDB_EXIT 0x00000400 /* Exiting LWP indicator for ptrace() */ /* * "Private" flags kept in td_pflags: @@ -577,6 +579,7 @@ struct proc { struct itimers *p_itimers; /* (c) POSIX interval timers. */ struct procdesc *p_procdesc; /* (e) Process descriptor, if any. */ u_int p_treeflag; /* (e) P_TREE flags */ + int p_pendingexits; /* (c) Count of pending thread exits. */ /* End area that is zeroed on creation. */ #define p_endzero p_magic @@ -695,6 +698,7 @@ struct proc { #define P2_NOTRACE 0x00000002 /* No ptrace(2) attach or coredumps. */ #define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */ #define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */ +#define P2_LWP_EVENTS 0x00000010 /* Report LWP events via ptrace(2). */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index 7ccd3d6cd596..88a587efafb9 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -64,6 +64,7 @@ #define PT_SYSCALL 22 #define PT_FOLLOW_FORK 23 +#define PT_LWP_EVENTS 24 /* report LWP birth and exit */ #define PT_GETREGS 33 /* get general-purpose registers */ #define PT_SETREGS 34 /* set general-purpose registers */ @@ -108,6 +109,8 @@ struct ptrace_lwpinfo { #define PL_FLAG_SI 0x20 /* siginfo is valid */ #define PL_FLAG_FORKED 0x40 /* new child */ #define PL_FLAG_CHILD 0x80 /* I am from child */ +#define PL_FLAG_BORN 0x100 /* new LWP */ +#define PL_FLAG_EXITED 0x200 /* exiting LWP */ sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_siglist; /* LWP pending signal */ struct __siginfo pl_siginfo; /* siginfo for signal */ diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c index f6112217f6d9..177f412c14c3 100644 --- a/tests/sys/kern/ptrace_test.c +++ b/tests/sys/kern/ptrace_test.c @@ -1094,6 +1094,16 @@ simple_thread(void *arg __unused) pthread_exit(NULL); } +static __dead2 void +simple_thread_main(void) +{ + pthread_t thread; + + CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0); + CHILD_REQUIRE(pthread_join(thread, NULL) == 0); + exit(1); +} + /* * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new * thread reports the correct value. @@ -1108,14 +1118,8 @@ ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc) ATF_REQUIRE((fpid = fork()) != -1); if (fpid == 0) { - pthread_t thread; - trace_me(); - - CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, - NULL) == 0); - CHILD_REQUIRE(pthread_join(thread, NULL) == 0); - exit(1); + simple_thread_main(); } /* The first wait() should report the stop from SIGSTOP. */ @@ -1178,6 +1182,179 @@ ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc) ATF_REQUIRE(errno == ECHILD); } +/* + * Verify that the expected LWP events are reported for a child thread. + */ +ATF_TC_WITHOUT_HEAD(ptrace__lwp_events); +ATF_TC_BODY(ptrace__lwp_events, tc) +{ + struct ptrace_lwpinfo pl; + pid_t fpid, wpid; + lwpid_t lwps[2]; + int status; + + ATF_REQUIRE((fpid = fork()) != -1); + if (fpid == 0) { + trace_me(); + simple_thread_main(); + } + + /* The first wait() should report the stop from SIGSTOP. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, + sizeof(pl)) != -1); + lwps[0] = pl.pl_lwpid; + + ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); + + /* Continue the child ignoring the SIGSTOP. */ + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The first event should be for the child thread's birth. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == + (PL_FLAG_BORN | PL_FLAG_SCX)); + ATF_REQUIRE(pl.pl_lwpid != lwps[0]); + lwps[1] = pl.pl_lwpid; + + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The next event should be for the child thread's death. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) == + (PL_FLAG_EXITED | PL_FLAG_SCE)); + ATF_REQUIRE(pl.pl_lwpid == lwps[1]); + + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The last event should be for the child process's exit. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE(WEXITSTATUS(status) == 1); + + wpid = wait(&status); + ATF_REQUIRE(wpid == -1); + ATF_REQUIRE(errno == ECHILD); +} + +static void * +exec_thread(void *arg __unused) +{ + + execl("/usr/bin/true", "true", NULL); + exit(127); +} + +static __dead2 void +exec_thread_main(void) +{ + pthread_t thread; + + CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0); + for (;;) + sleep(60); + exit(1); +} + +/* + * Verify that the expected LWP events are reported for a multithreaded + * process that calls execve(2). + */ +ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec); +ATF_TC_BODY(ptrace__lwp_events_exec, tc) +{ + struct ptrace_lwpinfo pl; + pid_t fpid, wpid; + lwpid_t lwps[2]; + int status; + + ATF_REQUIRE((fpid = fork()) != -1); + if (fpid == 0) { + trace_me(); + exec_thread_main(); + } + + /* The first wait() should report the stop from SIGSTOP. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, + sizeof(pl)) != -1); + lwps[0] = pl.pl_lwpid; + + ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); + + /* Continue the child ignoring the SIGSTOP. */ + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The first event should be for the child thread's birth. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == + (PL_FLAG_BORN | PL_FLAG_SCX)); + ATF_REQUIRE(pl.pl_lwpid != lwps[0]); + lwps[1] = pl.pl_lwpid; + + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* + * The next event should be for the main thread's death due to + * single threading from execve(). + */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) == + (PL_FLAG_EXITED)); + ATF_REQUIRE(pl.pl_lwpid == lwps[0]); + + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The next event should be for the child process's exec. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) == + (PL_FLAG_EXEC | PL_FLAG_SCX)); + ATF_REQUIRE(pl.pl_lwpid == lwps[1]); + + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The last event should be for the child process's exit. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE(WEXITSTATUS(status) == 0); + + wpid = wait(&status); + ATF_REQUIRE(wpid == -1); + ATF_REQUIRE(errno == ECHILD); +} + ATF_TP_ADD_TCS(tp) { @@ -1197,6 +1374,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork); ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork); ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread); + ATF_TP_ADD_TC(tp, ptrace__lwp_events); + ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec); return (atf_no_error()); } From d4f8a20c6b14e759c306002f671aeb60d9d98687 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 30 Dec 2015 00:04:57 +0000 Subject: [PATCH 08/55] Document the recently added support for ptrace(2) LWP events. --- lib/libc/sys/ptrace.2 | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2 index a94e314d93cb..786f4576db9b 100644 --- a/lib/libc/sys/ptrace.2 +++ b/lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd October 20, 2015 +.Dd December 29, 2015 .Dt PTRACE 2 .Os .Sh NAME @@ -372,6 +372,20 @@ The flag is set for first event reported from a new child, which is automatically attached due to .Dv PT_FOLLOW_FORK enabled. +.It PL_FLAG_BORN +This flag is set for the first event reported from a new LWP when LWP +events are enabled via +.Dv PT_LWP_EVENTS . +It is reported along with +.Dv PL_FLAG_SCX +and is always reported if LWP events are enabled. +.It PL_FLAG_EXITED +This flag is set for the last event reported by an exiting LWP when +LWP events are enabled via +.Dv PT_LWP_EVENTS . +Note that this event is not reported when the last LWP in a process exits. +The termination of the last thread is reported via a normal process exit +event. .El .It pl_sigmask The current signal mask of the LWP @@ -463,6 +477,29 @@ Child processes do not inherit this property. The traced process will set the .Dv PL_FLAG_FORKED flag upon exit from a system call that creates a new process. +.It PT_LWP_EVENTS +This request controls tracing of LWP creation and destruction. +If +.Fa data +is non-zero, +then LWPs will stop to report creation and destruction events. +If +.Fa data +is zero, +then LWP creation and destruction events will not be reported. +By default, tracing is not enabled for LWP events. +Child processes do not inherit this property. +New LWPs will stop to report an event with +.Dv PL_FLAG_BORN +set before executing their first instruction. +Exiting LWPs will stop to report an event with +.Dv PL_FLAG_EXITED +set before completing their termination. +.Pp +Note that new processes do not report an event for the creation of their +initial thread, +and exiting processes do not report an event for the termination of the +last thread. .It PT_VM_TIMESTAMP This request returns the generation number or timestamp of the memory map of the traced process as the return value from From f051dcad0775edede26c36c576146167f312243b Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 30 Dec 2015 00:17:37 +0000 Subject: [PATCH 09/55] Adapt CATR() to r283283. --- sys/sparc64/include/ktr.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/sparc64/include/ktr.h b/sys/sparc64/include/ktr.h index 0a7f0e125367..0a7f233fe32c 100644 --- a/sys/sparc64/include/ktr.h +++ b/sys/sparc64/include/ktr.h @@ -74,9 +74,9 @@ l2: add r2, 1, r3 ; \ * NB: this clobbers %y. */ #define CATR(mask, desc, r1, r2, r3, l1, l2, l3) \ - set mask, r1 ; \ - SET(ktr_mask, r3, r2) ; \ - lduw [r2], r2 ; \ + setx mask, r3, r1 ; \ + setx ktr_mask, r3, r2 ; \ + ldx [r2], r2 ; \ and r2, r1, r1 ; \ brz r1, l3 ## f ; \ nop ; \ From 73e30cf409d29ddc9d5d5fcf1cd8f70440a2f81c Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 30 Dec 2015 02:15:12 +0000 Subject: [PATCH 10/55] Fix stack leak introduced by SVN r97201 (nextboot_conf support). Fix erroneous error path in error messages when processing boot_conf. Fixup stack comments for functions introduced by SVN r97201. Remove a questioning stack comment introduced by SVN r186789. NB: Comment removed because strdup usage here is correct/not a leak. MFC after: 1 week --- sys/boot/forth/support.4th | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 08f500496d92..9a68872d2c95 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -833,7 +833,7 @@ get-current ( -- wid ) previous definitions >search ( wid -- ) repeat ; -: peek_file +: peek_file ( addr len -- ) 0 to end_of_file? reset_line_reading O_RDONLY fopen fd ! @@ -844,6 +844,7 @@ get-current ( -- wid ) previous definitions >search ( wid -- ) ['] process_assignment catch ['] free_buffers catch fd @ fclose + swap throw throw ; only forth also support-functions definitions @@ -1021,25 +1022,26 @@ string current_file_name_ref \ used to print the file name ; : get_nextboot_conf_file ( -- addr len ) - nextboot_conf_file strget strdup \ XXX is the strdup a leak ? + nextboot_conf_file strget strdup ; : rewrite_nextboot_file ( -- ) get_nextboot_conf_file O_WRONLY fopen fd ! fd @ -1 = if EOPEN throw then - fd @ s' nextboot_enable="NO" ' fwrite + fd @ s' nextboot_enable="NO" ' fwrite ( fd buf len -- nwritten ) drop fd @ fclose ; -: include_nextboot_file +: include_nextboot_file ( -- ) get_nextboot_conf_file - ['] peek_file catch + ['] peek_file catch if 2drop then nextboot? if get_nextboot_conf_file + current_file_name_ref strref ['] load_conf catch process_conf_errors - ['] rewrite_nextboot_file catch + ['] rewrite_nextboot_file catch if 2drop then then ; From 3d2aea56f4043bf704308110ea3a1053ffb02dd6 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Wed, 30 Dec 2015 02:23:14 +0000 Subject: [PATCH 11/55] Rewrite tid_flush() in C. There's no need for it to be in asm. Also, by writing in C, and marking it static in pmap.c, it saves a branch to the function itself, as it's only used in one location. The generated asm is virtually identical to the handwritten code. --- sys/powerpc/booke/locore.S | 71 -------------------------------------- sys/powerpc/booke/pmap.c | 49 ++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 73 deletions(-) diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S index 2ce6e69deda7..817cc4fab4a2 100644 --- a/sys/powerpc/booke/locore.S +++ b/sys/powerpc/booke/locore.S @@ -657,77 +657,6 @@ __boot_page_padding: /* locore subroutines */ /************************************************************************/ -/* - * void tid_flush(tlbtid_t tid); - * - * Invalidate all TLB0 entries which match the given TID. Note this is - * dedicated for cases when invalidation(s) should NOT be propagated to other - * CPUs. - * - * void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way); - * - * XXX: why isn't this in C? - */ -ENTRY(tid_flush) - cmpwi %r3, TID_KERNEL - beq tid_flush_end /* don't evict kernel translations */ - - /* Disable interrupts */ - mfmsr %r10 - wrteei 0 - - li %r6, 0 /* ways counter */ -loop_ways: - li %r7, 0 /* entries [per way] counter */ -loop_entries: - /* Select TLB0 and ESEL (way) */ - lis %r8, MAS0_TLBSEL0@h - rlwimi %r8, %r6, 16, 14, 15 - mtspr SPR_MAS0, %r8 - isync - - /* Select EPN (entry within the way) */ - rlwinm %r8, %r7, 12, 13, 19 - mtspr SPR_MAS2, %r8 - isync - tlbre - - /* Check if valid entry */ - mfspr %r8, SPR_MAS1 - andis. %r9, %r8, MAS1_VALID@h - beq next_entry /* invalid entry */ - - /* Check if this is our TID */ - rlwinm %r9, %r8, 16, 24, 31 - - cmplw %r9, %r3 - bne next_entry /* not our TID */ - - /* Clear VALID bit */ - rlwinm %r8, %r8, 0, 1, 31 - mtspr SPR_MAS1, %r8 - isync - tlbwe - isync - msync - -next_entry: - addi %r7, %r7, 1 - cmpw %r7, %r5 - bne loop_entries - - /* Next way */ - addi %r6, %r6, 1 - cmpw %r6, %r4 - bne loop_ways - - /* Restore MSR (possibly re-enable interrupts) */ - mtmsr %r10 - isync - -tid_flush_end: - blr - /* * Cache disable/enable/inval sequences according * to section 2.16 of E500CORE RM. diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 6ea98b77da7a..6d720a14d340 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -161,7 +161,6 @@ unsigned int kernel_ptbls; /* Number of KVA ptbls. */ #define PMAP_REMOVE_DONE(pmap) \ ((pmap) != kernel_pmap && (pmap)->pm_stats.resident_count == 0) -extern void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way); extern int elf32_nxstack; /**************************************************************************/ @@ -195,6 +194,7 @@ static unsigned int tlb1_idx; static vm_offset_t tlb1_map_base = VM_MAX_KERNEL_ADDRESS; static tlbtid_t tid_alloc(struct pmap *); +static void tid_flush(tlbtid_t tid); static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t); @@ -2915,7 +2915,7 @@ tid_alloc(pmap_t pmap) tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE; /* Flush all entries from TLB0 matching this TID. */ - tid_flush(tid, tlb0_ways, tlb0_entries_per_way); + tid_flush(tid); } tidbusy[thiscpu][tid] = pmap; @@ -3426,3 +3426,48 @@ tlb1_iomapped(int i, vm_paddr_t pa, vm_size_t size, vm_offset_t *va) *va = (tlb1[i].mas2 & MAS2_EPN_MASK) + (pa - pa_start); return (0); } + +/* + * Invalidate all TLB0 entries which match the given TID. Note this is + * dedicated for cases when invalidations should NOT be propagated to other + * CPUs. + */ +static void +tid_flush(tlbtid_t tid) +{ + register_t msr; + uint32_t mas0, mas1, mas2; + int entry, way; + + + /* Don't evict kernel translations */ + if (tid == TID_KERNEL) + return; + + msr = mfmsr(); + __asm __volatile("wrteei 0"); + + for (way = 0; way < TLB0_WAYS; way++) + for (entry = 0; entry < TLB0_ENTRIES_PER_WAY; entry++) { + + mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(way); + mtspr(SPR_MAS0, mas0); + __asm __volatile("isync"); + + mas2 = entry << MAS2_TLB0_ENTRY_IDX_SHIFT; + mtspr(SPR_MAS2, mas2); + + __asm __volatile("isync; tlbre"); + + mas1 = mfspr(SPR_MAS1); + + if (!(mas1 & MAS1_VALID)) + continue; + if (((mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT) != tid) + continue; + mas1 &= ~MAS1_VALID; + mtspr(SPR_MAS1, mas1); + __asm __volatile("isync; tlbwe; isync; msync"); + } + mtmsr(msr); +} From 2905d447cf9e6c71ffcf3816867e2712070364de Mon Sep 17 00:00:00 2001 From: jhibbits Date: Wed, 30 Dec 2015 02:26:04 +0000 Subject: [PATCH 12/55] Optimize zero_page for book-e mmu. Instead of indirectly calling bzero() through mmu_booke_zero_page_area, zero the full page the same way as the AIM pmap logic does: using dcbz. --- sys/powerpc/booke/pmap.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 6d720a14d340..bb1a7b57504f 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -2235,8 +2235,17 @@ mmu_booke_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size) static void mmu_booke_zero_page(mmu_t mmu, vm_page_t m) { + vm_offset_t off, va; - mmu_booke_zero_page_area(mmu, m, 0, PAGE_SIZE); + mtx_lock(&zero_page_mutex); + va = zero_page_va; + + mmu_booke_kenter(mmu, va, VM_PAGE_TO_PHYS(m)); + for (off = 0; off < PAGE_SIZE; off += cacheline_size) + __asm __volatile("dcbzl 0,%0" :: "r"(va + off)); + mmu_booke_kremove(mmu, va); + + mtx_unlock(&zero_page_mutex); } /* From 95fd2c39d8126c7d22e19c665390fb580101c853 Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 30 Dec 2015 03:36:22 +0000 Subject: [PATCH 13/55] Use __alignof__ instead of assuming int64_t to get the right alignment. Differential Revision: https://reviews.freebsd.org/D4708 --- lib/libc/stdio/findfp.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c index 6a68958d50f4..5e1f06924ac8 100644 --- a/lib/libc/stdio/findfp.c +++ b/lib/libc/stdio/findfp.c @@ -99,16 +99,7 @@ moreglue(int n) FILE *p; size_t align; - /* - * FILE has a mbstate_t variable. This variable tries to be int64_t - * aligned through its definition. int64_t may be larger than void *, - * which is the size traditionally used for ALIGNBYTES. So, use our own - * rounding instead of the MI ALIGN macros. If for some reason - * ALIGNBYTES is larger than int64_t, respect that too. There appears to - * be no portable way to ask for FILE's alignment requirements other - * than just knowing here. - */ - align = MAX(ALIGNBYTES, sizeof(int64_t)); + align = __alignof__(FILE); g = (struct glue *)malloc(sizeof(*g) + align + n * sizeof(FILE)); if (g == NULL) return (NULL); From 0ecd3402cf1e87e46681a45c04b370ae6a537082 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Wed, 30 Dec 2015 03:43:25 +0000 Subject: [PATCH 14/55] Add platform support for QorIQ SoCs. This includes the following changes: * SMP kickoff for QorIQ (tested on P5020) * Errata fixes for some silicon revisions * Enables L2 (and L3 if available) caches Obtained from: Semihalf Sponsored by: Alex Perez/Inertial Computing --- sys/powerpc/booke/booke_machdep.c | 14 +- sys/powerpc/booke/locore.S | 109 +++++++++++++++- sys/powerpc/booke/machdep_e500.c | 59 ++------- sys/powerpc/mpc85xx/mpc85xx.c | 171 +++++++++++++++++++++++++ sys/powerpc/mpc85xx/mpc85xx.h | 38 ++++++ sys/powerpc/mpc85xx/platform_mpc85xx.c | 100 +++++++++++++-- 6 files changed, 432 insertions(+), 59 deletions(-) diff --git a/sys/powerpc/booke/booke_machdep.c b/sys/powerpc/booke/booke_machdep.c index c98e301b86cd..f102677202bd 100644 --- a/sys/powerpc/booke/booke_machdep.c +++ b/sys/powerpc/booke/booke_machdep.c @@ -316,8 +316,20 @@ booke_init(uint32_t arg1, uint32_t arg2) ret = powerpc_init(dtbp, 0, 0, mdp); - /* Enable L1 caches */ + /* Default to 32 byte cache line size. */ + switch ((mfpvr()) >> 16) { + case FSL_E500mc: + case FSL_E5500: + case FSL_E6500: + cacheline_size = 64; + break; + } + + /* Enable caches */ booke_enable_l1_cache(); + booke_enable_l2_cache(); + + booke_enable_bpred(); return (ret); } diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S index 817cc4fab4a2..2d6c66d8bc68 100644 --- a/sys/powerpc/booke/locore.S +++ b/sys/powerpc/booke/locore.S @@ -301,7 +301,7 @@ bp_ntlb1s: .globl bp_tlb1 bp_tlb1: - .space 4 * 3 * 16 + .space 4 * 3 * 64 .globl bp_tlb1_end bp_tlb1_end: @@ -730,6 +730,113 @@ ENTRY(icache_enable) isync blr +/* + * L2 cache disable/enable/inval sequences for E500mc. + */ + +ENTRY(l2cache_inval) + mfspr %r3, SPR_L2CSR0 + oris %r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@h + ori %r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@l + isync + mtspr SPR_L2CSR0, %r3 + isync +1: mfspr %r3, SPR_L2CSR0 + andis. %r3, %r3, L2CSR0_L2FI@h + bne 1b + blr + +ENTRY(l2cache_enable) + mfspr %r3, SPR_L2CSR0 + oris %r3, %r3, (L2CSR0_L2E | L2CSR0_L2PE)@h + isync + mtspr SPR_L2CSR0, %r3 + isync + blr + +/* + * Branch predictor setup. + */ +ENTRY(bpred_enable) + mfspr %r3, SPR_BUCSR + ori %r3, %r3, BUCSR_BBFI + isync + mtspr SPR_BUCSR, %r3 + isync + ori %r3, %r3, BUCSR_BPEN + isync + mtspr SPR_BUCSR, %r3 + isync + blr + +ENTRY(dataloss_erratum_access) + /* Lock two cache lines into I-Cache */ + sync + mfspr %r11, SPR_L1CSR1 + rlwinm %r11, %r11, 0, ~L1CSR1_ICUL + sync + isync + mtspr SPR_L1CSR1, %r11 + isync + + mflr %r9 + bl 1f + .long 2f-. +1: + mflr %r5 + lwz %r8, 0(%r5) + mtlr %r9 + add %r8, %r8, %r5 + icbtls 0, 0, %r8 + addi %r9, %r8, 64 + + sync + mfspr %r11, SPR_L1CSR1 +3: andi. %r11, %r11, L1CSR1_ICUL + bne 3b + + icbtls 0, 0, %r9 + + sync + mfspr %r11, SPR_L1CSR1 +3: andi. %r11, %r11, L1CSR1_ICUL + bne 3b + + b 2f + .align 6 + /* Inside a locked cacheline, wait a while, write, then wait a while */ +2: sync + + mfspr %r5, TBR_TBL +4: addis %r11, %r5, 0x100000@h /* wait around one million timebase ticks */ + mfspr %r5, TBR_TBL + subf. %r5, %r5, %r11 + bgt 4b + + stw %r4, 0(%r3) + + mfspr %r5, TBR_TBL +4: addis %r11, %r5, 0x100000@h /* wait around one million timebase ticks */ + mfspr %r5, TBR_TBL + subf. %r5, %r5, %r11 + bgt 4b + + sync + + /* + * Fill out the rest of this cache line and the next with nops, + * to ensure that nothing outside the locked area will be + * fetched due to a branch. + */ + .rept 19 + nop + .endr + + icblc 0, 0, %r8 + icblc 0, 0, %r9 + + blr + /* * int setfault() * diff --git a/sys/powerpc/booke/machdep_e500.c b/sys/powerpc/booke/machdep_e500.c index ab47f620424a..e0e60952942c 100644 --- a/sys/powerpc/booke/machdep_e500.c +++ b/sys/powerpc/booke/machdep_e500.c @@ -27,9 +27,15 @@ #include __FBSDID("$FreeBSD$"); +#include #include +#include +#include #include +#include +#include + #include #include @@ -42,6 +48,7 @@ extern void icache_enable(void); extern void icache_inval(void); extern void l2cache_enable(void); extern void l2cache_inval(void); +extern void bpred_enable(void); void booke_init_tlb(vm_paddr_t fdt_immr_pa) @@ -79,7 +86,6 @@ booke_enable_l1_cache(void) (csr & L1CSR1_ICE) ? "en" : "dis"); } -#if 0 void booke_enable_l2_cache(void) { @@ -102,55 +108,18 @@ booke_enable_l2_cache(void) } void -booke_enable_l3_cache(void) +booke_enable_bpred(void) { - uint32_t csr, size, ver; + uint32_t csr; - /* Enable L3 CoreNet Platform Cache (CPC) */ - ver = SVR_VER(mfspr(SPR_SVR)); - if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 || - ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) { - csr = ccsr_read4(OCP85XX_CPC_CSR0); - if ((csr & OCP85XX_CPC_CSR0_CE) == 0) { - l3cache_inval(); - l3cache_enable(); - } - - csr = ccsr_read4(OCP85XX_CPC_CSR0); - if ((boothowto & RB_VERBOSE) != 0 || - (csr & OCP85XX_CPC_CSR0_CE) == 0) { - size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0)); - printf("L3 Corenet Platform Cache: %d KB %sabled\n", - size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ? - "dis" : "en"); - } - } + bpred_enable(); + csr = mfspr(SPR_BUCSR); + if ((boothowto & RB_VERBOSE) != 0 || (csr & BUCSR_BPEN) == 0) + printf("Branch Predictor %sabled\n", + (csr & BUCSR_BPEN) ? "en" : "dis"); } void booke_disable_l2_cache(void) { } - -static void -l3cache_inval(void) -{ - - /* Flash invalidate the CPC and clear all the locks */ - ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI | - OCP85XX_CPC_CSR0_LFC); - while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI | - OCP85XX_CPC_CSR0_LFC)) - ; -} - -static void -l3cache_enable(void) -{ - - ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE | - OCP85XX_CPC_CSR0_PE); - /* Read back to sync write */ - ccsr_read4(OCP85XX_CPC_CSR0); -} -#endif diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c index 6608b4d520c7..717e98af0d66 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.c +++ b/sys/powerpc/mpc85xx/mpc85xx.c @@ -32,18 +32,26 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include +#include #include #include #include +#include +#include +#include +#include + #include @@ -249,3 +257,166 @@ law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io) return (rv); } +static void +l3cache_inval(void) +{ + + /* Flash invalidate the CPC and clear all the locks */ + ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI | + OCP85XX_CPC_CSR0_LFC); + while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI | + OCP85XX_CPC_CSR0_LFC)) + ; +} + +static void +l3cache_enable(void) +{ + + ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE | + OCP85XX_CPC_CSR0_PE); + /* Read back to sync write */ + ccsr_read4(OCP85XX_CPC_CSR0); +} + +void +mpc85xx_enable_l3_cache(void) +{ + uint32_t csr, size, ver; + + /* Enable L3 CoreNet Platform Cache (CPC) */ + ver = SVR_VER(mfspr(SPR_SVR)); + if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 || + ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) { + csr = ccsr_read4(OCP85XX_CPC_CSR0); + if ((csr & OCP85XX_CPC_CSR0_CE) == 0) { + l3cache_inval(); + l3cache_enable(); + } + + csr = ccsr_read4(OCP85XX_CPC_CSR0); + if ((boothowto & RB_VERBOSE) != 0 || + (csr & OCP85XX_CPC_CSR0_CE) == 0) { + size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0)); + printf("L3 Corenet Platform Cache: %d KB %sabled\n", + size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ? + "dis" : "en"); + } + } +} + +static void +mpc85xx_dataloss_erratum_spr976(void) +{ + uint32_t svr = SVR_VER(mfspr(SPR_SVR)); + + /* Ignore whether it's the E variant */ + svr &= ~0x8; + + if (svr != SVR_P3041 && svr != SVR_P4040 && + svr != SVR_P4080 && svr != SVR_P5020) + return; + + mb(); + isync(); + mtspr(976, (mfspr(976) & ~0x1f8) | 0x48); + isync(); +} + +static vm_offset_t +mpc85xx_map_dcsr(void) +{ + phandle_t node; + u_long b, s; + int err; + + /* + * Try to access the dcsr node directly i.e. through /aliases/. + */ + if ((node = OF_finddevice("dcsr")) != -1) + if (fdt_is_compatible_strict(node, "fsl,dcsr")) + goto moveon; + /* + * Find the node the long way. + */ + if ((node = OF_finddevice("/")) == -1) + return (ENXIO); + + if ((node = ofw_bus_find_compatible(node, "fsl,dcsr")) == 0) + return (ENXIO); + +moveon: + err = fdt_get_range(node, 0, &b, &s); + + if (err != 0) + return (err); + +#ifdef QORIQ_DPAA + law_enable(OCP85XX_TGTIF_DCSR, b, 0x400000); +#endif + return pmap_early_io_map(b, 0x400000); +} + + + +void +mpc85xx_fix_errata(vm_offset_t va_ccsr) +{ + uint32_t svr = SVR_VER(mfspr(SPR_SVR)); + vm_offset_t va_dcsr; + + /* Ignore whether it's the E variant */ + svr &= ~0x8; + + if (svr != SVR_P3041 && svr != SVR_P4040 && + svr != SVR_P4080 && svr != SVR_P5020) + return; + + if (mfmsr() & PSL_EE) + return; + + /* + * dcsr region need to be mapped thus patch can refer to. + * Align dcsr right after ccsbar. + */ + va_dcsr = mpc85xx_map_dcsr(); + if (va_dcsr == 0) + goto err; + + /* + * As A004510 errata specify, special purpose register 976 + * SPR976[56:60] = 6'b001001 must be set. e500mc core reference manual + * does not document SPR976 register. + */ + mpc85xx_dataloss_erratum_spr976(); + + /* + * Specific settings in the CCF and core platform cache (CPC) + * are required to reconfigure the CoreNet coherency fabric. + * The register settings that should be updated are described + * in errata and relay on base address, offset and updated value. + * Special conditions must be used to update these registers correctly. + */ + dataloss_erratum_access(va_dcsr + 0xb0e08, 0xe0201800); + dataloss_erratum_access(va_dcsr + 0xb0e18, 0xe0201800); + dataloss_erratum_access(va_dcsr + 0xb0e38, 0xe0400000); + dataloss_erratum_access(va_dcsr + 0xb0008, 0x00900000); + dataloss_erratum_access(va_dcsr + 0xb0e40, 0xe00a0000); + + switch (svr) { + case SVR_P5020: + dataloss_erratum_access(va_ccsr + 0x18600, 0xc0000000); + break; + case SVR_P4040: + case SVR_P4080: + dataloss_erratum_access(va_ccsr + 0x18600, 0xff000000); + break; + case SVR_P3041: + dataloss_erratum_access(va_ccsr + 0x18600, 0xf0000000); + } + dataloss_erratum_access(va_ccsr + 0x10f00, 0x415e5000); + dataloss_erratum_access(va_ccsr + 0x11f00, 0x415e5000); + +err: + return; +} diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h index 31adc58e565d..ac8b8ff8ba55 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.h +++ b/sys/powerpc/mpc85xx/mpc85xx.h @@ -40,6 +40,25 @@ extern vm_offset_t ccsrbar_va; #define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0) #define OCP85XX_BPTR (CCSRBAR_VA + 0x20) +#define OCP85XX_BSTRH (CCSRBAR_VA + 0x20) +#define OCP85XX_BSTRL (CCSRBAR_VA + 0x24) +#define OCP85XX_BSTAR (CCSRBAR_VA + 0x28) + +#define OCP85XX_COREDISR (CCSRBAR_VA + 0xE0094) +#define OCP85XX_BRR (CCSRBAR_VA + 0xE00E4) + +/* + * Run Control and Power Management registers + */ +#define CCSR_CTBENR (CCSRBAR_VA + 0xE2084) +#define CCSR_CTBCKSELR (CCSRBAR_VA + 0xE208C) +#define CCSR_CTBCHLTCR (CCSRBAR_VA + 0xE2094) + +/* + * DDR Memory controller. + */ +#define OCP85XX_DDR1_CS0_CONFIG (CCSRBAR_VA + 0x8080) + /* * E500 Coherency Module registers */ @@ -68,6 +87,7 @@ extern vm_offset_t ccsrbar_va; #define OCP85XX_TGTIF_RAM1 0x10 #define OCP85XX_TGTIF_RAM2 0x11 #define OCP85XX_TGTIF_BMAN 0x18 +#define OCP85XX_TGTIF_DCSR 0x1D #define OCP85XX_TGTIF_QMAN 0x3C #define OCP85XX_TRGT_SHIFT 20 #else @@ -83,6 +103,20 @@ extern vm_offset_t ccsrbar_va; */ #define OCP85XX_L2CTL (CCSRBAR_VA + 0x20000) +/* + * L3 CoreNet platform cache (CPC) registers + */ +#define OCP85XX_CPC_CSR0 (CCSRBAR_VA + 0x10000) +#define OCP85XX_CPC_CSR0_CE 0x80000000 +#define OCP85XX_CPC_CSR0_PE 0x40000000 +#define OCP85XX_CPC_CSR0_FI 0x00200000 +#define OCP85XX_CPC_CSR0_WT 0x00080000 +#define OCP85XX_CPC_CSR0_FL 0x00000800 +#define OCP85XX_CPC_CSR0_LFC 0x00000400 +#define OCP85XX_CPC_CFG0 (CCSRBAR_VA + 0x10008) +#define OCP85XX_CPC_CFG_SZ_MASK 0x00003fff +#define OCP85XX_CPC_CFG0_SZ_K(x) (((x) & OCP85XX_CPC_CFG_SZ_MASK) << 6) + /* * Power-On Reset configuration */ @@ -110,4 +144,8 @@ int law_pci_target(struct resource *, int *, int *); DECLARE_CLASS(mpc85xx_platform); int mpc85xx_attach(platform_t); +void mpc85xx_enable_l3_cache(void); +void mpc85xx_fix_errata(vm_offset_t); +void dataloss_erratum_access(vm_offset_t, uint32_t); + #endif /* _MPC85XX_H_ */ diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c index eb9577f1128c..c84561d09c75 100644 --- a/sys/powerpc/mpc85xx/platform_mpc85xx.c +++ b/sys/powerpc/mpc85xx/platform_mpc85xx.c @@ -24,6 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_platform.h" #include __FBSDID("$FreeBSD$"); @@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -175,6 +177,9 @@ mpc85xx_attach(platform_t plat) } ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); + mpc85xx_fix_errata(ccsrbar_va); + mpc85xx_enable_l3_cache(); + /* * Clear local access windows. Skip DRAM entries, so we don't shoot * ourselves in the foot. @@ -182,14 +187,14 @@ mpc85xx_attach(platform_t plat) law_max = law_getmax(); for (i = 0; i < law_max; i++) { sr = ccsr_read4(OCP85XX_LAWSR(i)); - if ((sr & 0x80000000) == 0) + if ((sr & OCP85XX_ENA_MASK) == 0) continue; tgt = (sr & 0x01f00000) >> 20; if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || tgt == OCP85XX_TGTIF_RAM_INTL) continue; - ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); + ccsr_write4(OCP85XX_LAWSR(i), sr & OCP85XX_DIS_MASK); } return (0); @@ -256,7 +261,11 @@ mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) * HID0[SEL_TBCLK] = 0 */ if (freq != 0) +#ifdef QORIQ_DPAA + ticks = freq / 32; +#else ticks = freq / 8; +#endif out: if (ticks <= 0) @@ -309,17 +318,37 @@ mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) { #ifdef SMP uint32_t *tlb1; - uint32_t bptr, eebpcr; + vm_paddr_t bptr; + uint32_t reg; int i, timeout; + uintptr_t brr; + int cpuid; - eebpcr = ccsr_read4(OCP85XX_EEBPCR); - if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) { +#ifdef QORIQ_DPAA + uint32_t tgt; + + reg = ccsr_read4(OCP85XX_COREDISR); + cpuid = pc->pc_cpuid; + + if ((reg & cpuid) != 0) { + printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); + return (-1); + } + + brr = OCP85XX_BRR; +#else /* QORIQ_DPAA */ + brr = OCP85XX_EEBPCR; + cpuid = pc->pc_cpuid + 24; +#endif + reg = ccsr_read4(brr); + if ((reg & (1 << cpuid)) != 0) { printf("SMP: CPU %d already out of hold-off state!\n", pc->pc_cpuid); return (ENXIO); } ap_pcpu = pc; + __asm __volatile("msync; isync"); i = 0; tlb1 = bp_tlb1; @@ -335,24 +364,67 @@ mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) if (i < bp_ntlb1s) bp_ntlb1s = i; + /* Flush caches to have our changes hit DRAM. */ + cpu_flush_dcache(__boot_page, 4096); + + bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload; + KASSERT((bptr & 0xfff) == 0, + ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); +#ifdef QORIQ_DPAA + + /* + * Read DDR controller configuration to select proper BPTR target ID. + * + * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers + * interleaving. If this bit is set, we have to use + * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, + * this bit is reserved and always 0. + */ + + reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); + if (reg & (1 << 29)) + tgt = OCP85XX_TGTIF_RAM_INTL; + else + tgt = OCP85XX_TGTIF_RAM1; + + /* + * Set BSTR to the physical address of the boot page + */ + ccsr_write4(OCP85XX_BSTRH, bptr >> 32); + ccsr_write4(OCP85XX_BSTRL, bptr); + ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | + (tgt << OCP85XX_TRGT_SHIFT) | (ffsl(PAGE_SIZE) - 2)); + + /* Read back OCP85XX_BSTAR to synchronize write */ + ccsr_read4(OCP85XX_BSTAR); + + /* + * Enable and configure time base on new CPU. + */ + + /* Set TB clock source to platform clock / 32 */ + reg = ccsr_read4(CCSR_CTBCKSELR); + ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); + + /* Enable TB */ + reg = ccsr_read4(CCSR_CTBENR); + ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); +#else + /* * Set BPTR to the physical address of the boot page */ - bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; - KASSERT((bptr & 0xfff) == 0, - ("%s: boot page is not aligned (%#x)", __func__, bptr)); bptr = (bptr >> 12) | 0x80000000u; ccsr_write4(OCP85XX_BPTR, bptr); __asm __volatile("isync; msync"); - /* Flush caches to have our changes hit DRAM. */ - cpu_flush_dcache(__boot_page, 4096); +#endif /* QORIQ_DPAA */ /* * Release AP from hold-off state */ - eebpcr |= (1 << (pc->pc_cpuid + 24)); - ccsr_write4(OCP85XX_EEBPCR, eebpcr); + reg = ccsr_read4(brr); + ccsr_write4(brr, reg | (1 << cpuid)); __asm __volatile("isync; msync"); timeout = 500; @@ -364,7 +436,11 @@ mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) * address (= 0xfffff000) isn't permanently remapped and thus not * usable otherwise. */ +#ifdef QORIQ_DPAA + ccsr_write4(OCP85XX_BSTAR, 0); +#else ccsr_write4(OCP85XX_BPTR, 0); +#endif __asm __volatile("isync; msync"); if (!pc->pc_awake) From 4310e2d2f01d780c08134edddb3cf7ce22b30c4d Mon Sep 17 00:00:00 2001 From: dim Date: Wed, 30 Dec 2015 09:15:02 +0000 Subject: [PATCH 15/55] Add some more obsolete files, left over from the clang 3.7.0 -> 3.7.1 upgrade. Noticed by: Nikolai Lifanov , jtl --- ObsoleteFiles.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index cf5d2a29c50f..dff00ae453a1 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -105,6 +105,8 @@ OLD_FILES+=usr/lib/clang/3.7.0/include/xopintrin.h OLD_FILES+=usr/lib/clang/3.7.0/include/xtestintrin.h OLD_DIRS+=usr/lib/clang/3.7.0/include OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-i386.a +OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-preinit-i386.a +OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-preinit-x86_64.a OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-x86_64.a OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan_cxx-i386.a OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan_cxx-x86_64.a From 57db7407a7be3663a5aa3a3fa0c39cbb83e3bd7f Mon Sep 17 00:00:00 2001 From: ngie Date: Wed, 30 Dec 2015 11:15:07 +0000 Subject: [PATCH 16/55] Integrate tools/regression/sockets/unix_passfd into the FreeBSD test suite as tests/sys/kern/unix_passfd_test - Convert testcases to ATF - Fix an alignment issues - Mark rights_creds_payload(..) as an expected failure (see PR # 181741) Based [in part] on the following Differential Revision: https://reviews.freebsd.org/D689 MFC after: 1 week Submitted by: markj Sponsored by: EMC / Isilon Storage Division --- tests/sys/kern/Makefile | 1 + tests/sys/kern/unix_passfd_test.c | 396 ++++++++++++++++++ tools/regression/sockets/unix_passfd/Makefile | 7 - .../sockets/unix_passfd/unix_passfd.c | 390 ----------------- 4 files changed, 397 insertions(+), 397 deletions(-) create mode 100644 tests/sys/kern/unix_passfd_test.c delete mode 100644 tools/regression/sockets/unix_passfd/Makefile delete mode 100644 tools/regression/sockets/unix_passfd/unix_passfd.c diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index a38b1f25f0a1..c9a7cfd46bc8 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -8,6 +8,7 @@ ATF_TESTS_C+= kern_copyin ATF_TESTS_C+= kern_descrip_test ATF_TESTS_C+= ptrace_test ATF_TESTS_C+= unix_seqpacket_test +ATF_TESTS_C+= unix_passfd_test TEST_METADATA.unix_seqpacket_test+= timeout="15" LIBADD.ptrace_test+= pthread diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c new file mode 100644 index 000000000000..44f136fc1fea --- /dev/null +++ b/tests/sys/kern/unix_passfd_test.c @@ -0,0 +1,396 @@ +/*- + * Copyright (c) 2005 Robert N. M. Watson + * Copyright (c) 2015 Mark Johnston + * 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 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 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * UNIX domain sockets allow file descriptors to be passed via "ancillary + * data", or control messages. This regression test is intended to exercise + * this facility, both performing some basic tests that it operates, and also + * causing some kernel edge cases to execute, such as garbage collection when + * there are cyclic file descriptor references. Right now we test only with + * stream sockets, but ideally we'd also test with datagram sockets. + */ + +static void +domainsocketpair(int *fdp) +{ + + ATF_REQUIRE_MSG(socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) != -1, + "socketpair(PF_UNIX, SOCK_STREAM) failed: %s", strerror(errno)); +} + +static void +closesocketpair(int *fdp) +{ + + close(fdp[0]); + close(fdp[1]); +} + +static void +devnull(int *fdp) +{ + int fd; + + fd = open("/dev/null", O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno)); + *fdp = fd; +} + +static void +tempfile(int *fdp) +{ + char path[PATH_MAX]; + int fd; + + snprintf(path, PATH_MAX, "%s/unix_passfd.XXXXXXXXXXXXXXX", + getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")); + fd = mkstemp(path); + ATF_REQUIRE_MSG(fd != -1, "mkstemp(%s) failed", path); + (void)unlink(path); + *fdp = fd; +} + +static void +dofstat(int fd, struct stat *sb) +{ + + ATF_REQUIRE_MSG(fstat(fd, sb) == 0, + "fstat failed: %s", strerror(errno)); +} + +static void +samefile(struct stat *sb1, struct stat *sb2) +{ + + ATF_REQUIRE_MSG(sb1->st_dev == sb2->st_dev, "different device"); + ATF_REQUIRE_MSG(sb1->st_ino == sb2->st_ino, "different inode"); +} + +static void +sendfd_payload(int sockfd, int sendfd, void *payload, size_t paylen) +{ + struct iovec iovec; + char message[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsghdr; + struct msghdr msghdr; + ssize_t len; + + bzero(&msghdr, sizeof(msghdr)); + bzero(&message, sizeof(message)); + + msghdr.msg_control = message; + msghdr.msg_controllen = sizeof(message); + + iovec.iov_base = payload; + iovec.iov_len = paylen; + + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + + cmsghdr = (struct cmsghdr *)(void*)message; + cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsghdr->cmsg_level = SOL_SOCKET; + cmsghdr->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsghdr), &sendfd, sizeof(int)); + + len = sendmsg(sockfd, &msghdr, 0); + ATF_REQUIRE_MSG(len != -1, "sendmsg failed: %s", strerror(errno)); + ATF_REQUIRE_MSG((size_t)len == paylen, + "sendmsg: %zd messages sent; expected: %zu; %s", len, paylen, + strerror(errno)); +} + +static void +sendfd(int sockfd, int sendfd) +{ + char ch = 0; + + return (sendfd_payload(sockfd, sendfd, &ch, sizeof(ch))); +} + +static void +recvfd_payload(int sockfd, int *recvfd, void *buf, size_t buflen) +{ + struct cmsghdr *cmsghdr; + char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; + struct msghdr msghdr; + struct iovec iovec; + ssize_t len; + + bzero(&msghdr, sizeof(msghdr)); + + msghdr.msg_control = message; + msghdr.msg_controllen = sizeof(message); + + iovec.iov_base = buf; + iovec.iov_len = buflen; + + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + + len = recvmsg(sockfd, &msghdr, 0); + ATF_REQUIRE_MSG(len != -1, "recvmsg failed: %s", strerror(errno)); + ATF_REQUIRE_MSG((size_t)len == buflen, + "recvmsg: %zd bytes received; expected %zd", len, buflen); + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + ATF_REQUIRE_MSG(cmsghdr != NULL, + "recvmsg: did not receive control message"); + *recvfd = -1; + for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { + if (cmsghdr->cmsg_level == SOL_SOCKET && + cmsghdr->cmsg_type == SCM_RIGHTS && + cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { + memcpy(recvfd, CMSG_DATA(cmsghdr), sizeof(int)); + ATF_REQUIRE(*recvfd != -1); + } + } + ATF_REQUIRE_MSG(*recvfd != -1, + "recvmsg: did not receive single-fd message"); +} + +static void +recvfd(int sockfd, int *recvfd) +{ + char ch = 0; + + return (recvfd_payload(sockfd, recvfd, &ch, sizeof(ch))); +} + +/* + * Put a temporary file into a UNIX domain socket, then take it out and make + * sure it's the same file. First time around, don't close the reference + * after sending. + */ +ATF_TC_WITHOUT_HEAD(simple_send_fd); +ATF_TC_BODY(simple_send_fd, tc) +{ + struct stat getfd_stat, putfd_stat; + int fd[2], getfd, putfd; + + domainsocketpair(fd); + tempfile(&putfd); + dofstat(putfd, &putfd_stat); + sendfd(fd[0], putfd); + recvfd(fd[1], &getfd); + dofstat(getfd, &getfd_stat); + samefile(&putfd_stat, &getfd_stat); + close(putfd); + close(getfd); + closesocketpair(fd); +} + +/* + * Same as simple_send_fd, only close the file reference after sending, so that + * the only reference is the descriptor in the UNIX domain socket buffer. + */ +ATF_TC_WITHOUT_HEAD(send_and_close); +ATF_TC_BODY(send_and_close, tc) +{ + struct stat getfd_stat, putfd_stat; + int fd[2], getfd, putfd; + + domainsocketpair(fd); + tempfile(&putfd); + dofstat(putfd, &putfd_stat); + sendfd(fd[0], putfd); + close(putfd); + recvfd(fd[1], &getfd); + dofstat(getfd, &getfd_stat); + samefile(&putfd_stat, &getfd_stat); + close(getfd); + closesocketpair(fd); +} + +/* + * Put a temporary file into a UNIX domain socket, then close both endpoints + * causing garbage collection to kick off. + */ +ATF_TC_WITHOUT_HEAD(send_and_cancel); +ATF_TC_BODY(send_and_cancel, tc) +{ + int fd[2], putfd; + + domainsocketpair(fd); + tempfile(&putfd); + sendfd(fd[0], putfd); + close(putfd); + closesocketpair(fd); +} + +/* + * Send two files. Then receive them. Make sure they are returned in the + * right order, and both get there. + */ +ATF_TC_WITHOUT_HEAD(two_files); +ATF_TC_BODY(two_files, tc) +{ + struct stat getfd_1_stat, getfd_2_stat, putfd_1_stat, putfd_2_stat; + int fd[2], getfd_1, getfd_2, putfd_1, putfd_2; + + domainsocketpair(fd); + tempfile(&putfd_1); + tempfile(&putfd_2); + dofstat(putfd_1, &putfd_1_stat); + dofstat(putfd_2, &putfd_2_stat); + sendfd(fd[0], putfd_1); + sendfd(fd[0], putfd_2); + close(putfd_1); + close(putfd_2); + recvfd(fd[1], &getfd_1); + recvfd(fd[1], &getfd_2); + dofstat(getfd_1, &getfd_1_stat); + dofstat(getfd_2, &getfd_2_stat); + samefile(&putfd_1_stat, &getfd_1_stat); + samefile(&putfd_2_stat, &getfd_2_stat); + close(getfd_1); + close(getfd_2); + closesocketpair(fd); +} + +/* + * Big bundling test. Send an endpoint of the UNIX domain socket over itself, + * closing the door behind it. + */ +ATF_TC_WITHOUT_HEAD(bundle); +ATF_TC_BODY(bundle, tc) +{ + int fd[2], getfd; + + domainsocketpair(fd); + + sendfd(fd[0], fd[0]); + close(fd[0]); + recvfd(fd[1], &getfd); + close(getfd); + close(fd[1]); +} + +/* + * Big bundling test part two: Send an endpoint of the UNIX domain socket over + * itself, close the door behind it, and never remove it from the other end. + */ +ATF_TC_WITHOUT_HEAD(bundle_cancel); +ATF_TC_BODY(bundle_cancel, tc) +{ + int fd[2]; + + domainsocketpair(fd); + sendfd(fd[0], fd[0]); + sendfd(fd[1], fd[0]); + closesocketpair(fd); +} + +/* + * Test for PR 151758: Send an character device over the UNIX domain socket + * and then close both sockets to orphan the device. + */ +ATF_TC_WITHOUT_HEAD(devfs_orphan); +ATF_TC_BODY(devfs_orphan, tc) +{ + int fd[2], putfd; + + domainsocketpair(fd); + devnull(&putfd); + sendfd(fd[0], putfd); + close(putfd); + closesocketpair(fd); +} + +#define LOCAL_SENDSPACE_SYSCTL "net.local.stream.sendspace" + +/* + * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel prepends a + * control message to the data. Sender sends large payload. + * Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer limit, and receiver + * receives truncated data. + */ +ATF_TC_WITHOUT_HEAD(rights_creds_payload); +ATF_TC_BODY(rights_creds_payload, tc) +{ + const int on = 1; + u_long sendspace; + size_t len; + void *buf; + int fd[2], getfd, putfd, rc; + + atf_tc_expect_fail("PR 181741: Packet loss when 'control' messages " + "are present with large data"); + + len = sizeof(sendspace); + rc = sysctlbyname(LOCAL_SENDSPACE_SYSCTL, &sendspace, + &len, NULL, 0); + ATF_REQUIRE_MSG(rc != -1, + "sysctl %s failed: %s", LOCAL_SENDSPACE_SYSCTL, strerror(errno)); + + buf = calloc(1, sendspace); + ATF_REQUIRE(buf != NULL); + + domainsocketpair(fd); + rc = setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)); + ATF_REQUIRE_MSG(rc != -1, "setsockopt(LOCAL_CREDS) failed: %s", + strerror(errno)); + tempfile(&putfd); + sendfd_payload(fd[0], putfd, buf, sendspace); + recvfd_payload(fd[1], &getfd, buf, sendspace); + close(putfd); + close(getfd); + closesocketpair(fd); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, simple_send_fd); + ATF_TP_ADD_TC(tp, send_and_close); + ATF_TP_ADD_TC(tp, send_and_cancel); + ATF_TP_ADD_TC(tp, two_files); + ATF_TP_ADD_TC(tp, bundle); + ATF_TP_ADD_TC(tp, bundle_cancel); + ATF_TP_ADD_TC(tp, devfs_orphan); + ATF_TP_ADD_TC(tp, rights_creds_payload); + + return (atf_no_error()); +} diff --git a/tools/regression/sockets/unix_passfd/Makefile b/tools/regression/sockets/unix_passfd/Makefile deleted file mode 100644 index 600b7b11b402..000000000000 --- a/tools/regression/sockets/unix_passfd/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -PROG= unix_passfd -MAN= -WARNS?= 3 - -.include diff --git a/tools/regression/sockets/unix_passfd/unix_passfd.c b/tools/regression/sockets/unix_passfd/unix_passfd.c deleted file mode 100644 index 59c4c29b3ebb..000000000000 --- a/tools/regression/sockets/unix_passfd/unix_passfd.c +++ /dev/null @@ -1,390 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * Copyright (c) 2015 Mark Johnston - * 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 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 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 -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * UNIX domain sockets allow file descriptors to be passed via "ancillary - * data", or control messages. This regression test is intended to exercise - * this facility, both performing some basic tests that it operates, and also - * causing some kernel edge cases to execute, such as garbage collection when - * there are cyclic file descriptor references. Right now we test only with - * stream sockets, but ideally we'd also test with datagram sockets. - */ - -static void -domainsocketpair(const char *test, int *fdp) -{ - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) < 0) - err(-1, "%s: socketpair(PF_UNIX, SOCK_STREAM)", test); -} - -static void -closesocketpair(int *fdp) -{ - - close(fdp[0]); - close(fdp[1]); -} - -static void -devnull(const char *test, int *fdp) -{ - int fd; - - fd = open("/dev/null", O_RDONLY); - if (fd < 0) - err(-1, "%s: open(/dev/null)", test); - *fdp = fd; -} - -static void -tempfile(const char *test, int *fdp) -{ - char path[PATH_MAX]; - int fd; - - snprintf(path, PATH_MAX, "/tmp/unix_passfd.XXXXXXXXXXXXXXX"); - fd = mkstemp(path); - if (fd < 0) - err(-1, "%s: mkstemp(%s)", test, path); - (void)unlink(path); - *fdp = fd; -} - -static void -dofstat(const char *test, int fd, struct stat *sb) -{ - - if (fstat(fd, sb) < 0) - err(-1, "%s: fstat", test); -} - -static void -samefile(const char *test, struct stat *sb1, struct stat *sb2) -{ - - if (sb1->st_dev != sb2->st_dev) - errx(-1, "%s: samefile: different device", test); - if (sb1->st_ino != sb2->st_ino) - errx(-1, "%s: samefile: different inode", test); -} - -static void -sendfd_payload(const char *test, int sockfd, int sendfd, - void *payload, size_t paylen) -{ - struct iovec iovec; - char message[CMSG_SPACE(sizeof(int))]; - struct cmsghdr *cmsghdr; - struct msghdr msghdr; - ssize_t len; - - bzero(&msghdr, sizeof(msghdr)); - bzero(&message, sizeof(message)); - - msghdr.msg_control = message; - msghdr.msg_controllen = sizeof(message); - - iovec.iov_base = payload; - iovec.iov_len = paylen; - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - cmsghdr = (struct cmsghdr *)message; - cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); - cmsghdr->cmsg_level = SOL_SOCKET; - cmsghdr->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsghdr) = sendfd; - - len = sendmsg(sockfd, &msghdr, 0); - if (len < 0) - err(-1, "%s: sendmsg", test); - if ((size_t)len != paylen) - errx(-1, "%s: sendmsg: %zd bytes sent", test, len); -} - -static void -sendfd(const char *test, int sockfd, int sendfd) -{ - char ch = 0; - - return (sendfd_payload(test, sockfd, sendfd, &ch, sizeof(ch))); -} - -static void -recvfd_payload(const char *test, int sockfd, int *recvfd, - void *buf, size_t buflen) -{ - struct cmsghdr *cmsghdr; - char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; - struct msghdr msghdr; - struct iovec iovec; - ssize_t len; - - bzero(&msghdr, sizeof(msghdr)); - - msghdr.msg_control = message; - msghdr.msg_controllen = sizeof(message); - - iovec.iov_base = buf; - iovec.iov_len = buflen; - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - len = recvmsg(sockfd, &msghdr, 0); - if (len < 0) - err(-1, "%s: recvmsg", test); - if ((size_t)len != buflen) - errx(-1, "%s: recvmsg: %zd bytes received", test, len); - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (cmsghdr == NULL) - errx(-1, "%s: recvmsg: did not receive control message", test); - *recvfd = -1; - for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { - if (cmsghdr->cmsg_level == SOL_SOCKET && - cmsghdr->cmsg_type == SCM_RIGHTS && - cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { - *recvfd = *(int *)CMSG_DATA(cmsghdr); - if (*recvfd == -1) - errx(-1, "%s: recvmsg: received fd -1", test); - } - } - if (*recvfd == -1) - errx(-1, "%s: recvmsg: did not receive single-fd message", - test); -} - -static void -recvfd(const char *test, int sockfd, int *recvfd) -{ - char ch = 0; - - return (recvfd_payload(test, sockfd, recvfd, &ch, sizeof(ch))); -} - -int -main(void) -{ - struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat; - int fd[2], putfd_1, putfd_2, getfd_1, getfd_2; - const char *test; - - /* - * First test: put a temporary file into a UNIX domain socket, then - * take it out and make sure it's the same file. First time around, - * don't close the reference after sending. - */ - test = "test1-simplesendfd"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - dofstat(test, putfd_1, &putfd_1_stat); - sendfd(test, fd[0], putfd_1); - recvfd(test, fd[1], &getfd_1); - dofstat(test, getfd_1, &getfd_1_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - close(putfd_1); - close(getfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Second test: same as first, only close the file reference after - * sending, so that the only reference is the descriptor in the UNIX - * domain socket buffer. - */ - test = "test2-sendandclose"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - dofstat(test, putfd_1, &putfd_1_stat); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - recvfd(test, fd[1], &getfd_1); - dofstat(test, getfd_1, &getfd_1_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - close(getfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Third test: put a temporary file into a UNIX domain socket, then - * close both endpoints causing garbage collection to kick off. - */ - test = "test3-sendandcancel"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Send two files. Then receive them. Make sure they are returned - * in the right order, and both get there. - */ - - test = "test4-twofile"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - tempfile(test, &putfd_2); - dofstat(test, putfd_1, &putfd_1_stat); - dofstat(test, putfd_2, &putfd_2_stat); - sendfd(test, fd[0], putfd_1); - sendfd(test, fd[0], putfd_2); - close(putfd_1); - close(putfd_2); - recvfd(test, fd[1], &getfd_1); - recvfd(test, fd[1], &getfd_2); - dofstat(test, getfd_1, &getfd_1_stat); - dofstat(test, getfd_2, &getfd_2_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - samefile(test, &putfd_2_stat, &getfd_2_stat); - close(getfd_1); - close(getfd_2); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Big bundling test. Send an endpoint of the UNIX domain socket - * over itself, closing the door behind it. - */ - - test = "test5-bundle"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - - sendfd(test, fd[0], fd[0]); - close(fd[0]); - recvfd(test, fd[1], &getfd_1); - close(getfd_1); - close(fd[1]); - - printf("%s passed\n", test); - - /* - * Big bundling test part two: Send an endpoint of the UNIX domain - * socket over itself, close the door behind it, and never remove it - * from the other end. - */ - - test = "test6-bundlecancel"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - sendfd(test, fd[0], fd[0]); - sendfd(test, fd[1], fd[0]); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Test for PR 151758: Send an character device over the UNIX - * domain socket and then close both sockets to orphan the - * device. - */ - - test = "test7-devfsorphan"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - devnull(test, &putfd_1); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel - * prepends a control message to the data. Sender sends large - * payload. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer - * limit, and receiver receives truncated data. - */ - test = "test8-rights+creds+payload"; - printf("beginning %s\n", test); - - { - const int on = 1; - u_long sendspace; - size_t len; - void *buf; - - len = sizeof(sendspace); - if (sysctlbyname("net.local.stream.sendspace", &sendspace, - &len, NULL, 0) < 0) - err(-1, "%s: sysctlbyname(net.local.stream.sendspace)", - test); - - if ((buf = calloc(1, sendspace)) == NULL) - err(-1, "%s: calloc", test); - - domainsocketpair(test, fd); - if (setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)) < 0) - err(-1, "%s: setsockopt(LOCAL_CREDS)", test); - tempfile(test, &putfd_1); - sendfd_payload(test, fd[0], putfd_1, buf, sendspace); - recvfd_payload(test, fd[1], &getfd_1, buf, sendspace); - close(putfd_1); - close(getfd_1); - closesocketpair(fd); - } - - printf("%s passed\n", test); - - return (0); -} From 05a298f61f7894da149deb096693e926cdd71245 Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 30 Dec 2015 13:49:20 +0000 Subject: [PATCH 17/55] - (Ab)use udivx for dividing the u_int pc_cpuid when implementing CPU_ISSET(), CPU_SET etc. in sparc64 asm. This approach has the benefit of not clobbering %y, allowing to revert r222827 and partially r222828. - In r222828, CATR() already was changed to use the equivalent of PCPU_GET(cpuid) instead of the MD module ID for KTR_CPU, so belatedly also catch up with the C side of ktr(9). Originally, in r203838 CATR() was moved away from directly reading the module ID or equivalent as that became impractical with other CPU types than USI/II supported. With r222828 in place, per-CPU data generally is set up soon enough, though, that employing PCPU things in ktr(9) also for use during early stages works. - Unfortunately, an exception to the latter is the ktr(9) use in pmap_bootstrap(), which actually is run so early that even checking for bootverbose being set via the loader doesn't work. Consequently, replace the ktr(9) use in pmap_bootstrap() with OF_printf(9) and put it under #ifdef DIAGNOSTIC instead. MFC after: 3 days --- sys/kern/kern_ktr.c | 3 - sys/sparc64/include/ktr.h | 17 ++---- sys/sparc64/sparc64/exception.S | 94 +++++++++++++----------------- sys/sparc64/sparc64/mp_exception.S | 23 ++++---- sys/sparc64/sparc64/pmap.c | 17 ++++-- sys/sparc64/sparc64/swtch.S | 6 +- 6 files changed, 68 insertions(+), 92 deletions(-) diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c index 32ded48465a9..6885706e4c06 100644 --- a/sys/kern/kern_ktr.c +++ b/sys/kern/kern_ktr.c @@ -55,9 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include -#ifdef __sparc64__ -#include -#endif #ifdef DDB #include diff --git a/sys/sparc64/include/ktr.h b/sys/sparc64/include/ktr.h index 0a7f233fe32c..b129dd895c62 100644 --- a/sys/sparc64/include/ktr.h +++ b/sys/sparc64/include/ktr.h @@ -34,14 +34,10 @@ #include -#ifndef LOCORE - -#define KTR_CPU PCPU_GET(mid) - -#else +#ifdef LOCORE /* - * XXX could really use another register... + * XXX could really use another register ... */ #define ATR(desc, r1, r2, r3, l1, l2) \ .sect .rodata ; \ @@ -70,9 +66,6 @@ l2: add r2, 1, r3 ; \ SET(l1 ## b, r3, r2) ; \ stx r2, [r1 + KTR_DESC] -/* - * NB: this clobbers %y. - */ #define CATR(mask, desc, r1, r2, r3, l1, l2, l3) \ setx mask, r3, r1 ; \ setx ktr_mask, r3, r2 ; \ @@ -82,16 +75,14 @@ l2: add r2, 1, r3 ; \ nop ; \ lduw [PCPU(CPUID)], r2 ; \ mov _NCPUBITS, r3 ; \ - mov %g0, %y ; \ - udiv r2, r3, r2 ; \ + udivx r2, r3, r2 ; \ srl r2, 0, r2 ; \ sllx r2, PTR_SHIFT, r2 ; \ SET(ktr_cpumask, r3, r1) ; \ ldx [r1 + r2], r1 ; \ lduw [PCPU(CPUID)], r2 ; \ mov _NCPUBITS, r3 ; \ - mov %g0, %y ; \ - udiv r2, r3, r2 ; \ + udivx r2, r3, r2 ; \ srl r2, 0, r2 ; \ smul r2, r3, r3 ; \ lduw [PCPU(CPUID)], r2 ; \ diff --git a/sys/sparc64/sparc64/exception.S b/sys/sparc64/sparc64/exception.S index b3830c08049d..8a1160ba80aa 100644 --- a/sys/sparc64/sparc64/exception.S +++ b/sys/sparc64/sparc64/exception.S @@ -2628,9 +2628,9 @@ ENTRY(tl0_ret) andn %l4, TSTATE_CWP_MASK, %g2 /* - * Save %y in an alternate global. + * Restore %y. Could also be below if we had more alternate globals. */ - mov %l5, %g4 + wr %l5, 0, %y /* * Setup %wstate for return. We need to restore the user window state @@ -2675,8 +2675,8 @@ tl0_ret_fill: * Fixup %tstate so the saved %cwp points to the current window and * restore it. */ - rdpr %cwp, %g1 - wrpr %g2, %g1, %tstate + rdpr %cwp, %g4 + wrpr %g2, %g4, %tstate /* * Restore the user window state. The transition bit was set above @@ -2686,24 +2686,19 @@ tl0_ret_fill: #if KTR_COMPILE & KTR_TRAP CATR(KTR_TRAP, "tl0_ret: td=%#lx pil=%#lx pc=%#lx npc=%#lx sp=%#lx" - , %g1, %g2, %g3, 7, 8, 9) - ldx [PCPU(CURTHREAD)], %g2 - stx %g2, [%g1 + KTR_PARM1] - rdpr %pil, %g2 - stx %g2, [%g1 + KTR_PARM2] - rdpr %tpc, %g2 - stx %g2, [%g1 + KTR_PARM3] - rdpr %tnpc, %g2 - stx %g2, [%g1 + KTR_PARM4] - stx %sp, [%g1 + KTR_PARM5] + , %g2, %g3, %g4, 7, 8, 9) + ldx [PCPU(CURTHREAD)], %g3 + stx %g3, [%g2 + KTR_PARM1] + rdpr %pil, %g3 + stx %g3, [%g2 + KTR_PARM2] + rdpr %tpc, %g3 + stx %g3, [%g2 + KTR_PARM3] + rdpr %tnpc, %g3 + stx %g3, [%g2 + KTR_PARM4] + stx %sp, [%g2 + KTR_PARM5] 9: #endif - /* - * Restore %y. Note that the CATR above clobbered it. - */ - wr %g4, 0, %y - /* * Return to usermode. */ @@ -2718,11 +2713,6 @@ tl0_ret_fill_end: stx %l6, [%l0 + KTR_PARM2] stx %sp, [%l0 + KTR_PARM3] 9: - - /* - * Restore %y clobbered by the CATR. This was saved in %l5 above. - */ - wr %l5, 0, %y #endif /* @@ -2890,36 +2880,34 @@ ENTRY(tl1_ret) andn %l0, TSTATE_CWP_MASK, %g1 mov %l1, %g2 mov %l2, %g3 - mov %l4, %g4 wrpr %l3, 0, %pil + wr %l4, 0, %y restore wrpr %g0, 2, %tl + rdpr %cwp, %g4 + wrpr %g1, %g4, %tstate wrpr %g2, 0, %tpc wrpr %g3, 0, %tnpc - rdpr %cwp, %g2 - wrpr %g1, %g2, %tstate #if KTR_COMPILE & KTR_TRAP CATR(KTR_TRAP, "tl1_ret: td=%#lx pil=%#lx ts=%#lx pc=%#lx sp=%#lx" - , %g1, %g2, %g3, 7, 8, 9) - ldx [PCPU(CURTHREAD)], %g2 - stx %g2, [%g1 + KTR_PARM1] - rdpr %pil, %g2 - stx %g2, [%g1 + KTR_PARM2] - rdpr %tstate, %g2 - stx %g2, [%g1 + KTR_PARM3] - rdpr %tpc, %g2 - stx %g2, [%g1 + KTR_PARM4] - stx %sp, [%g1 + KTR_PARM5] + , %g2, %g3, %g4, 7, 8, 9) + ldx [PCPU(CURTHREAD)], %g3 + stx %g3, [%g2 + KTR_PARM1] + rdpr %pil, %g3 + stx %g3, [%g2 + KTR_PARM2] + rdpr %tstate, %g3 + stx %g3, [%g2 + KTR_PARM3] + rdpr %tpc, %g3 + stx %g3, [%g2 + KTR_PARM4] + stx %sp, [%g2 + KTR_PARM5] 9: #endif - wr %g4, 0, %y - retry END(tl1_ret) @@ -3020,35 +3008,33 @@ ENTRY(tl1_intr) andn %l0, TSTATE_CWP_MASK, %g1 mov %l1, %g2 mov %l2, %g3 - mov %l4, %g4 wrpr %l3, 0, %pil + wr %l4, 0, %y restore wrpr %g0, 2, %tl + rdpr %cwp, %g4 + wrpr %g1, %g4, %tstate wrpr %g2, 0, %tpc wrpr %g3, 0, %tnpc - rdpr %cwp, %g2 - wrpr %g1, %g2, %tstate #if KTR_COMPILE & KTR_INTR CATR(KTR_INTR, "tl1_intr: td=%#x pil=%#lx ts=%#lx pc=%#lx sp=%#lx" - , %g1, %g2, %g3, 7, 8, 9) - ldx [PCPU(CURTHREAD)], %g2 - stx %g2, [%g1 + KTR_PARM1] - rdpr %pil, %g2 - stx %g2, [%g1 + KTR_PARM2] - rdpr %tstate, %g2 - stx %g2, [%g1 + KTR_PARM3] - rdpr %tpc, %g2 - stx %g2, [%g1 + KTR_PARM4] - stx %sp, [%g1 + KTR_PARM5] + , %g2, %g3, %g4, 7, 8, 9) + ldx [PCPU(CURTHREAD)], %g3 + stx %g3, [%g2 + KTR_PARM1] + rdpr %pil, %g3 + stx %g3, [%g2 + KTR_PARM2] + rdpr %tstate, %g3 + stx %g3, [%g2 + KTR_PARM3] + rdpr %tpc, %g3 + stx %g3, [%g2 + KTR_PARM4] + stx %sp, [%g2 + KTR_PARM5] 9: #endif - wr %g4, 0, %y - retry END(tl1_intr) diff --git a/sys/sparc64/sparc64/mp_exception.S b/sys/sparc64/sparc64/mp_exception.S index 54a5e4dc1241..9bd61b910021 100644 --- a/sys/sparc64/sparc64/mp_exception.S +++ b/sys/sparc64/sparc64/mp_exception.S @@ -38,12 +38,10 @@ __FBSDID("$FreeBSD$"); .register %g2, #ignore .register %g3, #ignore -#define IPI_DONE(r1, r2, r3, r4, r5, r6) \ - rd %y, r6 ; \ +#define IPI_DONE(r1, r2, r3, r4, r5) \ lduw [PCPU(CPUID)], r2 ; \ mov _NCPUBITS, r3 ; \ - mov %g0, %y ; \ - udiv r2, r3, r4 ; \ + udivx r2, r3, r4 ; \ srl r4, 0, r5 ; \ sllx r5, PTR_SHIFT, r5 ; \ add r1, r5, r1 ; \ @@ -51,7 +49,6 @@ __FBSDID("$FreeBSD$"); sub r2, r3, r3 ; \ mov 1, r4 ; \ sllx r4, r3, r4 ; \ - wr r6, %y ; \ ATOMIC_CLEAR_LONG(r1, r2, r3, r4) /* @@ -89,7 +86,7 @@ ENTRY(tl_ipi_spitfire_dcache_page_inval) 2: brgz,pt %g2, 1b sub %g2, %g4, %g2 - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_spitfire_dcache_page_inval) @@ -129,7 +126,7 @@ ENTRY(tl_ipi_spitfire_icache_page_inval) 2: brgz,pt %g2, 1b sub %g2, %g4, %g2 - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_spitfire_icache_page_inval) @@ -160,7 +157,7 @@ ENTRY(tl_ipi_cheetah_dcache_page_inval) blt,a,pt %xcc, 1b nop - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_cheetah_dcache_page_inval) @@ -216,7 +213,7 @@ ENTRY(tl_ipi_tlb_page_demap) stxa %g0, [%g2] ASI_IMMU_DEMAP flush %g3 - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_tlb_page_demap) @@ -259,7 +256,7 @@ ENTRY(tl_ipi_tlb_range_demap) blt,a,pt %xcc, 1b sethi %hi(KERNBASE), %g6 - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_tlb_range_demap) @@ -283,7 +280,7 @@ ENTRY(tl_ipi_tlb_context_demap) stxa %g0, [%g1] ASI_IMMU_DEMAP flush %g3 - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_tlb_context_demap) @@ -295,7 +292,7 @@ ENTRY(tl_ipi_stick_rd) rd %asr24, %g2 stx %g2, [%g1] - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_stick_rd) @@ -307,6 +304,6 @@ ENTRY(tl_ipi_tick_rd) rd %tick, %g2 stx %g2, [%g1] - IPI_DONE(%g5, %g1, %g2, %g3, %g4, %g6) + IPI_DONE(%g5, %g1, %g2, %g3, %g4) retry END(tl_ipi_tick_rd) diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index e0dca86e69b2..21800dddc9fe 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -346,14 +346,18 @@ pmap_bootstrap(u_int cpu_impl) if (OF_getprop(pmem, "available", mra, sz) == -1) OF_panic("%s: getprop /memory/available", __func__); sz /= sizeof(*mra); - CTR0(KTR_PMAP, "pmap_bootstrap: physical memory"); +#ifdef DIAGNOSTIC + OF_printf("pmap_bootstrap: physical memory\n"); +#endif qsort(mra, sz, sizeof (*mra), mr_cmp); physsz = 0; getenv_quad("hw.physmem", &physmem); physmem = btoc(physmem); for (i = 0, j = 0; i < sz; i++, j += 2) { - CTR2(KTR_PMAP, "start=%#lx size=%#lx", mra[i].mr_start, +#ifdef DIAGNOSTIC + OF_printf("start=%#lx size=%#lx\n", mra[i].mr_start, mra[i].mr_size); +#endif if (physmem != 0 && btoc(physsz + mra[i].mr_size) >= physmem) { if (btoc(physsz) < physmem) { phys_avail[j] = mra[i].mr_start; @@ -617,13 +621,16 @@ pmap_bootstrap(u_int cpu_impl) __func__); sz /= sizeof(*translations); translations_size = sz; - CTR0(KTR_PMAP, "pmap_bootstrap: translations"); +#ifdef DIAGNOSTIC + OF_printf("pmap_bootstrap: translations\n"); +#endif qsort(translations, sz, sizeof (*translations), om_cmp); for (i = 0; i < sz; i++) { - CTR3(KTR_PMAP, - "translation: start=%#lx size=%#lx tte=%#lx", +#ifdef DIAGNOSTIC + OF_printf("translation: start=%#lx size=%#lx tte=%#lx\n", translations[i].om_start, translations[i].om_size, translations[i].om_tte); +#endif if ((translations[i].om_tte & TD_V) == 0) continue; if (translations[i].om_start < VM_MIN_PROM_ADDRESS || diff --git a/sys/sparc64/sparc64/swtch.S b/sys/sparc64/sparc64/swtch.S index 22db8053f632..49d3cf5b7573 100644 --- a/sys/sparc64/sparc64/swtch.S +++ b/sys/sparc64/sparc64/swtch.S @@ -173,8 +173,7 @@ ENTRY(cpu_switch) * active on this CPU. */ mov _NCPUBITS, %l5 - mov %g0, %y - udiv %l3, %l5, %l6 + udivx %l3, %l5, %l6 srl %l6, 0, %l4 sllx %l4, PTR_SHIFT, %l4 add %l4, PM_ACTIVE, %l4 @@ -242,8 +241,7 @@ ENTRY(cpu_switch) * Mark the pmap as active on this CPU. */ mov _NCPUBITS, %l5 - mov %g0, %y - udiv %l3, %l5, %l6 + udivx %l3, %l5, %l6 srl %l6, 0, %l4 sllx %l4, PTR_SHIFT, %l4 add %l4, PM_ACTIVE, %l4 From 8646e68235beb11902d497ae1fe0fe4ee777fe11 Mon Sep 17 00:00:00 2001 From: hselasky Date: Wed, 30 Dec 2015 14:54:08 +0000 Subject: [PATCH 18/55] 10G ER/LR should present itself as LR. MFC after: 1 week Submitted by: Shahar Klein Sponsored by: Mellanox Technologies --- sys/dev/mlx5/mlx5_en/en.h | 2 +- sys/dev/mlx5/mlx5_en/mlx5_en_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h index bb779d2b7ddb..7f45444a163c 100644 --- a/sys/dev/mlx5/mlx5_en/en.h +++ b/sys/dev/mlx5/mlx5_en/en.h @@ -698,7 +698,7 @@ enum mlx5e_link_mode { MLX5E_56GBASE_R4 = 8, MLX5E_10GBASE_CR = 12, MLX5E_10GBASE_SR = 13, - MLX5E_10GBASE_ER = 14, + MLX5E_10GBASE_LR = 14, MLX5E_40GBASE_SR4 = 15, MLX5E_40GBASE_LR4 = 16, MLX5E_100GBASE_CR4 = 20, diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c index 63db417f8573..05ab87e8056a 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c @@ -106,8 +106,8 @@ static const struct { .subtype = IFM_10G_SR, .baudrate = IF_Gbps(10ULL), }, - [MLX5E_10GBASE_ER] = { - .subtype = IFM_10G_ER, + [MLX5E_10GBASE_LR] = { + .subtype = IFM_10G_LR, .baudrate = IF_Gbps(10ULL), }, [MLX5E_40GBASE_SR4] = { From 58f5ebe6c799b202d362f35351dd27efec212438 Mon Sep 17 00:00:00 2001 From: smh Date: Wed, 30 Dec 2015 14:57:42 +0000 Subject: [PATCH 19/55] Fix use of uninitialised Nflag Initialise Nflag to 0 preventing use of uninitialised value. Reported by: uqs MFC after: 1 week X-MFC-With: r292266 Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D4449 --- sbin/reboot/reboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c index eaaa5b55a96a..961ba419556b 100644 --- a/sbin/reboot/reboot.c +++ b/sbin/reboot/reboot.c @@ -76,7 +76,7 @@ main(int argc, char *argv[]) howto = RB_HALT; } else howto = 0; - lflag = nflag = qflag = 0; + lflag = nflag = qflag = Nflag = 0; while ((ch = getopt(argc, argv, "dk:lNnpqr")) != -1) switch(ch) { case 'd': From 3e461a3c0e58d75b4e1c3937831ed0e65f36ddc2 Mon Sep 17 00:00:00 2001 From: hselasky Date: Wed, 30 Dec 2015 14:58:55 +0000 Subject: [PATCH 20/55] Allow I2C to read address 0x51 as well as address 0x50. MFC after: 1 week Submitted by: Shahar Klein Sponsored by: Mellanox Technologies --- sys/dev/mlx5/mlx5_en/mlx5_en_main.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c index 05ab87e8056a..28b3054d2c21 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c @@ -2298,6 +2298,7 @@ mlx5e_ioctl(struct ifnet *ifp, u_long command, caddr_t data) int size_read = 0; int module_num; int max_mtu; + uint8_t read_addr; priv = ifp->if_softc; @@ -2484,11 +2485,21 @@ out: } /* - * Note that we ignore i2c.addr here. The driver hardcodes - * the address to 0x50, while standard expects it to be 0xA0. + * Currently 0XA0 and 0xA2 are the only addresses permitted. + * The internal conversion is as follows: */ + if (i2c.dev_addr == 0xA0) + read_addr = MLX5E_I2C_ADDR_LOW; + else if (i2c.dev_addr == 0xA2) + read_addr = MLX5E_I2C_ADDR_HIGH; + else { + if_printf(ifp, "Query eeprom failed, " + "Invalid Address: %X\n", i2c.dev_addr); + error = EINVAL; + goto err_i2c; + } error = mlx5_query_eeprom(priv->mdev, - MLX5E_I2C_ADDR_LOW, MLX5E_EEPROM_LOW_PAGE, + read_addr, MLX5E_EEPROM_LOW_PAGE, (uint32_t)i2c.offset, (uint32_t)i2c.len, module_num, (uint32_t *)i2c.data, &size_read); if (error) { @@ -2499,7 +2510,7 @@ out: if (i2c.len > MLX5_EEPROM_MAX_BYTES) { error = mlx5_query_eeprom(priv->mdev, - MLX5E_I2C_ADDR_LOW, MLX5E_EEPROM_LOW_PAGE, + read_addr, MLX5E_EEPROM_LOW_PAGE, (uint32_t)(i2c.offset + size_read), (uint32_t)(i2c.len - size_read), module_num, (uint32_t *)(i2c.data + size_read), &size_read); From a34806ae5e52827216675ac0a1e0a89722756f73 Mon Sep 17 00:00:00 2001 From: hselasky Date: Wed, 30 Dec 2015 15:01:47 +0000 Subject: [PATCH 21/55] Add support for modifying coalescing parameters runtime. MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/dev/mlx5/mlx5_en/en.h | 1 + sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c | 92 ++++++++++++++------------ sys/dev/mlx5/mlx5_en/mlx5_en_main.c | 56 ++++++++++++++++ 3 files changed, 107 insertions(+), 42 deletions(-) diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h index 7f45444a163c..5b22d76de8b7 100644 --- a/sys/dev/mlx5/mlx5_en/en.h +++ b/sys/dev/mlx5/mlx5_en/en.h @@ -787,5 +787,6 @@ void mlx5e_create_stats(struct sysctl_ctx_list *, struct sysctl_oid_list *, const char *, const char **, unsigned, u64 *); void mlx5e_send_nop(struct mlx5e_sq *, u32, bool); +int mlx5e_refresh_channel_params(struct mlx5e_priv *); #endif /* _MLX5_EN_H_ */ diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c b/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c index 17e446113dec..e389a07b108e 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c @@ -69,12 +69,49 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) } else { error = 0; } - /* check if device is gone */ if (priv->gone) { error = ENXIO; goto done; } + /* import RX coal time */ + if (priv->params_ethtool.rx_coalesce_usecs < 1) + priv->params_ethtool.rx_coalesce_usecs = 0; + else if (priv->params_ethtool.rx_coalesce_usecs > + MLX5E_FLD_MAX(cqc, cq_period)) { + priv->params_ethtool.rx_coalesce_usecs = + MLX5E_FLD_MAX(cqc, cq_period); + } + priv->params.rx_cq_moderation_usec = priv->params_ethtool.rx_coalesce_usecs; + + /* import RX coal pkts */ + if (priv->params_ethtool.rx_coalesce_pkts < 1) + priv->params_ethtool.rx_coalesce_pkts = 0; + else if (priv->params_ethtool.rx_coalesce_pkts > + MLX5E_FLD_MAX(cqc, cq_max_count)) { + priv->params_ethtool.rx_coalesce_pkts = + MLX5E_FLD_MAX(cqc, cq_max_count); + } + priv->params.rx_cq_moderation_pkts = priv->params_ethtool.rx_coalesce_pkts; + + /* import TX coal time */ + if (priv->params_ethtool.tx_coalesce_usecs < 1) + priv->params_ethtool.tx_coalesce_usecs = 0; + else if (priv->params_ethtool.tx_coalesce_usecs > + MLX5E_FLD_MAX(cqc, cq_period)) { + priv->params_ethtool.tx_coalesce_usecs = + MLX5E_FLD_MAX(cqc, cq_period); + } + priv->params.tx_cq_moderation_usec = priv->params_ethtool.tx_coalesce_usecs; + + /* import TX coal pkts */ + if (priv->params_ethtool.tx_coalesce_pkts < 1) + priv->params_ethtool.tx_coalesce_pkts = 0; + else if (priv->params_ethtool.tx_coalesce_pkts > + MLX5E_FLD_MAX(cqc, cq_max_count)) { + priv->params_ethtool.tx_coalesce_pkts = MLX5E_FLD_MAX(cqc, cq_max_count); + } + priv->params.tx_cq_moderation_pkts = priv->params_ethtool.tx_coalesce_pkts; if (&priv->params_ethtool.arg[arg2] == &priv->params_ethtool.rx_pauseframe_control || &priv->params_ethtool.arg[arg2] == &priv->params_ethtool.tx_pauseframe_control) { @@ -92,9 +129,19 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) } was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); - if (was_opened) - mlx5e_close_locked(priv->ifp); + if (was_opened) { + u64 *xarg = priv->params_ethtool.arg + arg2; + if (xarg == &priv->params_ethtool.tx_coalesce_pkts || + xarg == &priv->params_ethtool.rx_coalesce_pkts || + xarg == &priv->params_ethtool.tx_coalesce_usecs || + xarg == &priv->params_ethtool.rx_coalesce_usecs) { + /* avoid downing and upping the network interface */ + error = mlx5e_refresh_channel_params(priv); + goto done; + } + mlx5e_close_locked(priv->ifp); + } /* import TX queue size */ if (priv->params_ethtool.tx_queue_size < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { @@ -145,45 +192,6 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) priv->params_ethtool.tx_coalesce_mode = 1; priv->params.tx_cq_moderation_mode = priv->params_ethtool.tx_coalesce_mode; - /* import RX coal time */ - if (priv->params_ethtool.rx_coalesce_usecs < 1) - priv->params_ethtool.rx_coalesce_usecs = 0; - else if (priv->params_ethtool.rx_coalesce_usecs > - MLX5E_FLD_MAX(cqc, cq_period)) { - priv->params_ethtool.rx_coalesce_usecs = - MLX5E_FLD_MAX(cqc, cq_period); - } - priv->params.rx_cq_moderation_usec = priv->params_ethtool.rx_coalesce_usecs; - - /* import RX coal pkts */ - if (priv->params_ethtool.rx_coalesce_pkts < 1) - priv->params_ethtool.rx_coalesce_pkts = 0; - else if (priv->params_ethtool.rx_coalesce_pkts > - MLX5E_FLD_MAX(cqc, cq_max_count)) { - priv->params_ethtool.rx_coalesce_pkts = - MLX5E_FLD_MAX(cqc, cq_max_count); - } - priv->params.rx_cq_moderation_pkts = priv->params_ethtool.rx_coalesce_pkts; - - /* import TX coal time */ - if (priv->params_ethtool.tx_coalesce_usecs < 1) - priv->params_ethtool.tx_coalesce_usecs = 0; - else if (priv->params_ethtool.tx_coalesce_usecs > - MLX5E_FLD_MAX(cqc, cq_period)) { - priv->params_ethtool.tx_coalesce_usecs = - MLX5E_FLD_MAX(cqc, cq_period); - } - priv->params.tx_cq_moderation_usec = priv->params_ethtool.tx_coalesce_usecs; - - /* import TX coal pkts */ - if (priv->params_ethtool.tx_coalesce_pkts < 1) - priv->params_ethtool.tx_coalesce_pkts = 0; - else if (priv->params_ethtool.tx_coalesce_pkts > - MLX5E_FLD_MAX(cqc, cq_max_count)) { - priv->params_ethtool.tx_coalesce_pkts = MLX5E_FLD_MAX(cqc, cq_max_count); - } - priv->params.tx_cq_moderation_pkts = priv->params_ethtool.tx_coalesce_pkts; - /* we always agree to turn off HW LRO - but not always to turn on */ if (priv->params_ethtool.hw_lro) { if (priv->params_ethtool.hw_lro != 1) { diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c index 28b3054d2c21..82ea69d57486 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c @@ -1711,6 +1711,62 @@ mlx5e_close_channels(struct mlx5e_priv *priv) free(ptr, M_MLX5EN); } +static int +mlx5e_refresh_sq_params(struct mlx5e_priv *priv, struct mlx5e_sq *sq) +{ + return (mlx5_core_modify_cq_moderation(priv->mdev, &sq->cq.mcq, + priv->params.tx_cq_moderation_usec, + priv->params.tx_cq_moderation_pkts)); +} + +static int +mlx5e_refresh_rq_params(struct mlx5e_priv *priv, struct mlx5e_rq *rq) +{ + return (mlx5_core_modify_cq_moderation(priv->mdev, &rq->cq.mcq, + priv->params.rx_cq_moderation_usec, + priv->params.rx_cq_moderation_pkts)); +} + +static int +mlx5e_refresh_channel_params_sub(struct mlx5e_priv *priv, struct mlx5e_channel *c) +{ + int err; + int i; + + if (c == NULL) + return (EINVAL); + + err = mlx5e_refresh_rq_params(priv, &c->rq); + if (err) + goto done; + + for (i = 0; i != c->num_tc; i++) { + err = mlx5e_refresh_sq_params(priv, &c->sq[i]); + if (err) + goto done; + } +done: + return (err); +} + +int +mlx5e_refresh_channel_params(struct mlx5e_priv *priv) +{ + int i; + + if (priv->channel == NULL) + return (EINVAL); + + for (i = 0; i < priv->params.num_channels; i++) { + int err; + + err = mlx5e_refresh_channel_params_sub(priv, priv->channel[i]); + if (err) + return (err); + } + return (0); +} + static int mlx5e_open_tis(struct mlx5e_priv *priv, int tc) { From 4820136b6aadbc80d05702e16ef1cfc01bce3ccc Mon Sep 17 00:00:00 2001 From: dim Date: Wed, 30 Dec 2015 16:14:30 +0000 Subject: [PATCH 22/55] Drop the clang patch which adds recognition of 'CC' suffixes as aliases for --driver-mode=g++, since this was never upstreamed. For backwards compatibility, add a wrapper shell script. MFC after: 1 week --- .../llvm/patches/patch-02-add-CC-aliases.diff | 23 ------------------- .../llvm/tools/clang/tools/driver/driver.cpp | 2 -- usr.bin/clang/clang/CC.sh | 4 ++++ usr.bin/clang/clang/Makefile | 4 +++- 4 files changed, 7 insertions(+), 26 deletions(-) delete mode 100644 contrib/llvm/patches/patch-02-add-CC-aliases.diff create mode 100755 usr.bin/clang/clang/CC.sh diff --git a/contrib/llvm/patches/patch-02-add-CC-aliases.diff b/contrib/llvm/patches/patch-02-add-CC-aliases.diff deleted file mode 100644 index 884b14cd3cd7..000000000000 --- a/contrib/llvm/patches/patch-02-add-CC-aliases.diff +++ /dev/null @@ -1,23 +0,0 @@ -This patch adds "CC" and "clang-CC" to the list of program name aliases which -invoke the C++ compiler. - -Introduced here: http://svnweb.freebsd.org/changeset/base/257109 - -Index: tools/clang/tools/driver/driver.cpp -=================================================================== ---- tools/clang/tools/driver/driver.cpp -+++ tools/clang/tools/driver/driver.cpp -@@ -213,11 +213,13 @@ static const DriverSuffix *FindDriverSuffix(String - {"clang", nullptr}, - {"clang++", "--driver-mode=g++"}, - {"clang-c++", "--driver-mode=g++"}, -+ {"clang-CC", "--driver-mode=g++"}, - {"clang-cc", nullptr}, - {"clang-cpp", "--driver-mode=cpp"}, - {"clang-g++", "--driver-mode=g++"}, - {"clang-gcc", nullptr}, - {"clang-cl", "--driver-mode=cl"}, -+ {"CC", "--driver-mode=g++"}, - {"cc", nullptr}, - {"cpp", "--driver-mode=cpp"}, - {"cl", "--driver-mode=cl"}, diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp index b64fa8c9fa00..5925447841fc 100644 --- a/contrib/llvm/tools/clang/tools/driver/driver.cpp +++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp @@ -214,13 +214,11 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName) { {"clang", nullptr}, {"clang++", "--driver-mode=g++"}, {"clang-c++", "--driver-mode=g++"}, - {"clang-CC", "--driver-mode=g++"}, {"clang-cc", nullptr}, {"clang-cpp", "--driver-mode=cpp"}, {"clang-g++", "--driver-mode=g++"}, {"clang-gcc", nullptr}, {"clang-cl", "--driver-mode=cl"}, - {"CC", "--driver-mode=g++"}, {"cc", nullptr}, {"cpp", "--driver-mode=cpp"}, {"cl", "--driver-mode=cl"}, diff --git a/usr.bin/clang/clang/CC.sh b/usr.bin/clang/clang/CC.sh new file mode 100755 index 000000000000..45faeec0ec45 --- /dev/null +++ b/usr.bin/clang/clang/CC.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# $FreeBSD$ +# This file is in the public domain. +exec /usr/bin/c++ "$@" diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile index 18ee730e448a..1489a5e2d327 100644 --- a/usr.bin/clang/clang/Makefile +++ b/usr.bin/clang/clang/Makefile @@ -18,9 +18,11 @@ LINKS= ${BINDIR}/clang ${BINDIR}/clang++ \ MLINKS= clang.1 clang++.1 \ clang.1 clang-cpp.1 .if ${MK_CLANG_IS_CC} != "no" +SCRIPTS=CC.sh +SCRIPTSNAME=CC + LINKS+= ${BINDIR}/clang ${BINDIR}/cc \ ${BINDIR}/clang ${BINDIR}/c++ \ - ${BINDIR}/clang ${BINDIR}/CC \ ${BINDIR}/clang ${BINDIR}/cpp MLINKS+= clang.1 cc.1 \ clang.1 c++.1 \ From be33cc799d8409186373ac352c5ce5146e2feede Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 30 Dec 2015 17:10:03 +0000 Subject: [PATCH 23/55] This code is not in modules that need KPI stability so no need to use the wrapper functions as used in r252511. We can directly use the locking macros. Reviewed by: jtl, rwatson MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D4731 --- sys/netinet6/in6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 0f8fb67a143f..aa770199bd8e 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1552,7 +1552,7 @@ in6ifa_llaonifp(struct ifnet *ifp) if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) return (NULL); - if_addr_rlock(ifp); + IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1562,7 +1562,7 @@ in6ifa_llaonifp(struct ifnet *ifp) IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr)) break; } - if_addr_runlock(ifp); + IF_ADDR_RUNLOCK(ifp); return ((struct in6_ifaddr *)ifa); } From 5e0178e881f17f6b48e40715fbd8174a328caf87 Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 30 Dec 2015 17:36:34 +0000 Subject: [PATCH 24/55] Decode and print the ID_AA64* registers on boot. These registers hold information on what the core supports. In most cases these will be identical across most CPUs in the SoC, however there may be the case where, with a big.LITTLE setup they may differ. In this case we print the decoded data on all CPUs. Reviewed by: kib Sponsored by: ABT Systems Ltd Differential Revision: https://reviews.freebsd.org/D4725 --- sys/arm64/arm64/identcpu.c | 505 +++++++++++++++++++++++++++++++++-- sys/arm64/arm64/mp_machdep.c | 10 +- sys/arm64/include/armreg.h | 152 ++++++++++- sys/arm64/include/cpu.h | 1 + 4 files changed, 639 insertions(+), 29 deletions(-) diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index fb5092291d59..72e2021e6dc1 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -37,9 +37,12 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include +static int ident_lock; + char machine[] = "arm64"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, @@ -56,6 +59,7 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, * Aff0 - CPU number in Aff1 cluster */ uint64_t __cpu_affinity[MAXCPU]; +static u_int cpu_aff_levels; struct cpu_desc { u_int cpu_impl; @@ -64,9 +68,32 @@ struct cpu_desc { u_int cpu_revision; const char *cpu_impl_name; const char *cpu_part_name; + + uint64_t mpidr; + uint64_t id_aa64afr0; + uint64_t id_aa64afr1; + uint64_t id_aa64dfr0; + uint64_t id_aa64dfr1; + uint64_t id_aa64isar0; + uint64_t id_aa64isar1; + uint64_t id_aa64mmfr0; + uint64_t id_aa64mmfr1; + uint64_t id_aa64pfr0; + uint64_t id_aa64pfr1; }; struct cpu_desc cpu_desc[MAXCPU]; +static u_int cpu_print_regs; +#define PRINT_ID_AA64_AFR0 0x00000001 +#define PRINT_ID_AA64_AFR1 0x00000002 +#define PRINT_ID_AA64_DFR0 0x00000004 +#define PRINT_ID_AA64_DFR1 0x00000008 +#define PRINT_ID_AA64_ISAR0 0x00000010 +#define PRINT_ID_AA64_ISAR1 0x00000020 +#define PRINT_ID_AA64_MMFR0 0x00000040 +#define PRINT_ID_AA64_MMFR1 0x00000080 +#define PRINT_ID_AA64_PFR0 0x00000100 +#define PRINT_ID_AA64_PFR1 0x00000200 struct cpu_parts { u_int part_id; @@ -124,7 +151,398 @@ const struct cpu_implementers cpu_implementers[] = { CPU_IMPLEMENTER_NONE, }; -void identify_cpu(void); +void +print_cpu_features(u_int cpu) +{ + int printed; + + printf("CPU%3d: %s %s r%dp%d", cpu, cpu_desc[cpu].cpu_impl_name, + cpu_desc[cpu].cpu_part_name, cpu_desc[cpu].cpu_variant, + cpu_desc[cpu].cpu_revision); + + printf(" affinity:"); + switch(cpu_aff_levels) { + default: + case 4: + printf(" %2d", CPU_AFF3(cpu_desc[cpu].mpidr)); + /* FALLTHROUGH */ + case 3: + printf(" %2d", CPU_AFF2(cpu_desc[cpu].mpidr)); + /* FALLTHROUGH */ + case 2: + printf(" %2d", CPU_AFF1(cpu_desc[cpu].mpidr)); + /* FALLTHROUGH */ + case 1: + case 0: /* On UP this will be zero */ + printf(" %2d", CPU_AFF0(cpu_desc[cpu].mpidr)); + break; + } + printf("\n"); + + if (cpu != 0 && cpu_print_regs == 0) + return; + +#define SEP_STR ((printed++) == 0) ? "" : "," + + /* AArch64 Instruction Set Attribute Register 0 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) { + printed = 0; + printf(" Instruction Set Attributes 0 = <"); + switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_AES_NONE: + break; + case ID_AA64ISAR0_AES_BASE: + printf("%sAES", SEP_STR); + break; + case ID_AA64ISAR0_AES_PMULL: + printf("%sAES+PMULL", SEP_STR); + break; + default: + printf("%sUnknown AES", SEP_STR); + break; + } + + switch (ID_AA64ISAR0_SHA1(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_SHA1_NONE: + break; + case ID_AA64ISAR0_SHA1_BASE: + printf("%sSHA1", SEP_STR); + break; + default: + printf("%sUnknown SHA1", SEP_STR); + break; + } + + switch (ID_AA64ISAR0_SHA2(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_SHA2_NONE: + break; + case ID_AA64ISAR0_SHA2_BASE: + printf("%sSHA2", SEP_STR); + break; + default: + printf("%sUnknown SHA2", SEP_STR); + break; + } + + switch (ID_AA64ISAR0_CRC32(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_CRC32_NONE: + break; + case ID_AA64ISAR0_CRC32_BASE: + printf("%sCRC32", SEP_STR); + break; + default: + printf("%sUnknown CRC32", SEP_STR); + break; + } + + if ((cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK) != 0) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK); + + printf(">\n"); + } + + /* AArch64 Instruction Set Attribute Register 1 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR1) != 0) { + printf(" Instruction Set Attributes 1 = <%#lx>\n", + cpu_desc[cpu].id_aa64isar1); + } + + /* AArch64 Processor Feature Register 0 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR0) != 0) { + printed = 0; + printf(" Processor Features 0 = <"); + switch (ID_AA64PFR0_GIC(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_GIC_CPUIF_NONE: + break; + case ID_AA64PFR0_GIC_CPUIF_EN: + printf("%sGIC", SEP_STR); + break; + default: + printf("%sUnknown GIC interface", SEP_STR); + break; + } + + switch (ID_AA64PFR0_ADV_SIMD(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_ADV_SIMD_NONE: + break; + case ID_AA64PFR0_ADV_SIMD_IMPL: + printf("%sAdvSIMD", SEP_STR); + break; + default: + printf("%sUnknown AdvSIMD", SEP_STR); + break; + } + + switch (ID_AA64PFR0_FP(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_FP_NONE: + break; + case ID_AA64PFR0_FP_IMPL: + printf("%sFloat", SEP_STR); + break; + default: + printf("%sUnknown Float", SEP_STR); + break; + } + + switch (ID_AA64PFR0_EL3(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_EL3_NONE: + printf("%sNo EL3", SEP_STR); + break; + case ID_AA64PFR0_EL3_64: + printf("%sEL3", SEP_STR); + break; + case ID_AA64PFR0_EL3_64_32: + printf("%sEL3 32", SEP_STR); + break; + default: + printf("%sUnknown EL3", SEP_STR); + break; + } + + switch (ID_AA64PFR0_EL2(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_EL2_NONE: + printf("%sNo EL2", SEP_STR); + break; + case ID_AA64PFR0_EL2_64: + printf("%sEL2", SEP_STR); + break; + case ID_AA64PFR0_EL2_64_32: + printf("%sEL2 32", SEP_STR); + break; + default: + printf("%sUnknown EL2", SEP_STR); + break; + } + + switch (ID_AA64PFR0_EL1(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_EL1_64: + printf("%sEL1", SEP_STR); + break; + case ID_AA64PFR0_EL1_64_32: + printf("%sEL1 32", SEP_STR); + break; + default: + printf("%sUnknown EL1", SEP_STR); + break; + } + + switch (ID_AA64PFR0_EL0(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_EL0_64: + printf("%sEL0", SEP_STR); + break; + case ID_AA64PFR0_EL0_64_32: + printf("%sEL0 32", SEP_STR); + break; + default: + printf("%sUnknown EL0", SEP_STR); + break; + } + + if ((cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK) != 0) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK); + + printf(">\n"); + } + + /* AArch64 Processor Feature Register 1 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR1) != 0) { + printf(" Processor Features 1 = <%#lx>\n", + cpu_desc[cpu].id_aa64pfr1); + } + + /* AArch64 Memory Model Feature Register 0 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR0) != 0) { + printed = 0; + printf(" Memory Model Features 0 = <"); + switch (ID_AA64MMFR0_TGRAN4(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_TGRAN4_NONE: + break; + case ID_AA64MMFR0_TGRAN4_IMPL: + printf("%s4k Granule", SEP_STR); + break; + default: + printf("%sUnknown 4k Granule", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_TGRAN16(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_TGRAN16_NONE: + break; + case ID_AA64MMFR0_TGRAN16_IMPL: + printf("%s16k Granule", SEP_STR); + break; + default: + printf("%sUnknown 16k Granule", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_TGRAN64(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_TGRAN64_NONE: + break; + case ID_AA64MMFR0_TGRAN64_IMPL: + printf("%s64k Granule", SEP_STR); + break; + default: + printf("%sUnknown 64k Granule", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_BIGEND(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_BIGEND_FIXED: + break; + case ID_AA64MMFR0_BIGEND_MIXED: + printf("%sMixedEndian", SEP_STR); + break; + default: + printf("%sUnknown Endian switching", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_BIGEND_EL0(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_BIGEND_EL0_FIXED: + break; + case ID_AA64MMFR0_BIGEND_EL0_MIXED: + printf("%sEL0 MixEndian", SEP_STR); + break; + default: + printf("%sUnknown EL0 Endian switching", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_S_NS_MEM(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_S_NS_MEM_NONE: + break; + case ID_AA64MMFR0_S_NS_MEM_DISTINCT: + printf("%sS/NS Mem", SEP_STR); + break; + default: + printf("%sUnknown S/NS Mem", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_ASID_BITS(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_ASID_BITS_8: + printf("%s8bit ASID", SEP_STR); + break; + case ID_AA64MMFR0_ASID_BITS_16: + printf("%s16bit ASID", SEP_STR); + break; + default: + printf("%sUnknown ASID", SEP_STR); + break; + } + + switch (ID_AA64MMFR0_PA_RANGE(cpu_desc[cpu].id_aa64mmfr0)) { + case ID_AA64MMFR0_PA_RANGE_4G: + printf("%s4GB PA", SEP_STR); + break; + case ID_AA64MMFR0_PA_RANGE_64G: + printf("%s64GB PA", SEP_STR); + break; + case ID_AA64MMFR0_PA_RANGE_1T: + printf("%s1TB PA", SEP_STR); + break; + case ID_AA64MMFR0_PA_RANGE_4T: + printf("%s4TB PA", SEP_STR); + break; + case ID_AA64MMFR0_PA_RANGE_16T: + printf("%s16TB PA", SEP_STR); + break; + case ID_AA64MMFR0_PA_RANGE_256T: + printf("%s256TB PA", SEP_STR); + break; + default: + printf("%sUnknown PA Range", SEP_STR); + break; + } + + if ((cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK) != 0) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK); + printf(">\n"); + } + + /* AArch64 Memory Model Feature Register 1 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) { + printf(" Memory Model Features 1 = <%#lx>\n", + cpu_desc[cpu].id_aa64mmfr1); + } + + /* AArch64 Debug Feature Register 0 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR0) != 0) { + printed = 0; + printf(" Debug Features 0 = <"); + printf("%s%lu CTX Breakpoints", SEP_STR, + ID_AA64DFR0_CTX_CMPS(cpu_desc[cpu].id_aa64dfr0)); + + printf("%s%lu Watchpoints", SEP_STR, + ID_AA64DFR0_WRPS(cpu_desc[cpu].id_aa64dfr0)); + + printf("%s%lu Breakpoints", SEP_STR, + ID_AA64DFR0_BRPS(cpu_desc[cpu].id_aa64dfr0)); + + switch (ID_AA64DFR0_PMU_VER(cpu_desc[cpu].id_aa64dfr0)) { + case ID_AA64DFR0_PMU_VER_NONE: + break; + case ID_AA64DFR0_PMU_VER_3: + printf("%sPMUv3", SEP_STR); + break; + case ID_AA64DFR0_PMU_VER_IMPL: + printf("%sImplementation defined PMU", SEP_STR); + break; + default: + printf("%sUnknown PMU", SEP_STR); + break; + } + + switch (ID_AA64DFR0_TRACE_VER(cpu_desc[cpu].id_aa64dfr0)) { + case ID_AA64DFR0_TRACE_VER_NONE: + break; + case ID_AA64DFR0_TRACE_VER_IMPL: + printf("%sTrace", SEP_STR); + break; + default: + printf("%sUnknown Trace", SEP_STR); + break; + } + + switch (ID_AA64DFR0_DEBUG_VER(cpu_desc[cpu].id_aa64dfr0)) { + case ID_AA64DFR0_DEBUG_VER_8: + printf("%sDebug v8", SEP_STR); + break; + default: + printf("%sUnknown Debug", SEP_STR); + break; + } + + if (cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK); + printf(">\n"); + } + + /* AArch64 Memory Model Feature Register 1 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR1) != 0) { + printf(" Debug Features 1 = <%#lx>\n", + cpu_desc[cpu].id_aa64dfr1); + } + + /* AArch64 Auxiliary Feature Register 0 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR0) != 0) { + printf(" Auxiliary Features 0 = <%#lx>\n", + cpu_desc[cpu].id_aa64afr0); + } + + /* AArch64 Auxiliary Feature Register 1 */ + if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR1) != 0) { + printf(" Auxiliary Features 1 = <%#lx>\n", + cpu_desc[cpu].id_aa64afr1); + } + +#undef SEP_STR +} void identify_cpu(void) @@ -133,7 +551,6 @@ identify_cpu(void) u_int impl_id; u_int part_id; u_int cpu; - uint64_t mpidr; size_t i; const struct cpu_parts *cpu_partsp = NULL; @@ -171,19 +588,77 @@ identify_cpu(void) cpu_desc[cpu].cpu_variant = CPU_VAR(midr); /* Save affinity for current CPU */ - mpidr = get_mpidr(); - CPU_AFFINITY(cpu) = mpidr & CPU_AFF_MASK; + cpu_desc[cpu].mpidr = get_mpidr(); + CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK; - /* Print details for boot CPU or if we want verbose output */ - if (cpu == 0 || bootverbose) { - printf("CPU(%d): %s %s r%dp%d\n", cpu, - cpu_desc[cpu].cpu_impl_name, - cpu_desc[cpu].cpu_part_name, - cpu_desc[cpu].cpu_variant, - cpu_desc[cpu].cpu_revision); + cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1); + cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1); + cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1); + cpu_desc[cpu].id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1); + cpu_desc[cpu].id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1); + cpu_desc[cpu].id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); + cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1); + cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1); + + if (cpu != 0) { + /* + * This code must run on one cpu at a time, but we are + * not scheduling on the current core so implement a + * simple spinlock. + */ + while (atomic_cmpset_acq_int(&ident_lock, 0, 1) == 0) + __asm __volatile("wfe" ::: "memory"); + + switch (cpu_aff_levels) { + case 0: + if (CPU_AFF0(cpu_desc[cpu].mpidr) != + CPU_AFF0(cpu_desc[0].mpidr)) + cpu_aff_levels = 1; + /* FALLTHROUGH */ + case 1: + if (CPU_AFF1(cpu_desc[cpu].mpidr) != + CPU_AFF1(cpu_desc[0].mpidr)) + cpu_aff_levels = 2; + /* FALLTHROUGH */ + case 2: + if (CPU_AFF2(cpu_desc[cpu].mpidr) != + CPU_AFF2(cpu_desc[0].mpidr)) + cpu_aff_levels = 3; + /* FALLTHROUGH */ + case 3: + if (CPU_AFF3(cpu_desc[cpu].mpidr) != + CPU_AFF3(cpu_desc[0].mpidr)) + cpu_aff_levels = 4; + break; + } + + if (cpu_desc[cpu].id_aa64afr0 != cpu_desc[0].id_aa64afr0) + cpu_print_regs |= PRINT_ID_AA64_AFR0; + if (cpu_desc[cpu].id_aa64afr1 != cpu_desc[0].id_aa64afr1) + cpu_print_regs |= PRINT_ID_AA64_AFR1; + + if (cpu_desc[cpu].id_aa64dfr0 != cpu_desc[0].id_aa64dfr0) + cpu_print_regs |= PRINT_ID_AA64_DFR0; + if (cpu_desc[cpu].id_aa64dfr1 != cpu_desc[0].id_aa64dfr1) + cpu_print_regs |= PRINT_ID_AA64_DFR1; + + if (cpu_desc[cpu].id_aa64isar0 != cpu_desc[0].id_aa64isar0) + cpu_print_regs |= PRINT_ID_AA64_ISAR0; + if (cpu_desc[cpu].id_aa64isar1 != cpu_desc[0].id_aa64isar1) + cpu_print_regs |= PRINT_ID_AA64_ISAR1; + + if (cpu_desc[cpu].id_aa64mmfr0 != cpu_desc[0].id_aa64mmfr0) + cpu_print_regs |= PRINT_ID_AA64_MMFR0; + if (cpu_desc[cpu].id_aa64mmfr1 != cpu_desc[0].id_aa64mmfr1) + cpu_print_regs |= PRINT_ID_AA64_MMFR1; + + if (cpu_desc[cpu].id_aa64pfr0 != cpu_desc[0].id_aa64pfr0) + cpu_print_regs |= PRINT_ID_AA64_PFR0; + if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1) + cpu_print_regs |= PRINT_ID_AA64_PFR1; + + /* Wake up the other CPUs */ + atomic_store_rel_int(&ident_lock, 0); + __asm __volatile("sev" ::: "memory"); } - - if (bootverbose) - printf("CPU%u affinity: %u.%u.%u.%u\n", 0, CPU_AFF0(mpidr), - CPU_AFF1(mpidr), CPU_AFF2(mpidr), CPU_AFF3(mpidr)); } diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c index 73adb760e05d..19cee7788c3f 100644 --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -175,7 +175,7 @@ arm64_cpu_attach(device_t dev) static void release_aps(void *dummy __unused) { - int i; + int cpu, i; /* Setup the IPI handler */ for (i = 0; i < COUNT_IPI; i++) @@ -188,8 +188,14 @@ release_aps(void *dummy __unused) printf("Release APs\n"); for (i = 0; i < 2000; i++) { - if (smp_started) + if (smp_started) { + for (cpu = 0; cpu <= mp_maxid; cpu++) { + if (CPU_ABSENT(cpu)) + continue; + print_cpu_features(cpu); + } return; + } DELAY(1000); } diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index de8ce40c5f26..f8d19960139e 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -121,19 +121,147 @@ /* ICC_SRE_EL2 */ #define ICC_SRE_EL2_EN (1U << 3) +/* ID_AA64DFR0_EL1 */ +#define ID_AA64DFR0_MASK 0xf0f0ffff +#define ID_AA64DFR0_DEBUG_VER_SHIFT 0 +#define ID_AA64DFR0_DEBUG_VER_MASK (0xf << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK) +#define ID_AA64DFR0_DEBUG_VER_8 (0x6 << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_SHIFT 4 +#define ID_AA64DFR0_TRACE_VER_MASK (0xf << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK) +#define ID_AA64DFR0_TRACE_VER_NONE (0x0 << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_IMPL (0x1 << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_SHIFT 8 +#define ID_AA64DFR0_PMU_VER_MASK (0xf << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK) +#define ID_AA64DFR0_PMU_VER_NONE (0x0 << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3 (0x1 << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_IMPL (0xf << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_BRPS_SHIFT 12 +#define ID_AA64DFR0_BRPS_MASK (0xf << ID_AA64DFR0_BRPS_SHIFT) +#define ID_AA64DFR0_BRPS(x) \ + ((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_WRPS_SHIFT 20 +#define ID_AA64DFR0_WRPS_MASK (0xf << ID_AA64DFR0_WRPS_SHIFT) +#define ID_AA64DFR0_WRPS(x) \ + ((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_CTX_CMPS_SHIFT 28 +#define ID_AA64DFR0_CTX_CMPS_MASK (0xf << ID_AA64DFR0_CTX_CMPS_SHIFT) +#define ID_AA64DFR0_CTX_CMPS(x) \ + ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1) + +/* ID_AA64ISAR0_EL1 */ +#define ID_AA64ISAR0_MASK 0x000ffff0 +#define ID_AA64ISAR0_AES_SHIFT 4 +#define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK) +#define ID_AA64ISAR0_AES_NONE (0x0 << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_BASE (0x1 << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_PMULL (0x2 << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_SHA1_SHIFT 8 +#define ID_AA64ISAR0_SHA1_MASK (0xf << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK) +#define ID_AA64ISAR0_SHA1_NONE (0x0 << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1_BASE (0x1 << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA2_SHIFT 12 +#define ID_AA64ISAR0_SHA2_MASK (0xf << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK) +#define ID_AA64ISAR0_SHA2_NONE (0x0 << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2_BASE (0x1 << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_CRC32_SHIFT 16 +#define ID_AA64ISAR0_CRC32_MASK (0xf << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK) +#define ID_AA64ISAR0_CRC32_NONE (0x0 << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32_BASE (0x1 << ID_AA64ISAR0_CRC32_SHIFT) + +/* ID_AA64MMFR0_EL1 */ +#define ID_AA64MMFR0_MASK 0xffffffff +#define ID_AA64MMFR0_PA_RANGE_SHIFT 0 +#define ID_AA64MMFR0_PA_RANGE_MASK (0xf << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE(x) ((x) & ID_AA64MMFR0_PA_RANGE_MASK) +#define ID_AA64MMFR0_PA_RANGE_4G (0x0 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_64G (0x1 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_1T (0x2 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_4T (0x3 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_16T (0x4 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_256T (0x5 << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_SHIFT 4 +#define ID_AA64MMFR0_ASID_BITS_MASK (0xf << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS(x) ((x) & ID_AA64MMFR0_ASID_BITS_MASK) +#define ID_AA64MMFR0_ASID_BITS_8 (0x0 << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_16 (0x2 << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_BIGEND_SHIFT 8 +#define ID_AA64MMFR0_BIGEND_MASK (0xf << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND(x) ((x) & ID_AA64MMFR0_BIGEND_MASK) +#define ID_AA64MMFR0_BIGEND_FIXED (0x0 << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND_MIXED (0x1 << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_SHIFT 12 +#define ID_AA64MMFR0_S_NS_MEM_MASK (0xf << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM(x) ((x) & ID_AA64MMFR0_S_NS_MEM_MASK) +#define ID_AA64MMFR0_S_NS_MEM_NONE (0x0 << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_DISTINCT (0x1 << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_SHIFT 16 +#define ID_AA64MMFR0_BIGEND_EL0_MASK (0xf << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0(x) ((x) & ID_AA64MMFR0_BIGEND_EL0_MASK) +#define ID_AA64MMFR0_BIGEND_EL0_FIXED (0x0 << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_MIXED (0x1 << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_TGRAN16_SHIFT 20 +#define ID_AA64MMFR0_TGRAN16_MASK (0xf << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16(x) ((x) & ID_AA64MMFR0_TGRAN16_MASK) +#define ID_AA64MMFR0_TGRAN16_NONE (0x0 << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16_IMPL (0x1 << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 +#define ID_AA64MMFR0_TGRAN64_MASK (0xf << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64(x) ((x) & ID_AA64MMFR0_TGRAN64_MASK) +#define ID_AA64MMFR0_TGRAN64_IMPL (0x0 << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64_NONE (0xf << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_TGRAN4_MASK (0xf << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4(x) ((x) & ID_AA64MMFR0_TGRAN4_MASK) +#define ID_AA64MMFR0_TGRAN4_IMPL (0x0 << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4_NONE (0xf << ID_AA64MMFR0_TGRAN4_SHIFT) + /* ID_AA64PFR0_EL1 */ -#define ID_AA64PFR0_EL0_MASK (0xf << 0) -#define ID_AA64PFR0_EL1_MASK (0xf << 4) -#define ID_AA64PFR0_EL2_MASK (0xf << 8) -#define ID_AA64PFR0_EL3_MASK (0xf << 12) -#define ID_AA64PFR0_FP_MASK (0xf << 16) -#define ID_AA64PFR0_FP_IMPL (0x0 << 16) /* Floating-point implemented */ -#define ID_AA64PFR0_FP_NONE (0xf << 16) /* Floating-point not implemented */ -#define ID_AA64PFR0_ADV_SIMD_MASK (0xf << 20) -#define ID_AA64PFR0_GIC_SHIFT (24) -#define ID_AA64PFR0_GIC_BITS (0x4) /* Number of bits in GIC field */ -#define ID_AA64PFR0_GIC_MASK (0xf << ID_AA64PFR0_GIC_SHIFT) -#define ID_AA64PFR0_GIC_CPUIF_EN (0x1 << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_MASK 0x0fffffff +#define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_EL0_MASK (0xf << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0(x) ((x) & ID_AA64PFR0_EL0_MASK) +#define ID_AA64PFR0_EL0_64 (1 << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0_64_32 (2 << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL1_SHIFT 4 +#define ID_AA64PFR0_EL1_MASK (0xf << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1(x) ((x) & ID_AA64PFR0_EL1_MASK) +#define ID_AA64PFR0_EL1_64 (1 << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1_64_32 (2 << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL2_SHIFT 8 +#define ID_AA64PFR0_EL2_MASK (0xf << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2(x) ((x) & ID_AA64PFR0_EL2_MASK) +#define ID_AA64PFR0_EL2_NONE (0 << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64 (1 << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64_32 (2 << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL3_SHIFT 12 +#define ID_AA64PFR0_EL3_MASK (0xf << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3(x) ((x) & ID_AA64PFR0_EL3_MASK) +#define ID_AA64PFR0_EL3_NONE (0 << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64 (1 << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64_32 (2 << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_FP_SHIFT 16 +#define ID_AA64PFR0_FP_MASK (0xf << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP(x) ((x) & ID_AA64PFR0_FP_MASK) +#define ID_AA64PFR0_FP_IMPL (0x0 << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP_NONE (0xf << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_SHIFT 20 +#define ID_AA64PFR0_ADV_SIMD_MASK (0xf << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD(x) ((x) & ID_AA64PFR0_ADV_SIMD_MASK) +#define ID_AA64PFR0_ADV_SIMD_IMPL (0x0 << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_NONE (0xf << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_GIC_BITS 0x4 /* Number of bits in GIC field */ +#define ID_AA64PFR0_GIC_SHIFT 24 +#define ID_AA64PFR0_GIC_MASK (0xf << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC(x) ((x) & ID_AA64PFR0_GIC_MASK) +#define ID_AA64PFR0_GIC_CPUIF_NONE (0x0 << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC_CPUIF_EN (0x1 << ID_AA64PFR0_GIC_SHIFT) /* MAIR_EL1 - Memory Attribute Indirection Register */ #define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8)) diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h index 14bffbc1f536..8f14e8238967 100644 --- a/sys/arm64/include/cpu.h +++ b/sys/arm64/include/cpu.h @@ -145,6 +145,7 @@ void cpu_halt(void) __dead2; void cpu_reset(void) __dead2; void fork_trampoline(void); void identify_cpu(void); +void print_cpu_features(u_int); void swi_vm(void *v); #define CPU_AFFINITY(cpu) __cpu_affinity[(cpu)] From df8d88f0e5d77d48c300b211488bd5da507ae857 Mon Sep 17 00:00:00 2001 From: jtl Date: Wed, 30 Dec 2015 18:04:50 +0000 Subject: [PATCH 25/55] Fix a file descriptor leak in mdXhl.c (which is used by numerous hashing algorithms. CID: 1305669,1305611,1305663,1305603,1305584,1305639,1346865,1305601 Differential Revision: https://reviews.freebsd.org/D4732 Reviewed by: allanjude, delphij MFC after: 2 weeks Sponsored by: Juniper Networks --- lib/libmd/mdXhl.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/libmd/mdXhl.c b/lib/libmd/mdXhl.c index f2e918f548d9..378d8adfafc0 100644 --- a/lib/libmd/mdXhl.c +++ b/lib/libmd/mdXhl.c @@ -59,14 +59,18 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len) f = open(filename, O_RDONLY); if (f < 0) return 0; - if (fstat(f, &stbuf) < 0) - return 0; + if (fstat(f, &stbuf) < 0) { + i = -1; + goto error; + } if (ofs > stbuf.st_size) ofs = stbuf.st_size; if ((len == 0) || (len > stbuf.st_size - ofs)) len = stbuf.st_size - ofs; - if (lseek(f, ofs, SEEK_SET) < 0) - return 0; + if (lseek(f, ofs, SEEK_SET) < 0) { + i = -1; + goto error; + } n = len; i = 0; while (n > 0) { @@ -79,6 +83,7 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len) MDXUpdate(&ctx, buffer, i); n -= i; } +error: e = errno; close(f); errno = e; From 3504bdc019d56f8c0bd0d7e965e08f67b912c3c4 Mon Sep 17 00:00:00 2001 From: jtl Date: Wed, 30 Dec 2015 18:08:05 +0000 Subject: [PATCH 26/55] Add the appropriate case statement for IPV6_BINDMULTI so the option can be retrieved with getsockopt(). CID: 1229928 Differential Revision: https://reviews.freebsd.org/D4737 Reviewed by: adrian Sponsored by: Juniper Networks --- sys/netinet6/ip6_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 778f39dab438..af9fdbafe195 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1830,6 +1830,7 @@ do { \ case IPV6_RSSBUCKETID: case IPV6_RECVRSSBUCKETID: #endif + case IPV6_BINDMULTI: switch (optname) { case IPV6_RECVHOPOPTS: From 20eb798a6f54b70ee706a991ffbc3eefea7b0e8b Mon Sep 17 00:00:00 2001 From: ngie Date: Wed, 30 Dec 2015 18:13:43 +0000 Subject: [PATCH 27/55] Rename `recvfd` and `sendfd` variables in recvfd/sendfd functions to avoid -Wshadow issues with gcc MFC after: 1 week Reported by: bz, jenkins Sponsored by: EMC / Isilon Storage Division --- tests/sys/kern/unix_passfd_test.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c index 44f136fc1fea..12568389bc3d 100644 --- a/tests/sys/kern/unix_passfd_test.c +++ b/tests/sys/kern/unix_passfd_test.c @@ -109,7 +109,7 @@ samefile(struct stat *sb1, struct stat *sb2) } static void -sendfd_payload(int sockfd, int sendfd, void *payload, size_t paylen) +sendfd_payload(int sockfd, int send_fd, void *payload, size_t paylen) { struct iovec iovec; char message[CMSG_SPACE(sizeof(int))]; @@ -133,7 +133,7 @@ sendfd_payload(int sockfd, int sendfd, void *payload, size_t paylen) cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); cmsghdr->cmsg_level = SOL_SOCKET; cmsghdr->cmsg_type = SCM_RIGHTS; - memcpy(CMSG_DATA(cmsghdr), &sendfd, sizeof(int)); + memcpy(CMSG_DATA(cmsghdr), &send_fd, sizeof(int)); len = sendmsg(sockfd, &msghdr, 0); ATF_REQUIRE_MSG(len != -1, "sendmsg failed: %s", strerror(errno)); @@ -143,15 +143,15 @@ sendfd_payload(int sockfd, int sendfd, void *payload, size_t paylen) } static void -sendfd(int sockfd, int sendfd) +sendfd(int sockfd, int send_fd) { char ch = 0; - return (sendfd_payload(sockfd, sendfd, &ch, sizeof(ch))); + return (sendfd_payload(sockfd, send_fd, &ch, sizeof(ch))); } static void -recvfd_payload(int sockfd, int *recvfd, void *buf, size_t buflen) +recvfd_payload(int sockfd, int *recv_fd, void *buf, size_t buflen) { struct cmsghdr *cmsghdr; char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; @@ -178,25 +178,25 @@ recvfd_payload(int sockfd, int *recvfd, void *buf, size_t buflen) cmsghdr = CMSG_FIRSTHDR(&msghdr); ATF_REQUIRE_MSG(cmsghdr != NULL, "recvmsg: did not receive control message"); - *recvfd = -1; + *recv_fd = -1; for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { if (cmsghdr->cmsg_level == SOL_SOCKET && cmsghdr->cmsg_type == SCM_RIGHTS && cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { - memcpy(recvfd, CMSG_DATA(cmsghdr), sizeof(int)); - ATF_REQUIRE(*recvfd != -1); + memcpy(recv_fd, CMSG_DATA(cmsghdr), sizeof(int)); + ATF_REQUIRE(*recv_fd != -1); } } - ATF_REQUIRE_MSG(*recvfd != -1, + ATF_REQUIRE_MSG(*recv_fd != -1, "recvmsg: did not receive single-fd message"); } static void -recvfd(int sockfd, int *recvfd) +recvfd(int sockfd, int *recv_fd) { char ch = 0; - return (recvfd_payload(sockfd, recvfd, &ch, sizeof(ch))); + return (recvfd_payload(sockfd, recv_fd, &ch, sizeof(ch))); } /* From 145664c6751612bf7643f2b985f18e5c0695be8b Mon Sep 17 00:00:00 2001 From: marius Date: Wed, 30 Dec 2015 18:57:29 +0000 Subject: [PATCH 28/55] Change the - hopefully - last piece of ktr(9) to use PCPU_GET(cpuid) instead of the MD module ID for KTR_CPU. --- sys/sparc64/include/ktr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sparc64/include/ktr.h b/sys/sparc64/include/ktr.h index b129dd895c62..f8c1b43e9cd0 100644 --- a/sys/sparc64/include/ktr.h +++ b/sys/sparc64/include/ktr.h @@ -59,7 +59,7 @@ l2: add r2, 1, r3 ; \ add r1, r2, r1 ; \ rd %tick, r2 ; \ stx r2, [r1 + KTR_TIMESTAMP] ; \ - lduw [PCPU(MID)], r2 ; \ + lduw [PCPU(CPUID)], r2 ; \ stw r2, [r1 + KTR_CPU] ; \ stw %g0, [r1 + KTR_LINE] ; \ stx %g0, [r1 + KTR_FILE] ; \ From f0089fdb6f3501da95454665558d11f5ee6c699c Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 30 Dec 2015 19:49:22 +0000 Subject: [PATCH 29/55] Force nullfs vnode reclaim after unlinking, to potentially unlink lower vnode. Otherwise, reference to the lower vnode from the upper one prevents final unlink. PR: 178238 Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/fs/nullfs/null_vnops.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 4762a3c8679e..72b884f65cac 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -568,14 +568,16 @@ static int null_remove(struct vop_remove_args *ap) { int retval, vreleit; - struct vnode *lvp; + struct vnode *lvp, *vp; - if (vrefcnt(ap->a_vp) > 1) { - lvp = NULLVPTOLOWERVP(ap->a_vp); + vp = ap->a_vp; + if (vrefcnt(vp) > 1) { + lvp = NULLVPTOLOWERVP(vp); VREF(lvp); vreleit = 1; } else vreleit = 0; + VTONULL(vp)->null_flags |= NULLV_DROP; retval = null_bypass(&ap->a_gen); if (vreleit != 0) vrele(lvp); From 2502999acda612f4678ed5461267695dd4647fb8 Mon Sep 17 00:00:00 2001 From: allanjude Date: Wed, 30 Dec 2015 22:43:07 +0000 Subject: [PATCH 30/55] Break up opencrypto/xform.c so it can be reused piecemeal Keep xform.c as a meta-file including the broken out bits existing code that includes xform.c continues to work as normal Individual algorithms can now be reused elsewhere, including outside of the kernel Reviewed by: bapt (previous version), gnn, delphij Approved by: secteam MFC after: 1 week Sponsored by: ScaleEngine Inc. Differential Revision: https://reviews.freebsd.org/D4674 --- sys/crypto/sha1.h | 2 +- sys/opencrypto/skipjack.h | 5 + sys/opencrypto/xform.c | 914 +------------------------------- sys/opencrypto/xform.h | 80 +-- sys/opencrypto/xform_aes_icm.c | 152 ++++++ sys/opencrypto/xform_aes_xts.c | 164 ++++++ sys/opencrypto/xform_auth.h | 89 ++++ sys/opencrypto/xform_blf.c | 127 +++++ sys/opencrypto/xform_cast5.c | 107 ++++ sys/opencrypto/xform_cml.c | 113 ++++ sys/opencrypto/xform_comp.h | 52 ++ sys/opencrypto/xform_deflate.c | 86 +++ sys/opencrypto/xform_des1.c | 116 ++++ sys/opencrypto/xform_des3.c | 119 +++++ sys/opencrypto/xform_enc.h | 92 ++++ sys/opencrypto/xform_gmac.c | 99 ++++ sys/opencrypto/xform_md5.c | 81 +++ sys/opencrypto/xform_null.c | 136 +++++ sys/opencrypto/xform_rijndael.c | 113 ++++ sys/opencrypto/xform_rmd160.c | 75 +++ sys/opencrypto/xform_sha1.c | 93 ++++ sys/opencrypto/xform_sha2.c | 109 ++++ sys/opencrypto/xform_skipjack.c | 117 ++++ sys/opencrypto/xform_userland.h | 48 ++ 24 files changed, 2118 insertions(+), 971 deletions(-) create mode 100644 sys/opencrypto/xform_aes_icm.c create mode 100644 sys/opencrypto/xform_aes_xts.c create mode 100644 sys/opencrypto/xform_auth.h create mode 100644 sys/opencrypto/xform_blf.c create mode 100644 sys/opencrypto/xform_cast5.c create mode 100644 sys/opencrypto/xform_cml.c create mode 100644 sys/opencrypto/xform_comp.h create mode 100644 sys/opencrypto/xform_deflate.c create mode 100644 sys/opencrypto/xform_des1.c create mode 100644 sys/opencrypto/xform_des3.c create mode 100644 sys/opencrypto/xform_enc.h create mode 100644 sys/opencrypto/xform_gmac.c create mode 100644 sys/opencrypto/xform_md5.c create mode 100644 sys/opencrypto/xform_null.c create mode 100644 sys/opencrypto/xform_rijndael.c create mode 100644 sys/opencrypto/xform_rmd160.c create mode 100644 sys/opencrypto/xform_sha1.c create mode 100644 sys/opencrypto/xform_sha2.c create mode 100644 sys/opencrypto/xform_skipjack.c create mode 100644 sys/opencrypto/xform_userland.h diff --git a/sys/crypto/sha1.h b/sys/crypto/sha1.h index 3686d7ddde51..d32aa8a17842 100644 --- a/sys/crypto/sha1.h +++ b/sys/crypto/sha1.h @@ -53,6 +53,7 @@ struct sha1_ctxt { } m; u_int8_t count; }; +typedef struct sha1_ctxt SHA1_CTX; #ifdef _KERNEL extern void sha1_init(struct sha1_ctxt *); @@ -61,7 +62,6 @@ extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t); extern void sha1_result(struct sha1_ctxt *, caddr_t); /* compatibilty with other SHA1 source codes */ -typedef struct sha1_ctxt SHA1_CTX; #define SHA1Init(x) sha1_init((x)) #define SHA1Update(x, y, z) sha1_loop((x), (y), (z)) #define SHA1Final(x, y) sha1_result((y), (x)) diff --git a/sys/opencrypto/skipjack.h b/sys/opencrypto/skipjack.h index 3e88418ce217..80367ea4177b 100644 --- a/sys/opencrypto/skipjack.h +++ b/sys/opencrypto/skipjack.h @@ -14,6 +14,11 @@ * 29 May 1998 */ +#ifndef _SKIPJACK_H_ +#define _SKIPJACK_H_ + extern void skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key); extern void skipjack_backwards(u_int8_t *cipher, u_int8_t *plain, u_int8_t **key); extern void subkey_table_gen(u_int8_t *key, u_int8_t **key_tables); + +#endif diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c index 3dee3664e0a4..ee9f0b6484e3 100644 --- a/sys/opencrypto/xform.c +++ b/sys/opencrypto/xform.c @@ -75,196 +75,9 @@ __FBSDID("$FreeBSD$"); #include #include -static int null_setkey(u_int8_t **, u_int8_t *, int); -static int des1_setkey(u_int8_t **, u_int8_t *, int); -static int des3_setkey(u_int8_t **, u_int8_t *, int); -static int blf_setkey(u_int8_t **, u_int8_t *, int); -static int cast5_setkey(u_int8_t **, u_int8_t *, int); -static int skipjack_setkey(u_int8_t **, u_int8_t *, int); -static int rijndael128_setkey(u_int8_t **, u_int8_t *, int); -static int aes_icm_setkey(u_int8_t **, u_int8_t *, int); -static int aes_xts_setkey(u_int8_t **, u_int8_t *, int); -static int cml_setkey(u_int8_t **, u_int8_t *, int); - -static void null_encrypt(caddr_t, u_int8_t *); -static void des1_encrypt(caddr_t, u_int8_t *); -static void des3_encrypt(caddr_t, u_int8_t *); -static void blf_encrypt(caddr_t, u_int8_t *); -static void cast5_encrypt(caddr_t, u_int8_t *); -static void skipjack_encrypt(caddr_t, u_int8_t *); -static void rijndael128_encrypt(caddr_t, u_int8_t *); -static void aes_xts_encrypt(caddr_t, u_int8_t *); -static void cml_encrypt(caddr_t, u_int8_t *); - -static void null_decrypt(caddr_t, u_int8_t *); -static void des1_decrypt(caddr_t, u_int8_t *); -static void des3_decrypt(caddr_t, u_int8_t *); -static void blf_decrypt(caddr_t, u_int8_t *); -static void cast5_decrypt(caddr_t, u_int8_t *); -static void skipjack_decrypt(caddr_t, u_int8_t *); -static void rijndael128_decrypt(caddr_t, u_int8_t *); -static void aes_xts_decrypt(caddr_t, u_int8_t *); -static void cml_decrypt(caddr_t, u_int8_t *); - -static void aes_icm_crypt(caddr_t, u_int8_t *); - -static void null_zerokey(u_int8_t **); -static void des1_zerokey(u_int8_t **); -static void des3_zerokey(u_int8_t **); -static void blf_zerokey(u_int8_t **); -static void cast5_zerokey(u_int8_t **); -static void skipjack_zerokey(u_int8_t **); -static void rijndael128_zerokey(u_int8_t **); -static void aes_icm_zerokey(u_int8_t **); -static void aes_xts_zerokey(u_int8_t **); -static void cml_zerokey(u_int8_t **); - -static void aes_icm_reinit(caddr_t, u_int8_t *); -static void aes_xts_reinit(caddr_t, u_int8_t *); -static void aes_gcm_reinit(caddr_t, u_int8_t *); - -static void null_init(void *); -static void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len); -static int null_update(void *, const u_int8_t *, u_int16_t); -static void null_final(u_int8_t *, void *); -static int MD5Update_int(void *, const u_int8_t *, u_int16_t); -static void SHA1Init_int(void *); -static int SHA1Update_int(void *, const u_int8_t *, u_int16_t); -static void SHA1Final_int(u_int8_t *, void *); -static int RMD160Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA256Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA384Update_int(void *, const u_int8_t *, u_int16_t); -static int SHA512Update_int(void *, const u_int8_t *, u_int16_t); - -static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **); -static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **); - -#define AESICM_BLOCKSIZE AES_BLOCK_LEN - -struct aes_icm_ctx { - u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)]; - /* ac_block is initalized to IV */ - u_int8_t ac_block[AESICM_BLOCKSIZE]; - int ac_nr; -}; - MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers"); /* Encryption instances */ -struct enc_xform enc_xform_null = { - CRYPTO_NULL_CBC, "NULL", - /* NB: blocksize of 4 is to generate a properly aligned ESP header */ - NULL_BLOCK_LEN, 0, NULL_MIN_KEY, NULL_MAX_KEY, - null_encrypt, - null_decrypt, - null_setkey, - null_zerokey, - NULL, -}; - -struct enc_xform enc_xform_des = { - CRYPTO_DES_CBC, "DES", - DES_BLOCK_LEN, DES_BLOCK_LEN, DES_MIN_KEY, DES_MAX_KEY, - des1_encrypt, - des1_decrypt, - des1_setkey, - des1_zerokey, - NULL, -}; - -struct enc_xform enc_xform_3des = { - CRYPTO_3DES_CBC, "3DES", - DES3_BLOCK_LEN, DES3_BLOCK_LEN, TRIPLE_DES_MIN_KEY, - TRIPLE_DES_MAX_KEY, - des3_encrypt, - des3_decrypt, - des3_setkey, - des3_zerokey, - NULL, -}; - -struct enc_xform enc_xform_blf = { - CRYPTO_BLF_CBC, "Blowfish", - BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, BLOWFISH_MIN_KEY, - BLOWFISH_MAX_KEY, - blf_encrypt, - blf_decrypt, - blf_setkey, - blf_zerokey, - NULL, -}; - -struct enc_xform enc_xform_cast5 = { - CRYPTO_CAST_CBC, "CAST-128", - CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, CAST_MIN_KEY, CAST_MAX_KEY, - cast5_encrypt, - cast5_decrypt, - cast5_setkey, - cast5_zerokey, - NULL, -}; - -struct enc_xform enc_xform_skipjack = { - CRYPTO_SKIPJACK_CBC, "Skipjack", - SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, SKIPJACK_MIN_KEY, - SKIPJACK_MAX_KEY, - skipjack_encrypt, - skipjack_decrypt, skipjack_setkey, - skipjack_zerokey, - NULL, -}; - -struct enc_xform enc_xform_rijndael128 = { - CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES", - RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, RIJNDAEL_MIN_KEY, - RIJNDAEL_MAX_KEY, - rijndael128_encrypt, - rijndael128_decrypt, - rijndael128_setkey, - rijndael128_zerokey, - NULL, -}; - -struct enc_xform enc_xform_aes_icm = { - CRYPTO_AES_ICM, "AES-ICM", - AES_BLOCK_LEN, AES_BLOCK_LEN, AES_MIN_KEY, AES_MAX_KEY, - aes_icm_crypt, - aes_icm_crypt, - aes_icm_setkey, - rijndael128_zerokey, - aes_icm_reinit, -}; - -struct enc_xform enc_xform_aes_nist_gcm = { - CRYPTO_AES_NIST_GCM_16, "AES-GCM", - AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY, - aes_icm_crypt, - aes_icm_crypt, - aes_icm_setkey, - aes_icm_zerokey, - aes_gcm_reinit, -}; - -struct enc_xform enc_xform_aes_nist_gmac = { - CRYPTO_AES_NIST_GMAC, "AES-GMAC", - AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -struct enc_xform enc_xform_aes_xts = { - CRYPTO_AES_XTS, "AES-XTS", - AES_BLOCK_LEN, AES_XTS_IV_LEN, AES_XTS_MIN_KEY, AES_XTS_MAX_KEY, - aes_xts_encrypt, - aes_xts_decrypt, - aes_xts_setkey, - aes_xts_zerokey, - aes_xts_reinit -}; - struct enc_xform enc_xform_arc4 = { CRYPTO_ARC4, "ARC4", ARC4_BLOCK_LEN, ARC4_IV_LEN, ARC4_MIN_KEY, ARC4_MAX_KEY, @@ -275,711 +88,26 @@ struct enc_xform enc_xform_arc4 = { NULL, }; -struct enc_xform enc_xform_camellia = { - CRYPTO_CAMELLIA_CBC, "Camellia", - CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, CAMELLIA_MIN_KEY, - CAMELLIA_MAX_KEY, - cml_encrypt, - cml_decrypt, - cml_setkey, - cml_zerokey, - NULL, -}; -/* Authentication instances */ -struct auth_hash auth_hash_null = { /* NB: context isn't used */ - CRYPTO_NULL_HMAC, "NULL-HMAC", - NULL_HMAC_KEY_LEN, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN, - null_init, null_reinit, null_reinit, null_update, null_final -}; +/* Include the encryption algorithms */ +#include "xform_null.c" +#include "xform_des1.c" +#include "xform_des3.c" +#include "xform_blf.c" +#include "xform_cast5.c" +#include "xform_skipjack.c" +#include "xform_rijndael.c" +#include "xform_aes_icm.c" +#include "xform_aes_xts.c" +#include "xform_cml.c" + +/* Include the authentication and hashing algorithms */ +#include "xform_gmac.c" +#include "xform_md5.c" +#include "xform_rmd160.c" +#include "xform_sha1.c" +#include "xform_sha2.c" + +/* Include the compression algorithms */ +#include "xform_deflate.c" -struct auth_hash auth_hash_hmac_md5 = { - CRYPTO_MD5_HMAC, "HMAC-MD5", - MD5_HMAC_KEY_LEN, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN, - (void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int, - (void (*) (u_int8_t *, void *)) MD5Final -}; - -struct auth_hash auth_hash_hmac_sha1 = { - CRYPTO_SHA1_HMAC, "HMAC-SHA1", - SHA1_HMAC_KEY_LEN, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN, - SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int -}; - -struct auth_hash auth_hash_hmac_ripemd_160 = { - CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160", - RIPEMD160_HMAC_KEY_LEN, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX), - RIPEMD160_HMAC_BLOCK_LEN, - (void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int, - (void (*)(u_int8_t *, void *)) RMD160Final -}; - -struct auth_hash auth_hash_key_md5 = { - CRYPTO_MD5_KPDK, "Keyed MD5", - NULL_HMAC_KEY_LEN, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0, - (void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int, - (void (*)(u_int8_t *, void *)) MD5Final -}; - -struct auth_hash auth_hash_key_sha1 = { - CRYPTO_SHA1_KPDK, "Keyed SHA1", - NULL_HMAC_KEY_LEN, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0, - SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int -}; - -struct auth_hash auth_hash_hmac_sha2_256 = { - CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256", - SHA2_256_HMAC_KEY_LEN, SHA2_256_HASH_LEN, sizeof(SHA256_CTX), - SHA2_256_HMAC_BLOCK_LEN, - (void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int, - (void (*)(u_int8_t *, void *)) SHA256_Final -}; - -struct auth_hash auth_hash_hmac_sha2_384 = { - CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384", - SHA2_384_HMAC_KEY_LEN, SHA2_384_HASH_LEN, sizeof(SHA384_CTX), - SHA2_384_HMAC_BLOCK_LEN, - (void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int, - (void (*)(u_int8_t *, void *)) SHA384_Final -}; - -struct auth_hash auth_hash_hmac_sha2_512 = { - CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512", - SHA2_512_HMAC_KEY_LEN, SHA2_512_HASH_LEN, sizeof(SHA512_CTX), - SHA2_512_HMAC_BLOCK_LEN, - (void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int, - (void (*)(u_int8_t *, void *)) SHA512_Final -}; - -struct auth_hash auth_hash_nist_gmac_aes_128 = { - CRYPTO_AES_128_NIST_GMAC, "GMAC-AES-128", - AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final -}; - -struct auth_hash auth_hash_nist_gmac_aes_192 = { - CRYPTO_AES_192_NIST_GMAC, "GMAC-AES-192", - AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final -}; - -struct auth_hash auth_hash_nist_gmac_aes_256 = { - CRYPTO_AES_256_NIST_GMAC, "GMAC-AES-256", - AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), - GMAC_BLOCK_LEN, - (void (*)(void *)) AES_GMAC_Init, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, - (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, - (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, - (void (*)(u_int8_t *, void *)) AES_GMAC_Final -}; - -/* Compression instance */ -struct comp_algo comp_algo_deflate = { - CRYPTO_DEFLATE_COMP, "Deflate", - 90, deflate_compress, - deflate_decompress -}; - -/* - * Encryption wrapper routines. - */ -static void -null_encrypt(caddr_t key, u_int8_t *blk) -{ -} -static void -null_decrypt(caddr_t key, u_int8_t *blk) -{ -} -static int -null_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - *sched = NULL; - return 0; -} -static void -null_zerokey(u_int8_t **sched) -{ - *sched = NULL; -} - -static void -des1_encrypt(caddr_t key, u_int8_t *blk) -{ - des_cblock *cb = (des_cblock *) blk; - des_key_schedule *p = (des_key_schedule *) key; - - des_ecb_encrypt(cb, cb, p[0], DES_ENCRYPT); -} - -static void -des1_decrypt(caddr_t key, u_int8_t *blk) -{ - des_cblock *cb = (des_cblock *) blk; - des_key_schedule *p = (des_key_schedule *) key; - - des_ecb_encrypt(cb, cb, p[0], DES_DECRYPT); -} - -static int -des1_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - des_key_schedule *p; - int err; - - p = malloc(sizeof (des_key_schedule), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (p != NULL) { - des_set_key((des_cblock *) key, p[0]); - err = 0; - } else - err = ENOMEM; - *sched = (u_int8_t *) p; - return err; -} - -static void -des1_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof (des_key_schedule)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -des3_encrypt(caddr_t key, u_int8_t *blk) -{ - des_cblock *cb = (des_cblock *) blk; - des_key_schedule *p = (des_key_schedule *) key; - - des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_ENCRYPT); -} - -static void -des3_decrypt(caddr_t key, u_int8_t *blk) -{ - des_cblock *cb = (des_cblock *) blk; - des_key_schedule *p = (des_key_schedule *) key; - - des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_DECRYPT); -} - -static int -des3_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - des_key_schedule *p; - int err; - - p = malloc(3*sizeof (des_key_schedule), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (p != NULL) { - des_set_key((des_cblock *)(key + 0), p[0]); - des_set_key((des_cblock *)(key + 8), p[1]); - des_set_key((des_cblock *)(key + 16), p[2]); - err = 0; - } else - err = ENOMEM; - *sched = (u_int8_t *) p; - return err; -} - -static void -des3_zerokey(u_int8_t **sched) -{ - bzero(*sched, 3*sizeof (des_key_schedule)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -blf_encrypt(caddr_t key, u_int8_t *blk) -{ - BF_LONG t[2]; - - memcpy(t, blk, sizeof (t)); - t[0] = ntohl(t[0]); - t[1] = ntohl(t[1]); - /* NB: BF_encrypt expects the block in host order! */ - BF_encrypt(t, (BF_KEY *) key); - t[0] = htonl(t[0]); - t[1] = htonl(t[1]); - memcpy(blk, t, sizeof (t)); -} - -static void -blf_decrypt(caddr_t key, u_int8_t *blk) -{ - BF_LONG t[2]; - - memcpy(t, blk, sizeof (t)); - t[0] = ntohl(t[0]); - t[1] = ntohl(t[1]); - /* NB: BF_decrypt expects the block in host order! */ - BF_decrypt(t, (BF_KEY *) key); - t[0] = htonl(t[0]); - t[1] = htonl(t[1]); - memcpy(blk, t, sizeof (t)); -} - -static int -blf_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - int err; - - *sched = malloc(sizeof(BF_KEY), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (*sched != NULL) { - BF_set_key((BF_KEY *) *sched, len, key); - err = 0; - } else - err = ENOMEM; - return err; -} - -static void -blf_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof(BF_KEY)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -cast5_encrypt(caddr_t key, u_int8_t *blk) -{ - cast_encrypt((cast_key *) key, blk, blk); -} - -static void -cast5_decrypt(caddr_t key, u_int8_t *blk) -{ - cast_decrypt((cast_key *) key, blk, blk); -} - -static int -cast5_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - int err; - - *sched = malloc(sizeof(cast_key), M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (*sched != NULL) { - cast_setkey((cast_key *)*sched, key, len); - err = 0; - } else - err = ENOMEM; - return err; -} - -static void -cast5_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof(cast_key)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -skipjack_encrypt(caddr_t key, u_int8_t *blk) -{ - skipjack_forwards(blk, blk, (u_int8_t **) key); -} - -static void -skipjack_decrypt(caddr_t key, u_int8_t *blk) -{ - skipjack_backwards(blk, blk, (u_int8_t **) key); -} - -static int -skipjack_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - int err; - - /* NB: allocate all the memory that's needed at once */ - *sched = malloc(10 * (sizeof(u_int8_t *) + 0x100), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (*sched != NULL) { - u_int8_t** key_tables = (u_int8_t**) *sched; - u_int8_t* table = (u_int8_t*) &key_tables[10]; - int k; - - for (k = 0; k < 10; k++) { - key_tables[k] = table; - table += 0x100; - } - subkey_table_gen(key, (u_int8_t **) *sched); - err = 0; - } else - err = ENOMEM; - return err; -} - -static void -skipjack_zerokey(u_int8_t **sched) -{ - bzero(*sched, 10 * (sizeof(u_int8_t *) + 0x100)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -rijndael128_encrypt(caddr_t key, u_int8_t *blk) -{ - rijndael_encrypt((rijndael_ctx *) key, (u_char *) blk, (u_char *) blk); -} - -static void -rijndael128_decrypt(caddr_t key, u_int8_t *blk) -{ - rijndael_decrypt(((rijndael_ctx *) key), (u_char *) blk, - (u_char *) blk); -} - -static int -rijndael128_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - int err; - - if (len != 16 && len != 24 && len != 32) - return (EINVAL); - *sched = malloc(sizeof(rijndael_ctx), M_CRYPTO_DATA, - M_NOWAIT|M_ZERO); - if (*sched != NULL) { - rijndael_set_key((rijndael_ctx *) *sched, (u_char *) key, - len * 8); - err = 0; - } else - err = ENOMEM; - return err; -} - -static void -rijndael128_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof(rijndael_ctx)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -void -aes_icm_reinit(caddr_t key, u_int8_t *iv) -{ - struct aes_icm_ctx *ctx; - - ctx = (struct aes_icm_ctx *)key; - bcopy(iv, ctx->ac_block, AESICM_BLOCKSIZE); -} - -void -aes_gcm_reinit(caddr_t key, u_int8_t *iv) -{ - struct aes_icm_ctx *ctx; - - aes_icm_reinit(key, iv); - - ctx = (struct aes_icm_ctx *)key; - /* GCM starts with 2 as counter 1 is used for final xor of tag. */ - bzero(&ctx->ac_block[AESICM_BLOCKSIZE - 4], 4); - ctx->ac_block[AESICM_BLOCKSIZE - 1] = 2; -} - -void -aes_icm_crypt(caddr_t key, u_int8_t *data) -{ - struct aes_icm_ctx *ctx; - u_int8_t keystream[AESICM_BLOCKSIZE]; - int i; - - ctx = (struct aes_icm_ctx *)key; - rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream); - for (i = 0; i < AESICM_BLOCKSIZE; i++) - data[i] ^= keystream[i]; - explicit_bzero(keystream, sizeof(keystream)); - - /* increment counter */ - for (i = AESICM_BLOCKSIZE - 1; - i >= 0; i--) - if (++ctx->ac_block[i]) /* continue on overflow */ - break; -} - -int -aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - struct aes_icm_ctx *ctx; - - if (len != 16 && len != 24 && len != 32) - return EINVAL; - - *sched = malloc(sizeof(struct aes_icm_ctx), M_CRYPTO_DATA, - M_NOWAIT | M_ZERO); - if (*sched == NULL) - return ENOMEM; - - ctx = (struct aes_icm_ctx *)*sched; - ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key, len * 8); - return 0; -} - -void -aes_icm_zerokey(u_int8_t **sched) -{ - - bzero(*sched, sizeof(struct aes_icm_ctx)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -#define AES_XTS_BLOCKSIZE 16 -#define AES_XTS_IVSIZE 8 -#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ - -struct aes_xts_ctx { - rijndael_ctx key1; - rijndael_ctx key2; - u_int8_t tweak[AES_XTS_BLOCKSIZE]; -}; - -void -aes_xts_reinit(caddr_t key, u_int8_t *iv) -{ - struct aes_xts_ctx *ctx = (struct aes_xts_ctx *)key; - u_int64_t blocknum; - u_int i; - - /* - * Prepare tweak as E_k2(IV). IV is specified as LE representation - * of a 64-bit block number which we allow to be passed in directly. - */ - bcopy(iv, &blocknum, AES_XTS_IVSIZE); - for (i = 0; i < AES_XTS_IVSIZE; i++) { - ctx->tweak[i] = blocknum & 0xff; - blocknum >>= 8; - } - /* Last 64 bits of IV are always zero */ - bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE); - - rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak); -} - -static void -aes_xts_crypt(struct aes_xts_ctx *ctx, u_int8_t *data, u_int do_encrypt) -{ - u_int8_t block[AES_XTS_BLOCKSIZE]; - u_int i, carry_in, carry_out; - - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) - block[i] = data[i] ^ ctx->tweak[i]; - - if (do_encrypt) - rijndael_encrypt(&ctx->key1, block, data); - else - rijndael_decrypt(&ctx->key1, block, data); - - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) - data[i] ^= ctx->tweak[i]; - - /* Exponentiate tweak */ - carry_in = 0; - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) { - carry_out = ctx->tweak[i] & 0x80; - ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); - carry_in = carry_out; - } - if (carry_in) - ctx->tweak[0] ^= AES_XTS_ALPHA; - bzero(block, sizeof(block)); -} - -void -aes_xts_encrypt(caddr_t key, u_int8_t *data) -{ - aes_xts_crypt((struct aes_xts_ctx *)key, data, 1); -} - -void -aes_xts_decrypt(caddr_t key, u_int8_t *data) -{ - aes_xts_crypt((struct aes_xts_ctx *)key, data, 0); -} - -int -aes_xts_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - struct aes_xts_ctx *ctx; - - if (len != 32 && len != 64) - return EINVAL; - - *sched = malloc(sizeof(struct aes_xts_ctx), M_CRYPTO_DATA, - M_NOWAIT | M_ZERO); - if (*sched == NULL) - return ENOMEM; - ctx = (struct aes_xts_ctx *)*sched; - - rijndael_set_key(&ctx->key1, key, len * 4); - rijndael_set_key(&ctx->key2, key + (len / 2), len * 4); - - return 0; -} - -void -aes_xts_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof(struct aes_xts_ctx)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -static void -cml_encrypt(caddr_t key, u_int8_t *blk) -{ - camellia_encrypt((camellia_ctx *) key, (u_char *) blk, (u_char *) blk); -} - -static void -cml_decrypt(caddr_t key, u_int8_t *blk) -{ - camellia_decrypt(((camellia_ctx *) key), (u_char *) blk, - (u_char *) blk); -} - -static int -cml_setkey(u_int8_t **sched, u_int8_t *key, int len) -{ - int err; - - if (len != 16 && len != 24 && len != 32) - return (EINVAL); - *sched = malloc(sizeof(camellia_ctx), M_CRYPTO_DATA, - M_NOWAIT|M_ZERO); - if (*sched != NULL) { - camellia_set_key((camellia_ctx *) *sched, (u_char *) key, - len * 8); - err = 0; - } else - err = ENOMEM; - return err; -} - -static void -cml_zerokey(u_int8_t **sched) -{ - bzero(*sched, sizeof(camellia_ctx)); - free(*sched, M_CRYPTO_DATA); - *sched = NULL; -} - -/* - * And now for auth. - */ - -static void -null_init(void *ctx) -{ -} - -static void -null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len) -{ -} - -static int -null_update(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - return 0; -} - -static void -null_final(u_int8_t *buf, void *ctx) -{ - if (buf != (u_int8_t *) 0) - bzero(buf, 12); -} - -static int -RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - RMD160Update(ctx, buf, len); - return 0; -} - -static int -MD5Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - MD5Update(ctx, buf, len); - return 0; -} - -static void -SHA1Init_int(void *ctx) -{ - SHA1Init(ctx); -} - -static int -SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - SHA1Update(ctx, buf, len); - return 0; -} - -static void -SHA1Final_int(u_int8_t *blk, void *ctx) -{ - SHA1Final(blk, ctx); -} - -static int -SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - SHA256_Update(ctx, buf, len); - return 0; -} - -static int -SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - SHA384_Update(ctx, buf, len); - return 0; -} - -static int -SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) -{ - SHA512_Update(ctx, buf, len); - return 0; -} - -/* - * And compression - */ - -static u_int32_t -deflate_compress(data, size, out) - u_int8_t *data; - u_int32_t size; - u_int8_t **out; -{ - return deflate_global(data, size, 0, out); -} - -static u_int32_t -deflate_decompress(data, size, out) - u_int8_t *data; - u_int32_t size; - u_int8_t **out; -{ - return deflate_global(data, size, 1, out); -} diff --git a/sys/opencrypto/xform.h b/sys/opencrypto/xform.h index 185e20324b51..a176fe756c66 100644 --- a/sys/opencrypto/xform.h +++ b/sys/opencrypto/xform.h @@ -39,83 +39,9 @@ #include #include -/* Declarations */ -struct auth_hash { - int type; - char *name; - u_int16_t keysize; - u_int16_t hashsize; - u_int16_t ctxsize; - u_int16_t blocksize; - void (*Init) (void *); - void (*Setkey) (void *, const u_int8_t *, u_int16_t); - void (*Reinit) (void *, const u_int8_t *, u_int16_t); - int (*Update) (void *, const u_int8_t *, u_int16_t); - void (*Final) (u_int8_t *, void *); -}; - -/* XXX use a define common with other hash stuff ! */ -#define AH_ALEN_MAX 64 /* max authenticator hash length */ - -struct enc_xform { - int type; - char *name; - u_int16_t blocksize; - u_int16_t ivsize; - u_int16_t minkey, maxkey; - void (*encrypt) (caddr_t, u_int8_t *); - void (*decrypt) (caddr_t, u_int8_t *); - int (*setkey) (u_int8_t **, u_int8_t *, int len); - void (*zerokey) (u_int8_t **); - void (*reinit) (caddr_t, u_int8_t *); -}; - -struct comp_algo { - int type; - char *name; - size_t minlen; - u_int32_t (*compress) (u_int8_t *, u_int32_t, u_int8_t **); - u_int32_t (*decompress) (u_int8_t *, u_int32_t, u_int8_t **); -}; - -union authctx { - MD5_CTX md5ctx; - SHA1_CTX sha1ctx; - RMD160_CTX rmd160ctx; - SHA256_CTX sha256ctx; - SHA384_CTX sha384ctx; - SHA512_CTX sha512ctx; - struct aes_gmac_ctx aes_gmac_ctx; -}; - -extern struct enc_xform enc_xform_null; -extern struct enc_xform enc_xform_des; -extern struct enc_xform enc_xform_3des; -extern struct enc_xform enc_xform_blf; -extern struct enc_xform enc_xform_cast5; -extern struct enc_xform enc_xform_skipjack; -extern struct enc_xform enc_xform_rijndael128; -extern struct enc_xform enc_xform_aes_icm; -extern struct enc_xform enc_xform_aes_nist_gcm; -extern struct enc_xform enc_xform_aes_nist_gmac; -extern struct enc_xform enc_xform_aes_xts; -extern struct enc_xform enc_xform_arc4; -extern struct enc_xform enc_xform_camellia; - -extern struct auth_hash auth_hash_null; -extern struct auth_hash auth_hash_key_md5; -extern struct auth_hash auth_hash_key_sha1; -extern struct auth_hash auth_hash_hmac_md5; -extern struct auth_hash auth_hash_hmac_sha1; -extern struct auth_hash auth_hash_hmac_ripemd_160; -extern struct auth_hash auth_hash_hmac_sha2_256; -extern struct auth_hash auth_hash_hmac_sha2_384; -extern struct auth_hash auth_hash_hmac_sha2_512; -extern struct auth_hash auth_hash_nist_gmac_aes_128; -extern struct auth_hash auth_hash_nist_gmac_aes_192; -extern struct auth_hash auth_hash_nist_gmac_aes_256; - -extern struct comp_algo comp_algo_deflate; +#include +#include +#include #ifdef _KERNEL #include diff --git a/sys/opencrypto/xform_aes_icm.c b/sys/opencrypto/xform_aes_icm.c new file mode 100644 index 000000000000..f4ce885172ef --- /dev/null +++ b/sys/opencrypto/xform_aes_icm.c @@ -0,0 +1,152 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +static int aes_icm_setkey(u_int8_t **, u_int8_t *, int); +static void aes_icm_crypt(caddr_t, u_int8_t *); +static void aes_icm_zerokey(u_int8_t **); +static void aes_icm_reinit(caddr_t, u_int8_t *); +static void aes_gcm_reinit(caddr_t, u_int8_t *); + +/* Encryption instances */ +struct enc_xform enc_xform_aes_icm = { + CRYPTO_AES_ICM, "AES-ICM", + AES_BLOCK_LEN, AES_BLOCK_LEN, AES_MIN_KEY, AES_MAX_KEY, + aes_icm_crypt, + aes_icm_crypt, + aes_icm_setkey, + rijndael128_zerokey, + aes_icm_reinit, +}; + +struct enc_xform enc_xform_aes_nist_gcm = { + CRYPTO_AES_NIST_GCM_16, "AES-GCM", + AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY, + aes_icm_crypt, + aes_icm_crypt, + aes_icm_setkey, + aes_icm_zerokey, + aes_gcm_reinit, +}; + +/* + * Encryption wrapper routines. + */ +static void +aes_icm_reinit(caddr_t key, u_int8_t *iv) +{ + struct aes_icm_ctx *ctx; + + ctx = (struct aes_icm_ctx *)key; + bcopy(iv, ctx->ac_block, AESICM_BLOCKSIZE); +} + +static void +aes_gcm_reinit(caddr_t key, u_int8_t *iv) +{ + struct aes_icm_ctx *ctx; + + aes_icm_reinit(key, iv); + + ctx = (struct aes_icm_ctx *)key; + /* GCM starts with 2 as counter 1 is used for final xor of tag. */ + bzero(&ctx->ac_block[AESICM_BLOCKSIZE - 4], 4); + ctx->ac_block[AESICM_BLOCKSIZE - 1] = 2; +} + +static void +aes_icm_crypt(caddr_t key, u_int8_t *data) +{ + struct aes_icm_ctx *ctx; + u_int8_t keystream[AESICM_BLOCKSIZE]; + int i; + + ctx = (struct aes_icm_ctx *)key; + rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream); + for (i = 0; i < AESICM_BLOCKSIZE; i++) + data[i] ^= keystream[i]; + explicit_bzero(keystream, sizeof(keystream)); + + /* increment counter */ + for (i = AESICM_BLOCKSIZE - 1; + i >= 0; i--) + if (++ctx->ac_block[i]) /* continue on overflow */ + break; +} + +static int +aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + struct aes_icm_ctx *ctx; + + if (len != 16 && len != 24 && len != 32) + return EINVAL; + + *sched = KMALLOC(sizeof(struct aes_icm_ctx), M_CRYPTO_DATA, + M_NOWAIT | M_ZERO); + if (*sched == NULL) + return ENOMEM; + + ctx = (struct aes_icm_ctx *)*sched; + ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key, len * 8); + return 0; +} + +static void +aes_icm_zerokey(u_int8_t **sched) +{ + + bzero(*sched, sizeof(struct aes_icm_ctx)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_aes_xts.c b/sys/opencrypto/xform_aes_xts.c new file mode 100644 index 000000000000..dedbe6275e10 --- /dev/null +++ b/sys/opencrypto/xform_aes_xts.c @@ -0,0 +1,164 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +static int aes_xts_setkey(u_int8_t **, u_int8_t *, int); +static void aes_xts_encrypt(caddr_t, u_int8_t *); +static void aes_xts_decrypt(caddr_t, u_int8_t *); +static void aes_xts_zerokey(u_int8_t **); +static void aes_xts_reinit(caddr_t, u_int8_t *); + +/* Encryption instances */ +struct enc_xform enc_xform_aes_xts = { + CRYPTO_AES_XTS, "AES-XTS", + AES_BLOCK_LEN, AES_XTS_IV_LEN, AES_XTS_MIN_KEY, AES_XTS_MAX_KEY, + aes_xts_encrypt, + aes_xts_decrypt, + aes_xts_setkey, + aes_xts_zerokey, + aes_xts_reinit +}; + +/* + * Encryption wrapper routines. + */ +static void +aes_xts_reinit(caddr_t key, u_int8_t *iv) +{ + struct aes_xts_ctx *ctx = (struct aes_xts_ctx *)key; + u_int64_t blocknum; + u_int i; + + /* + * Prepare tweak as E_k2(IV). IV is specified as LE representation + * of a 64-bit block number which we allow to be passed in directly. + */ + bcopy(iv, &blocknum, AES_XTS_IVSIZE); + for (i = 0; i < AES_XTS_IVSIZE; i++) { + ctx->tweak[i] = blocknum & 0xff; + blocknum >>= 8; + } + /* Last 64 bits of IV are always zero */ + bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE); + + rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak); +} + +static void +aes_xts_crypt(struct aes_xts_ctx *ctx, u_int8_t *data, u_int do_encrypt) +{ + u_int8_t block[AES_XTS_BLOCKSIZE]; + u_int i, carry_in, carry_out; + + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + block[i] = data[i] ^ ctx->tweak[i]; + + if (do_encrypt) + rijndael_encrypt(&ctx->key1, block, data); + else + rijndael_decrypt(&ctx->key1, block, data); + + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + data[i] ^= ctx->tweak[i]; + + /* Exponentiate tweak */ + carry_in = 0; + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) { + carry_out = ctx->tweak[i] & 0x80; + ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); + carry_in = carry_out; + } + if (carry_in) + ctx->tweak[0] ^= AES_XTS_ALPHA; + bzero(block, sizeof(block)); +} + +static void +aes_xts_encrypt(caddr_t key, u_int8_t *data) +{ + aes_xts_crypt((struct aes_xts_ctx *)key, data, 1); +} + +static void +aes_xts_decrypt(caddr_t key, u_int8_t *data) +{ + aes_xts_crypt((struct aes_xts_ctx *)key, data, 0); +} + +static int +aes_xts_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + struct aes_xts_ctx *ctx; + + if (len != 32 && len != 64) + return EINVAL; + + *sched = KMALLOC(sizeof(struct aes_xts_ctx), M_CRYPTO_DATA, + M_NOWAIT | M_ZERO); + if (*sched == NULL) + return ENOMEM; + ctx = (struct aes_xts_ctx *)*sched; + + rijndael_set_key(&ctx->key1, key, len * 4); + rijndael_set_key(&ctx->key2, key + (len / 2), len * 4); + + return 0; +} + +static void +aes_xts_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(struct aes_xts_ctx)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_auth.h b/sys/opencrypto/xform_auth.h new file mode 100644 index 000000000000..c51f9400f87f --- /dev/null +++ b/sys/opencrypto/xform_auth.h @@ -0,0 +1,89 @@ +/* $FreeBSD$ */ +/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */ + +/*- + * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) + * + * This code was written by Angelos D. Keromytis in Athens, Greece, in + * February 2000. Network Security Technologies Inc. (NSTI) kindly + * supported the development of this code. + * + * Copyright (c) 2000 Angelos D. Keromytis + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all source code copies of any software which is or includes a copy or + * modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _CRYPTO_XFORM_AUTH_H_ +#define _CRYPTO_XFORM_AUTH_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* XXX use a define common with other hash stuff ! */ +#define AH_ALEN_MAX 64 /* max authenticator hash length */ + +/* Declarations */ +struct auth_hash { + int type; + char *name; + u_int16_t keysize; + u_int16_t hashsize; + u_int16_t ctxsize; + u_int16_t blocksize; + void (*Init) (void *); + void (*Setkey) (void *, const u_int8_t *, u_int16_t); + void (*Reinit) (void *, const u_int8_t *, u_int16_t); + int (*Update) (void *, const u_int8_t *, u_int16_t); + void (*Final) (u_int8_t *, void *); +}; + +extern struct auth_hash auth_hash_null; +extern struct auth_hash auth_hash_key_md5; +extern struct auth_hash auth_hash_key_sha1; +extern struct auth_hash auth_hash_hmac_md5; +extern struct auth_hash auth_hash_hmac_sha1; +extern struct auth_hash auth_hash_hmac_ripemd_160; +extern struct auth_hash auth_hash_hmac_sha2_256; +extern struct auth_hash auth_hash_hmac_sha2_384; +extern struct auth_hash auth_hash_hmac_sha2_512; +extern struct auth_hash auth_hash_nist_gmac_aes_128; +extern struct auth_hash auth_hash_nist_gmac_aes_192; +extern struct auth_hash auth_hash_nist_gmac_aes_256; + +union authctx { + MD5_CTX md5ctx; + SHA1_CTX sha1ctx; + RMD160_CTX rmd160ctx; + SHA256_CTX sha256ctx; + SHA384_CTX sha384ctx; + SHA512_CTX sha512ctx; + struct aes_gmac_ctx aes_gmac_ctx; +}; + +#endif /* _CRYPTO_XFORM_AUTH_H_ */ diff --git a/sys/opencrypto/xform_blf.c b/sys/opencrypto/xform_blf.c new file mode 100644 index 000000000000..b4be5f8d4636 --- /dev/null +++ b/sys/opencrypto/xform_blf.c @@ -0,0 +1,127 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int blf_setkey(u_int8_t **, u_int8_t *, int); +static void blf_encrypt(caddr_t, u_int8_t *); +static void blf_decrypt(caddr_t, u_int8_t *); +static void blf_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_blf = { + CRYPTO_BLF_CBC, "Blowfish", + BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, BLOWFISH_MIN_KEY, + BLOWFISH_MAX_KEY, + blf_encrypt, + blf_decrypt, + blf_setkey, + blf_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +blf_encrypt(caddr_t key, u_int8_t *blk) +{ + BF_LONG t[2]; + + memcpy(t, blk, sizeof (t)); + t[0] = ntohl(t[0]); + t[1] = ntohl(t[1]); + /* NB: BF_encrypt expects the block in host order! */ + BF_encrypt(t, (BF_KEY *) key); + t[0] = htonl(t[0]); + t[1] = htonl(t[1]); + memcpy(blk, t, sizeof (t)); +} + +static void +blf_decrypt(caddr_t key, u_int8_t *blk) +{ + BF_LONG t[2]; + + memcpy(t, blk, sizeof (t)); + t[0] = ntohl(t[0]); + t[1] = ntohl(t[1]); + /* NB: BF_decrypt expects the block in host order! */ + BF_decrypt(t, (BF_KEY *) key); + t[0] = htonl(t[0]); + t[1] = htonl(t[1]); + memcpy(blk, t, sizeof (t)); +} + +static int +blf_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + int err; + + *sched = KMALLOC(sizeof(BF_KEY), + M_CRYPTO_DATA, M_NOWAIT|M_ZERO); + if (*sched != NULL) { + BF_set_key((BF_KEY *) *sched, len, key); + err = 0; + } else + err = ENOMEM; + return err; +} + +static void +blf_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(BF_KEY)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_cast5.c b/sys/opencrypto/xform_cast5.c new file mode 100644 index 000000000000..85b346eb2ca9 --- /dev/null +++ b/sys/opencrypto/xform_cast5.c @@ -0,0 +1,107 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int cast5_setkey(u_int8_t **, u_int8_t *, int); +static void cast5_encrypt(caddr_t, u_int8_t *); +static void cast5_decrypt(caddr_t, u_int8_t *); +static void cast5_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_cast5 = { + CRYPTO_CAST_CBC, "CAST-128", + CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, CAST_MIN_KEY, CAST_MAX_KEY, + cast5_encrypt, + cast5_decrypt, + cast5_setkey, + cast5_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +cast5_encrypt(caddr_t key, u_int8_t *blk) +{ + cast_encrypt((cast_key *) key, blk, blk); +} + +static void +cast5_decrypt(caddr_t key, u_int8_t *blk) +{ + cast_decrypt((cast_key *) key, blk, blk); +} + +static int +cast5_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + int err; + + *sched = KMALLOC(sizeof(cast_key), M_CRYPTO_DATA, M_NOWAIT|M_ZERO); + if (*sched != NULL) { + cast_setkey((cast_key *)*sched, key, len); + err = 0; + } else + err = ENOMEM; + return err; +} + +static void +cast5_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(cast_key)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_cml.c b/sys/opencrypto/xform_cml.c new file mode 100644 index 000000000000..c807fa97c98d --- /dev/null +++ b/sys/opencrypto/xform_cml.c @@ -0,0 +1,113 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int cml_setkey(u_int8_t **, u_int8_t *, int); +static void cml_encrypt(caddr_t, u_int8_t *); +static void cml_decrypt(caddr_t, u_int8_t *); +static void cml_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_camellia = { + CRYPTO_CAMELLIA_CBC, "Camellia", + CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, CAMELLIA_MIN_KEY, + CAMELLIA_MAX_KEY, + cml_encrypt, + cml_decrypt, + cml_setkey, + cml_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +cml_encrypt(caddr_t key, u_int8_t *blk) +{ + camellia_encrypt((camellia_ctx *) key, (u_char *) blk, (u_char *) blk); +} + +static void +cml_decrypt(caddr_t key, u_int8_t *blk) +{ + camellia_decrypt(((camellia_ctx *) key), (u_char *) blk, + (u_char *) blk); +} + +static int +cml_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + int err; + + if (len != 16 && len != 24 && len != 32) + return (EINVAL); + *sched = KMALLOC(sizeof(camellia_ctx), M_CRYPTO_DATA, + M_NOWAIT|M_ZERO); + if (*sched != NULL) { + camellia_set_key((camellia_ctx *) *sched, (u_char *) key, + len * 8); + err = 0; + } else + err = ENOMEM; + return err; +} + +static void +cml_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(camellia_ctx)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_comp.h b/sys/opencrypto/xform_comp.h new file mode 100644 index 000000000000..23e4eacf6e81 --- /dev/null +++ b/sys/opencrypto/xform_comp.h @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ +/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */ + +/*- + * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) + * + * This code was written by Angelos D. Keromytis in Athens, Greece, in + * February 2000. Network Security Technologies Inc. (NSTI) kindly + * supported the development of this code. + * + * Copyright (c) 2000 Angelos D. Keromytis + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all source code copies of any software which is or includes a copy or + * modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _CRYPTO_XFORM_COMP_H_ +#define _CRYPTO_XFORM_COMP_H_ + +#include +#include + +#include +#include +#include + +/* Declarations */ +struct comp_algo { + int type; + char *name; + size_t minlen; + u_int32_t (*compress) (u_int8_t *, u_int32_t, u_int8_t **); + u_int32_t (*decompress) (u_int8_t *, u_int32_t, u_int8_t **); +}; + +extern struct comp_algo comp_algo_deflate; + +#endif /* _CRYPTO_XFORM_COMP_H_ */ diff --git a/sys/opencrypto/xform_deflate.c b/sys/opencrypto/xform_deflate.c new file mode 100644 index 000000000000..c8864bf6228f --- /dev/null +++ b/sys/opencrypto/xform_deflate.c @@ -0,0 +1,86 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **); +static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **); + +/* Compression instance */ +struct comp_algo comp_algo_deflate = { + CRYPTO_DEFLATE_COMP, "Deflate", + 90, deflate_compress, + deflate_decompress +}; + +/* + * And compression + */ + +static u_int32_t +deflate_compress(data, size, out) + u_int8_t *data; + u_int32_t size; + u_int8_t **out; +{ + return deflate_global(data, size, 0, out); +} + +static u_int32_t +deflate_decompress(data, size, out) + u_int8_t *data; + u_int32_t size; + u_int8_t **out; +{ + return deflate_global(data, size, 1, out); +} diff --git a/sys/opencrypto/xform_des1.c b/sys/opencrypto/xform_des1.c new file mode 100644 index 000000000000..cbce5e290b2b --- /dev/null +++ b/sys/opencrypto/xform_des1.c @@ -0,0 +1,116 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int des1_setkey(u_int8_t **, u_int8_t *, int); +static void des1_encrypt(caddr_t, u_int8_t *); +static void des1_decrypt(caddr_t, u_int8_t *); +static void des1_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_des = { + CRYPTO_DES_CBC, "DES", + DES_BLOCK_LEN, DES_BLOCK_LEN, DES_MIN_KEY, DES_MAX_KEY, + des1_encrypt, + des1_decrypt, + des1_setkey, + des1_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +des1_encrypt(caddr_t key, u_int8_t *blk) +{ + des_cblock *cb = (des_cblock *) blk; + des_key_schedule *p = (des_key_schedule *) key; + + des_ecb_encrypt(cb, cb, p[0], DES_ENCRYPT); +} + +static void +des1_decrypt(caddr_t key, u_int8_t *blk) +{ + des_cblock *cb = (des_cblock *) blk; + des_key_schedule *p = (des_key_schedule *) key; + + des_ecb_encrypt(cb, cb, p[0], DES_DECRYPT); +} + +static int +des1_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + des_key_schedule *p; + int err; + + p = KMALLOC(sizeof (des_key_schedule), + M_CRYPTO_DATA, M_NOWAIT|M_ZERO); + if (p != NULL) { + des_set_key((des_cblock *) key, p[0]); + err = 0; + } else + err = ENOMEM; + *sched = (u_int8_t *) p; + return err; +} + +static void +des1_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof (des_key_schedule)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_des3.c b/sys/opencrypto/xform_des3.c new file mode 100644 index 000000000000..1b26b622f6b4 --- /dev/null +++ b/sys/opencrypto/xform_des3.c @@ -0,0 +1,119 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int des3_setkey(u_int8_t **, u_int8_t *, int); +static void des3_encrypt(caddr_t, u_int8_t *); +static void des3_decrypt(caddr_t, u_int8_t *); +static void des3_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_3des = { + CRYPTO_3DES_CBC, "3DES", + DES3_BLOCK_LEN, DES3_BLOCK_LEN, TRIPLE_DES_MIN_KEY, + TRIPLE_DES_MAX_KEY, + des3_encrypt, + des3_decrypt, + des3_setkey, + des3_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +des3_encrypt(caddr_t key, u_int8_t *blk) +{ + des_cblock *cb = (des_cblock *) blk; + des_key_schedule *p = (des_key_schedule *) key; + + des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_ENCRYPT); +} + +static void +des3_decrypt(caddr_t key, u_int8_t *blk) +{ + des_cblock *cb = (des_cblock *) blk; + des_key_schedule *p = (des_key_schedule *) key; + + des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_DECRYPT); +} + +static int +des3_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + des_key_schedule *p; + int err; + + p = KMALLOC(3*sizeof (des_key_schedule), + M_CRYPTO_DATA, M_NOWAIT|M_ZERO); + if (p != NULL) { + des_set_key((des_cblock *)(key + 0), p[0]); + des_set_key((des_cblock *)(key + 8), p[1]); + des_set_key((des_cblock *)(key + 16), p[2]); + err = 0; + } else + err = ENOMEM; + *sched = (u_int8_t *) p; + return err; +} + +static void +des3_zerokey(u_int8_t **sched) +{ + bzero(*sched, 3*sizeof (des_key_schedule)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_enc.h b/sys/opencrypto/xform_enc.h new file mode 100644 index 000000000000..7bb6a9dd1a37 --- /dev/null +++ b/sys/opencrypto/xform_enc.h @@ -0,0 +1,92 @@ +/* $FreeBSD$ */ +/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */ + +/*- + * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) + * + * This code was written by Angelos D. Keromytis in Athens, Greece, in + * February 2000. Network Security Technologies Inc. (NSTI) kindly + * supported the development of this code. + * + * Copyright (c) 2000 Angelos D. Keromytis + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all source code copies of any software which is or includes a copy or + * modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _CRYPTO_XFORM_ENC_H_ +#define _CRYPTO_XFORM_ENC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AESICM_BLOCKSIZE AES_BLOCK_LEN +#define AES_XTS_BLOCKSIZE 16 +#define AES_XTS_IVSIZE 8 +#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ + +/* Declarations */ +struct enc_xform { + int type; + char *name; + u_int16_t blocksize; + u_int16_t ivsize; + u_int16_t minkey, maxkey; + void (*encrypt) (caddr_t, u_int8_t *); + void (*decrypt) (caddr_t, u_int8_t *); + int (*setkey) (u_int8_t **, u_int8_t *, int len); + void (*zerokey) (u_int8_t **); + void (*reinit) (caddr_t, u_int8_t *); +}; + + +extern struct enc_xform enc_xform_null; +extern struct enc_xform enc_xform_des; +extern struct enc_xform enc_xform_3des; +extern struct enc_xform enc_xform_blf; +extern struct enc_xform enc_xform_cast5; +extern struct enc_xform enc_xform_skipjack; +extern struct enc_xform enc_xform_rijndael128; +extern struct enc_xform enc_xform_aes_icm; +extern struct enc_xform enc_xform_aes_nist_gcm; +extern struct enc_xform enc_xform_aes_nist_gmac; +extern struct enc_xform enc_xform_aes_xts; +extern struct enc_xform enc_xform_arc4; +extern struct enc_xform enc_xform_camellia; + +struct aes_icm_ctx { + u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)]; + /* ac_block is initalized to IV */ + u_int8_t ac_block[AESICM_BLOCKSIZE]; + int ac_nr; +}; + +struct aes_xts_ctx { + rijndael_ctx key1; + rijndael_ctx key2; + u_int8_t tweak[AES_XTS_BLOCKSIZE]; +}; + +#endif /* _CRYPTO_XFORM_ENC_H_ */ diff --git a/sys/opencrypto/xform_gmac.c b/sys/opencrypto/xform_gmac.c new file mode 100644 index 000000000000..156ed7f13443 --- /dev/null +++ b/sys/opencrypto/xform_gmac.c @@ -0,0 +1,99 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +/* Encryption instances */ +struct enc_xform enc_xform_aes_nist_gmac = { + CRYPTO_AES_NIST_GMAC, "AES-GMAC", + AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +/* Authentication instances */ +struct auth_hash auth_hash_nist_gmac_aes_128 = { + CRYPTO_AES_128_NIST_GMAC, "GMAC-AES-128", + AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), + GMAC_BLOCK_LEN, + (void (*)(void *)) AES_GMAC_Init, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, + (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, + (void (*)(u_int8_t *, void *)) AES_GMAC_Final +}; + +struct auth_hash auth_hash_nist_gmac_aes_192 = { + CRYPTO_AES_192_NIST_GMAC, "GMAC-AES-192", + AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), + GMAC_BLOCK_LEN, + (void (*)(void *)) AES_GMAC_Init, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, + (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, + (void (*)(u_int8_t *, void *)) AES_GMAC_Final +}; + +struct auth_hash auth_hash_nist_gmac_aes_256 = { + CRYPTO_AES_256_NIST_GMAC, "GMAC-AES-256", + AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx), + GMAC_BLOCK_LEN, + (void (*)(void *)) AES_GMAC_Init, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey, + (void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit, + (int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update, + (void (*)(u_int8_t *, void *)) AES_GMAC_Final +}; diff --git a/sys/opencrypto/xform_md5.c b/sys/opencrypto/xform_md5.c new file mode 100644 index 000000000000..3a8751d9c020 --- /dev/null +++ b/sys/opencrypto/xform_md5.c @@ -0,0 +1,81 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int MD5Update_int(void *, const u_int8_t *, u_int16_t); + +/* Authentication instances */ +struct auth_hash auth_hash_hmac_md5 = { + CRYPTO_MD5_HMAC, "HMAC-MD5", + MD5_HMAC_KEY_LEN, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN, + (void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int, + (void (*) (u_int8_t *, void *)) MD5Final +}; + +struct auth_hash auth_hash_key_md5 = { + CRYPTO_MD5_KPDK, "Keyed MD5", + NULL_HMAC_KEY_LEN, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0, + (void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int, + (void (*)(u_int8_t *, void *)) MD5Final +}; + +/* + * And now for auth. + */ +static int +MD5Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + MD5Update(ctx, buf, len); + return 0; +} diff --git a/sys/opencrypto/xform_null.c b/sys/opencrypto/xform_null.c new file mode 100644 index 000000000000..74f410cba945 --- /dev/null +++ b/sys/opencrypto/xform_null.c @@ -0,0 +1,136 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int null_setkey(u_int8_t **, u_int8_t *, int); +static void null_encrypt(caddr_t, u_int8_t *); +static void null_decrypt(caddr_t, u_int8_t *); +static void null_zerokey(u_int8_t **); + +static void null_init(void *); +static void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len); +static int null_update(void *, const u_int8_t *, u_int16_t); +static void null_final(u_int8_t *, void *); + +/* Encryption instances */ +struct enc_xform enc_xform_null = { + CRYPTO_NULL_CBC, "NULL", + /* NB: blocksize of 4 is to generate a properly aligned ESP header */ + NULL_BLOCK_LEN, 0, NULL_MIN_KEY, NULL_MAX_KEY, + null_encrypt, + null_decrypt, + null_setkey, + null_zerokey, + NULL, +}; + +/* Authentication instances */ +struct auth_hash auth_hash_null = { /* NB: context isn't used */ + CRYPTO_NULL_HMAC, "NULL-HMAC", + NULL_HMAC_KEY_LEN, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN, + null_init, null_reinit, null_reinit, null_update, null_final +}; + +/* + * Encryption wrapper routines. + */ +static void +null_encrypt(caddr_t key, u_int8_t *blk) +{ +} + +static void +null_decrypt(caddr_t key, u_int8_t *blk) +{ +} + +static int +null_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + *sched = NULL; + return 0; +} + +static void +null_zerokey(u_int8_t **sched) +{ + *sched = NULL; +} + +/* + * And now for auth. + */ + +static void +null_init(void *ctx) +{ +} + +static void +null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len) +{ +} + +static int +null_update(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + return 0; +} + +static void +null_final(u_int8_t *buf, void *ctx) +{ + if (buf != (u_int8_t *) 0) + bzero(buf, 12); +} diff --git a/sys/opencrypto/xform_rijndael.c b/sys/opencrypto/xform_rijndael.c new file mode 100644 index 000000000000..2c974f3d62df --- /dev/null +++ b/sys/opencrypto/xform_rijndael.c @@ -0,0 +1,113 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int rijndael128_setkey(u_int8_t **, u_int8_t *, int); +static void rijndael128_encrypt(caddr_t, u_int8_t *); +static void rijndael128_decrypt(caddr_t, u_int8_t *); +static void rijndael128_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_rijndael128 = { + CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES", + RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, RIJNDAEL_MIN_KEY, + RIJNDAEL_MAX_KEY, + rijndael128_encrypt, + rijndael128_decrypt, + rijndael128_setkey, + rijndael128_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +rijndael128_encrypt(caddr_t key, u_int8_t *blk) +{ + rijndael_encrypt((rijndael_ctx *) key, (u_char *) blk, (u_char *) blk); +} + +static void +rijndael128_decrypt(caddr_t key, u_int8_t *blk) +{ + rijndael_decrypt(((rijndael_ctx *) key), (u_char *) blk, + (u_char *) blk); +} + +static int +rijndael128_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + int err; + + if (len != 16 && len != 24 && len != 32) + return (EINVAL); + *sched = KMALLOC(sizeof(rijndael_ctx), M_CRYPTO_DATA, + M_NOWAIT|M_ZERO); + if (*sched != NULL) { + rijndael_set_key((rijndael_ctx *) *sched, (u_char *) key, + len * 8); + err = 0; + } else + err = ENOMEM; + return err; +} + +static void +rijndael128_zerokey(u_int8_t **sched) +{ + bzero(*sched, sizeof(rijndael_ctx)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_rmd160.c b/sys/opencrypto/xform_rmd160.c new file mode 100644 index 000000000000..4bce0729fa0b --- /dev/null +++ b/sys/opencrypto/xform_rmd160.c @@ -0,0 +1,75 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int RMD160Update_int(void *, const u_int8_t *, u_int16_t); + +/* Authentication instances */ +struct auth_hash auth_hash_hmac_ripemd_160 = { + CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160", + RIPEMD160_HMAC_KEY_LEN, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX), + RIPEMD160_HMAC_BLOCK_LEN, + (void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int, + (void (*)(u_int8_t *, void *)) RMD160Final +}; + +/* + * And now for auth. + */ +static int +RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + RMD160Update(ctx, buf, len); + return 0; +} diff --git a/sys/opencrypto/xform_sha1.c b/sys/opencrypto/xform_sha1.c new file mode 100644 index 000000000000..29a5916559c2 --- /dev/null +++ b/sys/opencrypto/xform_sha1.c @@ -0,0 +1,93 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static void SHA1Init_int(void *); +static int SHA1Update_int(void *, const u_int8_t *, u_int16_t); +static void SHA1Final_int(u_int8_t *, void *); + +/* Authentication instances */ +struct auth_hash auth_hash_hmac_sha1 = { + CRYPTO_SHA1_HMAC, "HMAC-SHA1", + SHA1_HMAC_KEY_LEN, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN, + SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int +}; + +struct auth_hash auth_hash_key_sha1 = { + CRYPTO_SHA1_KPDK, "Keyed SHA1", + NULL_HMAC_KEY_LEN, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0, + SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int +}; + +/* + * And now for auth. + */ +static void +SHA1Init_int(void *ctx) +{ + SHA1Init(ctx); +} + +static int +SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + SHA1Update(ctx, buf, len); + return 0; +} + +static void +SHA1Final_int(u_int8_t *blk, void *ctx) +{ + SHA1Final(blk, ctx); +} diff --git a/sys/opencrypto/xform_sha2.c b/sys/opencrypto/xform_sha2.c new file mode 100644 index 000000000000..389cb8dab981 --- /dev/null +++ b/sys/opencrypto/xform_sha2.c @@ -0,0 +1,109 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +static int SHA256Update_int(void *, const u_int8_t *, u_int16_t); +static int SHA384Update_int(void *, const u_int8_t *, u_int16_t); +static int SHA512Update_int(void *, const u_int8_t *, u_int16_t); + +/* Authentication instances */ +struct auth_hash auth_hash_hmac_sha2_256 = { + CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256", + SHA2_256_HMAC_KEY_LEN, SHA2_256_HASH_LEN, sizeof(SHA256_CTX), + SHA2_256_HMAC_BLOCK_LEN, + (void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int, + (void (*)(u_int8_t *, void *)) SHA256_Final +}; + +struct auth_hash auth_hash_hmac_sha2_384 = { + CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384", + SHA2_384_HMAC_KEY_LEN, SHA2_384_HASH_LEN, sizeof(SHA384_CTX), + SHA2_384_HMAC_BLOCK_LEN, + (void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int, + (void (*)(u_int8_t *, void *)) SHA384_Final +}; + +struct auth_hash auth_hash_hmac_sha2_512 = { + CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512", + SHA2_512_HMAC_KEY_LEN, SHA2_512_HASH_LEN, sizeof(SHA512_CTX), + SHA2_512_HMAC_BLOCK_LEN, + (void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int, + (void (*)(u_int8_t *, void *)) SHA512_Final +}; + +/* + * And now for auth. + */ +static int +SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + SHA256_Update(ctx, buf, len); + return 0; +} + +static int +SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + SHA384_Update(ctx, buf, len); + return 0; +} + +static int +SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + SHA512_Update(ctx, buf, len); + return 0; +} diff --git a/sys/opencrypto/xform_skipjack.c b/sys/opencrypto/xform_skipjack.c new file mode 100644 index 000000000000..94090d0d9612 --- /dev/null +++ b/sys/opencrypto/xform_skipjack.c @@ -0,0 +1,117 @@ +/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ +/*- + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * AES XTS implementation in 2008 by Damien Miller + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Copyright (C) 2001, Angelos D. Keromytis. + * + * Copyright (C) 2008, Damien Miller + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by John-Mark Gurney + * under sponsorship of the FreeBSD Foundation and + * Rubicon Communications, LLC (Netgate). + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int skipjack_setkey(u_int8_t **, u_int8_t *, int); +static void skipjack_encrypt(caddr_t, u_int8_t *); +static void skipjack_decrypt(caddr_t, u_int8_t *); +static void skipjack_zerokey(u_int8_t **); + +/* Encryption instances */ +struct enc_xform enc_xform_skipjack = { + CRYPTO_SKIPJACK_CBC, "Skipjack", + SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, SKIPJACK_MIN_KEY, + SKIPJACK_MAX_KEY, + skipjack_encrypt, + skipjack_decrypt, skipjack_setkey, + skipjack_zerokey, + NULL, +}; + +/* + * Encryption wrapper routines. + */ +static void +skipjack_encrypt(caddr_t key, u_int8_t *blk) +{ + skipjack_forwards(blk, blk, (u_int8_t **) key); +} + +static void +skipjack_decrypt(caddr_t key, u_int8_t *blk) +{ + skipjack_backwards(blk, blk, (u_int8_t **) key); +} + +static int +skipjack_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + int err; + + /* NB: allocate all the memory that's needed at once */ + *sched = KMALLOC(10 * (sizeof(u_int8_t *) + 0x100), + M_CRYPTO_DATA, M_NOWAIT|M_ZERO); + if (*sched != NULL) { + u_int8_t** key_tables = (u_int8_t**) *sched; + u_int8_t* table = (u_int8_t*) &key_tables[10]; + int k; + + for (k = 0; k < 10; k++) { + key_tables[k] = table; + table += 0x100; + } + subkey_table_gen(key, (u_int8_t **) *sched); + err = 0; + } else + err = ENOMEM; + return err; +} + +static void +skipjack_zerokey(u_int8_t **sched) +{ + bzero(*sched, 10 * (sizeof(u_int8_t *) + 0x100)); + KFREE(*sched, M_CRYPTO_DATA); + *sched = NULL; +} diff --git a/sys/opencrypto/xform_userland.h b/sys/opencrypto/xform_userland.h new file mode 100644 index 000000000000..04266dc8cd8e --- /dev/null +++ b/sys/opencrypto/xform_userland.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2015 Allan Jude + * 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 AUTHORS 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 AUTHORS 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$ + */ + +#ifndef _CRYPTO_XFORM_USERLAND_H_ +#define _CRYPTO_XFORM_USERLAND_H_ + +#ifdef _KERNEL +#include +#define KMALLOC(size, type, flags) malloc(size, type, flags) +#define KFREE(ptr, type) free(ptr, type) +#else /* not _KERNEL */ +#ifdef _STAND +#include +#else /* !_STAND */ +#include +#include +#endif /* _STAND */ +#define KMALLOC(size, type, flags) malloc(size) +#define KFREE(ptr, type) free(ptr) +#endif /* _KERNEL */ + + +#endif /* _CRYPTO_XFORM_USERLAND_H_ */ From 71b93c43ba5b4d196705cdfe8061b86047cc9bf9 Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 30 Dec 2015 23:04:08 +0000 Subject: [PATCH 31/55] Add the MOVT/MOVW types to the list of relocs which do not generate .plt entries. This fixes the segfaults in arm userland code compiled with -march= or -mcpu= values that allow the compiler to generate movw/movt sequences to load 32-bit constants. --- contrib/binutils/bfd/elf32-arm.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/contrib/binutils/bfd/elf32-arm.c b/contrib/binutils/bfd/elf32-arm.c index 753cdcc1783e..e20ccca85162 100644 --- a/contrib/binutils/bfd/elf32-arm.c +++ b/contrib/binutils/bfd/elf32-arm.c @@ -7720,12 +7720,26 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, refers to is in a different object. We can't tell for sure yet, because something later might force the symbol local. */ - if (r_type != R_ARM_ABS32 - && r_type != R_ARM_REL32 - && r_type != R_ARM_ABS32_NOI - && r_type != R_ARM_REL32_NOI - && r_type != R_ARM_ABS12) - h->needs_plt = 1; + switch (r_type) + { + case R_ARM_ABS12: + case R_ARM_ABS32: + case R_ARM_ABS32_NOI: + case R_ARM_REL32: + case R_ARM_REL32_NOI: + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + break; + default: + h->needs_plt = 1; + break; + } /* If we create a PLT entry, this relocation will reference it, even if it's an ABS32 relocation. */ From b4794ad3d5455631d996e514793f47fe380e0b7b Mon Sep 17 00:00:00 2001 From: allanjude Date: Wed, 30 Dec 2015 23:27:24 +0000 Subject: [PATCH 32/55] Bump __FreeBSD_version because r292782 removes sys/crypto/sha2.h Submitted by: Oliver Pinter --- sys/sys/param.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/param.h b/sys/sys/param.h index 69eb391d2c50..3c9747aa4045 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100092 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100093 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, From 0be55d57decb949acf2ef026080ebaf8bd94d8c0 Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 01:54:07 +0000 Subject: [PATCH 33/55] Clean up unused-but-set-variable spotted by gcc-4.9. Reviewed by: royger Approved by: rodrigc (mentor) Differential Revision: https://reviews.freebsd.org/D4733 --- sys/xen/xenbus/xenbusb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/xen/xenbus/xenbusb.c b/sys/xen/xenbus/xenbusb.c index 4853b3a211a1..03525484793d 100644 --- a/sys/xen/xenbus/xenbusb.c +++ b/sys/xen/xenbus/xenbusb.c @@ -561,7 +561,6 @@ xenbusb_devices_changed(struct xs_watch *watch, const char **vec, struct xenbusb_softc *xbs; device_t dev; char *node; - char *bus; char *type; char *id; char *p; @@ -580,7 +579,6 @@ xenbusb_devices_changed(struct xs_watch *watch, const char **vec, p = strchr(node, '/'); if (p == NULL) goto out; - bus = node; *p = 0; type = p + 1; From 095eb8147518134ad20380dc0ee73a8da400b656 Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 01:55:51 +0000 Subject: [PATCH 34/55] Clean up unused-but-set-variable spotted by gcc-4.9. Reviewed by: grehan Approved by: bapt (mentor) Differential Revision: https://reviews.freebsd.org/D4735 --- usr.sbin/bhyve/pci_emul.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index af427effdfdd..c6763c93c018 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -863,10 +863,9 @@ msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, int bytes, uint32_t val) { uint16_t msgctrl, rwmask; - int off, table_bar; + int off; off = offset - capoff; - table_bar = pi->pi_msix.table_bar; /* Message Control Register */ if (off == 2 && bytes == 2) { rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK; From 8571577d81a2a8b4a5567f4b77fbc388a6d67077 Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 01:57:55 +0000 Subject: [PATCH 35/55] Clean up unused-but-set-variable spotted by gcc-4.9. Approved by: bapt (mentor) Differential Revision: https://reviews.freebsd.org/D4736 --- usr.sbin/camdd/camdd.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/usr.sbin/camdd/camdd.c b/usr.sbin/camdd/camdd.c index 573214e5bc5b..9284eb5459d0 100644 --- a/usr.sbin/camdd/camdd.c +++ b/usr.sbin/camdd/camdd.c @@ -1276,7 +1276,6 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, struct camdd_dev_pass *pass_dev; struct kevent ke; int scsi_dev_type; - int retval; dev = NULL; @@ -1336,7 +1335,6 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - retval = 1; goto bailout; } @@ -1371,11 +1369,8 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, if (cam_send_ccb(cam_dev, ccb) < 0) { warn("error sending READ CAPACITY (16) command"); - cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - - retval = 1; goto bailout; } From 8da8855e8f1a66d82a9a08a2ac82c9d802bfd2f3 Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 02:01:20 +0000 Subject: [PATCH 36/55] Wrap using #ifdef 'notyet' those variables and statements not yet implemented to lower the compiler warnings. It fix the case of unused-but-set-variable spotted by gcc4.9. Reviewed by: ngie, ae Approved by: bapt (mentor) Differential Revision: https://reviews.freebsd.org/D4720 --- sys/net/if_gre.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 24ed971135c2..9d4a9763ca7f 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -682,7 +682,10 @@ gre_input(struct mbuf **mp, int *offp, int proto) struct grehdr *gh; struct ifnet *ifp; struct mbuf *m; - uint32_t *opts, key; + uint32_t *opts; +#ifdef notyet + uint32_t key; +#endif uint16_t flags; int hlen, isr, af; @@ -715,17 +718,28 @@ gre_input(struct mbuf **mp, int *offp, int proto) opts++; } if (flags & GRE_FLAGS_KP) { +#ifdef notyet + /* + * XXX: The current implementation uses the key only for outgoing + * packets. But we can check the key value here, or even in the + * encapcheck function. + */ key = ntohl(*opts); +#endif hlen += sizeof(uint32_t); opts++; + } +#ifdef notyet } else key = 0; - /* + if (sc->gre_key != 0 && (key != sc->gre_key || key != 0)) goto drop; - */ +#endif if (flags & GRE_FLAGS_SP) { - /* seq = ntohl(*opts); */ +#ifdef notyet + seq = ntohl(*opts); +#endif hlen += sizeof(uint32_t); } switch (ntohs(gh->gre_proto)) { From 93152c67c93acd0eca913cc1939a3393129c2c4d Mon Sep 17 00:00:00 2001 From: melifaro Date: Thu, 31 Dec 2015 05:03:27 +0000 Subject: [PATCH 37/55] Implement interface link header precomputation API. Add if_requestencap() interface method which is capable of calculating various link headers for given interface. Right now there is support for INET/INET6/ARP llheader calculation (IFENCAP_LL type request). Other types are planned to support more complex calculation (L2 multipath lagg nexthops, tunnel encap nexthops, etc..). Reshape 'struct route' to be able to pass additional data (with is length) to prepend to mbuf. These two changes permits routing code to pass pre-calculated nexthop data (like L2 header for route w/gateway) down to the stack eliminating the need for other lookups. It also brings us closer to more complex scenarios like transparently handling MPLS nexthops and tunnel interfaces. Last, but not least, it removes layering violation introduced by flowtable code (ro_lle) and simplifies handling of existing if_output consumers. ARP/ND changes: Make arp/ndp stack pre-calculate link header upon installing/updating lle record. Interface link address change are handled by re-calculating headers for all lles based on if_lladdr event. After these changes, arpresolve()/nd6_resolve() returns full pre-calculated header for supported interfaces thus simplifying if_output(). Move these lookups to separate ether_resolve_addr() function which ether returs error or fully-prepared link header. Add resolve_addr() compat versions to return link addresses instead of pre-calculated data. BPF changes: Raw bpf writes occupied _two_ cases: AF_UNSPEC and pseudo_AF_HDRCMPLT. Despite the naming, both of there have ther header "complete". The only difference is that interface source mac has to be filled by OS for AF_UNSPEC (controlled via BIOCGHDRCMPLT). This logic has to stay inside BPF and not pollute if_output() routines. Convert BPF to pass prepend data via new 'struct route' mechanism. Note that it does not change non-optimized if_output(): ro_prepend handling is purely optional. Side note: hackish pseudo_AF_HDRCMPLT is supported for ethernet and FDDI. It is not needed for ethernet anymore. The only remaining FDDI user is dev/pdq mostly untouched since 2007. FDDI support was eliminated from OpenBSD in 2013 (sys/net/if_fddisubr.c rev 1.65). Flowtable changes: Flowtable violates layering by saving (and not correctly managing) rtes/lles. Instead of passing lle pointer, pass pointer to pre-calculated header data from that lle. Differential Revision: https://reviews.freebsd.org/D4102 --- sys/dev/cxgb/ulp/tom/cxgb_l2t.c | 2 +- sys/dev/cxgbe/tom/t4_tom_l2t.c | 2 +- sys/net/bpf.c | 24 +- sys/net/flowtable.c | 10 +- sys/net/if.c | 41 +++ sys/net/if_ethersubr.c | 289 +++++++++++------- sys/net/if_llatbl.c | 102 ++++++- sys/net/if_llatbl.h | 20 +- sys/net/if_var.h | 44 +++ sys/net/route.h | 13 +- sys/netinet/if_ether.c | 178 ++++++++--- sys/netinet/if_ether.h | 2 + sys/netinet/in.c | 12 +- sys/netinet/ip_output.c | 2 +- sys/netinet/toecore.c | 2 +- sys/netinet6/icmp6.c | 2 +- sys/netinet6/in6.c | 10 +- sys/netinet6/in6.h | 6 +- sys/netinet6/nd6.c | 92 +++++- sys/netinet6/nd6.h | 2 + sys/netinet6/nd6_nbr.c | 22 +- .../drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 +- 22 files changed, 672 insertions(+), 213 deletions(-) diff --git a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c index 4352f33e6cd1..c2390ae2f93d 100644 --- a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c +++ b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c @@ -215,7 +215,7 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e) struct tom_data *td = sc->tom_softc; struct toedev *tod = &td->tod; struct sockaddr_in sin = {0}; - uint8_t dmac[ETHER_ADDR_LEN]; + uint8_t dmac[ETHER_HDR_LEN]; uint16_t vtag = EVL_VLID_MASK; int rc; diff --git a/sys/dev/cxgbe/tom/t4_tom_l2t.c b/sys/dev/cxgbe/tom/t4_tom_l2t.c index 65f7d2389473..8aadf34a9b5e 100644 --- a/sys/dev/cxgbe/tom/t4_tom_l2t.c +++ b/sys/dev/cxgbe/tom/t4_tom_l2t.c @@ -233,7 +233,7 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e) struct sockaddr_in sin = {0}; struct sockaddr_in6 sin6 = {0}; struct sockaddr *sa; - uint8_t dmac[ETHER_ADDR_LEN]; + uint8_t dmac[ETHER_HDR_LEN]; uint16_t vtag = VLAN_NONE; int rc; diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 37edbe827537..661a1cfbd1fb 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #ifdef BPF_JITTER @@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$"); #endif #include #include +#include #include #include @@ -164,7 +166,7 @@ static void bpf_detachd(struct bpf_d *); static void bpf_detachd_locked(struct bpf_d *); static void bpf_freed(struct bpf_d *); static int bpf_movein(struct uio *, int, struct ifnet *, struct mbuf **, - struct sockaddr *, int *, struct bpf_insn *); + struct sockaddr *, int *, struct bpf_d *); static int bpf_setif(struct bpf_d *, struct ifreq *); static void bpf_timed_out(void *); static __inline void @@ -454,7 +456,7 @@ bpf_ioctl_setzbuf(struct thread *td, struct bpf_d *d, struct bpf_zbuf *bz) */ static int bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp, - struct sockaddr *sockp, int *hdrlen, struct bpf_insn *wfilter) + struct sockaddr *sockp, int *hdrlen, struct bpf_d *d) { const struct ieee80211_bpf_params *p; struct ether_header *eh; @@ -549,7 +551,7 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp, if (error) goto bad; - slen = bpf_filter(wfilter, mtod(m, u_char *), len, len); + slen = bpf_filter(d->bd_wfilter, mtod(m, u_char *), len, len); if (slen == 0) { error = EPERM; goto bad; @@ -566,6 +568,10 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp, else m->m_flags |= M_MCAST; } + if (d->bd_hdrcmplt == 0) { + memcpy(eh->ether_shost, IF_LLADDR(ifp), + sizeof(eh->ether_shost)); + } break; } @@ -1088,6 +1094,7 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) struct ifnet *ifp; struct mbuf *m, *mc; struct sockaddr dst; + struct route ro; int error, hlen; error = devfs_get_cdevpriv((void **)&d); @@ -1119,7 +1126,7 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) hlen = 0; /* XXX: bpf_movein() can sleep */ error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp, - &m, &dst, &hlen, d->bd_wfilter); + &m, &dst, &hlen, d); if (error) { d->bd_wdcount++; return (error); @@ -1151,7 +1158,14 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) BPFD_UNLOCK(d); #endif - error = (*ifp->if_output)(ifp, m, &dst, NULL); + bzero(&ro, sizeof(ro)); + if (hlen != 0) { + ro.ro_prepend = (u_char *)&dst.sa_data; + ro.ro_plen = hlen; + ro.ro_flags = RT_HAS_HEADER; + } + + error = (*ifp->if_output)(ifp, m, &dst, &ro); if (error) d->bd_wdcount++; diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index a16584356ee4..f45a6872a815 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -665,6 +665,7 @@ int flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro) { struct flentry *fle; + struct llentry *lle; if (V_flowtable_enable == 0) return (ENXIO); @@ -693,8 +694,15 @@ flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro) } ro->ro_rt = fle->f_rt; - ro->ro_lle = fle->f_lle; ro->ro_flags |= RT_NORTREF; + lle = fle->f_lle; + if (lle != NULL && (lle->la_flags & LLE_VALID)) { + ro->ro_prepend = lle->r_linkdata; + ro->ro_plen = lle->r_hdrlen; + ro->ro_flags |= RT_MAY_LOOP; + if (lle->la_flags & LLE_IFADDR) + ro->ro_flags |= RT_L2_ME; + } return (0); } diff --git a/sys/net/if.c b/sys/net/if.c index 39656efa363d..b9e524cdad89 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -161,6 +161,7 @@ static int ifconf(u_long, caddr_t); static void if_freemulti(struct ifmultiaddr *); static void if_grow(void); static void if_input_default(struct ifnet *, struct mbuf *); +static int if_requestencap_default(struct ifnet *, struct if_encap_req *); static void if_route(struct ifnet *, int flag, int fam); static int if_setflag(struct ifnet *, int, int, int *, int); static int if_transmit(struct ifnet *ifp, struct mbuf *m); @@ -673,6 +674,9 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) if (ifp->if_input == NULL) ifp->if_input = if_input_default; + if (ifp->if_requestencap == NULL) + ifp->if_requestencap = if_requestencap_default; + if (!vmove) { #ifdef MAC mac_ifnet_create(ifp); @@ -3397,6 +3401,43 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) return (0); } +/* + * Compat function for handling basic encapsulation requests. + * Not converted stacks (FDDI, IB, ..) supports traditional + * output model: ARP (and other similar L2 protocols) are handled + * inside output routine, arpresolve/nd6_resolve() returns MAC + * address instead of full prepend. + * + * This function creates calculated header==MAC for IPv4/IPv6 and + * returns EAFNOSUPPORT (which is then handled in ARP code) for other + * address families. + */ +static int +if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req) +{ + + if (req->rtype != IFENCAP_LL) + return (EOPNOTSUPP); + + if (req->bufsize < req->lladdr_len) + return (ENOMEM); + + switch (req->family) { + case AF_INET: + case AF_INET6: + break; + default: + return (EAFNOSUPPORT); + } + + /* Copy lladdr to storage as is */ + memmove(req->buf, req->lladdr, req->lladdr_len); + req->bufsize = req->lladdr_len; + req->lladdr_off = 0; + + return (0); +} + /* * The name argument must be a pointer to storage which will last as * long as the interface does. For physical devices, the result of diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 71e28ea00166..5186406248d9 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -113,6 +113,7 @@ static int ether_resolvemulti(struct ifnet *, struct sockaddr **, #ifdef VIMAGE static void ether_reassign(struct ifnet *, struct vnet *, char *); #endif +static int ether_requestencap(struct ifnet *, struct if_encap_req *); #define ETHER_IS_BROADCAST(addr) \ (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) @@ -135,6 +136,138 @@ update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst) dst->m_pkthdr.csum_data = 0xffff; } +/* + * Handle link-layer encapsulation requests. + */ +static int +ether_requestencap(struct ifnet *ifp, struct if_encap_req *req) +{ + struct ether_header *eh; + struct arphdr *ah; + uint16_t etype; + const u_char *lladdr; + + if (req->rtype != IFENCAP_LL) + return (EOPNOTSUPP); + + if (req->bufsize < ETHER_HDR_LEN) + return (ENOMEM); + + eh = (struct ether_header *)req->buf; + lladdr = req->lladdr; + req->lladdr_off = 0; + + switch (req->family) { + case AF_INET: + etype = htons(ETHERTYPE_IP); + break; + case AF_INET6: + etype = htons(ETHERTYPE_IPV6); + break; + case AF_ARP: + ah = (struct arphdr *)req->hdata; + ah->ar_hrd = htons(ARPHRD_ETHER); + + switch(ntohs(ah->ar_op)) { + case ARPOP_REVREQUEST: + case ARPOP_REVREPLY: + etype = htons(ETHERTYPE_REVARP); + break; + case ARPOP_REQUEST: + case ARPOP_REPLY: + default: + etype = htons(ETHERTYPE_ARP); + break; + } + + if (req->flags & IFENCAP_FLAG_BROADCAST) + lladdr = ifp->if_broadcastaddr; + break; + default: + return (EAFNOSUPPORT); + } + + memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type)); + memcpy(eh->ether_dhost, lladdr, ETHER_ADDR_LEN); + memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); + req->bufsize = sizeof(struct ether_header); + + return (0); +} + + +static int +ether_resolve_addr(struct ifnet *ifp, struct mbuf *m, + const struct sockaddr *dst, struct route *ro, u_char *phdr, + uint32_t *pflags) +{ + struct ether_header *eh; + struct rtentry *rt; + uint32_t lleflags = 0; + int error = 0; +#if defined(INET) || defined(INET6) + uint16_t etype; +#endif + + eh = (struct ether_header *)phdr; + + switch (dst->sa_family) { +#ifdef INET + case AF_INET: + if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) + error = arpresolve(ifp, 0, m, dst, phdr, &lleflags); + else { + if (m->m_flags & M_BCAST) + memcpy(eh->ether_dhost, ifp->if_broadcastaddr, + ETHER_ADDR_LEN); + else { + const struct in_addr *a; + a = &(((const struct sockaddr_in *)dst)->sin_addr); + ETHER_MAP_IP_MULTICAST(a, eh->ether_dhost); + } + etype = htons(ETHERTYPE_IP); + memcpy(&eh->ether_type, &etype, sizeof(etype)); + memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if ((m->m_flags & M_MCAST) == 0) + error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags); + else { + const struct in6_addr *a6; + a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr); + ETHER_MAP_IPV6_MULTICAST(a6, eh->ether_dhost); + etype = htons(ETHERTYPE_IPV6); + memcpy(&eh->ether_type, &etype, sizeof(etype)); + memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); + } + break; +#endif + default: + if_printf(ifp, "can't handle af%d\n", dst->sa_family); + if (m != NULL) + m_freem(m); + return (EAFNOSUPPORT); + } + + if (error == EHOSTDOWN) { + rt = (ro != NULL) ? ro->ro_rt : NULL; + if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0) + error = EHOSTUNREACH; + } + + if (error != 0) + return (error); + + *pflags = RT_MAY_LOOP; + if (lleflags & LLE_IFADDR) + *pflags |= RT_L2_ME; + + return (0); +} + /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. @@ -145,27 +278,20 @@ int ether_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { - short type; - int error = 0, hdrcmplt = 0; - u_char edst[ETHER_ADDR_LEN]; - struct llentry *lle = NULL; - struct rtentry *rt0 = NULL; + int error = 0; + char linkhdr[ETHER_HDR_LEN], *phdr; struct ether_header *eh; struct pf_mtag *t; int loop_copy = 1; int hlen; /* link layer header length */ - int is_gw = 0; - uint32_t pflags = 0; + uint32_t pflags; + phdr = NULL; + pflags = 0; if (ro != NULL) { - if (!(m->m_flags & (M_BCAST | M_MCAST))) { - lle = ro->ro_lle; - if (lle != NULL) - pflags = lle->la_flags; - } - rt0 = ro->ro_rt; - if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0) - is_gw = 1; + phdr = ro->ro_prepend; + hlen = ro->ro_plen; + pflags = ro->ro_flags; } #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -180,94 +306,31 @@ ether_output(struct ifnet *ifp, struct mbuf *m, (ifp->if_drv_flags & IFF_DRV_RUNNING))) senderr(ENETDOWN); - hlen = ETHER_HDR_LEN; - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - if (lle != NULL && (pflags & LLE_VALID) != 0) - memcpy(edst, &lle->ll_addr.mac16, sizeof(edst)); - else - error = arpresolve(ifp, is_gw, m, dst, edst, &pflags); - if (error) + if (phdr == NULL) { + /* No prepend data supplied. Try to calculate ourselves. */ + phdr = linkhdr; + hlen = ETHER_HDR_LEN; + error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags); + if (error != 0) return (error == EWOULDBLOCK ? 0 : error); - type = htons(ETHERTYPE_IP); - break; - case AF_ARP: - { - struct arphdr *ah; - ah = mtod(m, struct arphdr *); - ah->ar_hrd = htons(ARPHRD_ETHER); - - loop_copy = 0; /* if this is for us, don't do it */ - - switch(ntohs(ah->ar_op)) { - case ARPOP_REVREQUEST: - case ARPOP_REVREPLY: - type = htons(ETHERTYPE_REVARP); - break; - case ARPOP_REQUEST: - case ARPOP_REPLY: - default: - type = htons(ETHERTYPE_ARP); - break; - } - - if (m->m_flags & M_BCAST) - bcopy(ifp->if_broadcastaddr, edst, ETHER_ADDR_LEN); - else - bcopy(ar_tha(ah), edst, ETHER_ADDR_LEN); - - } - break; -#endif -#ifdef INET6 - case AF_INET6: - if (lle != NULL && (pflags & LLE_VALID)) - memcpy(edst, &lle->ll_addr.mac16, sizeof(edst)); - else - error = nd6_resolve(ifp, is_gw, m, dst, (u_char *)edst, - &pflags); - if (error) - return (error == EWOULDBLOCK ? 0 : error); - type = htons(ETHERTYPE_IPV6); - break; -#endif - case pseudo_AF_HDRCMPLT: - { - const struct ether_header *eh; - - hdrcmplt = 1; - /* FALLTHROUGH */ - - case AF_UNSPEC: - loop_copy = 0; /* if this is for us, don't do it */ - eh = (const struct ether_header *)dst->sa_data; - (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); - type = eh->ether_type; - break; - } - default: - if_printf(ifp, "can't handle af%d\n", dst->sa_family); - senderr(EAFNOSUPPORT); } - if ((pflags & LLE_IFADDR) != 0) { + if ((pflags & RT_L2_ME) != 0) { update_mbuf_csumflags(m, m); return (if_simloop(ifp, m, dst->sa_family, 0)); } + loop_copy = pflags & RT_MAY_LOOP; /* * Add local net header. If no space in first mbuf, * allocate another. */ - M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT); + M_PREPEND(m, hlen, M_NOWAIT); if (m == NULL) senderr(ENOBUFS); - eh = mtod(m, struct ether_header *); - if (hdrcmplt == 0) { - memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); - memcpy(eh->ether_dhost, edst, sizeof (edst)); - memcpy(eh->ether_shost, IF_LLADDR(ifp),sizeof(eh->ether_shost)); + if ((pflags & RT_HAS_HEADER) == 0) { + eh = mtod(m, struct ether_header *); + memcpy(eh, phdr, hlen); } /* @@ -279,34 +342,27 @@ ether_output(struct ifnet *ifp, struct mbuf *m, * on the wire). However, we don't do that here for security * reasons and compatibility with the original behavior. */ - if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy && + if ((m->m_flags & M_BCAST) && loop_copy && (ifp->if_flags & IFF_SIMPLEX) && ((t = pf_find_mtag(m)) == NULL || !t->routed)) { - if (m->m_flags & M_BCAST) { - struct mbuf *n; + struct mbuf *n; - /* - * Because if_simloop() modifies the packet, we need a - * writable copy through m_dup() instead of a readonly - * one as m_copy[m] would give us. The alternative would - * be to modify if_simloop() to handle the readonly mbuf, - * but performancewise it is mostly equivalent (trading - * extra data copying vs. extra locking). - * - * XXX This is a local workaround. A number of less - * often used kernel parts suffer from the same bug. - * See PR kern/105943 for a proposed general solution. - */ - if ((n = m_dup(m, M_NOWAIT)) != NULL) { - update_mbuf_csumflags(m, n); - (void)if_simloop(ifp, n, dst->sa_family, hlen); - } else - if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); - } else if (bcmp(eh->ether_dhost, eh->ether_shost, - ETHER_ADDR_LEN) == 0) { - update_mbuf_csumflags(m, m); - (void) if_simloop(ifp, m, dst->sa_family, hlen); - return (0); /* XXX */ - } + /* + * Because if_simloop() modifies the packet, we need a + * writable copy through m_dup() instead of a readonly + * one as m_copy[m] would give us. The alternative would + * be to modify if_simloop() to handle the readonly mbuf, + * but performancewise it is mostly equivalent (trading + * extra data copying vs. extra locking). + * + * XXX This is a local workaround. A number of less + * often used kernel parts suffer from the same bug. + * See PR kern/105943 for a proposed general solution. + */ + if ((n = m_dup(m, M_NOWAIT)) != NULL) { + update_mbuf_csumflags(m, n); + (void)if_simloop(ifp, n, dst->sa_family, hlen); + } else + if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); } /* @@ -798,6 +854,7 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla) ifp->if_output = ether_output; ifp->if_input = ether_input; ifp->if_resolvemulti = ether_resolvemulti; + ifp->if_requestencap = ether_requestencap; #ifdef VIMAGE ifp->if_reassign = ether_reassign; #endif diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index b0450b36000b..beef6b481adb 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -278,10 +278,12 @@ lltable_drop_entry_queue(struct llentry *lle) void lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle, - const char *lladdr) + const char *linkhdr, size_t linkhdrsize, int lladdr_off) { - bcopy(lladdr, &lle->ll_addr, ifp->if_addrlen); + memcpy(lle->r_linkdata, linkhdr, linkhdrsize); + lle->r_hdrlen = linkhdrsize; + lle->ll_addr = &lle->r_linkdata[lladdr_off]; lle->la_flags |= LLE_VALID; lle->r_flags |= RLLE_VALID; } @@ -296,7 +298,7 @@ lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle, */ int lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, - const char *lladdr) + const char *linkhdr, size_t linkhdrsize, int lladdr_off) { /* Perform real LLE update */ @@ -318,7 +320,7 @@ lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, } /* Update data */ - lltable_set_entry_addr(ifp, lle, lladdr); + lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off); IF_AFDATA_WUNLOCK(ifp); @@ -327,6 +329,84 @@ lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, return (1); } + /* + * Helper function used to pre-compute full/partial link-layer + * header data suitable for feeding into if_output(). + */ +int +lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr, + char *buf, size_t *bufsize, int *lladdr_off) +{ + struct if_encap_req ereq; + int error; + + bzero(buf, *bufsize); + bzero(&ereq, sizeof(ereq)); + ereq.buf = buf; + ereq.bufsize = *bufsize; + ereq.rtype = IFENCAP_LL; + ereq.family = family; + ereq.lladdr = lladdr; + ereq.lladdr_len = ifp->if_addrlen; + error = ifp->if_requestencap(ifp, &ereq); + if (error == 0) { + *bufsize = ereq.bufsize; + *lladdr_off = ereq.lladdr_off; + } + + return (error); +} + +/* + * Update link-layer header for given @lle after + * interface lladdr was changed. + */ +static int +llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg) +{ + struct ifnet *ifp; + u_char linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + u_char *lladdr; + int lladdr_off; + + ifp = (struct ifnet *)farg; + + lladdr = lle->ll_addr; + + LLE_WLOCK(lle); + if ((lle->la_flags & LLE_VALID) == 0) { + LLE_WUNLOCK(lle); + return (0); + } + + if ((lle->la_flags & LLE_IFADDR) != 0) + lladdr = IF_LLADDR(ifp); + + linkhdrsize = sizeof(linkhdr); + lltable_calc_llheader(ifp, llt->llt_af, lladdr, linkhdr, &linkhdrsize, + &lladdr_off); + memcpy(lle->r_linkdata, linkhdr, linkhdrsize); + LLE_WUNLOCK(lle); + + return (0); +} + +/* + * Update all calculated headers for given @llt + */ +void +lltable_update_ifaddr(struct lltable *llt) +{ + + if (llt->llt_ifp->if_flags & IFF_LOOPBACK) + return; + + IF_AFDATA_WLOCK(llt->llt_ifp); + lltable_foreach_lle(llt, llentry_update_ifaddr, llt->llt_ifp); + IF_AFDATA_WUNLOCK(llt->llt_ifp); +} + /* * * Performes generic cleanup routines and frees lle. @@ -642,6 +722,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) struct ifnet *ifp; struct lltable *llt; struct llentry *lle, *lle_tmp; + uint8_t linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; u_int laflags = 0; int error; @@ -677,11 +760,14 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) if (lle == NULL) return (ENOMEM); - bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen); + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, dst->sa_family, LLADDR(dl), + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return (EINVAL); + lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, + lladdr_off); if ((rtm->rtm_flags & RTF_ANNOUNCE)) lle->la_flags |= LLE_PUB; - lle->la_flags |= LLE_VALID; - lle->r_flags |= RLLE_VALID; lle->la_expire = rtm->rtm_rmx.rmx_expire; laflags = lle->la_flags; @@ -767,7 +853,7 @@ llatbl_lle_show(struct llentry_sa *la) db_printf(" ln_router=%u\n", lle->ln_router); db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick); db_printf(" lle_refcnt=%d\n", lle->lle_refcnt); - bcopy(&lle->ll_addr.mac16, octet, sizeof(octet)); + bcopy(lle->ll_addr, octet, sizeof(octet)); db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n", octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]); db_printf(" lle_timer=%p\n", &lle->lle_timer); diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index 8a300c31ed16..b6111c65cc9f 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -48,6 +48,7 @@ extern struct rwlock lltable_rwlock; #define LLTABLE_WUNLOCK() rw_wunlock(&lltable_rwlock) #define LLTABLE_LOCK_ASSERT() rw_assert(&lltable_rwlock, RA_LOCKED) +#define LLE_MAX_LINKHDR 24 /* Full IB header */ /* * Code referencing llentry must at least hold * a shared lock @@ -58,14 +59,11 @@ struct llentry { struct in_addr addr4; struct in6_addr addr6; } r_l3addr; - union { - uint64_t mac_aligned; - uint16_t mac16[3]; - uint8_t mac8[20]; /* IB needs 20 bytes. */ - } ll_addr; + char r_linkdata[LLE_MAX_LINKHDR]; /* L2 data */ + uint8_t r_hdrlen; /* length for LL header */ + uint8_t spare0[3]; uint16_t r_flags; /* LLE runtime flags */ uint16_t r_skip_req; /* feedback from fast path */ - uint64_t spare1; struct lltable *lle_tbl; struct llentries *lle_head; @@ -82,6 +80,7 @@ struct llentry { time_t lle_remtime; /* Real time remaining */ time_t lle_hittime; /* Time when r_skip_req was unset */ int lle_refcnt; + char *ll_addr; /* link-layer address */ LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */ struct callout lle_timer; @@ -198,6 +197,8 @@ MALLOC_DECLARE(M_LLTABLE); /* LLE request flags */ #define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */ #define LLE_UNLOCKED 0x4000 /* return lle unlocked */ +#define LLE_ADDRONLY 0x4000 /* return lladdr instead of full header */ +#define LLE_CREATE 0x8000 /* hint to avoid lle lookup */ /* LLE flags used by fastpath code */ #define RLLE_VALID 0x0001 /* entry is valid */ @@ -223,10 +224,13 @@ struct llentry *llentry_alloc(struct ifnet *, struct lltable *, /* helper functions */ size_t lltable_drop_entry_queue(struct llentry *); void lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle, - const char *lladdr); + const char *linkhdr, size_t linkhdrsize, int lladdr_off); int lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, - const char *lladdr); + const char *linkhdr, size_t linkhdrsize, int lladdr_off); +int lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr, + char *buf, size_t *bufsize, int *lladdr_off); +void lltable_update_ifaddr(struct lltable *llt); struct llentry *lltable_alloc_entry(struct lltable *llt, u_int flags, const struct sockaddr *l4addr); void lltable_free_entry(struct lltable *llt, struct llentry *lle); diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 5911cecb706b..54de56727f91 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -134,6 +134,48 @@ struct ifnet_hw_tsomax { u_int tsomaxsegsize; /* TSO maximum segment size in bytes */ }; +/* Interface encap request types */ +typedef enum { + IFENCAP_LL = 1 /* pre-calculate link-layer header */ +} ife_type; + +/* + * The structure below allows to request various pre-calculated L2/L3 headers + * for different media. Requests varies by type (rtype field). + * + * IFENCAP_LL type: pre-calculates link header based on address family + * and destination lladdr. + * + * Input data fields: + * buf: pointer to destination buffer + * bufsize: buffer size + * flags: IFENCAP_FLAG_BROADCAST if destination is broadcast + * family: address family defined by AF_ constant. + * lladdr: pointer to link-layer address + * lladdr_len: length of link-layer address + * hdata: pointer to L3 header (optional, used for ARP requests). + * Output data fields: + * buf: encap data is stored here + * bufsize: resulting encap length is stored here + * lladdr_off: offset of link-layer address from encap hdr start + * hdata: L3 header may be altered if necessary + */ + +struct if_encap_req { + u_char *buf; /* Destination buffer (w) */ + size_t bufsize; /* size of provided buffer (r) */ + ife_type rtype; /* request type (r) */ + uint32_t flags; /* Request flags (r) */ + int family; /* Address family AF_* (r) */ + int lladdr_off; /* offset from header start (w) */ + int lladdr_len; /* lladdr length (r) */ + char *lladdr; /* link-level address pointer (r) */ + char *hdata; /* Upper layer header data (rw) */ +}; + +#define IFENCAP_FLAG_BROADCAST 0x02 /* Destination is broadcast */ + + /* * Structure defining a network interface. * @@ -235,6 +277,8 @@ struct ifnet { void (*if_reassign) /* reassign to vnet routine */ (struct ifnet *, struct vnet *, char *); if_get_counter_t if_get_counter; /* get counter values */ + int (*if_requestencap) /* make link header from request */ + (struct ifnet *, struct if_encap_req *); /* Statistics. */ counter_u64_t if_counters[IFCOUNTERS]; diff --git a/sys/net/route.h b/sys/net/route.h index 66f4d775bb84..743c830f54f9 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -51,14 +51,21 @@ */ struct route { struct rtentry *ro_rt; - struct llentry *ro_lle; - struct in_ifaddr *ro_ia; - int ro_flags; + char *ro_prepend; + uint16_t ro_plen; + uint16_t ro_flags; struct sockaddr ro_dst; }; +#define RT_L2_ME_BIT 2 /* dst L2 addr is our address */ +#define RT_MAY_LOOP_BIT 3 /* dst may require loop copy */ +#define RT_HAS_HEADER_BIT 4 /* mbuf already have its header prepended */ + #define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */ #define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */ +#define RT_L2_ME (1 << RT_L2_ME_BIT) +#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT) +#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT) struct rt_metrics { u_long rmx_locks; /* Kernel must leave these values alone */ diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 4c0c586b6643..0bf5cecb8eec 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -281,6 +281,37 @@ arptimer(void *arg) CURVNET_RESTORE(); } +/* + * Stores link-layer header for @ifp in format suitable for if_output() + * into buffer @buf. Resulting header length is stored in @bufsize. + * + * Returns 0 on success. + */ +static int +arp_fillheader(struct ifnet *ifp, struct arphdr *ah, int bcast, u_char *buf, + size_t *bufsize) +{ + struct if_encap_req ereq; + int error; + + bzero(buf, *bufsize); + bzero(&ereq, sizeof(ereq)); + ereq.buf = buf; + ereq.bufsize = *bufsize; + ereq.rtype = IFENCAP_LL; + ereq.family = AF_ARP; + ereq.lladdr = ar_tha(ah); + ereq.hdata = (u_char *)ah; + if (bcast) + ereq.flags = IFENCAP_FLAG_BROADCAST; + error = ifp->if_requestencap(ifp, &ereq); + if (error == 0) + *bufsize = ereq.bufsize; + + return (error); +} + + /* * Broadcast an ARP request. Caller specifies: * - arp header source ip address @@ -295,6 +326,10 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip, struct arphdr *ah; struct sockaddr sa; u_char *carpaddr = NULL; + uint8_t linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + struct route ro; + int error; if (sip == NULL) { /* @@ -350,12 +385,28 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip, bcopy(tip, ar_tpa(ah), ah->ar_pln); sa.sa_family = AF_ARP; sa.sa_len = 2; + + /* Calculate link header for sending frame */ + bzero(&ro, sizeof(ro)); + linkhdrsize = sizeof(linkhdr); + error = arp_fillheader(ifp, ah, 1, linkhdr, &linkhdrsize); + if (error != 0 && error != EAFNOSUPPORT) { + ARP_LOG(LOG_ERR, "Failed to calculate ARP header on %s: %d\n", + if_name(ifp), error); + return; + } + + ro.ro_prepend = linkhdr; + ro.ro_plen = linkhdrsize; + ro.ro_flags = 0; + m->m_flags |= M_BCAST; m_clrprotoflags(m); /* Avoid confusing lower layers. */ - (*ifp->if_output)(ifp, m, &sa, NULL); + (*ifp->if_output)(ifp, m, &sa, &ro); ARPSTAT_INC(txrequests); } + /* * Resolve an IP address into an ethernet address - heavy version. * Used internally by arpresolve(). @@ -368,18 +419,20 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip, * Note that m_freem() handles NULL. */ static int -arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m, +arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { struct llentry *la = NULL, *la_tmp; struct mbuf *curr = NULL; struct mbuf *next = NULL; int error, renew; + char *lladdr; + int ll_len; if (pflags != NULL) *pflags = 0; - if (create == 0) { + if ((flags & LLE_CREATE) == 0) { IF_AFDATA_RLOCK(ifp); la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); IF_AFDATA_RUNLOCK(ifp); @@ -413,7 +466,14 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m, if ((la->la_flags & LLE_VALID) && ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { - bcopy(&la->ll_addr, desten, ifp->if_addrlen); + if (flags & LLE_ADDRONLY) { + lladdr = la->ll_addr; + ll_len = ifp->if_addrlen; + } else { + lladdr = la->r_linkdata; + ll_len = la->r_hdrlen; + } + bcopy(lladdr, desten, ll_len); /* Check if we have feedback request from arptimer() */ if (la->r_skip_req != 0) { @@ -485,15 +545,31 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m, /* * Resolve an IP address into an ethernet address. + */ +int +arpresolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, + char *desten, uint32_t *pflags) +{ + int error; + + flags |= LLE_ADDRONLY; + error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags); + return (error); +} + + +/* + * Lookups link header based on an IP address. * On input: * ifp is the interface we use * is_gw != 0 if @dst represents gateway to some destination * m is the mbuf. May be NULL if we don't have a packet. * dst is the next hop, - * desten is the storage to put LL address. + * desten is the storage to put LL header. * flags returns subset of lle flags: LLE_VALID | LLE_IFADDR * - * On success, desten and flags are filled in and the function returns 0; + * On success, full/partial link header and flags are filled in and + * the function returns 0. * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. * Note that m_freem() handles NULL. @@ -525,7 +601,7 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, la = lla_lookup(LLTABLE(ifp), LLE_UNLOCKED, dst); if (la != NULL && (la->r_flags & RLLE_VALID) != 0) { /* Entry found, let's copy lle info */ - bcopy(&la->ll_addr, desten, ifp->if_addrlen); + bcopy(la->r_linkdata, desten, la->r_hdrlen); if (pflags != NULL) *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR); /* Check if we have feedback request from arptimer() */ @@ -539,7 +615,8 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, } IF_AFDATA_RUNLOCK(ifp); - return (arpresolve_full(ifp, is_gw, 1, m, dst, desten, pflags)); + return (arpresolve_full(ifp, is_gw, la == NULL ? LLE_CREATE : 0, m, dst, + desten, pflags)); } /* @@ -683,6 +760,11 @@ in_arpinput(struct mbuf *m) struct sockaddr_in sin; struct sockaddr *dst; struct nhop4_basic nh4; + uint8_t linkhdr[LLE_MAX_LINKHDR]; + struct route ro; + size_t linkhdrsize; + int lladdr_off; + int error; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; @@ -850,8 +932,14 @@ match: else if (itaddr.s_addr == myaddr.s_addr) { /* * Request/reply to our address, but no lle exists yet. - * Try to create new llentry. + * Calculate full link prepend to use in lle. */ + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr, + &linkhdrsize, &lladdr_off) != 0) + goto reply; + + /* Allocate new entry */ la = lltable_alloc_entry(LLTABLE(ifp), 0, dst); if (la == NULL) { @@ -863,7 +951,8 @@ match: */ goto reply; } - lltable_set_entry_addr(ifp, la, ar_sha(ah)); + lltable_set_entry_addr(ifp, la, linkhdr, linkhdrsize, + lladdr_off); IF_AFDATA_WLOCK(ifp); LLE_WLOCK(la); @@ -921,7 +1010,7 @@ reply: if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); + (void)memcpy(ar_sha(ah), lle->ll_addr, ah->ar_hln); LLE_RUNLOCK(lle); } else { @@ -991,8 +1080,29 @@ reply: m->m_pkthdr.rcvif = NULL; sa.sa_family = AF_ARP; sa.sa_len = 2; + + /* Calculate link header for sending frame */ + bzero(&ro, sizeof(ro)); + linkhdrsize = sizeof(linkhdr); + error = arp_fillheader(ifp, ah, 0, linkhdr, &linkhdrsize); + + /* + * arp_fillheader() may fail due to lack of support inside encap request + * routing. This is not necessary an error, AF_ARP can/should be handled + * by if_output(). + */ + if (error != 0 && error != EAFNOSUPPORT) { + ARP_LOG(LOG_ERR, "Failed to calculate ARP header on %s: %d\n", + if_name(ifp), error); + return; + } + + ro.ro_prepend = linkhdr; + ro.ro_plen = linkhdrsize; + ro.ro_flags = 0; + m_clrprotoflags(m); /* Avoid confusing lower layers. */ - (*ifp->if_output)(ifp, m, &sa, NULL); + (*ifp->if_output)(ifp, m, &sa, &ro); ARPSTAT_INC(txreplies); return; @@ -1011,6 +1121,9 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp { struct sockaddr sa; struct mbuf *m_hold, *m_hold_next; + uint8_t linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; LLE_WLOCK_ASSERT(la); @@ -1027,7 +1140,7 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp return; } if ((la->la_flags & LLE_VALID) && - bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { + bcmp(ar_sha(ah), la->ll_addr, ifp->if_addrlen)) { if (la->la_flags & LLE_STATIC) { LLE_WUNLOCK(la); if (log_arp_permanent_modify) @@ -1050,31 +1163,19 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp } } + /* Calculate full link prepend to use in lle */ + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr, + &linkhdrsize, &lladdr_off) != 0) + return; + /* Check if something has changed */ - if (memcmp(&la->ll_addr, ar_sha(ah), ifp->if_addrlen) != 0 || + if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 || (la->la_flags & LLE_VALID) == 0) { - /* Perform real LLE update */ - /* use afdata WLOCK to update fields */ - LLE_ADDREF(la); - LLE_WUNLOCK(la); - IF_AFDATA_WLOCK(ifp); - LLE_WLOCK(la); - - /* - * Since we droppped LLE lock, other thread might have deleted - * this lle. Check and return - */ - if ((la->la_flags & LLE_DELETED) != 0) { - IF_AFDATA_WUNLOCK(ifp); - LLE_FREE_LOCKED(la); + /* Try to perform LLE update */ + if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize, + lladdr_off) == 0) return; - } - - /* Update data */ - lltable_set_entry_addr(ifp, la, ar_sha(ah)); - - IF_AFDATA_WUNLOCK(ifp); - LLE_REMREF(la); /* Clear fast path feedback request if set */ la->r_skip_req = 0; @@ -1215,10 +1316,12 @@ arp_handle_ifllchange(struct ifnet *ifp) /* * A handler for interface link layer address change event. */ -static __noinline void +static void arp_iflladdr(void *arg __unused, struct ifnet *ifp) { + lltable_update_ifaddr(LLTABLE(ifp)); + if ((ifp->if_flags & IFF_UP) != 0) arp_handle_ifllchange(ifp); } @@ -1231,5 +1334,8 @@ arp_init(void) if (IS_DEFAULT_VNET(curvnet)) iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + if (IS_DEFAULT_VNET(curvnet)) + iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, + arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); } SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index 1583ca560770..06ec210c07fb 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -114,6 +114,8 @@ extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN]; struct ifaddr; +int arpresolve_addr(struct ifnet *ifp, int flags, + const struct sockaddr *dst, char *desten, uint32_t *pflags); int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags); void arprequest(struct ifnet *, const struct in_addr *, diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 7504c8ffdb93..c30c1f3fdf88 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1240,6 +1240,9 @@ in_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr; struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; + char linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; KASSERT(l3addr->sa_family == AF_INET, ("sin_family %d", l3addr->sa_family)); @@ -1262,7 +1265,12 @@ in_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr if (flags & LLE_STATIC) lle->r_flags |= RLLE_VALID; if ((flags & LLE_IFADDR) == LLE_IFADDR) { - lltable_set_entry_addr(ifp, lle, IF_LLADDR(ifp)); + linkhdrsize = LLE_MAX_LINKHDR; + if (lltable_calc_llheader(ifp, AF_INET, IF_LLADDR(ifp), + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return (NULL); + lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, + lladdr_off); lle->la_flags |= LLE_STATIC; lle->r_flags |= (RLLE_VALID | RLLE_IFADDR); } @@ -1349,7 +1357,7 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle, sdl->sdl_type = ifp->if_type; if ((lle->la_flags & LLE_VALID) == LLE_VALID) { sdl->sdl_alen = ifp->if_addrlen; - bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); + bcopy(lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); } else { sdl->sdl_alen = 0; bzero(LLADDR(sdl), ifp->if_addrlen); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 557458a320bd..7ad43a229dba 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -567,7 +567,7 @@ sendit: RO_RTFREE(ro); if (have_ia_ref) ifa_free(&ia->ia_ifa); - ro->ro_lle = NULL; + ro->ro_prepend = NULL; rte = NULL; gw = dst; ip = mtod(m, struct ip *); diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c index ef82f8aa7aae..6ed8eb02d260 100644 --- a/sys/netinet/toecore.c +++ b/sys/netinet/toecore.c @@ -428,7 +428,7 @@ toe_lle_event(void *arg __unused, struct llentry *lle, int evt) KASSERT(lle->la_flags & LLE_VALID, ("%s: %p resolved but not valid?", __func__, lle)); - lladdr = (uint8_t *)&lle->ll_addr; + lladdr = (uint8_t *)lle->ll_addr; #ifdef VLAN_TAG VLAN_TAG(ifp, &vtag); #endif diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index f0c5371d245d..a7bbac05ab03 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -2632,7 +2632,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; nd_opt->nd_opt_len = len >> 3; lladdr = (char *)(nd_opt + 1); - bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen); + bcopy(ln->ll_addr, lladdr, ifp->if_addrlen); p += len; } } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index aa770199bd8e..0d47d4b3707d 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2245,6 +2245,9 @@ in6_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; + char linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); @@ -2265,7 +2268,12 @@ in6_lltable_alloc(struct lltable *llt, u_int flags, } lle->la_flags = flags; if ((flags & LLE_IFADDR) == LLE_IFADDR) { - lltable_set_entry_addr(ifp, lle, IF_LLADDR(ifp)); + linkhdrsize = LLE_MAX_LINKHDR; + if (lltable_calc_llheader(ifp, AF_INET6, IF_LLADDR(ifp), + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return (NULL); + lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, + lladdr_off); lle->la_flags |= LLE_STATIC; } diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 8f08c8f195fa..9bc142a0068c 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -375,9 +375,9 @@ extern const struct in6_addr in6addr_linklocal_allv2routers; #if __BSD_VISIBLE struct route_in6 { struct rtentry *ro_rt; - struct llentry *ro_lle; - struct in6_addr *ro_ia6; - int ro_flags; + char *ro_prepend; + uint16_t ro_plen; + uint16_t ro_flags; struct sockaddr_in6 ro_dst; }; #endif diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 7ca172cd449c..fbbf4214776b 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -111,7 +111,7 @@ VNET_DEFINE(int, nd6_debug) = 1; VNET_DEFINE(int, nd6_debug) = 0; #endif -static eventhandler_tag lle_event_eh; +static eventhandler_tag lle_event_eh, iflladdr_event_eh; /* for debugging? */ #if 0 @@ -137,7 +137,7 @@ static void nd6_llinfo_timer(void *); static void nd6_llinfo_settimer_locked(struct llentry *, long); static void clear_llinfo_pqueue(struct llentry *); static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *); -static int nd6_resolve_slow(struct ifnet *, struct mbuf *, +static int nd6_resolve_slow(struct ifnet *, int, struct mbuf *, const struct sockaddr_in6 *, u_char *, uint32_t *); static int nd6_need_cache(struct ifnet *); @@ -188,7 +188,7 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt) gw.sdl_index = ifp->if_index; gw.sdl_type = ifp->if_type; if (evt == LLENTRY_RESOLVED) - bcopy(&lle->ll_addr, gw.sdl_data, ifp->if_addrlen); + bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen); rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst; rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY; @@ -196,6 +196,16 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt) type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB); } +/* + * A handler for interface link layer address change event. + */ +static void +nd6_iflladdr(void *arg __unused, struct ifnet *ifp) +{ + + lltable_update_ifaddr(LLTABLE6(ifp)); +} + void nd6_init(void) { @@ -211,9 +221,12 @@ nd6_init(void) nd6_slowtimo, curvnet); nd6_dad_init(); - if (IS_DEFAULT_VNET(curvnet)) + if (IS_DEFAULT_VNET(curvnet)) { lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event, NULL, EVENTHANDLER_PRI_ANY); + iflladdr_event_eh = EVENTHANDLER_REGISTER(iflladdr_event, + nd6_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + } } #ifdef VIMAGE @@ -223,8 +236,10 @@ nd6_destroy() callout_drain(&V_nd6_slowtimo_ch); callout_drain(&V_nd6_timer_ch); - if (IS_DEFAULT_VNET(curvnet)) + if (IS_DEFAULT_VNET(curvnet)) { EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh); + EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_event_eh); + } } #endif @@ -1844,6 +1859,9 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, uint16_t router = 0; struct sockaddr_in6 sin6; struct mbuf *chain = NULL; + u_char linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; IF_AFDATA_UNLOCK_ASSERT(ifp); @@ -1878,8 +1896,15 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, * Since we already know all the data for the new entry, * fill it before insertion. */ - if (lladdr != NULL) - lltable_set_entry_addr(ifp, ln, lladdr); + if (lladdr != NULL) { + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET6, lladdr, + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return; + lltable_set_entry_addr(ifp, ln, linkhdr, linkhdrsize, + lladdr_off); + } + IF_AFDATA_WLOCK(ifp); LLE_WLOCK(ln); /* Prefer any existing lle over newly-created one */ @@ -1911,7 +1936,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0; if (olladdr && lladdr) { - llchange = bcmp(lladdr, &ln->ll_addr, + llchange = bcmp(lladdr, ln->ll_addr, ifp->if_addrlen); } else if (!olladdr && lladdr) llchange = 1; @@ -1937,7 +1962,13 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, * Record source link-layer address * XXX is it dependent to ifp->if_type? */ - if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) { + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET6, lladdr, + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return; + + if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize, + lladdr_off) == 0) { /* Entry was deleted */ return; } @@ -2093,8 +2124,8 @@ nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m, } /* - * Do L2 address resolution for @sa_dst address. Stores found - * address in @desten buffer. Copy of lle ln_flags can be also + * Lookup link headerfor @sa_dst address. Stores found + * data in @desten buffer. Copy of lle ln_flags can be also * saved in @pflags if @pflags is non-NULL. * * If destination LLE does not exists or lle state modification @@ -2144,7 +2175,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, ln = nd6_lookup(&dst6->sin6_addr, LLE_UNLOCKED, ifp); if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) { /* Entry found, let's copy lle info */ - bcopy(&ln->ll_addr, desten, ifp->if_addrlen); + bcopy(ln->r_linkdata, desten, ln->r_hdrlen); if (pflags != NULL) *pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR); /* Check if we have feedback request from nd6 timer */ @@ -2159,7 +2190,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, } IF_AFDATA_RUNLOCK(ifp); - return (nd6_resolve_slow(ifp, m, dst6, desten, pflags)); + return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags)); } @@ -2175,12 +2206,13 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, * Set noinline to be dtrace-friendly */ static __noinline int -nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m, +nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m, const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags) { struct llentry *lle = NULL, *lle_tmp; struct in6_addr *psrc, src; - int send_ns; + int send_ns, ll_len; + char *lladdr; /* * Address resolution or Neighbor Unreachability Detection @@ -2252,7 +2284,14 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m, * send the packet. */ if (lle->ln_state > ND6_LLINFO_INCOMPLETE) { - bcopy(&lle->ll_addr, desten, ifp->if_addrlen); + if (flags & LLE_ADDRONLY) { + lladdr = lle->ll_addr; + ll_len = ifp->if_addrlen; + } else { + lladdr = lle->r_linkdata; + ll_len = lle->r_hdrlen; + } + bcopy(lladdr, desten, ll_len); if (pflags != NULL) *pflags = lle->la_flags; LLE_WUNLOCK(lle); @@ -2312,6 +2351,27 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m, return (EWOULDBLOCK); } +/* + * Do L2 address resolution for @sa_dst address. Stores found + * address in @desten buffer. Copy of lle ln_flags can be also + * saved in @pflags if @pflags is non-NULL. + * + * Return values: + * - 0 on success (address copied to buffer). + * - EWOULDBLOCK (no local error, but address is still unresolved) + * - other errors (alloc failure, etc) + */ +int +nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, + char *desten, uint32_t *pflags) +{ + int error; + + flags |= LLE_ADDRONLY; + error = nd6_resolve_slow(ifp, flags, NULL, + (const struct sockaddr_in6 *)dst, desten, pflags); + return (error); +} int nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain, diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 8a0a56e1b7f0..6ff4cac2918d 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -410,6 +410,8 @@ void nd6_setmtu(struct ifnet *); void nd6_llinfo_setstate(struct llentry *lle, int newstate); void nd6_timer(void *); void nd6_purge(struct ifnet *); +int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, + char *desten, uint32_t *pflags); int nd6_resolve(struct ifnet *, int, struct mbuf *, const struct sockaddr *, u_char *, uint32_t *); int nd6_ioctl(u_long, caddr_t, struct ifnet *); diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index bf43fb65d530..a5ce2ec83c84 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -643,6 +643,9 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) union nd_opts ndopts; struct mbuf *chain = NULL; struct sockaddr_in6 sin6; + u_char linkhdr[LLE_MAX_LINKHDR]; + size_t linkhdrsize; + int lladdr_off; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; if (ip6->ip6_hlim != 255) { @@ -765,7 +768,13 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) /* * Record link-layer address, and update the state. */ - if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) { + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET6, lladdr, + linkhdr, &linkhdrsize, &lladdr_off) != 0) + return; + + if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize, + lladdr_off) == 0) { ln = NULL; goto freeit; } @@ -792,7 +801,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) llchange = 0; else { if (ln->la_flags & LLE_VALID) { - if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen)) + if (bcmp(lladdr, ln->ll_addr, ifp->if_addrlen)) llchange = 1; else llchange = 0; @@ -834,9 +843,12 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) * Update link-local address, if any. */ if (lladdr != NULL) { - int ret; - ret = lltable_try_set_entry_addr(ifp, ln,lladdr); - if (ret == 0) { + linkhdrsize = sizeof(linkhdr); + if (lltable_calc_llheader(ifp, AF_INET6, lladdr, + linkhdr, &linkhdrsize, &lladdr_off) != 0) + goto freeit; + if (lltable_try_set_entry_addr(ifp, ln, linkhdr, + linkhdrsize, lladdr_off) == 0) { ln = NULL; goto freeit; } diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1077b4050f39..e1f2dc082d33 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1257,15 +1257,15 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { u_char edst[INFINIBAND_ALEN]; +#if defined(INET) || defined(INET6) struct llentry *lle = NULL; +#endif struct rtentry *rt0 = NULL; struct ipoib_header *eh; int error = 0, is_gw = 0; short type; if (ro != NULL) { - if (!(m->m_flags & (M_BCAST | M_MCAST))) - lle = ro->ro_lle; rt0 = ro->ro_rt; if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0) is_gw = 1; @@ -1291,7 +1291,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, #ifdef INET case AF_INET: if (lle != NULL && (lle->la_flags & LLE_VALID)) - memcpy(edst, &lle->ll_addr.mac8, sizeof(edst)); + memcpy(edst, lle->ll_addr, sizeof(edst)); else if (m->m_flags & M_MCAST) ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst); else @@ -1329,7 +1329,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, #ifdef INET6 case AF_INET6: if (lle != NULL && (lle->la_flags & LLE_VALID)) - memcpy(edst, &lle->ll_addr.mac8, sizeof(edst)); + memcpy(edst, lle->ll_addr, sizeof(edst)); else if (m->m_flags & M_MCAST) ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst); else From 124836f75ca4c8f12ae92df67fac8015adc2ed0f Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 07:03:41 +0000 Subject: [PATCH 38/55] Clean up unused-but-set-variable spotted by gcc4.9. Reviewed by: ngie Approved by: rodrigc (mentor) Differential Revision: https://reviews.freebsd.org/D4719 --- sys/net/if_gif.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 33d583c9686a..1607af9c8e65 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -529,7 +529,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) struct gif_softc *sc; struct ether_header *eh; struct ifnet *oldifp; - uint32_t gif_options; int isr, n, af; if (ifp == NULL) { @@ -538,7 +537,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) return; } sc = ifp->if_softc; - gif_options = sc->gif_options; m->m_pkthdr.rcvif = ifp; m_clrprotoflags(m); switch (proto) { From f943a0f8bd775b2658a33cf53c209586a0fdc030 Mon Sep 17 00:00:00 2001 From: araujo Date: Thu, 31 Dec 2015 07:08:21 +0000 Subject: [PATCH 39/55] Clean up unused-but-set-variable spotted by gcc-4.9. Reviewed by: grehan Approved by: rodrigc (mentor) Differential Revision: https://reviews.freebsd.org/D4734 --- usr.sbin/bhyve/bhyverun.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 4fd9c358f82a..cb29a484800b 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -310,14 +310,13 @@ static int vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) { int error; - int bytes, port, in, out, string; + int bytes, port, in, out; int vcpu; vcpu = *pvcpu; port = vme->u.inout.port; bytes = vme->u.inout.bytes; - string = vme->u.inout.string; in = vme->u.inout.in; out = !in; @@ -620,8 +619,6 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t startrip) if (error != 0) break; - prevcpu = vcpu; - exitcode = vmexit[vcpu].exitcode; if (exitcode >= VM_EXITCODE_MAX || handler[exitcode] == NULL) { fprintf(stderr, "vm_loop: unexpected exitcode 0x%x\n", @@ -629,7 +626,7 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t startrip) exit(1); } - rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu); + rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu); switch (rc) { case VMEXIT_CONTINUE: From ccc7e8d96a643a47f15d15a92ef25bed8220a43d Mon Sep 17 00:00:00 2001 From: bz Date: Thu, 31 Dec 2015 10:55:50 +0000 Subject: [PATCH 40/55] Remove unused variable after r292981 to unbreak the build. --- usr.sbin/bhyve/bhyverun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index cb29a484800b..bfa135b16cce 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -598,7 +598,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = { static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t startrip) { - int error, rc, prevcpu; + int error, rc; enum vm_exitcode exitcode; cpuset_t active_cpus; From 0219f2b937baf6515d4cd2bf7311adfbdfef2e20 Mon Sep 17 00:00:00 2001 From: bz Date: Thu, 31 Dec 2015 11:21:45 +0000 Subject: [PATCH 41/55] Bump copyright year. Happy New Year 2016! --- COPYRIGHT | 2 +- sys/sys/copyright.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index 1d7198f722ce..94046dd8d368 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -4,7 +4,7 @@ The compilation of software known as FreeBSD is distributed under the following terms: -Copyright (c) 1992-2015 The FreeBSD Project. All rights reserved. +Copyright (c) 1992-2016 The FreeBSD Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/sys/sys/copyright.h b/sys/sys/copyright.h index 6e47358ac14b..e3c1e40d3914 100644 --- a/sys/sys/copyright.h +++ b/sys/sys/copyright.h @@ -1,5 +1,5 @@ /*- - * Copyright (C) 1992-2015 The FreeBSD Project. All rights reserved. + * Copyright (C) 1992-2016 The FreeBSD Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,7 +34,7 @@ /* FreeBSD */ #define COPYRIGHT_FreeBSD \ - "Copyright (c) 1992-2015 The FreeBSD Project.\n" + "Copyright (c) 1992-2016 The FreeBSD Project.\n" /* Foundation */ #define TRADEMARK_Foundation \ From c5e1fb2b0fbc37a9e612bea86e0f53e6396e02ac Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 31 Dec 2015 11:27:36 +0000 Subject: [PATCH 42/55] Make the kobject refcounting compliant with Linux. Refcounting on the parent kobject cannot be factored out and must be done by the kobject consumers. MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/compat/linuxkpi/common/include/linux/cdev.h | 7 +++++++ sys/compat/linuxkpi/common/src/linux_compat.c | 5 +---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/cdev.h b/sys/compat/linuxkpi/common/include/linux/cdev.h index 5d8962f46355..0f81099d0efb 100644 --- a/sys/compat/linuxkpi/common/include/linux/cdev.h +++ b/sys/compat/linuxkpi/common/include/linux/cdev.h @@ -54,21 +54,27 @@ static inline void cdev_release(struct kobject *kobj) { struct linux_cdev *cdev; + struct kobject *parent; cdev = container_of(kobj, struct linux_cdev, kobj); + parent = kobj->parent; if (cdev->cdev) destroy_dev(cdev->cdev); kfree(cdev); + kobject_put(parent); } static inline void cdev_static_release(struct kobject *kobj) { struct linux_cdev *cdev; + struct kobject *parent; cdev = container_of(kobj, struct linux_cdev, kobj); + parent = kobj->parent; if (cdev->cdev) destroy_dev(cdev->cdev); + kobject_put(parent); } static struct kobj_type cdev_ktype = { @@ -114,6 +120,7 @@ cdev_add(struct linux_cdev *cdev, dev_t dev, unsigned count) cdev->dev = dev; cdev->cdev->si_drv1 = cdev; + kobject_get(cdev->kobj.parent); return (0); } diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index 91ec693065c3..b57326ae2e74 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -157,7 +157,7 @@ kobject_add_complete(struct kobject *kobj, struct kobject *parent) struct kobj_type *t; int error; - kobj->parent = kobject_get(parent); + kobj->parent = parent; error = sysfs_create_dir(kobj); if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) { struct attribute **attr; @@ -198,9 +198,6 @@ kobject_release(struct kref *kref) kobj = container_of(kref, struct kobject, kref); sysfs_remove_dir(kobj); - if (kobj->parent) - kobject_put(kobj->parent); - kobj->parent = NULL; name = kobj->name; if (kobj->ktype && kobj->ktype->release) kobj->ktype->release(kobj); From a7a7584c856f1480bfec0e1a68ca2b00eb704211 Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 31 Dec 2015 12:30:19 +0000 Subject: [PATCH 43/55] Minor LinuxKPI code cleanup: - Declare some static functions in linux_compat.c instead if inside various header files. - Prefix FreeBSD local functions in the LinuxKPI with "linux_" to avoid symbol name conflicts in the future and to make debugging easier. - Make the "struct kobj_ktype" declaractions constant to shave off a few bytes from the data segment. MFC after: 1 week Sponsored by: Mellanox Technologies --- .../linuxkpi/common/include/linux/cdev.h | 41 +--- .../linuxkpi/common/include/linux/device.h | 115 +---------- .../linuxkpi/common/include/linux/kobject.h | 16 +- .../common/include/linux/miscdevice.h | 8 +- sys/compat/linuxkpi/common/src/linux_compat.c | 188 +++++++++++++++--- sys/compat/linuxkpi/common/src/linux_pci.c | 6 +- 6 files changed, 192 insertions(+), 182 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/cdev.h b/sys/compat/linuxkpi/common/include/linux/cdev.h index 0f81099d0efb..84b7b70947d1 100644 --- a/sys/compat/linuxkpi/common/include/linux/cdev.h +++ b/sys/compat/linuxkpi/common/include/linux/cdev.h @@ -41,6 +41,8 @@ struct inode; struct module; extern struct cdevsw linuxcdevsw; +extern const struct kobj_type linux_cdev_ktype; +extern const struct kobj_type linux_cdev_static_ktype; struct linux_cdev { struct kobject kobj; @@ -50,46 +52,11 @@ struct linux_cdev { const struct file_operations *ops; }; -static inline void -cdev_release(struct kobject *kobj) -{ - struct linux_cdev *cdev; - struct kobject *parent; - - cdev = container_of(kobj, struct linux_cdev, kobj); - parent = kobj->parent; - if (cdev->cdev) - destroy_dev(cdev->cdev); - kfree(cdev); - kobject_put(parent); -} - -static inline void -cdev_static_release(struct kobject *kobj) -{ - struct linux_cdev *cdev; - struct kobject *parent; - - cdev = container_of(kobj, struct linux_cdev, kobj); - parent = kobj->parent; - if (cdev->cdev) - destroy_dev(cdev->cdev); - kobject_put(parent); -} - -static struct kobj_type cdev_ktype = { - .release = cdev_release, -}; - -static struct kobj_type cdev_static_ktype = { - .release = cdev_static_release, -}; - static inline void cdev_init(struct linux_cdev *cdev, const struct file_operations *ops) { - kobject_init(&cdev->kobj, &cdev_static_ktype); + kobject_init(&cdev->kobj, &linux_cdev_static_ktype); cdev->ops = ops; } @@ -100,7 +67,7 @@ cdev_alloc(void) cdev = kzalloc(sizeof(struct linux_cdev), M_WAITOK); if (cdev) - kobject_init(&cdev->kobj, &cdev_ktype); + kobject_init(&cdev->kobj, &linux_cdev_ktype); return (cdev); } diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h index 02b2064587d5..f4b8ec664514 100644 --- a/sys/compat/linuxkpi/common/include/linux/device.h +++ b/sys/compat/linuxkpi/common/include/linux/device.h @@ -73,8 +73,10 @@ struct device { unsigned int msix_max; }; -extern struct device linux_rootdev; -extern struct kobject class_root; +extern struct device linux_root_device; +extern struct kobject linux_class_root; +extern const struct kobj_type linux_dev_ktype; +extern const struct kobj_type linux_class_ktype; struct class_attribute { struct attribute attr; @@ -170,62 +172,14 @@ put_device(struct device *dev) kobject_put(&dev->kobj); } -static inline ssize_t -class_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct class_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct class_attribute, attr); - error = -EIO; - if (dattr->show) - error = dattr->show(container_of(kobj, struct class, kobj), - dattr, buf); - return (error); -} - -static inline ssize_t -class_store(struct kobject *kobj, struct attribute *attr, const char *buf, - size_t count) -{ - struct class_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct class_attribute, attr); - error = -EIO; - if (dattr->store) - error = dattr->store(container_of(kobj, struct class, kobj), - dattr, buf, count); - return (error); -} - -static inline void -class_release(struct kobject *kobj) -{ - struct class *class; - - class = container_of(kobj, struct class, kobj); - if (class->class_release) - class->class_release(class); -} - -static struct sysfs_ops class_sysfs = { - .show = class_show, - .store = class_store, -}; -static struct kobj_type class_ktype = { - .release = class_release, - .sysfs_ops = &class_sysfs -}; - static inline int class_register(struct class *class) { class->bsdclass = devclass_create(class->name); - kobject_init(&class->kobj, &class_ktype); + kobject_init(&class->kobj, &linux_class_ktype); kobject_set_name(&class->kobj, class->name); - kobject_add(&class->kobj, &class_root, class->name); + kobject_add(&class->kobj, &linux_class_root, class->name); return (0); } @@ -237,54 +191,6 @@ class_unregister(struct class *class) kobject_put(&class->kobj); } -static inline void -device_release(struct kobject *kobj) -{ - struct device *dev; - - dev = container_of(kobj, struct device, kobj); - /* This is the precedence defined by linux. */ - if (dev->release) - dev->release(dev); - else if (dev->class && dev->class->dev_release) - dev->class->dev_release(dev); -} - -static inline ssize_t -dev_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct device_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct device_attribute, attr); - error = -EIO; - if (dattr->show) - error = dattr->show(container_of(kobj, struct device, kobj), - dattr, buf); - return (error); -} - -static inline ssize_t -dev_store(struct kobject *kobj, struct attribute *attr, const char *buf, - size_t count) -{ - struct device_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct device_attribute, attr); - error = -EIO; - if (dattr->store) - error = dattr->store(container_of(kobj, struct device, kobj), - dattr, buf, count); - return (error); -} - -static struct sysfs_ops dev_sysfs = { .show = dev_show, .store = dev_store, }; -static struct kobj_type dev_ktype = { - .release = device_release, - .sysfs_ops = &dev_sysfs -}; - /* * Devices are registered and created for exporting to sysfs. create * implies register and register assumes the device fields have been @@ -311,7 +217,7 @@ device_register(struct device *dev) device_set_softc(bsddev, dev); } dev->bsddev = bsddev; - kobject_init(&dev->kobj, &dev_ktype); + kobject_init(&dev->kobj, &linux_dev_ktype); kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev)); return (0); @@ -346,7 +252,7 @@ device_destroy(struct class *class, dev_t devt) } static inline void -class_kfree(struct class *class) +linux_class_kfree(struct class *class) { kfree(class); @@ -361,7 +267,7 @@ class_create(struct module *owner, const char *name) class = kzalloc(sizeof(*class), M_WAITOK); class->owner = owner; class->name= name; - class->class_release = class_kfree; + class->class_release = linux_class_kfree; error = class_register(class); if (error) { kfree(class); @@ -414,7 +320,8 @@ class_remove_file(struct class *class, const struct class_attribute *attr) sysfs_remove_file(&class->kobj, &attr->attr); } -static inline int dev_to_node(struct device *dev) +static inline int +dev_to_node(struct device *dev) { return -1; } diff --git a/sys/compat/linuxkpi/common/include/linux/kobject.h b/sys/compat/linuxkpi/common/include/linux/kobject.h index 475095e0963e..a000c4eebc10 100644 --- a/sys/compat/linuxkpi/common/include/linux/kobject.h +++ b/sys/compat/linuxkpi/common/include/linux/kobject.h @@ -46,13 +46,13 @@ struct kobj_type { struct attribute **default_attrs; }; -extern struct kobj_type kfree_type; +extern const struct kobj_type linux_kfree_type; struct kobject { struct kobject *parent; char *name; struct kref kref; - struct kobj_type *ktype; + const struct kobj_type *ktype; struct list_head entry; struct sysctl_oid *oidp; }; @@ -74,7 +74,7 @@ struct kobj_attribute { }; static inline void -kobject_init(struct kobject *kobj, struct kobj_type *ktype) +kobject_init(struct kobject *kobj, const struct kobj_type *ktype) { kref_init(&kobj->kref); @@ -83,15 +83,14 @@ kobject_init(struct kobject *kobj, struct kobj_type *ktype) kobj->oidp = NULL; } -static inline void kobject_put(struct kobject *kobj); -void kobject_release(struct kref *kref); +void linux_kobject_release(struct kref *kref); static inline void kobject_put(struct kobject *kobj) { if (kobj) - kref_put(&kobj->kref, kobject_release); + kref_put(&kobj->kref, linux_kobject_release); } static inline struct kobject * @@ -115,7 +114,7 @@ kobject_create(void) kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); if (kobj == NULL) return (NULL); - kobject_init(kobj, &kfree_type); + kobject_init(kobj, &linux_kfree_type); return (kobj); } @@ -135,7 +134,6 @@ kobject_create_and_add(const char *name, struct kobject *parent) return (NULL); } - static inline char * kobject_name(const struct kobject *kobj) { @@ -144,7 +142,7 @@ kobject_name(const struct kobject *kobj) } int kobject_set_name(struct kobject *kobj, const char *fmt, ...); -int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, +int kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype, struct kobject *parent, const char *fmt, ...); #endif /* _LINUX_KOBJECT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/miscdevice.h b/sys/compat/linuxkpi/common/include/linux/miscdevice.h index 96d8fe7f2dad..a873987888fd 100644 --- a/sys/compat/linuxkpi/common/include/linux/miscdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/miscdevice.h @@ -46,13 +46,13 @@ struct miscdevice { umode_t mode; }; -extern struct class miscclass; +extern struct class linux_class_misc; static inline int misc_register(struct miscdevice *misc) { - misc->this_device = device_create(&miscclass, &linux_rootdev, 0, misc, - misc->name); + misc->this_device = device_create(&linux_class_misc, + &linux_root_device, 0, misc, misc->name); misc->cdev = cdev_alloc(); if (misc->cdev == NULL) return -ENOMEM; @@ -67,7 +67,7 @@ misc_register(struct miscdevice *misc) static inline int misc_deregister(struct miscdevice *misc) { - device_destroy(&miscclass, misc->this_device->devt); + device_destroy(&linux_class_misc, misc->this_device->devt); cdev_del(misc->cdev); return (0); diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index b57326ae2e74..4d48519ff43d 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -77,9 +77,9 @@ MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat"); #undef cdev #define RB_ROOT(head) (head)->rbh_root -struct kobject class_root; -struct device linux_rootdev; -struct class miscclass; +struct kobject linux_class_root; +struct device linux_root_device; +struct class linux_class_misc; struct list_head pci_drivers; struct list_head pci_devices; struct net init_net; @@ -151,10 +151,10 @@ kobject_set_name(struct kobject *kobj, const char *fmt, ...) return (error); } -static inline int +static int kobject_add_complete(struct kobject *kobj, struct kobject *parent) { - struct kobj_type *t; + const struct kobj_type *t; int error; kobj->parent = parent; @@ -191,7 +191,7 @@ kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) } void -kobject_release(struct kref *kref) +linux_kobject_release(struct kref *kref) { struct kobject *kobj; char *name; @@ -205,28 +205,131 @@ kobject_release(struct kref *kref) } static void -kobject_kfree(struct kobject *kobj) +linux_kobject_kfree(struct kobject *kobj) { kfree(kobj); } static void -kobject_kfree_name(struct kobject *kobj) +linux_kobject_kfree_name(struct kobject *kobj) { if (kobj) { kfree(kobj->name); } } -struct kobj_type kfree_type = { .release = kobject_kfree }; +const struct kobj_type linux_kfree_type = { + .release = linux_kobject_kfree +}; static void -dev_release(struct device *dev) +linux_device_release(struct device *dev) { - pr_debug("dev_release: %s\n", dev_name(dev)); + pr_debug("linux_device_release: %s\n", dev_name(dev)); kfree(dev); } +static ssize_t +linux_class_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct class_attribute *dattr; + ssize_t error; + + dattr = container_of(attr, struct class_attribute, attr); + error = -EIO; + if (dattr->show) + error = dattr->show(container_of(kobj, struct class, kobj), + dattr, buf); + return (error); +} + +static ssize_t +linux_class_store(struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + struct class_attribute *dattr; + ssize_t error; + + dattr = container_of(attr, struct class_attribute, attr); + error = -EIO; + if (dattr->store) + error = dattr->store(container_of(kobj, struct class, kobj), + dattr, buf, count); + return (error); +} + +static void +linux_class_release(struct kobject *kobj) +{ + struct class *class; + + class = container_of(kobj, struct class, kobj); + if (class->class_release) + class->class_release(class); +} + +static const struct sysfs_ops linux_class_sysfs = { + .show = linux_class_show, + .store = linux_class_store, +}; + +const struct kobj_type linux_class_ktype = { + .release = linux_class_release, + .sysfs_ops = &linux_class_sysfs +}; + +static void +linux_dev_release(struct kobject *kobj) +{ + struct device *dev; + + dev = container_of(kobj, struct device, kobj); + /* This is the precedence defined by linux. */ + if (dev->release) + dev->release(dev); + else if (dev->class && dev->class->dev_release) + dev->class->dev_release(dev); +} + +static ssize_t +linux_dev_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct device_attribute *dattr; + ssize_t error; + + dattr = container_of(attr, struct device_attribute, attr); + error = -EIO; + if (dattr->show) + error = dattr->show(container_of(kobj, struct device, kobj), + dattr, buf); + return (error); +} + +static ssize_t +linux_dev_store(struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + struct device_attribute *dattr; + ssize_t error; + + dattr = container_of(attr, struct device_attribute, attr); + error = -EIO; + if (dattr->store) + error = dattr->store(container_of(kobj, struct device, kobj), + dattr, buf, count); + return (error); +} + +static const struct sysfs_ops linux_dev_sysfs = { + .show = linux_dev_show, + .store = linux_dev_store, +}; + +const struct kobj_type linux_dev_ktype = { + .release = linux_dev_release, + .sysfs_ops = &linux_dev_sysfs +}; + struct device * device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) @@ -239,7 +342,7 @@ device_create(struct class *class, struct device *parent, dev_t devt, dev->class = class; dev->devt = devt; dev->driver_data = drvdata; - dev->release = dev_release; + dev->release = linux_device_release; va_start(args, fmt); kobject_set_name_vargs(&dev->kobj, fmt, args); va_end(args); @@ -249,7 +352,7 @@ device_create(struct class *class, struct device *parent, dev_t devt, } int -kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, +kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype, struct kobject *parent, const char *fmt, ...) { va_list args; @@ -998,6 +1101,41 @@ destroy_workqueue(struct workqueue_struct *wq) kfree(wq); } +static void +linux_cdev_release(struct kobject *kobj) +{ + struct linux_cdev *cdev; + struct kobject *parent; + + cdev = container_of(kobj, struct linux_cdev, kobj); + parent = kobj->parent; + if (cdev->cdev) + destroy_dev(cdev->cdev); + kfree(cdev); + kobject_put(parent); +} + +static void +linux_cdev_static_release(struct kobject *kobj) +{ + struct linux_cdev *cdev; + struct kobject *parent; + + cdev = container_of(kobj, struct linux_cdev, kobj); + parent = kobj->parent; + if (cdev->cdev) + destroy_dev(cdev->cdev); + kobject_put(parent); +} + +const struct kobj_type linux_cdev_ktype = { + .release = linux_cdev_release, +}; + +const struct kobj_type linux_cdev_static_ktype = { + .release = linux_cdev_static_release, +}; + static void linux_compat_init(void *arg) { @@ -1006,18 +1144,18 @@ linux_compat_init(void *arg) rootoid = SYSCTL_ADD_ROOT_NODE(NULL, OID_AUTO, "sys", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "sys"); - kobject_init(&class_root, &class_ktype); - kobject_set_name(&class_root, "class"); - class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid), + kobject_init(&linux_class_root, &linux_class_ktype); + kobject_set_name(&linux_class_root, "class"); + linux_class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid), OID_AUTO, "class", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "class"); - kobject_init(&linux_rootdev.kobj, &dev_ktype); - kobject_set_name(&linux_rootdev.kobj, "device"); - linux_rootdev.kobj.oidp = SYSCTL_ADD_NODE(NULL, + kobject_init(&linux_root_device.kobj, &linux_dev_ktype); + kobject_set_name(&linux_root_device.kobj, "device"); + linux_root_device.kobj.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid), OID_AUTO, "device", CTLFLAG_RD, NULL, "device"); - linux_rootdev.bsddev = root_bus; - miscclass.name = "misc"; - class_register(&miscclass); + linux_root_device.bsddev = root_bus; + linux_class_misc.name = "misc"; + class_register(&linux_class_misc); INIT_LIST_HEAD(&pci_drivers); INIT_LIST_HEAD(&pci_devices); spin_lock_init(&pci_lock); @@ -1030,9 +1168,9 @@ SYSINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_init, NULL); static void linux_compat_uninit(void *arg) { - kobject_kfree_name(&class_root); - kobject_kfree_name(&linux_rootdev.kobj); - kobject_kfree_name(&miscclass.kobj); + linux_kobject_kfree_name(&linux_class_root); + linux_kobject_kfree_name(&linux_root_device.kobj); + linux_kobject_kfree_name(&linux_class_misc.kobj); } SYSUNINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_uninit, NULL); diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 2d3d03b7de40..7c49a54a6dc0 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -119,16 +119,16 @@ linux_pci_attach(device_t dev) pdrv = linux_pci_find(dev, &id); pdev = device_get_softc(dev); - pdev->dev.parent = &linux_rootdev; + pdev->dev.parent = &linux_root_device; pdev->dev.bsddev = dev; INIT_LIST_HEAD(&pdev->dev.irqents); pdev->device = id->device; pdev->vendor = id->vendor; pdev->dev.dma_mask = &pdev->dma_mask; pdev->pdrv = pdrv; - kobject_init(&pdev->dev.kobj, &dev_ktype); + kobject_init(&pdev->dev.kobj, &linux_dev_ktype); kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); - kobject_add(&pdev->dev.kobj, &linux_rootdev.kobj, + kobject_add(&pdev->dev.kobj, &linux_root_device.kobj, kobject_name(&pdev->dev.kobj)); rle = _pci_get_rle(pdev, SYS_RES_IRQ, 0); if (rle) From c4acbb92b9330eaa35165a35044d46705be5cfcd Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 31 Dec 2015 14:47:45 +0000 Subject: [PATCH 44/55] Handle when filedescriptors are closed before initialized. An early fdclose() call can cause fget_unlocked() to fail. Found by: mjg @ MFC after: 1 week Reviewed by: Mark Block Sponsored by: Mellanox Technologies Differential Revision: https://reviews.freebsd.org/D4351 --- sys/compat/linuxkpi/common/include/linux/file.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h index e52afa55f202..559ac0437681 100644 --- a/sys/compat/linuxkpi/common/include/linux/file.h +++ b/sys/compat/linuxkpi/common/include/linux/file.h @@ -101,10 +101,11 @@ fd_install(unsigned int fd, struct linux_file *filp) if (fget_unlocked(curthread->td_proc->p_fd, fd, cap_rights_init(&rights), &file, NULL) != 0) { - file = NULL; + filp->_file = NULL; + } else { + filp->_file = file; + finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); } - filp->_file = file; - finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); /* drop the extra reference */ fput(filp); From 098890d68891fffeb50c725b678b77f0078cb533 Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 31 Dec 2015 17:51:15 +0000 Subject: [PATCH 45/55] sh: Perform IFS splitting during the first expansion phases. This simplifies the code and should be faster in some cases. Side effect: the order of operations is different so that the value of IFS used when IFS is modified during expansion (${IFS:=...}, ${IFS=...} or $((...IFS=...))) may be different. Note that this order is highly unportable between shells. --- bin/sh/expand.c | 615 ++++++++++++++++++++---------------------------- 1 file changed, 253 insertions(+), 362 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index c876abb8028b..653ffc4c8c86 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -3,6 +3,8 @@ * The Regents of the University of California. All rights reserved. * Copyright (c) 1997-2005 * Herbert Xu . All rights reserved. + * Copyright (c) 2010-2015 + * Jilles Tjoelker . All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. @@ -79,42 +81,32 @@ __FBSDID("$FreeBSD$"); #include "show.h" #include "builtins.h" -/* - * Structure specifying which parts of the string should be searched - * for IFS characters. - */ +enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK }; -struct ifsregion { - struct ifsregion *next; /* next region in list */ - int begoff; /* offset of start of region */ - int endoff; /* offset of end of region */ - int inquotes; /* search for nul bytes only */ +struct worddest { + struct arglist list; + enum wordstate state; }; - static char *expdest; /* output of current string */ static struct nodelist *argbackq; /* list of back quote expressions */ -static struct ifsregion ifsfirst; /* first struct in list of ifs regions */ -static struct ifsregion *ifslastp; /* last struct in list */ -static char *argstr(char *, int); +static char *argstr(char *, int, struct worddest *); static char *exptilde(char *, int); -static char *expari(char *); -static void expbackq(union node *, int, int); -static int subevalvar_trim(char *, int, int, int, int); +static char *expari(char *, int, struct worddest *); +static void expbackq(union node *, int, int, struct worddest *); +static void subevalvar_trim(char *, int, int, int); static int subevalvar_misc(char *, const char *, int, int, int); -static char *evalvar(char *, int); +static char *evalvar(char *, int, struct worddest *); static int varisset(const char *, int); -static void strtodest(const char *, int, int, int); -static void varvalue(const char *, int, int, int); -static void recordregion(int, int, int); -static void removerecordregions(int); -static void ifsbreakup(char *, struct arglist *); +static void strtodest(const char *, int, int, int, struct worddest *); +static void reprocess(int, int, int, int, struct worddest *); +static void varvalue(const char *, int, int, int, struct worddest *); static void expandmeta(struct arglist *, struct arglist *); static void expmeta(char *, char *, struct arglist *); static int expsortcmp(const void *, const void *); -static int patmatch(const char *, const char *, int); -static char *cvtnum(int, char *); +static int patmatch(const char *, const char *); +static void cvtnum(int, char *); static int collate_range_cmp(wchar_t, wchar_t); void @@ -169,6 +161,50 @@ stputs_quotes(const char *data, const char *syntax, char *p) } #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p) +static char * +nextword(char c, char *p, struct worddest *dst) +{ + int is_ws; + + is_ws = c == '\t' || c == '\n' || c == ' '; + if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK : + dst->state != WORD_WS_DELIMITED) || c == '\0') { + STPUTC('\0', p); + appendarglist(&dst->list, grabstackstr(p)); + dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE; + } else if (!is_ws && dst->state == WORD_WS_DELIMITED) + dst->state = WORD_IDLE; + /* Reserve space while the stack string is empty. */ + appendarglist(&dst->list, NULL); + dst->list.count--; + STARTSTACKSTR(p); + return p; +} +#define NEXTWORD(c, p, dstlist) p = nextword(c, p, dstlist) + +static char * +stputs_split(const char *data, const char *syntax, char *p, + struct worddest *dst) +{ + const char *ifs; + char c; + + ifs = ifsset() ? ifsval() : " \t\n"; + while (*data) { + CHECKSTRSPACE(2, p); + c = *data++; + if (strchr(ifs, c) != NULL) { + NEXTWORD(c, p, dst); + continue; + } + if (syntax[(int)c] == CCTL) + USTPUTC(CTLESC, p); + USTPUTC(c, p); + } + return (p); +} +#define STPUTS_SPLIT(data, syntax, p, dst) p = stputs_split((data), syntax, p, dst) + /* * Perform expansions on an argument, placing the resulting list of arguments * in arglist. Parameter expansion, command substitution and arithmetic @@ -184,34 +220,27 @@ stputs_quotes(const char *data, const char *syntax, char *p) void expandarg(union node *arg, struct arglist *arglist, int flag) { - struct arglist exparg; - char *p; + struct worddest exparg; argbackq = arg->narg.backquote; + emptyarglist(&exparg.list); + exparg.state = WORD_IDLE; STARTSTACKSTR(expdest); - ifsfirst.next = NULL; - ifslastp = NULL; - argstr(arg->narg.text, flag); + argstr(arg->narg.text, flag, &exparg); if (arglist == NULL) { STACKSTRNUL(expdest); return; /* here document expanded */ } - STPUTC('\0', expdest); - p = grabstackstr(expdest); - emptyarglist(&exparg); - if (flag & EXP_FULL) { - ifsbreakup(p, &exparg); - expandmeta(&exparg, arglist); - } else - appendarglist(arglist, p); - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; + if ((flag & EXP_FULL) == 0 || expdest != stackblock() || + exparg.state == WORD_QUOTEMARK) { + STPUTC('\0', expdest); + if (flag & EXP_FULL) + appendarglist(&exparg.list, grabstackstr(expdest)); } + if (flag & EXP_FULL) + expandmeta(&exparg.list, arglist); + else + appendarglist(arglist, grabstackstr(expdest)); } @@ -223,10 +252,11 @@ expandarg(union node *arg, struct arglist *arglist, int flag) * This is used to expand word in ${var+word} etc. * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC * characters to allow for further processing. - * If EXP_FULL is set, also preserve CTLQUOTEMARK characters. + * + * If EXP_FULL is set, dst receives any complete words produced. */ static char * -argstr(char *p, int flag) +argstr(char *p, int flag, struct worddest *dst) { char c; int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ @@ -253,32 +283,33 @@ argstr(char *p, int flag) if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 && p[2] == '@' && p[3] == '=') break; - if ((flag & EXP_FULL) != 0) - USTPUTC(c, expdest); + if ((flag & EXP_FULL) != 0 && expdest == stackblock()) + dst->state = WORD_QUOTEMARK; break; case CTLQUOTEEND: lit_quoted = 0; break; case CTLESC: - if (quotes) - USTPUTC(c, expdest); c = *p++; + if (split_lit && !lit_quoted && + strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { + NEXTWORD(c, expdest, dst); + break; + } + if (quotes) + USTPUTC(CTLESC, expdest); USTPUTC(c, expdest); - if (split_lit && !lit_quoted) - recordregion(expdest - stackblock() - - (quotes ? 2 : 1), - expdest - stackblock(), 0); break; case CTLVAR: - p = evalvar(p, flag); + p = evalvar(p, flag, dst); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: - expbackq(argbackq->n, c & CTLQUOTE, flag); + expbackq(argbackq->n, c & CTLQUOTE, flag, dst); argbackq = argbackq->next; break; case CTLARI: - p = expari(p); + p = expari(p, flag, dst); break; case ':': case '=': @@ -286,10 +317,12 @@ argstr(char *p, int flag) * sort of a hack - expand tildes in variable * assignments (after the first '=' and after ':'s). */ + if (split_lit && !lit_quoted && + strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { + NEXTWORD(c, expdest, dst); + break; + } USTPUTC(c, expdest); - if (split_lit && !lit_quoted) - recordregion(expdest - stackblock() - 1, - expdest - stackblock(), 0); if (flag & EXP_VARTILDE && *p == '~' && (c != '=' || firsteq)) { if (c == '=') @@ -298,10 +331,12 @@ argstr(char *p, int flag) } break; default: + if (split_lit && !lit_quoted && + strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { + NEXTWORD(c, expdest, dst); + break; + } USTPUTC(c, expdest); - if (split_lit && !lit_quoted) - recordregion(expdest - stackblock() - 1, - expdest - stackblock(), 0); } } } @@ -345,7 +380,7 @@ exptilde(char *p, int flag) *p = c; if (home == NULL || *home == '\0') return (startp); - strtodest(home, flag, VSNORMAL, 1); + strtodest(home, flag, VSNORMAL, 1, NULL); return (p); } p++; @@ -353,51 +388,11 @@ exptilde(char *p, int flag) } -static void -removerecordregions(int endoff) -{ - if (ifslastp == NULL) - return; - - if (ifsfirst.endoff > endoff) { - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; - } - if (ifsfirst.begoff > endoff) - ifslastp = NULL; - else { - ifslastp = &ifsfirst; - ifsfirst.endoff = endoff; - } - return; - } - - ifslastp = &ifsfirst; - while (ifslastp->next && ifslastp->next->begoff < endoff) - ifslastp=ifslastp->next; - while (ifslastp->next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifslastp->next->next; - ckfree(ifslastp->next); - ifslastp->next = ifsp; - INTON; - } - if (ifslastp->endoff > endoff) - ifslastp->endoff = endoff; -} - /* * Expand arithmetic expression. - * Note that flag is not required as digits never require CTLESC characters. */ static char * -expari(char *p) +expari(char *p, int flag, struct worddest *dst) { char *q, *start; arith_t result; @@ -407,8 +402,7 @@ expari(char *p) quoted = *p++ == '"'; begoff = expdest - stackblock(); - p = argstr(p, 0); - removerecordregions(begoff); + p = argstr(p, 0, NULL); STPUTC('\0', expdest); start = stackblock() + begoff; @@ -425,7 +419,7 @@ expari(char *p) adj = strlen(expdest); STADJUST(adj, expdest); if (!quoted) - recordregion(begoff, expdest - stackblock(), 0); + reprocess(expdest - adj - stackblock(), flag, VSNORMAL, 0, dst); return p; } @@ -434,35 +428,34 @@ expari(char *p) * Perform command substitution. */ static void -expbackq(union node *cmd, int quoted, int flag) +expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) { struct backcmd in; int i; char buf[128]; char *p; char *dest = expdest; - struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; - int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int quotes = flag & (EXP_FULL | EXP_CASE); size_t nnl; + const char *ifs; INTOFF; - saveifs = ifsfirst; - savelastp = ifslastp; saveargbackq = argbackq; p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); - ifsfirst = saveifs; - ifslastp = savelastp; argbackq = saveargbackq; p = in.buf; lastc = '\0'; nnl = 0; + if (!quoted && flag & EXP_FULL) + ifs = ifsset() ? ifsval() : " \t\n"; + else + ifs = ""; /* Don't copy trailing newlines */ for (;;) { if (--in.nleft < 0) { @@ -476,15 +469,27 @@ expbackq(union node *cmd, int quoted, int flag) in.nleft = i - 1; } lastc = *p++; - if (lastc != '\0') { - if (lastc == '\n') { - nnl++; - } else { - CHECKSTRSPACE(nnl + 2, dest); - while (nnl > 0) { - nnl--; - USTPUTC('\n', dest); + if (lastc == '\0') + continue; + if (lastc == '\n') { + nnl++; + } else { + if (nnl > 0) { + if (strchr(ifs, '\n') != NULL) { + NEXTWORD('\n', dest, dst); + nnl = 0; + } else { + CHECKSTRSPACE(nnl + 2, dest); + while (nnl > 0) { + nnl--; + USTPUTC('\n', dest); + } } + } + if (strchr(ifs, lastc) != NULL) + NEXTWORD(lastc, dest, dst); + else { + CHECKSTRSPACE(2, dest); if (quotes && syntax[(int)lastc] == CCTL) USTPUTC(CTLESC, dest); USTPUTC(lastc, dest); @@ -498,8 +503,6 @@ expbackq(union node *cmd, int quoted, int flag) ckfree(in.buf); if (in.jp) exitstatus = waitforjob(in.jp, (int *)NULL); - if (quoted == 0) - recordregion(startloc, dest - stackblock(), 0); TRACE(("expbackq: size=%td: \"%.*s\"\n", ((dest - stackblock()) - startloc), (int)((dest - stackblock()) - startloc), @@ -521,18 +524,17 @@ recordleft(const char *str, const char *loc, char *startp) *startp++ = *loc++; } -static int -subevalvar_trim(char *p, int strloc, int subtype, int startloc, int quotes) +static void +subevalvar_trim(char *p, int strloc, int subtype, int startloc) { char *startp; char *loc = NULL; - char *q; char *str; int c = 0; struct nodelist *saveargbackq = argbackq; int amount; - argstr(p, EXP_CASE | EXP_TILDE); + argstr(p, EXP_CASE | EXP_TILDE, NULL); STACKSTRNUL(expdest); argbackq = saveargbackq; startp = stackblock() + startloc; @@ -543,72 +545,56 @@ subevalvar_trim(char *p, int strloc, int subtype, int startloc, int quotes) for (loc = startp; loc < str; loc++) { c = *loc; *loc = '\0'; - if (patmatch(str, startp, quotes)) { + if (patmatch(str, startp)) { *loc = c; recordleft(str, loc, startp); - return 1; + return; } *loc = c; - if (quotes && *loc == CTLESC) - loc++; } - return 0; + break; case VSTRIMLEFTMAX: for (loc = str - 1; loc >= startp;) { c = *loc; *loc = '\0'; - if (patmatch(str, startp, quotes)) { + if (patmatch(str, startp)) { *loc = c; recordleft(str, loc, startp); - return 1; + return; } *loc = c; loc--; - if (quotes && loc > startp && *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } } - return 0; + break; case VSTRIMRIGHT: for (loc = str - 1; loc >= startp;) { - if (patmatch(str, loc, quotes)) { + if (patmatch(str, loc)) { amount = loc - expdest; STADJUST(amount, expdest); - return 1; + return; } loc--; - if (quotes && loc > startp && *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } } - return 0; + break; case VSTRIMRIGHTMAX: for (loc = startp; loc < str - 1; loc++) { - if (patmatch(str, loc, quotes)) { + if (patmatch(str, loc)) { amount = loc - expdest; STADJUST(amount, expdest); - return 1; + return; } - if (quotes && *loc == CTLESC) - loc++; } - return 0; + break; default: abort(); } + amount = (expdest - stackblock() - strloc) + 1; + STADJUST(-amount, expdest); } @@ -620,7 +606,7 @@ subevalvar_misc(char *p, const char *var, int subtype, int startloc, struct nodelist *saveargbackq = argbackq; int amount; - argstr(p, EXP_TILDE); + argstr(p, EXP_TILDE, NULL); STACKSTRNUL(expdest); argbackq = saveargbackq; startp = stackblock() + startloc; @@ -653,7 +639,7 @@ subevalvar_misc(char *p, const char *var, int subtype, int startloc, */ static char * -evalvar(char *p, int flag) +evalvar(char *p, int flag, struct worddest *dst) { int subtype; int varflags; @@ -666,9 +652,7 @@ evalvar(char *p, int flag) int startloc; int varlen; int varlenb; - int easy; - int quotes = flag & (EXP_FULL | EXP_CASE); - int record = 0; + char buf[21]; varflags = (unsigned char)*p++; subtype = varflags & VSTYPE; @@ -710,10 +694,16 @@ again: /* jump here after setting a variable with ${var=text} */ if (set && subtype != VSPLUS) { /* insert the value of the variable */ if (special) { - if (varflags & VSLINENO) - STPUTBIN(var, p - var - 1, expdest); - else - varvalue(var, varflags & VSQUOTE, subtype, flag); + if (varflags & VSLINENO) { + if (p - var > (ptrdiff_t)sizeof(buf)) + abort(); + memcpy(buf, var, p - var - 1); + buf[p - var - 1] = '\0'; + strtodest(buf, flag, subtype, + varflags & VSQUOTE, dst); + } else + varvalue(var, varflags & VSQUOTE, subtype, flag, + dst); if (subtype == VSLENGTH) { varlenb = expdest - stackblock() - startloc; varlen = varlenb; @@ -734,35 +724,29 @@ again: /* jump here after setting a variable with ${var=text} */ } else strtodest(val, flag, subtype, - varflags & VSQUOTE); + varflags & VSQUOTE, dst); } } if (subtype == VSPLUS) set = ! set; - easy = ((varflags & VSQUOTE) == 0 || - (*var == '@' && shellparam.nparam != 1)); - - switch (subtype) { case VSLENGTH: - expdest = cvtnum(varlen, expdest); - record = 1; + cvtnum(varlen, buf); + strtodest(buf, flag, VSNORMAL, varflags & VSQUOTE, dst); break; case VSNORMAL: - record = easy; break; case VSPLUS: case VSMINUS: if (!set) { argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) | - (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0)); + (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst); break; } - record = easy; break; case VSTRIMLEFT: @@ -777,14 +761,10 @@ again: /* jump here after setting a variable with ${var=text} */ */ STPUTC('\0', expdest); patloc = expdest - stackblock(); - if (subevalvar_trim(p, patloc, subtype, - startloc, quotes) == 0) { - int amount = (expdest - stackblock() - patloc) + 1; - STADJUST(-amount, expdest); - } - /* Remove any recorded regions beyond start of variable */ - removerecordregions(startloc); - record = 1; + subevalvar_trim(p, patloc, subtype, startloc); + reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst); + if (flag & EXP_FULL && *var == '@' && varflags & VSQUOTE) + dst->state = WORD_QUOTEMARK; break; case VSASSIGN: @@ -793,16 +773,10 @@ again: /* jump here after setting a variable with ${var=text} */ if (subevalvar_misc(p, var, subtype, startloc, varflags)) { varflags &= ~VSNUL; - /* - * Remove any recorded regions beyond - * start of variable - */ - removerecordregions(startloc); goto again; } break; } - record = easy; break; case VSERROR: @@ -814,11 +788,6 @@ again: /* jump here after setting a variable with ${var=text} */ abort(); } - if (record) - recordregion(startloc, expdest - stackblock(), - varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' && - (*var == '@' || *var == '*'))); - if (subtype != VSNORMAL) { /* skip to end of alternative */ int nesting = 1; for (;;) { @@ -884,26 +853,80 @@ varisset(const char *name, int nulok) } static void -strtodest(const char *p, int flag, int subtype, int quoted) +strtodest(const char *p, int flag, int subtype, int quoted, + struct worddest *dst) { - if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) + if (subtype == VSLENGTH || subtype == VSTRIMLEFT || + subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT || + subtype == VSTRIMRIGHTMAX) + STPUTS(p, expdest); + else if (flag & EXP_FULL && !quoted && dst != NULL) + STPUTS_SPLIT(p, BASESYNTAX, expdest, dst); + else if (flag & (EXP_FULL | EXP_CASE)) STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest); else STPUTS(p, expdest); } +static void +reprocess(int startloc, int flag, int subtype, int quoted, + struct worddest *dst) +{ + static char *buf = NULL; + static size_t buflen = 0; + char *startp; + size_t len, zpos, zlen; + + startp = stackblock() + startloc; + len = expdest - startp; + if (len >= SIZE_MAX / 2) + abort(); + INTOFF; + if (len >= buflen) { + ckfree(buf); + buf = NULL; + } + if (buflen < 128) + buflen = 128; + while (len >= buflen) + buflen <<= 1; + if (buf == NULL) + buf = ckmalloc(buflen); + INTON; + memcpy(buf, startp, len); + buf[len] = '\0'; + STADJUST(-len, expdest); + for (zpos = 0;;) { + zlen = strlen(buf + zpos); + strtodest(buf + zpos, flag, subtype, quoted, dst); + zpos += zlen + 1; + if (zpos == len + 1) + break; + if (flag & EXP_FULL && (quoted || (zlen > 0 && zpos < len))) + NEXTWORD('\0', expdest, dst); + } +} + /* * Add the value of a specialized variable to the stack string. */ static void -varvalue(const char *name, int quoted, int subtype, int flag) +varvalue(const char *name, int quoted, int subtype, int flag, + struct worddest *dst) { int num; char *p; int i; + int splitlater; char sep[2]; char **ap; + char buf[(NSHORTOPTS > 10 ? NSHORTOPTS : 10) + 1]; + + if (subtype == VSLENGTH) + flag &= ~EXP_FULL; + splitlater = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX || + subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX; switch (*name) { case '$': @@ -919,18 +942,27 @@ varvalue(const char *name, int quoted, int subtype, int flag) num = backgndpidval(); break; case '-': + p = buf; for (i = 0 ; i < NSHORTOPTS ; i++) { if (optlist[i].val) - STPUTC(optlist[i].letter, expdest); + *p++ = optlist[i].letter; } + *p = '\0'; + strtodest(buf, flag, subtype, quoted, dst); return; case '@': if (flag & EXP_FULL && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - strtodest(p, flag, subtype, quoted); - if (*ap) - STPUTC('\0', expdest); + strtodest(p, flag, subtype, quoted, dst); + if (*ap) { + if (splitlater) + STPUTC('\0', expdest); + else + NEXTWORD('\0', expdest, dst); + } } + if (shellparam.nparam > 0) + dst->state = WORD_QUOTEMARK; return; } /* FALLTHROUGH */ @@ -941,13 +973,17 @@ varvalue(const char *name, int quoted, int subtype, int flag) sep[0] = ' '; sep[1] = '\0'; for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - strtodest(p, flag, subtype, quoted); + strtodest(p, flag, subtype, quoted, dst); if (!*ap) break; if (sep[0]) - strtodest(sep, flag, subtype, quoted); - else if (flag & EXP_FULL && !quoted && **ap != '\0') - STPUTC('\0', expdest); + strtodest(sep, flag, subtype, quoted, dst); + else if (flag & EXP_FULL && !quoted && **ap != '\0') { + if (splitlater) + STPUTC('\0', expdest); + else + NEXTWORD('\0', expdest, dst); + } } return; default: @@ -959,149 +995,16 @@ varvalue(const char *name, int quoted, int subtype, int flag) p = shellparam.p[num - 1]; else return; - strtodest(p, flag, subtype, quoted); + strtodest(p, flag, subtype, quoted, dst); } return; } - expdest = cvtnum(num, expdest); + cvtnum(num, buf); + strtodest(buf, flag, subtype, quoted, dst); } -/* - * Record the fact that we have to scan this region of the - * string for IFS characters. - */ - -static void -recordregion(int start, int end, int inquotes) -{ - struct ifsregion *ifsp; - - INTOFF; - if (ifslastp == NULL) { - ifsp = &ifsfirst; - } else { - if (ifslastp->endoff == start - && ifslastp->inquotes == inquotes) { - /* extend previous area */ - ifslastp->endoff = end; - INTON; - return; - } - ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); - ifslastp->next = ifsp; - } - ifslastp = ifsp; - ifslastp->next = NULL; - ifslastp->begoff = start; - ifslastp->endoff = end; - ifslastp->inquotes = inquotes; - INTON; -} - - - -/* - * Break the argument string into pieces based upon IFS and add the - * strings to the argument list. The regions of the string to be - * searched for IFS characters have been stored by recordregion. - * CTLESC characters are preserved but have little effect in this pass - * other than escaping CTL* characters. In particular, they do not escape - * IFS characters: that should be done with the ifsregion mechanism. - * CTLQUOTEMARK characters are used to preserve empty quoted strings. - * This pass treats them as a regular character, making the string non-empty. - * Later, they are removed along with the other CTL* characters. - */ -static void -ifsbreakup(char *string, struct arglist *arglist) -{ - struct ifsregion *ifsp; - char *start; - char *p; - char *q; - const char *ifs; - const char *ifsspc; - int had_param_ch = 0; - - start = string; - - if (ifslastp == NULL) { - /* Return entire argument, IFS doesn't apply to any of it */ - appendarglist(arglist, start); - return; - } - - ifs = ifsset() ? ifsval() : " \t\n"; - - for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { - p = string + ifsp->begoff; - while (p < string + ifsp->endoff) { - q = p; - if (*p == CTLESC) - p++; - if (ifsp->inquotes) { - /* Only NULs (should be from "$@") end args */ - had_param_ch = 1; - if (*p != 0) { - p++; - continue; - } - ifsspc = NULL; - } else { - if (!strchr(ifs, *p)) { - had_param_ch = 1; - p++; - continue; - } - ifsspc = strchr(" \t\n", *p); - - /* Ignore IFS whitespace at start */ - if (q == start && ifsspc != NULL) { - p++; - start = p; - continue; - } - had_param_ch = 0; - } - - /* Save this argument... */ - *q = '\0'; - appendarglist(arglist, start); - p++; - - if (ifsspc != NULL) { - /* Ignore further trailing IFS whitespace */ - for (; p < string + ifsp->endoff; p++) { - q = p; - if (*p == CTLESC) - p++; - if (strchr(ifs, *p) == NULL) { - p = q; - break; - } - if (strchr(" \t\n", *p) == NULL) { - p++; - break; - } - } - } - start = p; - } - } - - /* - * Save anything left as an argument. - * Traditionally we have treated 'IFS=':'; set -- x$IFS' as - * generating 2 arguments, the second of which is empty. - * Some recent clarification of the Posix spec say that it - * should only generate one.... - */ - if (had_param_ch || *start != 0) - appendarglist(arglist, start); -} - - static char expdir[PATH_MAX]; #define expdir_end (expdir + sizeof(expdir)) @@ -1264,7 +1167,7 @@ expmeta(char *enddir, char *name, struct arglist *arglist) while (! int_pending() && (dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.' && ! matchdot) continue; - if (patmatch(start, dp->d_name, 0)) { + if (patmatch(start, dp->d_name)) { namlen = dp->d_namlen; if (enddir + namlen + 1 > expdir_end) continue; @@ -1354,7 +1257,7 @@ match_charclass(const char *p, wchar_t chr, const char **end) */ static int -patmatch(const char *pattern, const char *string, int squoted) +patmatch(const char *pattern, const char *string) { const char *p, *q, *end; const char *bt_p, *bt_q; @@ -1372,16 +1275,12 @@ patmatch(const char *pattern, const char *string, int squoted) goto backtrack; return 1; case CTLESC: - if (squoted && *q == CTLESC) - q++; if (*q++ != *p++) goto backtrack; break; case CTLQUOTEMARK: continue; case '?': - if (squoted && *q == CTLESC) - q++; if (*q == '\0') return 0; if (localeisutf8) { @@ -1426,8 +1325,6 @@ patmatch(const char *pattern, const char *string, int squoted) p++; } found = 0; - if (squoted && *q == CTLESC) - q++; if (*q == '\0') return 0; if (localeisutf8) { @@ -1485,8 +1382,6 @@ patmatch(const char *pattern, const char *string, int squoted) break; } dft: default: - if (squoted && *q == CTLESC) - q++; if (*q == '\0') return 0; if (*q++ == c) @@ -1499,8 +1394,6 @@ backtrack: */ if (bt_p == NULL) return 0; - if (squoted && *bt_q == CTLESC) - bt_q++; if (*bt_q == '\0') return 0; bt_q++; @@ -1556,11 +1449,10 @@ casematch(union node *pattern, const char *val) setstackmark(&smark); argbackq = pattern->narg.backquote; STARTSTACKSTR(expdest); - ifslastp = NULL; - argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); + argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, NULL); STPUTC('\0', expdest); p = grabstackstr(expdest); - result = patmatch(p, val, 0); + result = patmatch(p, val); popstackmark(&smark); return result; } @@ -1569,7 +1461,7 @@ casematch(union node *pattern, const char *val) * Our own itoa(). */ -static char * +static void cvtnum(int num, char *buf) { char temp[32]; @@ -1585,8 +1477,7 @@ cvtnum(int num, char *buf) if (neg) *--p = '-'; - STPUTS(p, buf); - return buf; + memcpy(buf, p, temp + 32 - p); } /* From a4ab0640fd84773b6017ac880c415cfdc6cdd80f Mon Sep 17 00:00:00 2001 From: kp Date: Thu, 31 Dec 2015 18:12:35 +0000 Subject: [PATCH 46/55] Add suppoort for the Sitecom LN-031 This is an AX88178 chip, which we already support so all we have to do is add the USB product and vendor ID. --- sys/dev/usb/net/if_axe.c | 1 + sys/dev/usb/usbdevs | 1 + 2 files changed, 2 insertions(+) diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c index 199549729de7..aa1ce0ed4c37 100644 --- a/sys/dev/usb/net/if_axe.c +++ b/sys/dev/usb/net/if_axe.c @@ -175,6 +175,7 @@ static const STRUCT_USB_HOST_ID axe_devs[] = { AXE_DEV(PLANEX3, GU1000T, AXE_FLAG_178), AXE_DEV(SITECOM, LN029, 0), AXE_DEV(SITECOMEU, LN028, AXE_FLAG_178), + AXE_DEV(SITECOMEU, LN031, AXE_FLAG_178), AXE_DEV(SYSTEMTALKS, SGCX2UL, 0), #undef AXE_DEV }; diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 42ba9c1ffcd0..2a55e7cba4e8 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -4203,6 +4203,7 @@ product SITECOMEU RTL8188CU_1 0x0052 RTL8188CU product SITECOMEU RTL8188CU_2 0x005c RTL8188CU product SITECOMEU RTL8192CU 0x0061 RTL8192CU product SITECOMEU LN032 0x0072 LN-032 +product SITECOMEU LN031 0x0056 LN-031 product SITECOMEU LN028 0x061c LN-028 product SITECOMEU WL113 0x9071 WL-113 product SITECOMEU ZD1211B 0x9075 ZD1211B From 7781ba8bccd49aa41633fe9c52ee38d36e33fc93 Mon Sep 17 00:00:00 2001 From: ian Date: Thu, 31 Dec 2015 18:29:24 +0000 Subject: [PATCH 47/55] When building libstand for arm, don't emit instructions that require relocation fixups unsupported by the self_reloc() code, and don't optimize memcpy/memset using floating point registers, because in a standalone environment nothing has initialized the fpu hardware. --- lib/libstand/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile index a69a935b3809..3126c1c30197 100644 --- a/lib/libstand/Makefile +++ b/lib/libstand/Makefile @@ -44,6 +44,12 @@ SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \ .if ${MACHINE_CPUARCH} == "arm" .PATH: ${LIBC_SRC}/arm/gen +# Do not generate movt/movw, because the relocation fixup for them does not +# translate to the -Bsymbolic -pie format required by self_reloc() in loader(8). +# Also, the fpu is not available in a standalone environment. +CFLAGS.clang+= -mllvm -arm-use-movt=0 +CFLAGS.clang+= -mfpu=none + # Compiler support functions .PATH: ${LIBSTAND_SRC}/../../contrib/compiler-rt/lib/builtins/ # __clzsi2 and ctzsi2 for various builtin functions From e4f897d527982c994f29593631ee908a72b278e4 Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 31 Dec 2015 18:47:54 +0000 Subject: [PATCH 48/55] sh: Perform pathname generation during the first expansion phases. This avoids the need to add and remove CTLESC bytes if pathname generation will not be performed (set -f). Side effect: the order of operations is slightly different: pathname generation in ${$+* $(CMD)} will not see filesystem changes from CMD. --- bin/sh/expand.c | 104 ++++++++++++++++++++++++------------------------ bin/sh/expand.h | 5 ++- 2 files changed, 57 insertions(+), 52 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 653ffc4c8c86..70280a1b8e21 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -84,7 +84,7 @@ __FBSDID("$FreeBSD$"); enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK }; struct worddest { - struct arglist list; + struct arglist *list; enum wordstate state; }; @@ -102,7 +102,7 @@ static int varisset(const char *, int); static void strtodest(const char *, int, int, int, struct worddest *); static void reprocess(int, int, int, int, struct worddest *); static void varvalue(const char *, int, int, int, struct worddest *); -static void expandmeta(struct arglist *, struct arglist *); +static void expandmeta(char *, struct arglist *); static void expmeta(char *, char *, struct arglist *); static int expsortcmp(const void *, const void *); static int patmatch(const char *, const char *); @@ -162,7 +162,7 @@ stputs_quotes(const char *data, const char *syntax, char *p) #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p) static char * -nextword(char c, char *p, struct worddest *dst) +nextword(char c, int flag, char *p, struct worddest *dst) { int is_ws; @@ -170,20 +170,23 @@ nextword(char c, char *p, struct worddest *dst) if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK : dst->state != WORD_WS_DELIMITED) || c == '\0') { STPUTC('\0', p); - appendarglist(&dst->list, grabstackstr(p)); + if (flag & EXP_GLOB) + expandmeta(grabstackstr(p), dst->list); + else + appendarglist(dst->list, grabstackstr(p)); dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE; } else if (!is_ws && dst->state == WORD_WS_DELIMITED) dst->state = WORD_IDLE; /* Reserve space while the stack string is empty. */ - appendarglist(&dst->list, NULL); - dst->list.count--; + appendarglist(dst->list, NULL); + dst->list->count--; STARTSTACKSTR(p); return p; } -#define NEXTWORD(c, p, dstlist) p = nextword(c, p, dstlist) +#define NEXTWORD(c, flag, p, dstlist) p = nextword(c, flag, p, dstlist) static char * -stputs_split(const char *data, const char *syntax, char *p, +stputs_split(const char *data, const char *syntax, int flag, char *p, struct worddest *dst) { const char *ifs; @@ -194,16 +197,16 @@ stputs_split(const char *data, const char *syntax, char *p, CHECKSTRSPACE(2, p); c = *data++; if (strchr(ifs, c) != NULL) { - NEXTWORD(c, p, dst); + NEXTWORD(c, flag, p, dst); continue; } - if (syntax[(int)c] == CCTL) + if (flag & EXP_GLOB && syntax[(int)c] == CCTL) USTPUTC(CTLESC, p); USTPUTC(c, p); } return (p); } -#define STPUTS_SPLIT(data, syntax, p, dst) p = stputs_split((data), syntax, p, dst) +#define STPUTS_SPLIT(data, syntax, flag, p, dst) p = stputs_split((data), syntax, flag, p, dst) /* * Perform expansions on an argument, placing the resulting list of arguments @@ -222,8 +225,10 @@ expandarg(union node *arg, struct arglist *arglist, int flag) { struct worddest exparg; + if (fflag) + flag &= ~EXP_GLOB; argbackq = arg->narg.backquote; - emptyarglist(&exparg.list); + exparg.list = arglist; exparg.state = WORD_IDLE; STARTSTACKSTR(expdest); argstr(arg->narg.text, flag, &exparg); @@ -231,15 +236,17 @@ expandarg(union node *arg, struct arglist *arglist, int flag) STACKSTRNUL(expdest); return; /* here document expanded */ } - if ((flag & EXP_FULL) == 0 || expdest != stackblock() || + if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() || exparg.state == WORD_QUOTEMARK) { STPUTC('\0', expdest); - if (flag & EXP_FULL) - appendarglist(&exparg.list, grabstackstr(expdest)); + if (flag & EXP_SPLIT) { + if (flag & EXP_GLOB) + expandmeta(grabstackstr(expdest), exparg.list); + else + appendarglist(exparg.list, grabstackstr(expdest)); + } } - if (flag & EXP_FULL) - expandmeta(&exparg.list, arglist); - else + if ((flag & EXP_SPLIT) == 0) appendarglist(arglist, grabstackstr(expdest)); } @@ -250,16 +257,16 @@ expandarg(union node *arg, struct arglist *arglist, int flag) * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE. * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'. * This is used to expand word in ${var+word} etc. - * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC + * If EXP_GLOB or EXP_CASE are set, keep and/or generate CTLESC * characters to allow for further processing. * - * If EXP_FULL is set, dst receives any complete words produced. + * If EXP_SPLIT is set, dst receives any complete words produced. */ static char * argstr(char *p, int flag, struct worddest *dst) { char c; - int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ + int quotes = flag & (EXP_GLOB | EXP_CASE); /* do CTLESC */ int firsteq = 1; int split_lit; int lit_quoted; @@ -283,7 +290,7 @@ argstr(char *p, int flag, struct worddest *dst) if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 && p[2] == '@' && p[3] == '=') break; - if ((flag & EXP_FULL) != 0 && expdest == stackblock()) + if ((flag & EXP_SPLIT) != 0 && expdest == stackblock()) dst->state = WORD_QUOTEMARK; break; case CTLQUOTEEND: @@ -293,7 +300,7 @@ argstr(char *p, int flag, struct worddest *dst) c = *p++; if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } if (quotes) @@ -319,7 +326,7 @@ argstr(char *p, int flag, struct worddest *dst) */ if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } USTPUTC(c, expdest); @@ -333,7 +340,7 @@ argstr(char *p, int flag, struct worddest *dst) default: if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } USTPUTC(c, expdest); @@ -438,7 +445,7 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) struct nodelist *saveargbackq; char lastc; char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int quotes = flag & (EXP_FULL | EXP_CASE); + int quotes = flag & (EXP_GLOB | EXP_CASE); size_t nnl; const char *ifs; @@ -452,7 +459,7 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) p = in.buf; lastc = '\0'; nnl = 0; - if (!quoted && flag & EXP_FULL) + if (!quoted && flag & EXP_SPLIT) ifs = ifsset() ? ifsval() : " \t\n"; else ifs = ""; @@ -476,7 +483,7 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) } else { if (nnl > 0) { if (strchr(ifs, '\n') != NULL) { - NEXTWORD('\n', dest, dst); + NEXTWORD('\n', flag, dest, dst); nnl = 0; } else { CHECKSTRSPACE(nnl + 2, dest); @@ -487,7 +494,7 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) } } if (strchr(ifs, lastc) != NULL) - NEXTWORD(lastc, dest, dst); + NEXTWORD(lastc, flag, dest, dst); else { CHECKSTRSPACE(2, dest); if (quotes && syntax[(int)lastc] == CCTL) @@ -743,7 +750,7 @@ again: /* jump here after setting a variable with ${var=text} */ case VSPLUS: case VSMINUS: if (!set) { - argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) | + argstr(p, flag | (flag & EXP_SPLIT ? EXP_SPLIT_LIT : 0) | (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst); break; } @@ -763,7 +770,7 @@ again: /* jump here after setting a variable with ${var=text} */ patloc = expdest - stackblock(); subevalvar_trim(p, patloc, subtype, startloc); reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst); - if (flag & EXP_FULL && *var == '@' && varflags & VSQUOTE) + if (flag & EXP_SPLIT && *var == '@' && varflags & VSQUOTE) dst->state = WORD_QUOTEMARK; break; @@ -860,9 +867,9 @@ strtodest(const char *p, int flag, int subtype, int quoted, subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX) STPUTS(p, expdest); - else if (flag & EXP_FULL && !quoted && dst != NULL) - STPUTS_SPLIT(p, BASESYNTAX, expdest, dst); - else if (flag & (EXP_FULL | EXP_CASE)) + else if (flag & EXP_SPLIT && !quoted && dst != NULL) + STPUTS_SPLIT(p, BASESYNTAX, flag, expdest, dst); + else if (flag & (EXP_GLOB | EXP_CASE)) STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest); else STPUTS(p, expdest); @@ -902,8 +909,8 @@ reprocess(int startloc, int flag, int subtype, int quoted, zpos += zlen + 1; if (zpos == len + 1) break; - if (flag & EXP_FULL && (quoted || (zlen > 0 && zpos < len))) - NEXTWORD('\0', expdest, dst); + if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len))) + NEXTWORD('\0', flag, expdest, dst); } } @@ -951,14 +958,15 @@ varvalue(const char *name, int quoted, int subtype, int flag, strtodest(buf, flag, subtype, quoted, dst); return; case '@': - if (flag & EXP_FULL && quoted) { + if (flag & EXP_SPLIT && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { strtodest(p, flag, subtype, quoted, dst); if (*ap) { if (splitlater) STPUTC('\0', expdest); else - NEXTWORD('\0', expdest, dst); + NEXTWORD('\0', flag, expdest, + dst); } } if (shellparam.nparam > 0) @@ -978,11 +986,11 @@ varvalue(const char *name, int quoted, int subtype, int flag, break; if (sep[0]) strtodest(sep, flag, subtype, quoted, dst); - else if (flag & EXP_FULL && !quoted && **ap != '\0') { + else if (flag & EXP_SPLIT && !quoted && **ap != '\0') { if (splitlater) STPUTC('\0', expdest); else - NEXTWORD('\0', expdest, dst); + NEXTWORD('\0', flag, expdest, dst); } } return; @@ -1014,40 +1022,34 @@ static char expdir[PATH_MAX]; * The results are stored in the list dstlist. */ static void -expandmeta(struct arglist *srclist, struct arglist *dstlist) +expandmeta(char *pattern, struct arglist *dstlist) { char *p; int firstmatch; - int i; char c; - for (i = 0; i < srclist->count; i++) { firstmatch = dstlist->count; - if (!fflag) { - p = srclist->args[i]; + p = pattern; for (; (c = *p) != '\0'; p++) { /* fast check for meta chars */ if (c == '*' || c == '?' || c == '[') { INTOFF; - expmeta(expdir, srclist->args[i], - dstlist); + expmeta(expdir, pattern, dstlist); INTON; break; } } - } if (dstlist->count == firstmatch) { /* * no matches */ - rmescapes(srclist->args[i]); - appendarglist(dstlist, srclist->args[i]); + rmescapes(pattern); + appendarglist(dstlist, pattern); } else { qsort(&dstlist->args[firstmatch], dstlist->count - firstmatch, sizeof(dstlist->args[0]), expsortcmp); } - } } diff --git a/bin/sh/expand.h b/bin/sh/expand.h index d024e8f6b7af..7fa7613007fb 100644 --- a/bin/sh/expand.h +++ b/bin/sh/expand.h @@ -43,12 +43,15 @@ struct arglist { /* * expandarg() flags */ -#define EXP_FULL 0x1 /* perform word splitting & file globbing */ +#define EXP_SPLIT 0x1 /* perform word splitting */ #define EXP_TILDE 0x2 /* do normal tilde expansion */ #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ #define EXP_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */ #define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */ +#define EXP_GLOB 0x80 /* perform file globbing */ + +#define EXP_FULL (EXP_SPLIT | EXP_GLOB) void emptyarglist(struct arglist *); From 249aea4a20095ca1b8ddd14c3bb95fd4236babcb Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 31 Dec 2015 18:56:11 +0000 Subject: [PATCH 49/55] sh: Reindent expandmeta(). --- bin/sh/expand.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 70280a1b8e21..6d5819dc6509 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -1028,28 +1028,28 @@ expandmeta(char *pattern, struct arglist *dstlist) int firstmatch; char c; - firstmatch = dstlist->count; - p = pattern; - for (; (c = *p) != '\0'; p++) { - /* fast check for meta chars */ - if (c == '*' || c == '?' || c == '[') { - INTOFF; - expmeta(expdir, pattern, dstlist); - INTON; - break; - } - } - if (dstlist->count == firstmatch) { - /* - * no matches - */ - rmescapes(pattern); - appendarglist(dstlist, pattern); - } else { - qsort(&dstlist->args[firstmatch], - dstlist->count - firstmatch, - sizeof(dstlist->args[0]), expsortcmp); + firstmatch = dstlist->count; + p = pattern; + for (; (c = *p) != '\0'; p++) { + /* fast check for meta chars */ + if (c == '*' || c == '?' || c == '[') { + INTOFF; + expmeta(expdir, pattern, dstlist); + INTON; + break; } + } + if (dstlist->count == firstmatch) { + /* + * no matches + */ + rmescapes(pattern); + appendarglist(dstlist, pattern); + } else { + qsort(&dstlist->args[firstmatch], + dstlist->count - firstmatch, + sizeof(dstlist->args[0]), expsortcmp); + } } From 0a47132513582fe66f2cb109d44de39958ac52ee Mon Sep 17 00:00:00 2001 From: dteske Date: Thu, 31 Dec 2015 19:00:45 +0000 Subject: [PATCH 50/55] Remove debugging messages. NB: SVN r187143 reads: comment out some debugging messages that slipped in by mistake (removing them 7 years after they have been commented out) MFC after: 1 week --- sys/boot/forth/support.4th | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 9a68872d2c95..0fe9a8c94712 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -852,7 +852,6 @@ only forth also support-functions definitions \ Interface to loading conf files : load_conf ( addr len -- ) - \ ." ----- Trying conf " 2dup type cr \ debugging 0 to end_of_file? reset_line_reading O_RDONLY fopen fd ! @@ -944,7 +943,6 @@ string current_file_name_ref \ used to print the file name \ loader_conf_files processing support functions : get_conf_files ( -- addr len ) \ put addr/len on stack, reset var - \ ." -- starting on <" conf_files strtype ." >" cr \ debugging conf_files strget 0 0 conf_files strset ; @@ -971,7 +969,6 @@ string current_file_name_ref \ used to print the file name pos char+ to pos repeat addr len pos addr r@ + pos r> - - \ 2dup ." get_file_name has " type cr \ debugging ; : get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 ) From 68a7758bef0c3004773925ced73c1a75edac03b4 Mon Sep 17 00:00:00 2001 From: emaste Date: Thu, 31 Dec 2015 19:25:35 +0000 Subject: [PATCH 51/55] newvers.sh: put variable assignments on separate lines This makes it easier to grep for where they're set, and may simplify future merging for FreeBSD derivatives that change these. --- sys/conf/newvers.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index fc812c515e2d..a5d47491eb06 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -97,7 +97,10 @@ then fi touch version -v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} +v=`cat version` +u=${USER:-root} +d=`pwd` +h=${HOSTNAME:-`hostname`} if [ -n "$SOURCE_DATE_EPOCH" ]; then if ! t=`date -r $SOURCE_DATE_EPOCH 2>/dev/null`; then echo "Invalid SOURCE_DATE_EPOCH" >&2 From e31d4ef62a674f2f74ac2d2e59487537a2d74ec6 Mon Sep 17 00:00:00 2001 From: dteske Date: Thu, 31 Dec 2015 19:33:17 +0000 Subject: [PATCH 52/55] Fix a memory leak. nextboot_conf_file is not volatile, as far as I can tell, and thus the strdup is entirely unnecessary. Thanks to: Toomas Soome (tsoome at-me dot-com) MFC after: 1 week --- sys/boot/forth/support.4th | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 0fe9a8c94712..7812a9bafd3d 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -1019,7 +1019,7 @@ string current_file_name_ref \ used to print the file name ; : get_nextboot_conf_file ( -- addr len ) - nextboot_conf_file strget strdup + nextboot_conf_file strget ; : rewrite_nextboot_file ( -- ) From ac84f941a7e91b97e1d1271f4523bda334b68a69 Mon Sep 17 00:00:00 2001 From: dteske Date: Thu, 31 Dec 2015 19:37:14 +0000 Subject: [PATCH 53/55] Remove supposition comment that code would better live elsewhere. Thinking this through, and looking at process_assignment, I believe moving the code would be wrong considering that set_conf_files is called in one condition while set_nextboot_conf is guarded by a different condition of having nextboot_enable="YES". So these must stay separated and not combined. MFC after: 1 week --- sys/boot/forth/support.4th | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 7812a9bafd3d..5a005b4acd83 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -684,7 +684,7 @@ only forth also support-functions also file-processing definitions s" loader_conf_files" getenv conf_files string= ; -: set_nextboot_conf \ XXX maybe do as set_conf_files ? +: set_nextboot_conf value_buffer strget unquote nextboot_conf_file string= ; From c3d7a5b30499e13ffd21909109aa59b196db6933 Mon Sep 17 00:00:00 2001 From: allanjude Date: Thu, 31 Dec 2015 20:00:53 +0000 Subject: [PATCH 54/55] Introduce the ZFS Boot Environments menu to the loader menu If the system was booted with ZFS, a new menu item (#7) appears It contains an autogenerated list of ZFS Boot Environments This allows the user to switch to an alternate root file system Use Cases: - Revert a failed upgrade - Concurrently run different versions of FreeBSD with common home directory - Easier integration with the sysadmin/beadm utility Requested by: many Reviewed by: dteske MFC after: 10 days Relnotes: yes Sponsored by: ScaleEngine Inc. Differential Revision: https://reviews.freebsd.org/D3167 --- sys/boot/forth/loader.conf | 1 + sys/boot/forth/menu-commands.4th | 64 ++++++++++++ sys/boot/forth/menu.rc | 53 ++++++++++ sys/boot/forth/support.4th | 24 +++++ sys/boot/i386/loader/main.c | 57 +++++++++++ sys/boot/zfs/libzfs.h | 3 + sys/boot/zfs/zfs.c | 166 ++++++++++++++++++++++++++++++- sys/boot/zfs/zfsimpl.c | 62 ++++++++++-- 8 files changed, 423 insertions(+), 7 deletions(-) diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index e2338abe4c05..c13e90ec7d44 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -90,6 +90,7 @@ ram_blacklist_type="ram_blacklist" # Required for the kernel to find #password="" # Prevent changes to boot options #bootlock_password="" # Prevent booting (see check-password.4th(8)) #geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root +bootenv_autolist="YES" # Auto populate the list of ZFS Boot Environments #beastie_disable="NO" # Turn the beastie boot menu on and off #kernels="kernel kernel.old" # Kernels to display in the boot menu #loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none diff --git a/sys/boot/forth/menu-commands.4th b/sys/boot/forth/menu-commands.4th index 07846760021e..9adf30a46b66 100644 --- a/sys/boot/forth/menu-commands.4th +++ b/sys/boot/forth/menu-commands.4th @@ -351,4 +351,68 @@ also menu-namespace also menu-command-helpers 2 goto_menu ; +\ +\ Set boot environment defaults +\ + +: init_bootenv ( -- ) + s" set menu_caption[1]=${bemenu_current}${vfs.root.mountfrom}" evaluate + s" set ansi_caption[1]=${beansi_current}${vfs.root.mountfrom}" evaluate + s" set menu_caption[2]=${bemenu_bootfs}${zfs_be_active}" evaluate + s" set ansi_caption[2]=${beansi_bootfs}${zfs_be_active}" evaluate + s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate + s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate +; + +\ +\ Redraw the entire screen. A long BE name can corrupt the menu +\ + +: be_draw_screen + clear \ Clear the screen (in screen.4th) + print_version \ print version string (bottom-right; see version.4th) + draw-beastie \ Draw FreeBSD logo at right (in beastie.4th) + draw-brand \ Draw brand.4th logo at top (in brand.4th) + menu-init \ Initialize menu and draw bounding box (in menu.4th) +; + +\ +\ Select a boot environment +\ + +: set_bootenv ( N -- N TRUE ) + dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate + s" set currdev=${vfs.root.mountfrom}:" evaluate + s" unload" evaluate + free-module-options + s" /boot/defaults/loader.conf" read-conf + s" /boot/loader.conf" read-conf + s" /boot/loader.conf.local" read-conf + init_bootenv + be_draw_screen + menu-redraw + TRUE +; + +\ +\ Switch to the next page of boot environments +\ + +: set_be_page ( N -- N TRUE ) + s" zfs_be_currpage" getenv dup -1 = if + drop s" 1" + else + 0 s>d 2swap + >number ( ud caddr/u -- ud' caddr'/u' ) \ convert string to numbers + 2drop \ drop the string + 1 um/mod ( ud u1 -- u2 u3 ) \ convert double ud' to single u3' and remainder u2 + swap drop ( ud2 u3 -- u3 ) \ drop the remainder u2 + 1+ \ increment the page number + s>d <# #s #> \ convert back to a string + then + s" zfs_be_currpage" setenv + s" reloadbe" evaluate + 3 goto_menu +; + only forth definitions diff --git a/sys/boot/forth/menu.rc b/sys/boot/forth/menu.rc index 7ffeef40aced..3c7de7138b8a 100644 --- a/sys/boot/forth/menu.rc +++ b/sys/boot/forth/menu.rc @@ -68,6 +68,13 @@ set mainmenu_command[6]="2 goto_menu" set mainmenu_keycode[6]=111 set mainansi_caption[6]="Configure Boot ^[1mO^[mptions..." +s" currdev" getenv dup 0> [if] drop 4 s" zfs:" compare 0= [if] + set mainmenu_caption[7]="Select Boot [E]nvironment..." + set mainmenu_command[7]="3 goto_menu" + set mainmenu_keycode[7]=101 + set mainansi_caption[7]="Select Boot ^[1mE^[37mnvironment..." +[then] [else] drop [then] + \ \ BOOT OPTIONS MENU \ @@ -119,6 +126,37 @@ set optionsmenu_keycode[6]=118 set optionsansi_caption[6]="^[1mV^[merbose..... ^[34;1mOff^[m" set optionstoggled_ansi[6]="^[1mV^[merbose..... ^[32;7mOn^[m" +\ +\ BOOT ENVIRONMENT MENU +\ + +set menuset_name3="bootenv" + +set bemenu_current="Active: " +set beansi_current="^[1m${bemenu_current}^[m" +set bemenu_bootfs="bootfs: " +set beansi_bootfs="^[1m${bemenu_bootfs}^[m" +set bemenu_page="[P]age: " +set beansi_page="^[1mP^[mage: " +set bemenu_pageof=" of " +set beansi_pageof="${bemenu_pageof}" +set zfs_be_currpage=1 + +set bootenvmenu_init="init_bootenv" + +set bootenvmenu_command[1]="be_draw_screen 1 goto_menu" +set bootenvmenu_keycode[1]=8 + +set bootenvmenu_command[2]="set_bootenv" +set bootenvmenu_keycode[2]=97 +set bootenv_root[2]="${zfs_be_active}" + +set bootenvmenu_command[3]="set_be_page" +set bootenvmenu_keycode[3]=112 + +set bootenvmenu_options=4 +set bootenvmenu_optionstext="Boot Environments:" + \ Enable automatic booting (add ``autoboot_delay=N'' to loader.conf(5) to \ customize the timeout; default is 10-seconds) \ @@ -128,6 +166,21 @@ set menu_timeout_command="boot" \ try-include /boot/menu.rc.local +\ Initialize boot environment variables +\ +s" reloadbe" sfind ( xt|0 bool ) [if] + s" bootenv_autolist" getenv dup -1 = [if] + drop s" execute" evaluate \ Use evaluate to avoid passing + \ reloadbe an optional parameter + [else] + s" YES" compare-insensitive 0= [if] + s" execute" evaluate + [then] + [then] +[else] + drop ( xt=0 ) +[then] + \ Display the main menu (see `menu.4th') set menuset_initial=1 menuset-loadinitial diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 5a005b4acd83..3a8e1f24e04c 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -930,6 +930,30 @@ only forth definitions also support-functions repeat ; +: free-one-module { addr -- addr } + addr module.name strfree + addr module.loadname strfree + addr module.type strfree + addr module.args strfree + addr module.beforeload strfree + addr module.afterload strfree + addr module.loaderror strfree + addr +; + +: free-module-options + module_options @ + begin + ?dup + while + free-one-module + dup module.next @ + swap free-memory + repeat + 0 module_options ! + 0 last_module_option ! +; + only forth also support-functions definitions \ Variables used for processing multiple conf files diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index 00873383e299..d4073e7da714 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -69,6 +69,7 @@ static int isa_inb(int port); static void isa_outb(int port, int value); void exit(int code); #ifdef LOADER_ZFS_SUPPORT +static void init_zfs_bootenv(char *currdev); static void i386_zfs_probe(void); #endif @@ -294,12 +295,40 @@ extract_currdev(void) new_currdev.d_unit = 0; } +#ifdef LOADER_ZFS_SUPPORT + init_zfs_bootenv(zfs_fmtdev(&new_currdev)); +#endif + env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), i386_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, env_nounset); } +#ifdef LOADER_ZFS_SUPPORT +static void +init_zfs_bootenv(char *currdev) +{ + char *beroot; + + /* Remove the trailing : */ + currdev[strlen(currdev) - 1] = '\0'; + setenv("zfs_be_active", currdev, 1); + /* Do not overwrite if already set */ + setenv("vfs.root.mountfrom", currdev, 0); + /* Forward past zfs: */ + currdev = strchr(currdev, ':'); + currdev++; + /* Remove the last element (current bootenv) */ + beroot = strrchr(currdev, '/'); + beroot[0] = '\0'; + + beroot = currdev; + + setenv("zfs_be_root", beroot, 1); +} +#endif + COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int @@ -353,6 +382,34 @@ command_lszfs(int argc, char *argv[]) command_errmsg = strerror(err); return (CMD_ERROR); } + + return (CMD_OK); +} + +COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments", + command_reloadbe); + +static int +command_reloadbe(int argc, char *argv[]) +{ + int err; + + if (argc > 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } + + if (argc == 2) { + err = zfs_bootenv(argv[1]); + } else { + err = zfs_bootenv(getenv("zfs_be_root")); + } + + if (err != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } + return (CMD_OK); } #endif diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h index 6834f8b14ba5..b28984958c9a 100644 --- a/sys/boot/zfs/libzfs.h +++ b/sys/boot/zfs/libzfs.h @@ -62,6 +62,9 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, char *zfs_fmtdev(void *vdev); int zfs_probe_dev(const char *devname, uint64_t *pool_guid); int zfs_list(const char *name); +int zfs_bootenv(const char *name); +int zfs_belist_add(const char *name); +int zfs_set_env(void); extern struct devsw zfs_dev; extern struct fs_ops zfs_fsops; diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index 64c738de314a..0e15ac48ff6a 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -48,6 +48,10 @@ __FBSDID("$FreeBSD$"); #include "zfsimpl.c" +/* Define the range of indexes to be populated with ZFS Boot Environments */ +#define ZFS_BE_FIRST 4 +#define ZFS_BE_LAST 8 + static int zfs_open(const char *path, struct open_file *f); static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); static int zfs_close(struct open_file *f); @@ -80,6 +84,16 @@ struct file { zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */ }; +static int zfs_env_index; +static int zfs_env_count; + +SLIST_HEAD(zfs_be_list, zfs_be_entry) zfs_be_head = SLIST_HEAD_INITIALIZER(zfs_be_head); +struct zfs_be_list *zfs_be_headp; +struct zfs_be_entry { + const char *name; + SLIST_ENTRY(zfs_be_entry) entries; +} *zfs_be, *zfs_be_tmp; + /* * Open a file. */ @@ -691,6 +705,156 @@ zfs_list(const char *name) rv = zfs_lookup_dataset(spa, dsname, &objid); if (rv != 0) return (rv); - rv = zfs_list_dataset(spa, objid); + + return (zfs_list_dataset(spa, objid)); +} + +int +zfs_bootenv(const char *name) +{ + static char poolname[ZFS_MAXNAMELEN], *dsname; + char becount[4]; + uint64_t objid; + spa_t *spa; + int len, rv, pages, perpage, currpage; + + if (strcmp(name, getenv("zfs_be_root")) != 0) { + if (setenv("zfs_be_root", name, 1) != 0) + return (ENOMEM); + } + + SLIST_INIT(&zfs_be_head); + zfs_env_count = 0; + len = strlen(name); + dsname = strchr(name, '/'); + if (dsname != NULL) { + len = dsname - name; + dsname++; + } else + dsname = ""; + memcpy(poolname, name, len); + poolname[len] = '\0'; + + spa = spa_find_by_name(poolname); + if (!spa) + return (ENXIO); + rv = zfs_lookup_dataset(spa, dsname, &objid); + if (rv != 0) + return (rv); + rv = zfs_callback_dataset(spa, objid, zfs_belist_add); + + /* Calculate and store the number of pages of BEs */ + perpage = (ZFS_BE_LAST - ZFS_BE_FIRST + 1); + pages = (zfs_env_count / perpage) + ((zfs_env_count % perpage) > 0 ? 1 : 0); + snprintf(becount, 4, "%d", pages); + if (setenv("zfs_be_pages", becount, 1) != 0) + return (ENOMEM); + + /* Roll over the page counter if it has exceeded the maximum */ + currpage = strtol(getenv("zfs_be_currpage"), NULL, 10); + if (currpage > pages) { + if (setenv("zfs_be_currpage", "1", 1) != 0) + return (ENOMEM); + } + + /* Populate the menu environment variables */ + zfs_set_env(); + + /* Clean up the SLIST of ZFS BEs */ + while (!SLIST_EMPTY(&zfs_be_head)) { + zfs_be = SLIST_FIRST(&zfs_be_head); + SLIST_REMOVE_HEAD(&zfs_be_head, entries); + free(zfs_be); + } + return (rv); } + +int +zfs_belist_add(const char *name) +{ + + /* Add the boot environment to the head of the SLIST */ + zfs_be = malloc(sizeof(struct zfs_be_entry)); + zfs_be->name = name; + SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries); + zfs_env_count++; + + return (0); +} + +int +zfs_set_env(void) +{ + char envname[32], envval[256]; + char *beroot, *pagenum; + int rv, page, ctr; + + beroot = getenv("zfs_be_root"); + if (beroot == NULL) { + return (1); + } + + pagenum = getenv("zfs_be_currpage"); + if (pagenum != NULL) { + page = strtol(pagenum, NULL, 10); + } else { + page = 1; + } + + ctr = 1; + rv = 0; + zfs_env_index = ZFS_BE_FIRST; + SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) { + /* Skip to the requested page number */ + if (ctr <= ((ZFS_BE_LAST - ZFS_BE_FIRST + 1) * (page - 1))) { + ctr++; + continue; + } + + snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index); + snprintf(envval, sizeof(envval), "%s", zfs_be->name); + rv = setenv(envname, envval, 1); + if (rv != 0) { + break; + } + + snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index); + rv = setenv(envname, envval, 1); + if (rv != 0){ + break; + } + + snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index); + rv = setenv(envname, "set_bootenv", 1); + if (rv != 0){ + break; + } + + snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index); + snprintf(envval, sizeof(envval), "zfs:%s/%s", beroot, zfs_be->name); + rv = setenv(envname, envval, 1); + if (rv != 0){ + break; + } + + zfs_env_index++; + if (zfs_env_index > ZFS_BE_LAST) { + break; + } + + } + + for (; zfs_env_index <= ZFS_BE_LAST; zfs_env_index++) { + snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index); + (void)unsetenv(envname); + snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index); + (void)unsetenv(envname); + snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index); + (void)unsetenv(envname); + snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index); + (void)unsetenv(envname); + } + + return (rv); +} \ No newline at end of file diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index d889047ffbd5..927fbadd8021 100644 --- a/sys/boot/zfs/zfsimpl.c +++ b/sys/boot/zfs/zfsimpl.c @@ -1473,7 +1473,7 @@ zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64 * the directory contents. */ static int -mzap_list(const dnode_phys_t *dnode) +mzap_list(const dnode_phys_t *dnode, int (*callback)(const char *)) { const mzap_phys_t *mz; const mzap_ent_phys_t *mze; @@ -1492,7 +1492,7 @@ mzap_list(const dnode_phys_t *dnode) mze = &mz->mz_chunk[i]; if (mze->mze_name[0]) //printf("%-32s 0x%jx\n", mze->mze_name, (uintmax_t)mze->mze_value); - printf("%s\n", mze->mze_name); + callback(mze->mze_name); } return (0); @@ -1503,7 +1503,7 @@ mzap_list(const dnode_phys_t *dnode) * the directory header. */ static int -fzap_list(const spa_t *spa, const dnode_phys_t *dnode) +fzap_list(const spa_t *spa, const dnode_phys_t *dnode, int (*callback)(const char *)) { int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; zap_phys_t zh = *(zap_phys_t *) zap_scratch; @@ -1566,13 +1566,21 @@ fzap_list(const spa_t *spa, const dnode_phys_t *dnode) value = fzap_leaf_value(&zl, zc); //printf("%s 0x%jx\n", name, (uintmax_t)value); - printf("%s\n", name); + callback((const char *)name); } } return (0); } +static int zfs_printf(const char *name) +{ + + printf("%s\n", name); + + return (0); +} + /* * List a zap directory. */ @@ -1587,9 +1595,9 @@ zap_list(const spa_t *spa, const dnode_phys_t *dnode) zap_type = *(uint64_t *) zap_scratch; if (zap_type == ZBT_MICRO) - return mzap_list(dnode); + return mzap_list(dnode, zfs_printf); else - return fzap_list(spa, dnode); + return fzap_list(spa, dnode, zfs_printf); } static int @@ -1858,6 +1866,48 @@ zfs_list_dataset(const spa_t *spa, uint64_t objnum/*, int pos, char *entry*/) return (zap_list(spa, &child_dir_zap) != 0); } + +int +zfs_callback_dataset(const spa_t *spa, uint64_t objnum, int (*callback)(const char *name)) +{ + uint64_t dir_obj, child_dir_zapobj, zap_type; + dnode_phys_t child_dir_zap, dir, dataset; + dsl_dataset_phys_t *ds; + dsl_dir_phys_t *dd; + int err; + + err = objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset); + if (err != 0) { + printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum); + return (err); + } + ds = (dsl_dataset_phys_t *) &dataset.dn_bonus; + dir_obj = ds->ds_dir_obj; + + err = objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir); + if (err != 0) { + printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj); + return (err); + } + dd = (dsl_dir_phys_t *)&dir.dn_bonus; + + child_dir_zapobj = dd->dd_child_dir_zapobj; + err = objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap); + if (err != 0) { + printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj); + return (err); + } + + err = dnode_read(spa, &child_dir_zap, 0, zap_scratch, child_dir_zap.dn_datablkszsec * 512); + if (err != 0) + return (err); + + zap_type = *(uint64_t *) zap_scratch; + if (zap_type == ZBT_MICRO) + return mzap_list(&child_dir_zap, callback); + else + return fzap_list(spa, &child_dir_zap, callback); +} #endif /* From b8cae6c53bb98cfc07d21feaa7d74ffcf5e09bb2 Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 31 Dec 2015 20:15:57 +0000 Subject: [PATCH 55/55] sh: Remove redundant CTLQUOTEMARK checks. With the new expand.c code, the intermediate representation passed to the pathname generation code only contains CTLESC, not CTLQUOTEMARK. CTLQUOTEMARK now only occurs in the text of NARG nodes (output of the parser). --- bin/sh/expand.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 6d5819dc6509..59ba5490f7fe 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -1018,7 +1018,7 @@ static char expdir[PATH_MAX]; /* * Perform pathname generation and remove control characters. - * At this point, the only control characters should be CTLESC and CTLQUOTEMARK. + * At this point, the only control characters should be CTLESC. * The results are stored in the list dstlist. */ static void @@ -1083,8 +1083,6 @@ expmeta(char *enddir, char *name, struct arglist *arglist) if (*q == '!' || *q == '^') q++; for (;;) { - while (*q == CTLQUOTEMARK) - q++; if (*q == CTLESC) q++; if (*q == '/' || *q == '\0') @@ -1096,8 +1094,6 @@ expmeta(char *enddir, char *name, struct arglist *arglist) } } else if (*p == '\0') break; - else if (*p == CTLQUOTEMARK) - continue; else { if (*p == CTLESC) esc++; @@ -1112,8 +1108,6 @@ expmeta(char *enddir, char *name, struct arglist *arglist) if (enddir != expdir) metaflag++; for (p = name ; ; p++) { - if (*p == CTLQUOTEMARK) - continue; if (*p == CTLESC) p++; *enddir++ = *p; @@ -1130,8 +1124,6 @@ expmeta(char *enddir, char *name, struct arglist *arglist) if (start != name) { p = name; while (p < start) { - while (*p == CTLQUOTEMARK) - p++; if (*p == CTLESC) p++; *enddir++ = *p++; @@ -1160,8 +1152,6 @@ expmeta(char *enddir, char *name, struct arglist *arglist) } matchdot = 0; p = start; - while (*p == CTLQUOTEMARK) - p++; if (*p == CTLESC) p++; if (*p == '.') @@ -1280,8 +1270,6 @@ patmatch(const char *pattern, const char *string) if (*q++ != *p++) goto backtrack; break; - case CTLQUOTEMARK: - continue; case '?': if (*q == '\0') return 0; @@ -1298,7 +1286,7 @@ patmatch(const char *pattern, const char *string) break; case '*': c = *p; - while (c == CTLQUOTEMARK || c == '*') + while (c == '*') c = *++p; /* * If the pattern ends here, we know the string @@ -1342,8 +1330,6 @@ patmatch(const char *pattern, const char *string) c = '['; goto dft; } - if (c == CTLQUOTEMARK) - continue; if (c == '[' && *p == ':') { found |= match_charclass(p, chr, &end); if (end != NULL) @@ -1360,8 +1346,6 @@ patmatch(const char *pattern, const char *string) wc = (unsigned char)c; if (*p == '-' && p[1] != ']') { p++; - while (*p == CTLQUOTEMARK) - p++; if (*p == CTLESC) p++; if (localeisutf8) {