diff options
author | Renato Botelho <renato@netgate.com> | 2016-01-25 08:56:15 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-01-25 08:56:15 -0200 |
commit | eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4 (patch) | |
tree | fec6b99d018e13f1fccbe31478aaf29a28a55642 /sys | |
parent | c50df8e1b90c4f9b8bbffa592477c129854776ce (diff) | |
parent | 94b1bbbd44bd88b6db1c00d795cdf7675b3ae254 (diff) | |
download | FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.zip FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys')
223 files changed, 7152 insertions, 3495 deletions
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c index d961f09..d7c9fef 100644 --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -83,6 +83,7 @@ struct sysentvec elf64_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 03334f1..15265aa 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1847,7 +1847,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) if (kmdp == NULL) kmdp = preload_search_by_type("elf64 kernel"); boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); - kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE; + init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE, 0); #ifdef DDB ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 3ecfabe..218c8cf 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -327,6 +327,13 @@ trap(struct trapframe *frame) break; case T_PAGEFLT: /* page fault */ + /* + * Emulator can take care about this trap? + */ + if (*p->p_sysent->sv_trap != NULL && + (*p->p_sysent->sv_trap)(td) == 0) + goto userout; + addr = frame->tf_addr; i = trap_pfault(frame, TRUE); if (i == -1) diff --git a/sys/amd64/include/metadata.h b/sys/amd64/include/metadata.h index 7dc22bf..98d0272 100644 --- a/sys/amd64/include/metadata.h +++ b/sys/amd64/include/metadata.h @@ -1,56 +1,6 @@ /*- - * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org> - * 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$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_METADATA_H_ -#define _MACHINE_METADATA_H_ - -#define MODINFOMD_SMAP 0x1001 -#define MODINFOMD_SMAP_XATTR 0x1002 -#define MODINFOMD_DTBP 0x1003 -#define MODINFOMD_EFI_MAP 0x1004 -#define MODINFOMD_EFI_FB 0x1005 - -struct efi_map_header { - size_t memory_size; - size_t descriptor_size; - uint32_t descriptor_version; -}; - -struct efi_fb { - uint64_t fb_addr; - uint64_t fb_size; - int fb_height; - int fb_width; - int fb_stride; - uint32_t fb_mask_red; - uint32_t fb_mask_green; - uint32_t fb_mask_blue; - uint32_t fb_mask_reserved; -}; - -#endif /* !_MACHINE_METADATA_H_ */ +#include <x86/metadata.h> diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 4bf9a4f..3f8d4c7 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -44,15 +44,19 @@ #include <machine/segments.h> #ifdef __amd64__ +/* + * NB: The fields marked with (*) are used by kernel debuggers. Their + * ABI should be preserved. + */ struct pcb { - register_t pcb_r15; - register_t pcb_r14; - register_t pcb_r13; - register_t pcb_r12; - register_t pcb_rbp; - register_t pcb_rsp; - register_t pcb_rbx; - register_t pcb_rip; + register_t pcb_r15; /* (*) */ + register_t pcb_r14; /* (*) */ + register_t pcb_r13; /* (*) */ + register_t pcb_r12; /* (*) */ + register_t pcb_rbp; /* (*) */ + register_t pcb_rsp; /* (*) */ + register_t pcb_rbx; /* (*) */ + register_t pcb_rip; /* (*) */ register_t pcb_fsbase; register_t pcb_gsbase; register_t pcb_kgsbase; diff --git a/sys/amd64/linux/linux_proto.h b/sys/amd64/linux/linux_proto.h index eedd423..0a0cbe6 100644 --- a/sys/amd64/linux/linux_proto.h +++ b/sys/amd64/linux/linux_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ #ifndef _LINUX_SYSPROTO_H_ diff --git a/sys/amd64/linux/linux_syscall.h b/sys/amd64/linux/linux_syscall.h index c8d811a..874651c 100644 --- a/sys/amd64/linux/linux_syscall.h +++ b/sys/amd64/linux/linux_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ #define LINUX_SYS_read 0 diff --git a/sys/amd64/linux/linux_syscalls.c b/sys/amd64/linux/linux_syscalls.c index 5c1e1a2..fcea91e 100644 --- a/sys/amd64/linux/linux_syscalls.c +++ b/sys/amd64/linux/linux_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ const char *linux_syscallnames[] = { diff --git a/sys/amd64/linux/linux_sysent.c b/sys/amd64/linux/linux_sysent.c index 97a15cc..14d5c87 100644 --- a/sys/amd64/linux/linux_sysent.c +++ b/sys/amd64/linux/linux_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ #include <sys/param.h> diff --git a/sys/amd64/linux/linux_systrace_args.c b/sys/amd64/linux/linux_systrace_args.c index 529e768..d649eed 100644 --- a/sys/amd64/linux/linux_systrace_args.c +++ b/sys/amd64/linux/linux_systrace_args.c @@ -73,8 +73,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) /* poll */ case 7: { struct poll_args *p = params; - iarg[0] = p->*; /* struct pollfd */ - uarg[1] = p->nfds; /* unsigned int */ + uarg[0] = (intptr_t) p->fds; /* struct pollfd * */ + uarg[1] = p->nfds; /* u_int */ iarg[2] = p->timeout; /* int */ *n_args = 3; break; @@ -591,7 +591,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) iarg[0] = p->semid; /* l_int */ iarg[1] = p->semnum; /* l_int */ iarg[2] = p->cmd; /* l_int */ - uarg[3] = p->arg; /* union l_semun */ + uarg[3] = p->arg.buf; /* union l_semun */ *n_args = 4; break; } @@ -1327,7 +1327,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) /* settimeofday */ case 164: { struct settimeofday_args *p = params; - uarg[0] = (intptr_t) p->tp; /* struct l_timeval * */ + uarg[0] = (intptr_t) p->tv; /* struct l_timeval * */ uarg[1] = (intptr_t) p->tzp; /* struct timezone * */ *n_args = 2; break; @@ -2380,10 +2380,10 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) case 7: switch(ndx) { case 0: - p = "struct pollfd"; + p = "struct pollfd *"; break; case 1: - p = "unsigned int"; + p = "u_int"; break; case 2: p = "int"; diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c index 37c1b69..d53a266 100644 --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -129,6 +129,7 @@ static void linux_set_syscall_retval(struct thread *td, int error); static int linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack); +static int linux_vsyscall(struct thread *td); /* * Linux syscalls return negative errno's, we do positive and map them @@ -746,6 +747,53 @@ exec_linux_imgact_try(struct image_params *imgp) return(error); } +#define LINUX_VSYSCALL_START (-10UL << 20) +#define LINUX_VSYSCALL_SZ 1024 + +const unsigned long linux_vsyscall_vector[] = { + LINUX_SYS_gettimeofday, + LINUX_SYS_linux_time, + /* getcpu not implemented */ +}; + +static int +linux_vsyscall(struct thread *td) +{ + struct trapframe *frame; + uint64_t retqaddr; + int code, traced; + int error; + + frame = td->td_frame; + + /* Check %rip for vsyscall area */ + if (__predict_true(frame->tf_rip < LINUX_VSYSCALL_START)) + return (EINVAL); + if ((frame->tf_rip & (LINUX_VSYSCALL_SZ - 1)) != 0) + return (EINVAL); + code = (frame->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SZ; + if (code >= nitems(linux_vsyscall_vector)) + return (EINVAL); + + /* + * vsyscall called as callq *(%rax), so we must + * use return address from %rsp and also fixup %rsp + */ + error = copyin((void *)frame->tf_rsp, &retqaddr, sizeof(retqaddr)); + if (error) + return (error); + + frame->tf_rip = retqaddr; + frame->tf_rax = linux_vsyscall_vector[code]; + frame->tf_rsp += 8; + + traced = (frame->tf_flags & PSL_T); + + amd64_syscall(td, traced); + + return (0); +} + struct sysentvec elf_linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, @@ -781,7 +829,8 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_base = SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, - .sv_thread_detach = linux_thread_detach + .sv_thread_detach = linux_thread_detach, + .sv_trap = linux_vsyscall, }; static void diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master index d840f88..87c8000 100644 --- a/sys/amd64/linux/syscalls.master +++ b/sys/amd64/linux/syscalls.master @@ -49,8 +49,8 @@ struct l_newstat *buf); } 6 AUE_LSTAT STD { int linux_newlstat(char *path, \ struct l_newstat *buf); } -7 AUE_POLL NOPROTO { int poll(struct pollfd*, \ - unsigned int nfds, int timeout); } +7 AUE_POLL NOPROTO { int poll(struct pollfd *fds, u_int nfds, \ + int timeout); } 8 AUE_LSEEK STD { int linux_lseek(l_uint fdes, l_off_t off, \ l_int whence); } 9 AUE_MMAP STD { int linux_mmap2(l_ulong addr, l_ulong len, \ @@ -316,7 +316,7 @@ 161 AUE_CHROOT NOPROTO { int chroot(char *path); } 162 AUE_SYNC NOPROTO { int sync(void); } 163 AUE_ACCT NOPROTO { int acct(char *path); } -164 AUE_SETTIMEOFDAY NOPROTO { int settimeofday(struct l_timeval *tp, struct timezone *tzp); } +164 AUE_SETTIMEOFDAY NOPROTO { int settimeofday(struct l_timeval *tv, struct timezone *tzp); } 165 AUE_MOUNT STD { int linux_mount(char *specialfile, \ char *dir, char *filesystemtype, \ l_ulong rwflag, void *data); } diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index e3b9f11..02d12f5 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -40,7 +40,7 @@ * debugging support */ extern u_char linux_debug_map[]; -#define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name) +#define ldebug(name) isclr(linux_debug_map, LINUX32_SYS_linux_ ## name) #define ARGS(nm, fmt) "linux(%ld/%ld): "#nm"("fmt")\n", \ (long)td->td_proc->p_pid, (long)td->td_tid #define LMSG(fmt) "linux(%ld/%ld): "fmt"\n", \ diff --git a/sys/amd64/linux32/linux32_locore.s b/sys/amd64/linux32/linux32_locore.s index 4edbdf3..7bbd69a 100644 --- a/sys/amd64/linux32/linux32_locore.s +++ b/sys/amd64/linux32/linux32_locore.s @@ -28,7 +28,7 @@ NON_GPROF_ENTRY(linux32_sigcode) jmp *LINUX_SIGF_HANDLER(%ebx) .startsigcode: popl %eax - movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */ + movl $LINUX32_SYS_linux_sigreturn,%eax /* linux_sigreturn() */ int $0x80 /* enter kernel with args */ .endsigcode: 0: jmp 0b @@ -44,7 +44,7 @@ NON_GPROF_ENTRY(linux32_rt_sigcode) push %eax jmp *LINUX_RT_SIGF_HANDLER(%edi) .startrtsigcode: - movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */ + movl $LINUX32_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */ int $0x80 /* enter kernel with args */ .endrtsigcode: 0: jmp 0b diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h index 56106d7..124abb1 100644 --- a/sys/amd64/linux32/linux32_proto.h +++ b/sys/amd64/linux32/linux32_proto.h @@ -3,11 +3,11 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ -#ifndef _LINUX_SYSPROTO_H_ -#define _LINUX_SYSPROTO_H_ +#ifndef _LINUX32_SYSPROTO_H_ +#define _LINUX32_SYSPROTO_H_ #include <sys/signal.h> #include <sys/acl.h> @@ -1464,286 +1464,286 @@ int linux_process_vm_writev(struct thread *, struct linux_process_vm_writev_args #endif /* COMPAT_FREEBSD7 */ -#define LINUX_SYS_AUE_linux_exit AUE_EXIT -#define LINUX_SYS_AUE_linux_fork AUE_FORK -#define LINUX_SYS_AUE_linux_open AUE_OPEN_RWTC -#define LINUX_SYS_AUE_linux_waitpid AUE_WAIT4 -#define LINUX_SYS_AUE_linux_creat AUE_CREAT -#define LINUX_SYS_AUE_linux_link AUE_LINK -#define LINUX_SYS_AUE_linux_unlink AUE_UNLINK -#define LINUX_SYS_AUE_linux_execve AUE_EXECVE -#define LINUX_SYS_AUE_linux_chdir AUE_CHDIR -#define LINUX_SYS_AUE_linux_time AUE_NULL -#define LINUX_SYS_AUE_linux_mknod AUE_MKNOD -#define LINUX_SYS_AUE_linux_chmod AUE_CHMOD -#define LINUX_SYS_AUE_linux_lchown16 AUE_LCHOWN -#define LINUX_SYS_AUE_linux_stat AUE_STAT -#define LINUX_SYS_AUE_linux_lseek AUE_LSEEK -#define LINUX_SYS_AUE_linux_getpid AUE_GETPID -#define LINUX_SYS_AUE_linux_mount AUE_MOUNT -#define LINUX_SYS_AUE_linux_oldumount AUE_UMOUNT -#define LINUX_SYS_AUE_linux_setuid16 AUE_SETUID -#define LINUX_SYS_AUE_linux_getuid16 AUE_GETUID -#define LINUX_SYS_AUE_linux_stime AUE_SETTIMEOFDAY -#define LINUX_SYS_AUE_linux_ptrace AUE_PTRACE -#define LINUX_SYS_AUE_linux_alarm AUE_NULL -#define LINUX_SYS_AUE_linux_pause AUE_NULL -#define LINUX_SYS_AUE_linux_utime AUE_UTIME -#define LINUX_SYS_AUE_linux_access AUE_ACCESS -#define LINUX_SYS_AUE_linux_nice AUE_NICE -#define LINUX_SYS_AUE_linux_kill AUE_KILL -#define LINUX_SYS_AUE_linux_rename AUE_RENAME -#define LINUX_SYS_AUE_linux_mkdir AUE_MKDIR -#define LINUX_SYS_AUE_linux_rmdir AUE_RMDIR -#define LINUX_SYS_AUE_linux_pipe AUE_PIPE -#define LINUX_SYS_AUE_linux_times AUE_NULL -#define LINUX_SYS_AUE_linux_brk AUE_NULL -#define LINUX_SYS_AUE_linux_setgid16 AUE_SETGID -#define LINUX_SYS_AUE_linux_getgid16 AUE_GETGID -#define LINUX_SYS_AUE_linux_signal AUE_NULL -#define LINUX_SYS_AUE_linux_geteuid16 AUE_GETEUID -#define LINUX_SYS_AUE_linux_getegid16 AUE_GETEGID -#define LINUX_SYS_AUE_linux_umount AUE_UMOUNT -#define LINUX_SYS_AUE_linux_ioctl AUE_IOCTL -#define LINUX_SYS_AUE_linux_fcntl AUE_FCNTL -#define LINUX_SYS_AUE_linux_olduname AUE_NULL -#define LINUX_SYS_AUE_linux_ustat AUE_NULL -#define LINUX_SYS_AUE_linux_getppid AUE_GETPPID -#define LINUX_SYS_AUE_linux_sigaction AUE_NULL -#define LINUX_SYS_AUE_linux_sgetmask AUE_NULL -#define LINUX_SYS_AUE_linux_ssetmask AUE_NULL -#define LINUX_SYS_AUE_linux_setreuid16 AUE_SETREUID -#define LINUX_SYS_AUE_linux_setregid16 AUE_SETREGID -#define LINUX_SYS_AUE_linux_sigsuspend AUE_NULL -#define LINUX_SYS_AUE_linux_sigpending AUE_NULL -#define LINUX_SYS_AUE_linux_sethostname AUE_SYSCTL -#define LINUX_SYS_AUE_linux_setrlimit AUE_SETRLIMIT -#define LINUX_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT -#define LINUX_SYS_AUE_linux_getrusage AUE_GETRUSAGE -#define LINUX_SYS_AUE_linux_gettimeofday AUE_NULL -#define LINUX_SYS_AUE_linux_settimeofday AUE_SETTIMEOFDAY -#define LINUX_SYS_AUE_linux_getgroups16 AUE_GETGROUPS -#define LINUX_SYS_AUE_linux_setgroups16 AUE_SETGROUPS -#define LINUX_SYS_AUE_linux_old_select AUE_SELECT -#define LINUX_SYS_AUE_linux_symlink AUE_SYMLINK -#define LINUX_SYS_AUE_linux_lstat AUE_LSTAT -#define LINUX_SYS_AUE_linux_readlink AUE_READLINK -#define LINUX_SYS_AUE_linux_reboot AUE_REBOOT -#define LINUX_SYS_AUE_linux_readdir AUE_GETDIRENTRIES -#define LINUX_SYS_AUE_linux_mmap AUE_MMAP -#define LINUX_SYS_AUE_linux_truncate AUE_TRUNCATE -#define LINUX_SYS_AUE_linux_ftruncate AUE_FTRUNCATE -#define LINUX_SYS_AUE_linux_getpriority AUE_GETPRIORITY -#define LINUX_SYS_AUE_linux_statfs AUE_STATFS -#define LINUX_SYS_AUE_linux_fstatfs AUE_FSTATFS -#define LINUX_SYS_AUE_linux_socketcall AUE_NULL -#define LINUX_SYS_AUE_linux_syslog AUE_NULL -#define LINUX_SYS_AUE_linux_setitimer AUE_SETITIMER -#define LINUX_SYS_AUE_linux_getitimer AUE_GETITIMER -#define LINUX_SYS_AUE_linux_newstat AUE_STAT -#define LINUX_SYS_AUE_linux_newlstat AUE_LSTAT -#define LINUX_SYS_AUE_linux_newfstat AUE_FSTAT -#define LINUX_SYS_AUE_linux_uname AUE_NULL -#define LINUX_SYS_AUE_linux_iopl AUE_NULL -#define LINUX_SYS_AUE_linux_vhangup AUE_NULL -#define LINUX_SYS_AUE_linux_wait4 AUE_WAIT4 -#define LINUX_SYS_AUE_linux_swapoff AUE_SWAPOFF -#define LINUX_SYS_AUE_linux_sysinfo AUE_NULL -#define LINUX_SYS_AUE_linux_ipc AUE_NULL -#define LINUX_SYS_AUE_linux_sigreturn AUE_SIGRETURN -#define LINUX_SYS_AUE_linux_clone AUE_RFORK -#define LINUX_SYS_AUE_linux_setdomainname AUE_SYSCTL -#define LINUX_SYS_AUE_linux_newuname AUE_NULL -#define LINUX_SYS_AUE_linux_adjtimex AUE_ADJTIME -#define LINUX_SYS_AUE_linux_mprotect AUE_MPROTECT -#define LINUX_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK -#define LINUX_SYS_AUE_linux_create_module AUE_NULL -#define LINUX_SYS_AUE_linux_init_module AUE_NULL -#define LINUX_SYS_AUE_linux_delete_module AUE_NULL -#define LINUX_SYS_AUE_linux_get_kernel_syms AUE_NULL -#define LINUX_SYS_AUE_linux_quotactl AUE_QUOTACTL -#define LINUX_SYS_AUE_linux_bdflush AUE_BDFLUSH -#define LINUX_SYS_AUE_linux_sysfs AUE_NULL -#define LINUX_SYS_AUE_linux_personality AUE_PERSONALITY -#define LINUX_SYS_AUE_linux_setfsuid16 AUE_SETFSUID -#define LINUX_SYS_AUE_linux_setfsgid16 AUE_SETFSGID -#define LINUX_SYS_AUE_linux_llseek AUE_LSEEK -#define LINUX_SYS_AUE_linux_getdents AUE_GETDIRENTRIES -#define LINUX_SYS_AUE_linux_select AUE_SELECT -#define LINUX_SYS_AUE_linux_msync AUE_MSYNC -#define LINUX_SYS_AUE_linux_readv AUE_READV -#define LINUX_SYS_AUE_linux_writev AUE_WRITEV -#define LINUX_SYS_AUE_linux_getsid AUE_GETSID -#define LINUX_SYS_AUE_linux_fdatasync AUE_NULL -#define LINUX_SYS_AUE_linux_sysctl AUE_SYSCTL -#define LINUX_SYS_AUE_linux_sched_setparam AUE_SCHED_SETPARAM -#define LINUX_SYS_AUE_linux_sched_getparam AUE_SCHED_GETPARAM -#define LINUX_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER -#define LINUX_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER -#define LINUX_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX -#define LINUX_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN -#define LINUX_SYS_AUE_linux_sched_rr_get_interval AUE_SCHED_RR_GET_INTERVAL -#define LINUX_SYS_AUE_linux_nanosleep AUE_NULL -#define LINUX_SYS_AUE_linux_mremap AUE_NULL -#define LINUX_SYS_AUE_linux_setresuid16 AUE_SETRESUID -#define LINUX_SYS_AUE_linux_getresuid16 AUE_GETRESUID -#define LINUX_SYS_AUE_linux_query_module AUE_NULL -#define LINUX_SYS_AUE_linux_nfsservctl AUE_NULL -#define LINUX_SYS_AUE_linux_setresgid16 AUE_SETRESGID -#define LINUX_SYS_AUE_linux_getresgid16 AUE_GETRESGID -#define LINUX_SYS_AUE_linux_prctl AUE_PRCTL -#define LINUX_SYS_AUE_linux_rt_sigreturn AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigaction AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigprocmask AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigpending AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigtimedwait AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL -#define LINUX_SYS_AUE_linux_rt_sigsuspend AUE_NULL -#define LINUX_SYS_AUE_linux_pread AUE_PREAD -#define LINUX_SYS_AUE_linux_pwrite AUE_PWRITE -#define LINUX_SYS_AUE_linux_chown16 AUE_CHOWN -#define LINUX_SYS_AUE_linux_getcwd AUE_GETCWD -#define LINUX_SYS_AUE_linux_capget AUE_CAPGET -#define LINUX_SYS_AUE_linux_capset AUE_CAPSET -#define LINUX_SYS_AUE_linux_sigaltstack AUE_NULL -#define LINUX_SYS_AUE_linux_sendfile AUE_SENDFILE -#define LINUX_SYS_AUE_linux_vfork AUE_VFORK -#define LINUX_SYS_AUE_linux_getrlimit AUE_GETRLIMIT -#define LINUX_SYS_AUE_linux_mmap2 AUE_MMAP -#define LINUX_SYS_AUE_linux_truncate64 AUE_TRUNCATE -#define LINUX_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE -#define LINUX_SYS_AUE_linux_stat64 AUE_STAT -#define LINUX_SYS_AUE_linux_lstat64 AUE_LSTAT -#define LINUX_SYS_AUE_linux_fstat64 AUE_FSTAT -#define LINUX_SYS_AUE_linux_lchown AUE_LCHOWN -#define LINUX_SYS_AUE_linux_getuid AUE_GETUID -#define LINUX_SYS_AUE_linux_getgid AUE_GETGID -#define LINUX_SYS_AUE_linux_getgroups AUE_GETGROUPS -#define LINUX_SYS_AUE_linux_setgroups AUE_SETGROUPS -#define LINUX_SYS_AUE_linux_chown AUE_CHOWN -#define LINUX_SYS_AUE_linux_setfsuid AUE_SETFSUID -#define LINUX_SYS_AUE_linux_setfsgid AUE_SETFSGID -#define LINUX_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT -#define LINUX_SYS_AUE_linux_mincore AUE_MINCORE -#define LINUX_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES -#define LINUX_SYS_AUE_linux_fcntl64 AUE_FCNTL -#define LINUX_SYS_AUE_linux_gettid AUE_NULL -#define LINUX_SYS_AUE_linux_setxattr AUE_NULL -#define LINUX_SYS_AUE_linux_lsetxattr AUE_NULL -#define LINUX_SYS_AUE_linux_fsetxattr AUE_NULL -#define LINUX_SYS_AUE_linux_getxattr AUE_NULL -#define LINUX_SYS_AUE_linux_lgetxattr AUE_NULL -#define LINUX_SYS_AUE_linux_fgetxattr AUE_NULL -#define LINUX_SYS_AUE_linux_listxattr AUE_NULL -#define LINUX_SYS_AUE_linux_llistxattr AUE_NULL -#define LINUX_SYS_AUE_linux_flistxattr AUE_NULL -#define LINUX_SYS_AUE_linux_removexattr AUE_NULL -#define LINUX_SYS_AUE_linux_lremovexattr AUE_NULL -#define LINUX_SYS_AUE_linux_fremovexattr AUE_NULL -#define LINUX_SYS_AUE_linux_tkill AUE_NULL -#define LINUX_SYS_AUE_linux_sys_futex AUE_NULL -#define LINUX_SYS_AUE_linux_sched_setaffinity AUE_NULL -#define LINUX_SYS_AUE_linux_sched_getaffinity AUE_NULL -#define LINUX_SYS_AUE_linux_set_thread_area AUE_NULL -#define LINUX_SYS_AUE_linux_fadvise64 AUE_NULL -#define LINUX_SYS_AUE_linux_exit_group AUE_EXIT -#define LINUX_SYS_AUE_linux_lookup_dcookie AUE_NULL -#define LINUX_SYS_AUE_linux_epoll_create AUE_NULL -#define LINUX_SYS_AUE_linux_epoll_ctl AUE_NULL -#define LINUX_SYS_AUE_linux_epoll_wait AUE_NULL -#define LINUX_SYS_AUE_linux_remap_file_pages AUE_NULL -#define LINUX_SYS_AUE_linux_set_tid_address AUE_NULL -#define LINUX_SYS_AUE_linux_timer_create AUE_NULL -#define LINUX_SYS_AUE_linux_timer_settime AUE_NULL -#define LINUX_SYS_AUE_linux_timer_gettime AUE_NULL -#define LINUX_SYS_AUE_linux_timer_getoverrun AUE_NULL -#define LINUX_SYS_AUE_linux_timer_delete AUE_NULL -#define LINUX_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME -#define LINUX_SYS_AUE_linux_clock_gettime AUE_NULL -#define LINUX_SYS_AUE_linux_clock_getres AUE_NULL -#define LINUX_SYS_AUE_linux_clock_nanosleep AUE_NULL -#define LINUX_SYS_AUE_linux_statfs64 AUE_STATFS -#define LINUX_SYS_AUE_linux_fstatfs64 AUE_FSTATFS -#define LINUX_SYS_AUE_linux_tgkill AUE_NULL -#define LINUX_SYS_AUE_linux_utimes AUE_UTIMES -#define LINUX_SYS_AUE_linux_fadvise64_64 AUE_NULL -#define LINUX_SYS_AUE_linux_mbind AUE_NULL -#define LINUX_SYS_AUE_linux_get_mempolicy AUE_NULL -#define LINUX_SYS_AUE_linux_set_mempolicy AUE_NULL -#define LINUX_SYS_AUE_linux_mq_open AUE_NULL -#define LINUX_SYS_AUE_linux_mq_unlink AUE_NULL -#define LINUX_SYS_AUE_linux_mq_timedsend AUE_NULL -#define LINUX_SYS_AUE_linux_mq_timedreceive AUE_NULL -#define LINUX_SYS_AUE_linux_mq_notify AUE_NULL -#define LINUX_SYS_AUE_linux_mq_getsetattr AUE_NULL -#define LINUX_SYS_AUE_linux_kexec_load AUE_NULL -#define LINUX_SYS_AUE_linux_waitid AUE_WAIT6 -#define LINUX_SYS_AUE_linux_add_key AUE_NULL -#define LINUX_SYS_AUE_linux_request_key AUE_NULL -#define LINUX_SYS_AUE_linux_keyctl AUE_NULL -#define LINUX_SYS_AUE_linux_ioprio_set AUE_NULL -#define LINUX_SYS_AUE_linux_ioprio_get AUE_NULL -#define LINUX_SYS_AUE_linux_inotify_init AUE_NULL -#define LINUX_SYS_AUE_linux_inotify_add_watch AUE_NULL -#define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL -#define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL -#define LINUX_SYS_AUE_linux_openat AUE_OPEN_RWTC -#define LINUX_SYS_AUE_linux_mkdirat AUE_MKDIRAT -#define LINUX_SYS_AUE_linux_mknodat AUE_MKNODAT -#define LINUX_SYS_AUE_linux_fchownat AUE_FCHOWNAT -#define LINUX_SYS_AUE_linux_futimesat AUE_FUTIMESAT -#define LINUX_SYS_AUE_linux_fstatat64 AUE_FSTATAT -#define LINUX_SYS_AUE_linux_unlinkat AUE_UNLINKAT -#define LINUX_SYS_AUE_linux_renameat AUE_RENAMEAT -#define LINUX_SYS_AUE_linux_linkat AUE_LINKAT -#define LINUX_SYS_AUE_linux_symlinkat AUE_SYMLINKAT -#define LINUX_SYS_AUE_linux_readlinkat AUE_READLINKAT -#define LINUX_SYS_AUE_linux_fchmodat AUE_FCHMODAT -#define LINUX_SYS_AUE_linux_faccessat AUE_FACCESSAT -#define LINUX_SYS_AUE_linux_pselect6 AUE_SELECT -#define LINUX_SYS_AUE_linux_ppoll AUE_POLL -#define LINUX_SYS_AUE_linux_unshare AUE_NULL -#define LINUX_SYS_AUE_linux_set_robust_list AUE_NULL -#define LINUX_SYS_AUE_linux_get_robust_list AUE_NULL -#define LINUX_SYS_AUE_linux_splice AUE_NULL -#define LINUX_SYS_AUE_linux_sync_file_range AUE_NULL -#define LINUX_SYS_AUE_linux_tee AUE_NULL -#define LINUX_SYS_AUE_linux_vmsplice AUE_NULL -#define LINUX_SYS_AUE_linux_move_pages AUE_NULL -#define LINUX_SYS_AUE_linux_getcpu AUE_NULL -#define LINUX_SYS_AUE_linux_epoll_pwait AUE_NULL -#define LINUX_SYS_AUE_linux_utimensat AUE_FUTIMESAT -#define LINUX_SYS_AUE_linux_signalfd AUE_NULL -#define LINUX_SYS_AUE_linux_timerfd_create AUE_NULL -#define LINUX_SYS_AUE_linux_eventfd AUE_NULL -#define LINUX_SYS_AUE_linux_fallocate AUE_NULL -#define LINUX_SYS_AUE_linux_timerfd_settime AUE_NULL -#define LINUX_SYS_AUE_linux_timerfd_gettime AUE_NULL -#define LINUX_SYS_AUE_linux_signalfd4 AUE_NULL -#define LINUX_SYS_AUE_linux_eventfd2 AUE_NULL -#define LINUX_SYS_AUE_linux_epoll_create1 AUE_NULL -#define LINUX_SYS_AUE_linux_dup3 AUE_NULL -#define LINUX_SYS_AUE_linux_pipe2 AUE_NULL -#define LINUX_SYS_AUE_linux_inotify_init1 AUE_NULL -#define LINUX_SYS_AUE_linux_preadv AUE_NULL -#define LINUX_SYS_AUE_linux_pwritev AUE_NULL -#define LINUX_SYS_AUE_linux_rt_tsigqueueinfo AUE_NULL -#define LINUX_SYS_AUE_linux_perf_event_open AUE_NULL -#define LINUX_SYS_AUE_linux_recvmmsg AUE_NULL -#define LINUX_SYS_AUE_linux_fanotify_init AUE_NULL -#define LINUX_SYS_AUE_linux_fanotify_mark AUE_NULL -#define LINUX_SYS_AUE_linux_prlimit64 AUE_NULL -#define LINUX_SYS_AUE_linux_name_to_handle_at AUE_NULL -#define LINUX_SYS_AUE_linux_open_by_handle_at AUE_NULL -#define LINUX_SYS_AUE_linux_clock_adjtime AUE_NULL -#define LINUX_SYS_AUE_linux_syncfs AUE_SYNC -#define LINUX_SYS_AUE_linux_sendmmsg AUE_NULL -#define LINUX_SYS_AUE_linux_setns AUE_NULL -#define LINUX_SYS_AUE_linux_process_vm_readv AUE_NULL -#define LINUX_SYS_AUE_linux_process_vm_writev AUE_NULL +#define LINUX32_SYS_AUE_linux_exit AUE_EXIT +#define LINUX32_SYS_AUE_linux_fork AUE_FORK +#define LINUX32_SYS_AUE_linux_open AUE_OPEN_RWTC +#define LINUX32_SYS_AUE_linux_waitpid AUE_WAIT4 +#define LINUX32_SYS_AUE_linux_creat AUE_CREAT +#define LINUX32_SYS_AUE_linux_link AUE_LINK +#define LINUX32_SYS_AUE_linux_unlink AUE_UNLINK +#define LINUX32_SYS_AUE_linux_execve AUE_EXECVE +#define LINUX32_SYS_AUE_linux_chdir AUE_CHDIR +#define LINUX32_SYS_AUE_linux_time AUE_NULL +#define LINUX32_SYS_AUE_linux_mknod AUE_MKNOD +#define LINUX32_SYS_AUE_linux_chmod AUE_CHMOD +#define LINUX32_SYS_AUE_linux_lchown16 AUE_LCHOWN +#define LINUX32_SYS_AUE_linux_stat AUE_STAT +#define LINUX32_SYS_AUE_linux_lseek AUE_LSEEK +#define LINUX32_SYS_AUE_linux_getpid AUE_GETPID +#define LINUX32_SYS_AUE_linux_mount AUE_MOUNT +#define LINUX32_SYS_AUE_linux_oldumount AUE_UMOUNT +#define LINUX32_SYS_AUE_linux_setuid16 AUE_SETUID +#define LINUX32_SYS_AUE_linux_getuid16 AUE_GETUID +#define LINUX32_SYS_AUE_linux_stime AUE_SETTIMEOFDAY +#define LINUX32_SYS_AUE_linux_ptrace AUE_PTRACE +#define LINUX32_SYS_AUE_linux_alarm AUE_NULL +#define LINUX32_SYS_AUE_linux_pause AUE_NULL +#define LINUX32_SYS_AUE_linux_utime AUE_UTIME +#define LINUX32_SYS_AUE_linux_access AUE_ACCESS +#define LINUX32_SYS_AUE_linux_nice AUE_NICE +#define LINUX32_SYS_AUE_linux_kill AUE_KILL +#define LINUX32_SYS_AUE_linux_rename AUE_RENAME +#define LINUX32_SYS_AUE_linux_mkdir AUE_MKDIR +#define LINUX32_SYS_AUE_linux_rmdir AUE_RMDIR +#define LINUX32_SYS_AUE_linux_pipe AUE_PIPE +#define LINUX32_SYS_AUE_linux_times AUE_NULL +#define LINUX32_SYS_AUE_linux_brk AUE_NULL +#define LINUX32_SYS_AUE_linux_setgid16 AUE_SETGID +#define LINUX32_SYS_AUE_linux_getgid16 AUE_GETGID +#define LINUX32_SYS_AUE_linux_signal AUE_NULL +#define LINUX32_SYS_AUE_linux_geteuid16 AUE_GETEUID +#define LINUX32_SYS_AUE_linux_getegid16 AUE_GETEGID +#define LINUX32_SYS_AUE_linux_umount AUE_UMOUNT +#define LINUX32_SYS_AUE_linux_ioctl AUE_IOCTL +#define LINUX32_SYS_AUE_linux_fcntl AUE_FCNTL +#define LINUX32_SYS_AUE_linux_olduname AUE_NULL +#define LINUX32_SYS_AUE_linux_ustat AUE_NULL +#define LINUX32_SYS_AUE_linux_getppid AUE_GETPPID +#define LINUX32_SYS_AUE_linux_sigaction AUE_NULL +#define LINUX32_SYS_AUE_linux_sgetmask AUE_NULL +#define LINUX32_SYS_AUE_linux_ssetmask AUE_NULL +#define LINUX32_SYS_AUE_linux_setreuid16 AUE_SETREUID +#define LINUX32_SYS_AUE_linux_setregid16 AUE_SETREGID +#define LINUX32_SYS_AUE_linux_sigsuspend AUE_NULL +#define LINUX32_SYS_AUE_linux_sigpending AUE_NULL +#define LINUX32_SYS_AUE_linux_sethostname AUE_SYSCTL +#define LINUX32_SYS_AUE_linux_setrlimit AUE_SETRLIMIT +#define LINUX32_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT +#define LINUX32_SYS_AUE_linux_getrusage AUE_GETRUSAGE +#define LINUX32_SYS_AUE_linux_gettimeofday AUE_NULL +#define LINUX32_SYS_AUE_linux_settimeofday AUE_SETTIMEOFDAY +#define LINUX32_SYS_AUE_linux_getgroups16 AUE_GETGROUPS +#define LINUX32_SYS_AUE_linux_setgroups16 AUE_SETGROUPS +#define LINUX32_SYS_AUE_linux_old_select AUE_SELECT +#define LINUX32_SYS_AUE_linux_symlink AUE_SYMLINK +#define LINUX32_SYS_AUE_linux_lstat AUE_LSTAT +#define LINUX32_SYS_AUE_linux_readlink AUE_READLINK +#define LINUX32_SYS_AUE_linux_reboot AUE_REBOOT +#define LINUX32_SYS_AUE_linux_readdir AUE_GETDIRENTRIES +#define LINUX32_SYS_AUE_linux_mmap AUE_MMAP +#define LINUX32_SYS_AUE_linux_truncate AUE_TRUNCATE +#define LINUX32_SYS_AUE_linux_ftruncate AUE_FTRUNCATE +#define LINUX32_SYS_AUE_linux_getpriority AUE_GETPRIORITY +#define LINUX32_SYS_AUE_linux_statfs AUE_STATFS +#define LINUX32_SYS_AUE_linux_fstatfs AUE_FSTATFS +#define LINUX32_SYS_AUE_linux_socketcall AUE_NULL +#define LINUX32_SYS_AUE_linux_syslog AUE_NULL +#define LINUX32_SYS_AUE_linux_setitimer AUE_SETITIMER +#define LINUX32_SYS_AUE_linux_getitimer AUE_GETITIMER +#define LINUX32_SYS_AUE_linux_newstat AUE_STAT +#define LINUX32_SYS_AUE_linux_newlstat AUE_LSTAT +#define LINUX32_SYS_AUE_linux_newfstat AUE_FSTAT +#define LINUX32_SYS_AUE_linux_uname AUE_NULL +#define LINUX32_SYS_AUE_linux_iopl AUE_NULL +#define LINUX32_SYS_AUE_linux_vhangup AUE_NULL +#define LINUX32_SYS_AUE_linux_wait4 AUE_WAIT4 +#define LINUX32_SYS_AUE_linux_swapoff AUE_SWAPOFF +#define LINUX32_SYS_AUE_linux_sysinfo AUE_NULL +#define LINUX32_SYS_AUE_linux_ipc AUE_NULL +#define LINUX32_SYS_AUE_linux_sigreturn AUE_SIGRETURN +#define LINUX32_SYS_AUE_linux_clone AUE_RFORK +#define LINUX32_SYS_AUE_linux_setdomainname AUE_SYSCTL +#define LINUX32_SYS_AUE_linux_newuname AUE_NULL +#define LINUX32_SYS_AUE_linux_adjtimex AUE_ADJTIME +#define LINUX32_SYS_AUE_linux_mprotect AUE_MPROTECT +#define LINUX32_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK +#define LINUX32_SYS_AUE_linux_create_module AUE_NULL +#define LINUX32_SYS_AUE_linux_init_module AUE_NULL +#define LINUX32_SYS_AUE_linux_delete_module AUE_NULL +#define LINUX32_SYS_AUE_linux_get_kernel_syms AUE_NULL +#define LINUX32_SYS_AUE_linux_quotactl AUE_QUOTACTL +#define LINUX32_SYS_AUE_linux_bdflush AUE_BDFLUSH +#define LINUX32_SYS_AUE_linux_sysfs AUE_NULL +#define LINUX32_SYS_AUE_linux_personality AUE_PERSONALITY +#define LINUX32_SYS_AUE_linux_setfsuid16 AUE_SETFSUID +#define LINUX32_SYS_AUE_linux_setfsgid16 AUE_SETFSGID +#define LINUX32_SYS_AUE_linux_llseek AUE_LSEEK +#define LINUX32_SYS_AUE_linux_getdents AUE_GETDIRENTRIES +#define LINUX32_SYS_AUE_linux_select AUE_SELECT +#define LINUX32_SYS_AUE_linux_msync AUE_MSYNC +#define LINUX32_SYS_AUE_linux_readv AUE_READV +#define LINUX32_SYS_AUE_linux_writev AUE_WRITEV +#define LINUX32_SYS_AUE_linux_getsid AUE_GETSID +#define LINUX32_SYS_AUE_linux_fdatasync AUE_NULL +#define LINUX32_SYS_AUE_linux_sysctl AUE_SYSCTL +#define LINUX32_SYS_AUE_linux_sched_setparam AUE_SCHED_SETPARAM +#define LINUX32_SYS_AUE_linux_sched_getparam AUE_SCHED_GETPARAM +#define LINUX32_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER +#define LINUX32_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER +#define LINUX32_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX +#define LINUX32_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN +#define LINUX32_SYS_AUE_linux_sched_rr_get_interval AUE_SCHED_RR_GET_INTERVAL +#define LINUX32_SYS_AUE_linux_nanosleep AUE_NULL +#define LINUX32_SYS_AUE_linux_mremap AUE_NULL +#define LINUX32_SYS_AUE_linux_setresuid16 AUE_SETRESUID +#define LINUX32_SYS_AUE_linux_getresuid16 AUE_GETRESUID +#define LINUX32_SYS_AUE_linux_query_module AUE_NULL +#define LINUX32_SYS_AUE_linux_nfsservctl AUE_NULL +#define LINUX32_SYS_AUE_linux_setresgid16 AUE_SETRESGID +#define LINUX32_SYS_AUE_linux_getresgid16 AUE_GETRESGID +#define LINUX32_SYS_AUE_linux_prctl AUE_PRCTL +#define LINUX32_SYS_AUE_linux_rt_sigreturn AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigaction AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigprocmask AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigpending AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigtimedwait AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_sigsuspend AUE_NULL +#define LINUX32_SYS_AUE_linux_pread AUE_PREAD +#define LINUX32_SYS_AUE_linux_pwrite AUE_PWRITE +#define LINUX32_SYS_AUE_linux_chown16 AUE_CHOWN +#define LINUX32_SYS_AUE_linux_getcwd AUE_GETCWD +#define LINUX32_SYS_AUE_linux_capget AUE_CAPGET +#define LINUX32_SYS_AUE_linux_capset AUE_CAPSET +#define LINUX32_SYS_AUE_linux_sigaltstack AUE_NULL +#define LINUX32_SYS_AUE_linux_sendfile AUE_SENDFILE +#define LINUX32_SYS_AUE_linux_vfork AUE_VFORK +#define LINUX32_SYS_AUE_linux_getrlimit AUE_GETRLIMIT +#define LINUX32_SYS_AUE_linux_mmap2 AUE_MMAP +#define LINUX32_SYS_AUE_linux_truncate64 AUE_TRUNCATE +#define LINUX32_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE +#define LINUX32_SYS_AUE_linux_stat64 AUE_STAT +#define LINUX32_SYS_AUE_linux_lstat64 AUE_LSTAT +#define LINUX32_SYS_AUE_linux_fstat64 AUE_FSTAT +#define LINUX32_SYS_AUE_linux_lchown AUE_LCHOWN +#define LINUX32_SYS_AUE_linux_getuid AUE_GETUID +#define LINUX32_SYS_AUE_linux_getgid AUE_GETGID +#define LINUX32_SYS_AUE_linux_getgroups AUE_GETGROUPS +#define LINUX32_SYS_AUE_linux_setgroups AUE_SETGROUPS +#define LINUX32_SYS_AUE_linux_chown AUE_CHOWN +#define LINUX32_SYS_AUE_linux_setfsuid AUE_SETFSUID +#define LINUX32_SYS_AUE_linux_setfsgid AUE_SETFSGID +#define LINUX32_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT +#define LINUX32_SYS_AUE_linux_mincore AUE_MINCORE +#define LINUX32_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES +#define LINUX32_SYS_AUE_linux_fcntl64 AUE_FCNTL +#define LINUX32_SYS_AUE_linux_gettid AUE_NULL +#define LINUX32_SYS_AUE_linux_setxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_lsetxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_fsetxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_getxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_lgetxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_fgetxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_listxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_llistxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_flistxattr AUE_NULL +#define LINUX32_SYS_AUE_linux_removexattr AUE_NULL +#define LINUX32_SYS_AUE_linux_lremovexattr AUE_NULL +#define LINUX32_SYS_AUE_linux_fremovexattr AUE_NULL +#define LINUX32_SYS_AUE_linux_tkill AUE_NULL +#define LINUX32_SYS_AUE_linux_sys_futex AUE_NULL +#define LINUX32_SYS_AUE_linux_sched_setaffinity AUE_NULL +#define LINUX32_SYS_AUE_linux_sched_getaffinity AUE_NULL +#define LINUX32_SYS_AUE_linux_set_thread_area AUE_NULL +#define LINUX32_SYS_AUE_linux_fadvise64 AUE_NULL +#define LINUX32_SYS_AUE_linux_exit_group AUE_EXIT +#define LINUX32_SYS_AUE_linux_lookup_dcookie AUE_NULL +#define LINUX32_SYS_AUE_linux_epoll_create AUE_NULL +#define LINUX32_SYS_AUE_linux_epoll_ctl AUE_NULL +#define LINUX32_SYS_AUE_linux_epoll_wait AUE_NULL +#define LINUX32_SYS_AUE_linux_remap_file_pages AUE_NULL +#define LINUX32_SYS_AUE_linux_set_tid_address AUE_NULL +#define LINUX32_SYS_AUE_linux_timer_create AUE_NULL +#define LINUX32_SYS_AUE_linux_timer_settime AUE_NULL +#define LINUX32_SYS_AUE_linux_timer_gettime AUE_NULL +#define LINUX32_SYS_AUE_linux_timer_getoverrun AUE_NULL +#define LINUX32_SYS_AUE_linux_timer_delete AUE_NULL +#define LINUX32_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME +#define LINUX32_SYS_AUE_linux_clock_gettime AUE_NULL +#define LINUX32_SYS_AUE_linux_clock_getres AUE_NULL +#define LINUX32_SYS_AUE_linux_clock_nanosleep AUE_NULL +#define LINUX32_SYS_AUE_linux_statfs64 AUE_STATFS +#define LINUX32_SYS_AUE_linux_fstatfs64 AUE_FSTATFS +#define LINUX32_SYS_AUE_linux_tgkill AUE_NULL +#define LINUX32_SYS_AUE_linux_utimes AUE_UTIMES +#define LINUX32_SYS_AUE_linux_fadvise64_64 AUE_NULL +#define LINUX32_SYS_AUE_linux_mbind AUE_NULL +#define LINUX32_SYS_AUE_linux_get_mempolicy AUE_NULL +#define LINUX32_SYS_AUE_linux_set_mempolicy AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_open AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_unlink AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_timedsend AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_timedreceive AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_notify AUE_NULL +#define LINUX32_SYS_AUE_linux_mq_getsetattr AUE_NULL +#define LINUX32_SYS_AUE_linux_kexec_load AUE_NULL +#define LINUX32_SYS_AUE_linux_waitid AUE_WAIT6 +#define LINUX32_SYS_AUE_linux_add_key AUE_NULL +#define LINUX32_SYS_AUE_linux_request_key AUE_NULL +#define LINUX32_SYS_AUE_linux_keyctl AUE_NULL +#define LINUX32_SYS_AUE_linux_ioprio_set AUE_NULL +#define LINUX32_SYS_AUE_linux_ioprio_get AUE_NULL +#define LINUX32_SYS_AUE_linux_inotify_init AUE_NULL +#define LINUX32_SYS_AUE_linux_inotify_add_watch AUE_NULL +#define LINUX32_SYS_AUE_linux_inotify_rm_watch AUE_NULL +#define LINUX32_SYS_AUE_linux_migrate_pages AUE_NULL +#define LINUX32_SYS_AUE_linux_openat AUE_OPEN_RWTC +#define LINUX32_SYS_AUE_linux_mkdirat AUE_MKDIRAT +#define LINUX32_SYS_AUE_linux_mknodat AUE_MKNODAT +#define LINUX32_SYS_AUE_linux_fchownat AUE_FCHOWNAT +#define LINUX32_SYS_AUE_linux_futimesat AUE_FUTIMESAT +#define LINUX32_SYS_AUE_linux_fstatat64 AUE_FSTATAT +#define LINUX32_SYS_AUE_linux_unlinkat AUE_UNLINKAT +#define LINUX32_SYS_AUE_linux_renameat AUE_RENAMEAT +#define LINUX32_SYS_AUE_linux_linkat AUE_LINKAT +#define LINUX32_SYS_AUE_linux_symlinkat AUE_SYMLINKAT +#define LINUX32_SYS_AUE_linux_readlinkat AUE_READLINKAT +#define LINUX32_SYS_AUE_linux_fchmodat AUE_FCHMODAT +#define LINUX32_SYS_AUE_linux_faccessat AUE_FACCESSAT +#define LINUX32_SYS_AUE_linux_pselect6 AUE_SELECT +#define LINUX32_SYS_AUE_linux_ppoll AUE_POLL +#define LINUX32_SYS_AUE_linux_unshare AUE_NULL +#define LINUX32_SYS_AUE_linux_set_robust_list AUE_NULL +#define LINUX32_SYS_AUE_linux_get_robust_list AUE_NULL +#define LINUX32_SYS_AUE_linux_splice AUE_NULL +#define LINUX32_SYS_AUE_linux_sync_file_range AUE_NULL +#define LINUX32_SYS_AUE_linux_tee AUE_NULL +#define LINUX32_SYS_AUE_linux_vmsplice AUE_NULL +#define LINUX32_SYS_AUE_linux_move_pages AUE_NULL +#define LINUX32_SYS_AUE_linux_getcpu AUE_NULL +#define LINUX32_SYS_AUE_linux_epoll_pwait AUE_NULL +#define LINUX32_SYS_AUE_linux_utimensat AUE_FUTIMESAT +#define LINUX32_SYS_AUE_linux_signalfd AUE_NULL +#define LINUX32_SYS_AUE_linux_timerfd_create AUE_NULL +#define LINUX32_SYS_AUE_linux_eventfd AUE_NULL +#define LINUX32_SYS_AUE_linux_fallocate AUE_NULL +#define LINUX32_SYS_AUE_linux_timerfd_settime AUE_NULL +#define LINUX32_SYS_AUE_linux_timerfd_gettime AUE_NULL +#define LINUX32_SYS_AUE_linux_signalfd4 AUE_NULL +#define LINUX32_SYS_AUE_linux_eventfd2 AUE_NULL +#define LINUX32_SYS_AUE_linux_epoll_create1 AUE_NULL +#define LINUX32_SYS_AUE_linux_dup3 AUE_NULL +#define LINUX32_SYS_AUE_linux_pipe2 AUE_NULL +#define LINUX32_SYS_AUE_linux_inotify_init1 AUE_NULL +#define LINUX32_SYS_AUE_linux_preadv AUE_NULL +#define LINUX32_SYS_AUE_linux_pwritev AUE_NULL +#define LINUX32_SYS_AUE_linux_rt_tsigqueueinfo AUE_NULL +#define LINUX32_SYS_AUE_linux_perf_event_open AUE_NULL +#define LINUX32_SYS_AUE_linux_recvmmsg AUE_NULL +#define LINUX32_SYS_AUE_linux_fanotify_init AUE_NULL +#define LINUX32_SYS_AUE_linux_fanotify_mark AUE_NULL +#define LINUX32_SYS_AUE_linux_prlimit64 AUE_NULL +#define LINUX32_SYS_AUE_linux_name_to_handle_at AUE_NULL +#define LINUX32_SYS_AUE_linux_open_by_handle_at AUE_NULL +#define LINUX32_SYS_AUE_linux_clock_adjtime AUE_NULL +#define LINUX32_SYS_AUE_linux_syncfs AUE_SYNC +#define LINUX32_SYS_AUE_linux_sendmmsg AUE_NULL +#define LINUX32_SYS_AUE_linux_setns AUE_NULL +#define LINUX32_SYS_AUE_linux_process_vm_readv AUE_NULL +#define LINUX32_SYS_AUE_linux_process_vm_writev AUE_NULL #undef PAD_ #undef PADL_ #undef PADR_ -#endif /* !_LINUX_SYSPROTO_H_ */ +#endif /* !_LINUX32_SYSPROTO_H_ */ diff --git a/sys/amd64/linux32/linux32_syscall.h b/sys/amd64/linux32/linux32_syscall.h index e3424b4..29c78a6 100644 --- a/sys/amd64/linux32/linux32_syscall.h +++ b/sys/amd64/linux32/linux32_syscall.h @@ -3,322 +3,322 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ -#define LINUX_SYS_linux_exit 1 -#define LINUX_SYS_linux_fork 2 -#define LINUX_SYS_read 3 -#define LINUX_SYS_write 4 -#define LINUX_SYS_linux_open 5 -#define LINUX_SYS_close 6 -#define LINUX_SYS_linux_waitpid 7 -#define LINUX_SYS_linux_creat 8 -#define LINUX_SYS_linux_link 9 -#define LINUX_SYS_linux_unlink 10 -#define LINUX_SYS_linux_execve 11 -#define LINUX_SYS_linux_chdir 12 -#define LINUX_SYS_linux_time 13 -#define LINUX_SYS_linux_mknod 14 -#define LINUX_SYS_linux_chmod 15 -#define LINUX_SYS_linux_lchown16 16 -#define LINUX_SYS_linux_stat 18 -#define LINUX_SYS_linux_lseek 19 -#define LINUX_SYS_linux_getpid 20 -#define LINUX_SYS_linux_mount 21 -#define LINUX_SYS_linux_oldumount 22 -#define LINUX_SYS_linux_setuid16 23 -#define LINUX_SYS_linux_getuid16 24 -#define LINUX_SYS_linux_stime 25 -#define LINUX_SYS_linux_ptrace 26 -#define LINUX_SYS_linux_alarm 27 -#define LINUX_SYS_linux_pause 29 -#define LINUX_SYS_linux_utime 30 -#define LINUX_SYS_linux_access 33 -#define LINUX_SYS_linux_nice 34 -#define LINUX_SYS_sync 36 -#define LINUX_SYS_linux_kill 37 -#define LINUX_SYS_linux_rename 38 -#define LINUX_SYS_linux_mkdir 39 -#define LINUX_SYS_linux_rmdir 40 -#define LINUX_SYS_dup 41 -#define LINUX_SYS_linux_pipe 42 -#define LINUX_SYS_linux_times 43 -#define LINUX_SYS_linux_brk 45 -#define LINUX_SYS_linux_setgid16 46 -#define LINUX_SYS_linux_getgid16 47 -#define LINUX_SYS_linux_signal 48 -#define LINUX_SYS_linux_geteuid16 49 -#define LINUX_SYS_linux_getegid16 50 -#define LINUX_SYS_acct 51 -#define LINUX_SYS_linux_umount 52 -#define LINUX_SYS_linux_ioctl 54 -#define LINUX_SYS_linux_fcntl 55 -#define LINUX_SYS_setpgid 57 -#define LINUX_SYS_linux_olduname 59 -#define LINUX_SYS_umask 60 -#define LINUX_SYS_chroot 61 -#define LINUX_SYS_linux_ustat 62 -#define LINUX_SYS_dup2 63 -#define LINUX_SYS_linux_getppid 64 -#define LINUX_SYS_getpgrp 65 -#define LINUX_SYS_setsid 66 -#define LINUX_SYS_linux_sigaction 67 -#define LINUX_SYS_linux_sgetmask 68 -#define LINUX_SYS_linux_ssetmask 69 -#define LINUX_SYS_linux_setreuid16 70 -#define LINUX_SYS_linux_setregid16 71 -#define LINUX_SYS_linux_sigsuspend 72 -#define LINUX_SYS_linux_sigpending 73 -#define LINUX_SYS_linux_sethostname 74 -#define LINUX_SYS_linux_setrlimit 75 -#define LINUX_SYS_linux_old_getrlimit 76 -#define LINUX_SYS_linux_getrusage 77 -#define LINUX_SYS_linux_gettimeofday 78 -#define LINUX_SYS_linux_settimeofday 79 -#define LINUX_SYS_linux_getgroups16 80 -#define LINUX_SYS_linux_setgroups16 81 -#define LINUX_SYS_linux_old_select 82 -#define LINUX_SYS_linux_symlink 83 -#define LINUX_SYS_linux_lstat 84 -#define LINUX_SYS_linux_readlink 85 -#define LINUX_SYS_swapon 87 -#define LINUX_SYS_linux_reboot 88 -#define LINUX_SYS_linux_readdir 89 -#define LINUX_SYS_linux_mmap 90 -#define LINUX_SYS_munmap 91 -#define LINUX_SYS_linux_truncate 92 -#define LINUX_SYS_linux_ftruncate 93 -#define LINUX_SYS_fchmod 94 -#define LINUX_SYS_fchown 95 -#define LINUX_SYS_linux_getpriority 96 -#define LINUX_SYS_setpriority 97 -#define LINUX_SYS_linux_statfs 99 -#define LINUX_SYS_linux_fstatfs 100 -#define LINUX_SYS_linux_socketcall 102 -#define LINUX_SYS_linux_syslog 103 -#define LINUX_SYS_linux_setitimer 104 -#define LINUX_SYS_linux_getitimer 105 -#define LINUX_SYS_linux_newstat 106 -#define LINUX_SYS_linux_newlstat 107 -#define LINUX_SYS_linux_newfstat 108 -#define LINUX_SYS_linux_uname 109 -#define LINUX_SYS_linux_iopl 110 -#define LINUX_SYS_linux_vhangup 111 -#define LINUX_SYS_linux_wait4 114 -#define LINUX_SYS_linux_swapoff 115 -#define LINUX_SYS_linux_sysinfo 116 -#define LINUX_SYS_linux_ipc 117 -#define LINUX_SYS_fsync 118 -#define LINUX_SYS_linux_sigreturn 119 -#define LINUX_SYS_linux_clone 120 -#define LINUX_SYS_linux_setdomainname 121 -#define LINUX_SYS_linux_newuname 122 -#define LINUX_SYS_linux_adjtimex 124 -#define LINUX_SYS_linux_mprotect 125 -#define LINUX_SYS_linux_sigprocmask 126 -#define LINUX_SYS_linux_create_module 127 -#define LINUX_SYS_linux_init_module 128 -#define LINUX_SYS_linux_delete_module 129 -#define LINUX_SYS_linux_get_kernel_syms 130 -#define LINUX_SYS_linux_quotactl 131 -#define LINUX_SYS_getpgid 132 -#define LINUX_SYS_fchdir 133 -#define LINUX_SYS_linux_bdflush 134 -#define LINUX_SYS_linux_sysfs 135 -#define LINUX_SYS_linux_personality 136 -#define LINUX_SYS_linux_setfsuid16 138 -#define LINUX_SYS_linux_setfsgid16 139 -#define LINUX_SYS_linux_llseek 140 -#define LINUX_SYS_linux_getdents 141 -#define LINUX_SYS_linux_select 142 -#define LINUX_SYS_flock 143 -#define LINUX_SYS_linux_msync 144 -#define LINUX_SYS_linux_readv 145 -#define LINUX_SYS_linux_writev 146 -#define LINUX_SYS_linux_getsid 147 -#define LINUX_SYS_linux_fdatasync 148 -#define LINUX_SYS_linux_sysctl 149 -#define LINUX_SYS_mlock 150 -#define LINUX_SYS_munlock 151 -#define LINUX_SYS_mlockall 152 -#define LINUX_SYS_munlockall 153 -#define LINUX_SYS_linux_sched_setparam 154 -#define LINUX_SYS_linux_sched_getparam 155 -#define LINUX_SYS_linux_sched_setscheduler 156 -#define LINUX_SYS_linux_sched_getscheduler 157 -#define LINUX_SYS_sched_yield 158 -#define LINUX_SYS_linux_sched_get_priority_max 159 -#define LINUX_SYS_linux_sched_get_priority_min 160 -#define LINUX_SYS_linux_sched_rr_get_interval 161 -#define LINUX_SYS_linux_nanosleep 162 -#define LINUX_SYS_linux_mremap 163 -#define LINUX_SYS_linux_setresuid16 164 -#define LINUX_SYS_linux_getresuid16 165 -#define LINUX_SYS_linux_query_module 167 -#define LINUX_SYS_poll 168 -#define LINUX_SYS_linux_nfsservctl 169 -#define LINUX_SYS_linux_setresgid16 170 -#define LINUX_SYS_linux_getresgid16 171 -#define LINUX_SYS_linux_prctl 172 -#define LINUX_SYS_linux_rt_sigreturn 173 -#define LINUX_SYS_linux_rt_sigaction 174 -#define LINUX_SYS_linux_rt_sigprocmask 175 -#define LINUX_SYS_linux_rt_sigpending 176 -#define LINUX_SYS_linux_rt_sigtimedwait 177 -#define LINUX_SYS_linux_rt_sigqueueinfo 178 -#define LINUX_SYS_linux_rt_sigsuspend 179 -#define LINUX_SYS_linux_pread 180 -#define LINUX_SYS_linux_pwrite 181 -#define LINUX_SYS_linux_chown16 182 -#define LINUX_SYS_linux_getcwd 183 -#define LINUX_SYS_linux_capget 184 -#define LINUX_SYS_linux_capset 185 -#define LINUX_SYS_linux_sigaltstack 186 -#define LINUX_SYS_linux_sendfile 187 -#define LINUX_SYS_linux_vfork 190 -#define LINUX_SYS_linux_getrlimit 191 -#define LINUX_SYS_linux_mmap2 192 -#define LINUX_SYS_linux_truncate64 193 -#define LINUX_SYS_linux_ftruncate64 194 -#define LINUX_SYS_linux_stat64 195 -#define LINUX_SYS_linux_lstat64 196 -#define LINUX_SYS_linux_fstat64 197 -#define LINUX_SYS_linux_lchown 198 -#define LINUX_SYS_linux_getuid 199 -#define LINUX_SYS_linux_getgid 200 -#define LINUX_SYS_geteuid 201 -#define LINUX_SYS_getegid 202 -#define LINUX_SYS_setreuid 203 -#define LINUX_SYS_setregid 204 -#define LINUX_SYS_linux_getgroups 205 -#define LINUX_SYS_linux_setgroups 206 -#define LINUX_SYS_setresuid 208 -#define LINUX_SYS_getresuid 209 -#define LINUX_SYS_setresgid 210 -#define LINUX_SYS_getresgid 211 -#define LINUX_SYS_linux_chown 212 -#define LINUX_SYS_setuid 213 -#define LINUX_SYS_setgid 214 -#define LINUX_SYS_linux_setfsuid 215 -#define LINUX_SYS_linux_setfsgid 216 -#define LINUX_SYS_linux_pivot_root 217 -#define LINUX_SYS_linux_mincore 218 -#define LINUX_SYS_madvise 219 -#define LINUX_SYS_linux_getdents64 220 -#define LINUX_SYS_linux_fcntl64 221 -#define LINUX_SYS_linux_gettid 224 -#define LINUX_SYS_linux_setxattr 226 -#define LINUX_SYS_linux_lsetxattr 227 -#define LINUX_SYS_linux_fsetxattr 228 -#define LINUX_SYS_linux_getxattr 229 -#define LINUX_SYS_linux_lgetxattr 230 -#define LINUX_SYS_linux_fgetxattr 231 -#define LINUX_SYS_linux_listxattr 232 -#define LINUX_SYS_linux_llistxattr 233 -#define LINUX_SYS_linux_flistxattr 234 -#define LINUX_SYS_linux_removexattr 235 -#define LINUX_SYS_linux_lremovexattr 236 -#define LINUX_SYS_linux_fremovexattr 237 -#define LINUX_SYS_linux_tkill 238 -#define LINUX_SYS_linux_sys_futex 240 -#define LINUX_SYS_linux_sched_setaffinity 241 -#define LINUX_SYS_linux_sched_getaffinity 242 -#define LINUX_SYS_linux_set_thread_area 243 -#define LINUX_SYS_linux_fadvise64 250 -#define LINUX_SYS_linux_exit_group 252 -#define LINUX_SYS_linux_lookup_dcookie 253 -#define LINUX_SYS_linux_epoll_create 254 -#define LINUX_SYS_linux_epoll_ctl 255 -#define LINUX_SYS_linux_epoll_wait 256 -#define LINUX_SYS_linux_remap_file_pages 257 -#define LINUX_SYS_linux_set_tid_address 258 -#define LINUX_SYS_linux_timer_create 259 -#define LINUX_SYS_linux_timer_settime 260 -#define LINUX_SYS_linux_timer_gettime 261 -#define LINUX_SYS_linux_timer_getoverrun 262 -#define LINUX_SYS_linux_timer_delete 263 -#define LINUX_SYS_linux_clock_settime 264 -#define LINUX_SYS_linux_clock_gettime 265 -#define LINUX_SYS_linux_clock_getres 266 -#define LINUX_SYS_linux_clock_nanosleep 267 -#define LINUX_SYS_linux_statfs64 268 -#define LINUX_SYS_linux_fstatfs64 269 -#define LINUX_SYS_linux_tgkill 270 -#define LINUX_SYS_linux_utimes 271 -#define LINUX_SYS_linux_fadvise64_64 272 -#define LINUX_SYS_linux_mbind 274 -#define LINUX_SYS_linux_get_mempolicy 275 -#define LINUX_SYS_linux_set_mempolicy 276 -#define LINUX_SYS_linux_mq_open 277 -#define LINUX_SYS_linux_mq_unlink 278 -#define LINUX_SYS_linux_mq_timedsend 279 -#define LINUX_SYS_linux_mq_timedreceive 280 -#define LINUX_SYS_linux_mq_notify 281 -#define LINUX_SYS_linux_mq_getsetattr 282 -#define LINUX_SYS_linux_kexec_load 283 -#define LINUX_SYS_linux_waitid 284 -#define LINUX_SYS_linux_add_key 286 -#define LINUX_SYS_linux_request_key 287 -#define LINUX_SYS_linux_keyctl 288 -#define LINUX_SYS_linux_ioprio_set 289 -#define LINUX_SYS_linux_ioprio_get 290 -#define LINUX_SYS_linux_inotify_init 291 -#define LINUX_SYS_linux_inotify_add_watch 292 -#define LINUX_SYS_linux_inotify_rm_watch 293 -#define LINUX_SYS_linux_migrate_pages 294 -#define LINUX_SYS_linux_openat 295 -#define LINUX_SYS_linux_mkdirat 296 -#define LINUX_SYS_linux_mknodat 297 -#define LINUX_SYS_linux_fchownat 298 -#define LINUX_SYS_linux_futimesat 299 -#define LINUX_SYS_linux_fstatat64 300 -#define LINUX_SYS_linux_unlinkat 301 -#define LINUX_SYS_linux_renameat 302 -#define LINUX_SYS_linux_linkat 303 -#define LINUX_SYS_linux_symlinkat 304 -#define LINUX_SYS_linux_readlinkat 305 -#define LINUX_SYS_linux_fchmodat 306 -#define LINUX_SYS_linux_faccessat 307 -#define LINUX_SYS_linux_pselect6 308 -#define LINUX_SYS_linux_ppoll 309 -#define LINUX_SYS_linux_unshare 310 -#define LINUX_SYS_linux_set_robust_list 311 -#define LINUX_SYS_linux_get_robust_list 312 -#define LINUX_SYS_linux_splice 313 -#define LINUX_SYS_linux_sync_file_range 314 -#define LINUX_SYS_linux_tee 315 -#define LINUX_SYS_linux_vmsplice 316 -#define LINUX_SYS_linux_move_pages 317 -#define LINUX_SYS_linux_getcpu 318 -#define LINUX_SYS_linux_epoll_pwait 319 -#define LINUX_SYS_linux_utimensat 320 -#define LINUX_SYS_linux_signalfd 321 -#define LINUX_SYS_linux_timerfd_create 322 -#define LINUX_SYS_linux_eventfd 323 -#define LINUX_SYS_linux_fallocate 324 -#define LINUX_SYS_linux_timerfd_settime 325 -#define LINUX_SYS_linux_timerfd_gettime 326 -#define LINUX_SYS_linux_signalfd4 327 -#define LINUX_SYS_linux_eventfd2 328 -#define LINUX_SYS_linux_epoll_create1 329 -#define LINUX_SYS_linux_dup3 330 -#define LINUX_SYS_linux_pipe2 331 -#define LINUX_SYS_linux_inotify_init1 332 -#define LINUX_SYS_linux_preadv 333 -#define LINUX_SYS_linux_pwritev 334 -#define LINUX_SYS_linux_rt_tsigqueueinfo 335 -#define LINUX_SYS_linux_perf_event_open 336 -#define LINUX_SYS_linux_recvmmsg 337 -#define LINUX_SYS_linux_fanotify_init 338 -#define LINUX_SYS_linux_fanotify_mark 339 -#define LINUX_SYS_linux_prlimit64 340 -#define LINUX_SYS_linux_name_to_handle_at 341 -#define LINUX_SYS_linux_open_by_handle_at 342 -#define LINUX_SYS_linux_clock_adjtime 343 -#define LINUX_SYS_linux_syncfs 344 -#define LINUX_SYS_linux_sendmmsg 345 -#define LINUX_SYS_linux_setns 346 -#define LINUX_SYS_linux_process_vm_readv 347 -#define LINUX_SYS_linux_process_vm_writev 348 -#define LINUX_SYS_MAXSYSCALL 350 +#define LINUX32_SYS_linux_exit 1 +#define LINUX32_SYS_linux_fork 2 +#define LINUX32_SYS_read 3 +#define LINUX32_SYS_write 4 +#define LINUX32_SYS_linux_open 5 +#define LINUX32_SYS_close 6 +#define LINUX32_SYS_linux_waitpid 7 +#define LINUX32_SYS_linux_creat 8 +#define LINUX32_SYS_linux_link 9 +#define LINUX32_SYS_linux_unlink 10 +#define LINUX32_SYS_linux_execve 11 +#define LINUX32_SYS_linux_chdir 12 +#define LINUX32_SYS_linux_time 13 +#define LINUX32_SYS_linux_mknod 14 +#define LINUX32_SYS_linux_chmod 15 +#define LINUX32_SYS_linux_lchown16 16 +#define LINUX32_SYS_linux_stat 18 +#define LINUX32_SYS_linux_lseek 19 +#define LINUX32_SYS_linux_getpid 20 +#define LINUX32_SYS_linux_mount 21 +#define LINUX32_SYS_linux_oldumount 22 +#define LINUX32_SYS_linux_setuid16 23 +#define LINUX32_SYS_linux_getuid16 24 +#define LINUX32_SYS_linux_stime 25 +#define LINUX32_SYS_linux_ptrace 26 +#define LINUX32_SYS_linux_alarm 27 +#define LINUX32_SYS_linux_pause 29 +#define LINUX32_SYS_linux_utime 30 +#define LINUX32_SYS_linux_access 33 +#define LINUX32_SYS_linux_nice 34 +#define LINUX32_SYS_sync 36 +#define LINUX32_SYS_linux_kill 37 +#define LINUX32_SYS_linux_rename 38 +#define LINUX32_SYS_linux_mkdir 39 +#define LINUX32_SYS_linux_rmdir 40 +#define LINUX32_SYS_dup 41 +#define LINUX32_SYS_linux_pipe 42 +#define LINUX32_SYS_linux_times 43 +#define LINUX32_SYS_linux_brk 45 +#define LINUX32_SYS_linux_setgid16 46 +#define LINUX32_SYS_linux_getgid16 47 +#define LINUX32_SYS_linux_signal 48 +#define LINUX32_SYS_linux_geteuid16 49 +#define LINUX32_SYS_linux_getegid16 50 +#define LINUX32_SYS_acct 51 +#define LINUX32_SYS_linux_umount 52 +#define LINUX32_SYS_linux_ioctl 54 +#define LINUX32_SYS_linux_fcntl 55 +#define LINUX32_SYS_setpgid 57 +#define LINUX32_SYS_linux_olduname 59 +#define LINUX32_SYS_umask 60 +#define LINUX32_SYS_chroot 61 +#define LINUX32_SYS_linux_ustat 62 +#define LINUX32_SYS_dup2 63 +#define LINUX32_SYS_linux_getppid 64 +#define LINUX32_SYS_getpgrp 65 +#define LINUX32_SYS_setsid 66 +#define LINUX32_SYS_linux_sigaction 67 +#define LINUX32_SYS_linux_sgetmask 68 +#define LINUX32_SYS_linux_ssetmask 69 +#define LINUX32_SYS_linux_setreuid16 70 +#define LINUX32_SYS_linux_setregid16 71 +#define LINUX32_SYS_linux_sigsuspend 72 +#define LINUX32_SYS_linux_sigpending 73 +#define LINUX32_SYS_linux_sethostname 74 +#define LINUX32_SYS_linux_setrlimit 75 +#define LINUX32_SYS_linux_old_getrlimit 76 +#define LINUX32_SYS_linux_getrusage 77 +#define LINUX32_SYS_linux_gettimeofday 78 +#define LINUX32_SYS_linux_settimeofday 79 +#define LINUX32_SYS_linux_getgroups16 80 +#define LINUX32_SYS_linux_setgroups16 81 +#define LINUX32_SYS_linux_old_select 82 +#define LINUX32_SYS_linux_symlink 83 +#define LINUX32_SYS_linux_lstat 84 +#define LINUX32_SYS_linux_readlink 85 +#define LINUX32_SYS_swapon 87 +#define LINUX32_SYS_linux_reboot 88 +#define LINUX32_SYS_linux_readdir 89 +#define LINUX32_SYS_linux_mmap 90 +#define LINUX32_SYS_munmap 91 +#define LINUX32_SYS_linux_truncate 92 +#define LINUX32_SYS_linux_ftruncate 93 +#define LINUX32_SYS_fchmod 94 +#define LINUX32_SYS_fchown 95 +#define LINUX32_SYS_linux_getpriority 96 +#define LINUX32_SYS_setpriority 97 +#define LINUX32_SYS_linux_statfs 99 +#define LINUX32_SYS_linux_fstatfs 100 +#define LINUX32_SYS_linux_socketcall 102 +#define LINUX32_SYS_linux_syslog 103 +#define LINUX32_SYS_linux_setitimer 104 +#define LINUX32_SYS_linux_getitimer 105 +#define LINUX32_SYS_linux_newstat 106 +#define LINUX32_SYS_linux_newlstat 107 +#define LINUX32_SYS_linux_newfstat 108 +#define LINUX32_SYS_linux_uname 109 +#define LINUX32_SYS_linux_iopl 110 +#define LINUX32_SYS_linux_vhangup 111 +#define LINUX32_SYS_linux_wait4 114 +#define LINUX32_SYS_linux_swapoff 115 +#define LINUX32_SYS_linux_sysinfo 116 +#define LINUX32_SYS_linux_ipc 117 +#define LINUX32_SYS_fsync 118 +#define LINUX32_SYS_linux_sigreturn 119 +#define LINUX32_SYS_linux_clone 120 +#define LINUX32_SYS_linux_setdomainname 121 +#define LINUX32_SYS_linux_newuname 122 +#define LINUX32_SYS_linux_adjtimex 124 +#define LINUX32_SYS_linux_mprotect 125 +#define LINUX32_SYS_linux_sigprocmask 126 +#define LINUX32_SYS_linux_create_module 127 +#define LINUX32_SYS_linux_init_module 128 +#define LINUX32_SYS_linux_delete_module 129 +#define LINUX32_SYS_linux_get_kernel_syms 130 +#define LINUX32_SYS_linux_quotactl 131 +#define LINUX32_SYS_getpgid 132 +#define LINUX32_SYS_fchdir 133 +#define LINUX32_SYS_linux_bdflush 134 +#define LINUX32_SYS_linux_sysfs 135 +#define LINUX32_SYS_linux_personality 136 +#define LINUX32_SYS_linux_setfsuid16 138 +#define LINUX32_SYS_linux_setfsgid16 139 +#define LINUX32_SYS_linux_llseek 140 +#define LINUX32_SYS_linux_getdents 141 +#define LINUX32_SYS_linux_select 142 +#define LINUX32_SYS_flock 143 +#define LINUX32_SYS_linux_msync 144 +#define LINUX32_SYS_linux_readv 145 +#define LINUX32_SYS_linux_writev 146 +#define LINUX32_SYS_linux_getsid 147 +#define LINUX32_SYS_linux_fdatasync 148 +#define LINUX32_SYS_linux_sysctl 149 +#define LINUX32_SYS_mlock 150 +#define LINUX32_SYS_munlock 151 +#define LINUX32_SYS_mlockall 152 +#define LINUX32_SYS_munlockall 153 +#define LINUX32_SYS_linux_sched_setparam 154 +#define LINUX32_SYS_linux_sched_getparam 155 +#define LINUX32_SYS_linux_sched_setscheduler 156 +#define LINUX32_SYS_linux_sched_getscheduler 157 +#define LINUX32_SYS_sched_yield 158 +#define LINUX32_SYS_linux_sched_get_priority_max 159 +#define LINUX32_SYS_linux_sched_get_priority_min 160 +#define LINUX32_SYS_linux_sched_rr_get_interval 161 +#define LINUX32_SYS_linux_nanosleep 162 +#define LINUX32_SYS_linux_mremap 163 +#define LINUX32_SYS_linux_setresuid16 164 +#define LINUX32_SYS_linux_getresuid16 165 +#define LINUX32_SYS_linux_query_module 167 +#define LINUX32_SYS_poll 168 +#define LINUX32_SYS_linux_nfsservctl 169 +#define LINUX32_SYS_linux_setresgid16 170 +#define LINUX32_SYS_linux_getresgid16 171 +#define LINUX32_SYS_linux_prctl 172 +#define LINUX32_SYS_linux_rt_sigreturn 173 +#define LINUX32_SYS_linux_rt_sigaction 174 +#define LINUX32_SYS_linux_rt_sigprocmask 175 +#define LINUX32_SYS_linux_rt_sigpending 176 +#define LINUX32_SYS_linux_rt_sigtimedwait 177 +#define LINUX32_SYS_linux_rt_sigqueueinfo 178 +#define LINUX32_SYS_linux_rt_sigsuspend 179 +#define LINUX32_SYS_linux_pread 180 +#define LINUX32_SYS_linux_pwrite 181 +#define LINUX32_SYS_linux_chown16 182 +#define LINUX32_SYS_linux_getcwd 183 +#define LINUX32_SYS_linux_capget 184 +#define LINUX32_SYS_linux_capset 185 +#define LINUX32_SYS_linux_sigaltstack 186 +#define LINUX32_SYS_linux_sendfile 187 +#define LINUX32_SYS_linux_vfork 190 +#define LINUX32_SYS_linux_getrlimit 191 +#define LINUX32_SYS_linux_mmap2 192 +#define LINUX32_SYS_linux_truncate64 193 +#define LINUX32_SYS_linux_ftruncate64 194 +#define LINUX32_SYS_linux_stat64 195 +#define LINUX32_SYS_linux_lstat64 196 +#define LINUX32_SYS_linux_fstat64 197 +#define LINUX32_SYS_linux_lchown 198 +#define LINUX32_SYS_linux_getuid 199 +#define LINUX32_SYS_linux_getgid 200 +#define LINUX32_SYS_geteuid 201 +#define LINUX32_SYS_getegid 202 +#define LINUX32_SYS_setreuid 203 +#define LINUX32_SYS_setregid 204 +#define LINUX32_SYS_linux_getgroups 205 +#define LINUX32_SYS_linux_setgroups 206 +#define LINUX32_SYS_setresuid 208 +#define LINUX32_SYS_getresuid 209 +#define LINUX32_SYS_setresgid 210 +#define LINUX32_SYS_getresgid 211 +#define LINUX32_SYS_linux_chown 212 +#define LINUX32_SYS_setuid 213 +#define LINUX32_SYS_setgid 214 +#define LINUX32_SYS_linux_setfsuid 215 +#define LINUX32_SYS_linux_setfsgid 216 +#define LINUX32_SYS_linux_pivot_root 217 +#define LINUX32_SYS_linux_mincore 218 +#define LINUX32_SYS_madvise 219 +#define LINUX32_SYS_linux_getdents64 220 +#define LINUX32_SYS_linux_fcntl64 221 +#define LINUX32_SYS_linux_gettid 224 +#define LINUX32_SYS_linux_setxattr 226 +#define LINUX32_SYS_linux_lsetxattr 227 +#define LINUX32_SYS_linux_fsetxattr 228 +#define LINUX32_SYS_linux_getxattr 229 +#define LINUX32_SYS_linux_lgetxattr 230 +#define LINUX32_SYS_linux_fgetxattr 231 +#define LINUX32_SYS_linux_listxattr 232 +#define LINUX32_SYS_linux_llistxattr 233 +#define LINUX32_SYS_linux_flistxattr 234 +#define LINUX32_SYS_linux_removexattr 235 +#define LINUX32_SYS_linux_lremovexattr 236 +#define LINUX32_SYS_linux_fremovexattr 237 +#define LINUX32_SYS_linux_tkill 238 +#define LINUX32_SYS_linux_sys_futex 240 +#define LINUX32_SYS_linux_sched_setaffinity 241 +#define LINUX32_SYS_linux_sched_getaffinity 242 +#define LINUX32_SYS_linux_set_thread_area 243 +#define LINUX32_SYS_linux_fadvise64 250 +#define LINUX32_SYS_linux_exit_group 252 +#define LINUX32_SYS_linux_lookup_dcookie 253 +#define LINUX32_SYS_linux_epoll_create 254 +#define LINUX32_SYS_linux_epoll_ctl 255 +#define LINUX32_SYS_linux_epoll_wait 256 +#define LINUX32_SYS_linux_remap_file_pages 257 +#define LINUX32_SYS_linux_set_tid_address 258 +#define LINUX32_SYS_linux_timer_create 259 +#define LINUX32_SYS_linux_timer_settime 260 +#define LINUX32_SYS_linux_timer_gettime 261 +#define LINUX32_SYS_linux_timer_getoverrun 262 +#define LINUX32_SYS_linux_timer_delete 263 +#define LINUX32_SYS_linux_clock_settime 264 +#define LINUX32_SYS_linux_clock_gettime 265 +#define LINUX32_SYS_linux_clock_getres 266 +#define LINUX32_SYS_linux_clock_nanosleep 267 +#define LINUX32_SYS_linux_statfs64 268 +#define LINUX32_SYS_linux_fstatfs64 269 +#define LINUX32_SYS_linux_tgkill 270 +#define LINUX32_SYS_linux_utimes 271 +#define LINUX32_SYS_linux_fadvise64_64 272 +#define LINUX32_SYS_linux_mbind 274 +#define LINUX32_SYS_linux_get_mempolicy 275 +#define LINUX32_SYS_linux_set_mempolicy 276 +#define LINUX32_SYS_linux_mq_open 277 +#define LINUX32_SYS_linux_mq_unlink 278 +#define LINUX32_SYS_linux_mq_timedsend 279 +#define LINUX32_SYS_linux_mq_timedreceive 280 +#define LINUX32_SYS_linux_mq_notify 281 +#define LINUX32_SYS_linux_mq_getsetattr 282 +#define LINUX32_SYS_linux_kexec_load 283 +#define LINUX32_SYS_linux_waitid 284 +#define LINUX32_SYS_linux_add_key 286 +#define LINUX32_SYS_linux_request_key 287 +#define LINUX32_SYS_linux_keyctl 288 +#define LINUX32_SYS_linux_ioprio_set 289 +#define LINUX32_SYS_linux_ioprio_get 290 +#define LINUX32_SYS_linux_inotify_init 291 +#define LINUX32_SYS_linux_inotify_add_watch 292 +#define LINUX32_SYS_linux_inotify_rm_watch 293 +#define LINUX32_SYS_linux_migrate_pages 294 +#define LINUX32_SYS_linux_openat 295 +#define LINUX32_SYS_linux_mkdirat 296 +#define LINUX32_SYS_linux_mknodat 297 +#define LINUX32_SYS_linux_fchownat 298 +#define LINUX32_SYS_linux_futimesat 299 +#define LINUX32_SYS_linux_fstatat64 300 +#define LINUX32_SYS_linux_unlinkat 301 +#define LINUX32_SYS_linux_renameat 302 +#define LINUX32_SYS_linux_linkat 303 +#define LINUX32_SYS_linux_symlinkat 304 +#define LINUX32_SYS_linux_readlinkat 305 +#define LINUX32_SYS_linux_fchmodat 306 +#define LINUX32_SYS_linux_faccessat 307 +#define LINUX32_SYS_linux_pselect6 308 +#define LINUX32_SYS_linux_ppoll 309 +#define LINUX32_SYS_linux_unshare 310 +#define LINUX32_SYS_linux_set_robust_list 311 +#define LINUX32_SYS_linux_get_robust_list 312 +#define LINUX32_SYS_linux_splice 313 +#define LINUX32_SYS_linux_sync_file_range 314 +#define LINUX32_SYS_linux_tee 315 +#define LINUX32_SYS_linux_vmsplice 316 +#define LINUX32_SYS_linux_move_pages 317 +#define LINUX32_SYS_linux_getcpu 318 +#define LINUX32_SYS_linux_epoll_pwait 319 +#define LINUX32_SYS_linux_utimensat 320 +#define LINUX32_SYS_linux_signalfd 321 +#define LINUX32_SYS_linux_timerfd_create 322 +#define LINUX32_SYS_linux_eventfd 323 +#define LINUX32_SYS_linux_fallocate 324 +#define LINUX32_SYS_linux_timerfd_settime 325 +#define LINUX32_SYS_linux_timerfd_gettime 326 +#define LINUX32_SYS_linux_signalfd4 327 +#define LINUX32_SYS_linux_eventfd2 328 +#define LINUX32_SYS_linux_epoll_create1 329 +#define LINUX32_SYS_linux_dup3 330 +#define LINUX32_SYS_linux_pipe2 331 +#define LINUX32_SYS_linux_inotify_init1 332 +#define LINUX32_SYS_linux_preadv 333 +#define LINUX32_SYS_linux_pwritev 334 +#define LINUX32_SYS_linux_rt_tsigqueueinfo 335 +#define LINUX32_SYS_linux_perf_event_open 336 +#define LINUX32_SYS_linux_recvmmsg 337 +#define LINUX32_SYS_linux_fanotify_init 338 +#define LINUX32_SYS_linux_fanotify_mark 339 +#define LINUX32_SYS_linux_prlimit64 340 +#define LINUX32_SYS_linux_name_to_handle_at 341 +#define LINUX32_SYS_linux_open_by_handle_at 342 +#define LINUX32_SYS_linux_clock_adjtime 343 +#define LINUX32_SYS_linux_syncfs 344 +#define LINUX32_SYS_linux_sendmmsg 345 +#define LINUX32_SYS_linux_setns 346 +#define LINUX32_SYS_linux_process_vm_readv 347 +#define LINUX32_SYS_linux_process_vm_writev 348 +#define LINUX32_SYS_MAXSYSCALL 350 diff --git a/sys/amd64/linux32/linux32_syscalls.c b/sys/amd64/linux32/linux32_syscalls.c index 6d81d6b..8e7585a 100644 --- a/sys/amd64/linux32/linux32_syscalls.c +++ b/sys/amd64/linux32/linux32_syscalls.c @@ -3,10 +3,10 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ -const char *linux_syscallnames[] = { +const char *linux32_syscallnames[] = { #define nosys linux_nosys "#0", /* 0 = setup */ "linux_exit", /* 1 = linux_exit */ diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c index a4d3075..f254a86 100644 --- a/sys/amd64/linux32/linux32_sysent.c +++ b/sys/amd64/linux32/linux32_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin + * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb */ #include "opt_compat.h" @@ -17,7 +17,7 @@ #define AS(name) (sizeof(struct name) / sizeof(register_t)) /* The casts are bogus but will do for now. */ -struct sysent linux_sysent[] = { +struct sysent linux32_sysent[] = { #define nosys linux_nosys { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 0 = setup */ { AS(linux_exit_args), (sy_call_t *)linux_exit, AUE_EXIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 1 = linux_exit */ diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 250e16b..73949d9 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -105,8 +105,8 @@ MODULE_VERSION(linux, 1); * to syscall 0. This is slightly less bogus than using * ldebug(sigreturn). */ -#define LINUX_SYS_linux_rt_sendsig 0 -#define LINUX_SYS_linux_sendsig 0 +#define LINUX32_SYS_linux_rt_sendsig 0 +#define LINUX32_SYS_linux_sendsig 0 const char *linux_kplatform; static int linux_szsigcode; @@ -115,7 +115,7 @@ static char *linux_shared_page_mapping; extern char _binary_linux32_locore_o_start; extern char _binary_linux32_locore_o_end; -extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; +extern struct sysent linux32_sysent[LINUX32_SYS_MAXSYSCALL]; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); @@ -1008,8 +1008,8 @@ linux32_fixlimit(struct rlimit *rl, int which) } struct sysentvec elf_linux_sysvec = { - .sv_size = LINUX_SYS_MAXSYSCALL, - .sv_table = linux_sysent, + .sv_size = LINUX32_SYS_MAXSYSCALL, + .sv_table = linux32_sysent, .sv_mask = 0, .sv_sigsize = 0, .sv_sigtbl = NULL, @@ -1043,6 +1043,7 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; static void diff --git a/sys/amd64/linux32/syscalls.conf b/sys/amd64/linux32/syscalls.conf index dc0ad82..7d096b5 100644 --- a/sys/amd64/linux32/syscalls.conf +++ b/sys/amd64/linux32/syscalls.conf @@ -1,11 +1,11 @@ # $FreeBSD$ sysnames="linux32_syscalls.c" sysproto="linux32_proto.h" -sysproto_h=_LINUX_SYSPROTO_H_ +sysproto_h=_LINUX32_SYSPROTO_H_ syshdr="linux32_syscall.h" syssw="linux32_sysent.c" sysmk="/dev/null" -syscallprefix="LINUX_SYS_" -switchname="linux_sysent" -namesname="linux_syscallnames" +syscallprefix="LINUX32_SYS_" +switchname="linux32_sysent" +namesname="linux32_syscallnames" systrace="linux32_systrace_args.c" diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master index 6e09c5a..0396b30 100644 --- a/sys/amd64/linux32/syscalls.master +++ b/sys/amd64/linux32/syscalls.master @@ -2,7 +2,7 @@ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 ; System call name/number master file (or rather, slave, from LINUX). -; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h. +; Processed to create linux32_sysent.c, linux32_proto.h and linux32_syscall.h. ; Columns: number audit type nargs name alt{name,tag,rtyp}/comments ; number system call number, must be in order diff --git a/sys/arm/arm/bcopyinout.S b/sys/arm/arm/bcopyinout.S index 3624f92..0a12e45 100644 --- a/sys/arm/arm/bcopyinout.S +++ b/sys/arm/arm/bcopyinout.S @@ -38,6 +38,7 @@ #include "assym.s" +#include <machine/acle-compat.h> #include <machine/asm.h> #include <sys/errno.h> @@ -54,7 +55,7 @@ __FBSDID("$FreeBSD$"); .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/bcopyinout_xscale.S b/sys/arm/arm/bcopyinout_xscale.S index 487737e..b4204f6 100644 --- a/sys/arm/arm/bcopyinout_xscale.S +++ b/sys/arm/arm/bcopyinout_xscale.S @@ -38,11 +38,13 @@ #include <machine/asm.h> __FBSDID("$FreeBSD$"); +#include <machine/acle-compat.h> + .syntax unified .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index d24f2d2..c130731 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -786,10 +786,9 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) ba = coherent_allocator; else ba = standard_allocator; - uma_zfree(dmamap_zone, map); free(map->slist, M_DEVBUF); - /* Be careful not to access map from here on. */ + uma_zfree(dmamap_zone, map); bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize); diff --git a/sys/arm/arm/copystr.S b/sys/arm/arm/copystr.S index 57c9e70..89b1708 100644 --- a/sys/arm/arm/copystr.S +++ b/sys/arm/arm/copystr.S @@ -40,6 +40,7 @@ #include "assym.s" +#include <machine/acle-compat.h> #include <machine/asm.h> #include <machine/armreg.h> __FBSDID("$FreeBSD$"); @@ -49,7 +50,7 @@ __FBSDID("$FreeBSD$"); .text .align 2 -#ifdef _ARM_ARCH_6 +#if __ARM_ARCH >= 6 #define GET_PCB(tmp) \ mrc p15, 0, tmp, c13, c0, 4; \ add tmp, tmp, #(TD_PCB) diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 8472858..55d4a41 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -80,6 +80,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf32_Brandinfo freebsd_brand_info = { diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S index dec49ed..7bc3a98 100644 --- a/sys/arm/arm/fusu.S +++ b/sys/arm/arm/fusu.S @@ -131,8 +131,8 @@ EENTRY_NP(fuword32) str r1, [r2, #PCB_ONFAULT] mov r0, r3 RET -EEND(fuword32) -END(fuword) +EEND(fueword32) +END(fueword) /* * fusword(caddr_t uaddr); diff --git a/sys/arm/arm/locore-v4.S b/sys/arm/arm/locore-v4.S index 6c20b68..c46c0bf 100644 --- a/sys/arm/arm/locore-v4.S +++ b/sys/arm/arm/locore-v4.S @@ -42,20 +42,8 @@ __FBSDID("$FreeBSD$"); -/* - * Sanity check the configuration. - * FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases. - * ARMv4 and ARMv5 make assumptions on where they are loaded. - * - * TODO: Fix the ARMv4/v5 case. - */ -#if (defined(FLASHADDR) || defined(LOADERRAMADDR) || !defined(_ARM_ARCH_6)) && \ - !defined(PHYSADDR) -#error PHYSADDR must be defined for this configuration -#endif - -/* What size should this really be ? It is only used by initarm() */ -#define INIT_ARM_STACK_SIZE (2048 * 4) +/* 2K initial stack is plenty, it is only used by initarm() */ +#define INIT_ARM_STACK_SIZE 2048 #define CPWAIT_BRANCH \ sub pc, pc, #4 @@ -110,13 +98,23 @@ ASENTRY_NP(_start) msr cpsr_c, r7 #if defined (FLASHADDR) && defined(LOADERRAMADDR) +/* + * Sanity check the configuration. + * FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases. + * ARMv4 and ARMv5 make assumptions on where they are loaded. + * TODO: Fix the ARMv4/v5 case. + */ +#ifndef PHYSADDR +#error PHYSADDR must be defined for this configuration +#endif + /* Check if we're running from flash. */ ldr r7, =FLASHADDR /* * If we're running with MMU disabled, test against the * physical address instead. */ - mrc p15, 0, r2, c1, c0, 0 + mrc p15, 0, r2, c1, c0, 0 ands r2, r2, #CPU_CONTROL_MMU_ENABLE ldreq r6, =PHYSADDR ldrne r6, =LOADERRAMADDR @@ -125,7 +123,7 @@ ASENTRY_NP(_start) cmp r7, pc bhi from_ram b do_copy - + flash_lower: cmp r6, pc bls from_ram @@ -148,12 +146,12 @@ from_ram: disable_mmu: /* Disable MMU for a while */ - mrc p15, 0, r2, c1, c0, 0 + mrc p15, 0, r2, c1, c0, 0 bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ CPU_CONTROL_WBUF_ENABLE) bic r2, r2, #(CPU_CONTROL_IC_ENABLE) bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) - mcr p15, 0, r2, c1, c0, 0 + mcr p15, 0, r2, c1, c0, 0 nop nop @@ -165,85 +163,57 @@ Lunmapped: * Build page table from scratch. */ - /* Find the delta between VA and PA */ + /* + * 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 -#ifndef _ARM_ARCH_6 - /* - * Some of the older ports (the various XScale, mostly) assume - * that the memory before the kernel is mapped, and use it for - * the various stacks, page tables, etc. For those CPUs, map the - * 64 first MB of RAM, as it used to be. + /* + * 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. */ - /* - * Map PA == VA - */ - ldr r5, =PHYSADDR - mov r1, r5 - mov r2, r5 - /* Map 64MiB, preserved over calls to build_pagetables */ - mov r3, #64 - bl build_pagetables - - /* Create the kernel map to jump to */ - mov r1, r5 - ldr r2, =(KERNBASE) - bl build_pagetables - ldr r5, =(KERNPHYSADDR) -#else - /* - * Map PA == VA - */ - /* Find the start kernels load address */ - adr r5, _start - ldr r2, =(L1_S_OFFSET) - bic r5, r2 - mov r1, r5 - mov r2, r5 - /* Map 64MiB, preserved over calls to build_pagetables */ - mov r3, #64 + mov r1, #0 + mov r2, #0 + mov r3, #4096 bl build_pagetables - /* Create the kernel map to jump to */ + /* + * Next we do 64MiB starting at the physical load address, mapped to + * the VA the kernel is linked for. + */ mov r1, r5 ldr r2, =(KERNVIRTADDR) + mov r3, #64 bl build_pagetables -#endif - + + /* Create a device mapping for early_printf if specified. */ #if defined(SOCDEV_PA) && defined(SOCDEV_VA) - /* Create the custom map */ ldr r1, =SOCDEV_PA ldr r2, =SOCDEV_VA - bl build_pagetables + mov r3, #1 + bl build_device_pagetables #endif -#if defined(SMP) - orr r0, r0, #2 /* Set TTB shared memory flag */ -#endif mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ -#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) - mov r0, #0 - mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ -#endif - /* Set the Domain Access register. Very important! */ - mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) + mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) mcr p15, 0, r0, c3, c0, 0 - /* + /* * Enable MMU. - * On armv6 enable extended page tables, and set alignment checking - * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd - * instructions emitted by clang. */ mrc p15, 0, r0, c1, c0, 0 -#ifdef _ARM_ARCH_6 - orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE) - orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE) - orr r0, r0, #(CPU_CONTROL_AF_ENABLE) -#endif orr r0, r0, #(CPU_CONTROL_MMU_ENABLE) mcr p15, 0, r0, c1, c0, 0 nop @@ -251,6 +221,9 @@ Lunmapped: nop CPWAIT(r0) + /* Transition the PC from physical to virtual addressing. */ + ldr pc,=mmu_done + mmu_done: nop adr r1, .Lstart @@ -261,7 +234,6 @@ mmu_done: str r3, [r1], #0x0004 /* get zero init data */ subs r2, r2, #4 bgt .L1 - ldr pc, .Lvirt_done virt_done: mov r1, #28 /* loader info size is 28 bytes also second arg */ @@ -283,7 +255,7 @@ virt_done: /* init arm will return the new stack pointer. */ mov sp, r0 - bl _C_LABEL(mi_startup) /* call mi_startup()! */ + bl _C_LABEL(mi_startup) /* call mi_startup()! */ adr r0, .Lmainreturned b _C_LABEL(panic) @@ -335,24 +307,25 @@ translate_va_to_pa: * * Addresses must be 1MiB aligned */ +build_device_pagetables: + ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)) + b 1f build_pagetables: /* Set the required page attributed */ ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) -#if defined(SMP) - orr r4, #(L1_SHARED) -#endif +1: orr r1, r4 /* Move the virtual address to the correct bit location */ lsr r2, #(L1_S_SHIFT - 2) mov r4, r3 -1: +2: str r1, [r0, r2] add r2, r2, #4 add r1, r1, #(L1_S_SIZE) adds r4, r4, #-1 - bhi 1b + bhi 2b RET @@ -394,98 +367,12 @@ pagetable: .Lcpufuncs: .word _C_LABEL(cpufuncs) -#if defined(SMP) - -.Lmpvirt_done: - .word mpvirt_done -VA_TO_PA_POINTER(Lstartup_pagetable_secondary, temp_pagetable) - -ASENTRY_NP(mpentry) - - /* Make sure interrupts are disabled. */ - mrs r7, cpsr - orr r7, r7, #(PSR_I | PSR_F) - msr cpsr_c, r7 - - /* Disable MMU. It should be disabled already, but make sure. */ - mrc p15, 0, r2, c1, c0, 0 - bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ - CPU_CONTROL_WBUF_ENABLE) - bic r2, r2, #(CPU_CONTROL_IC_ENABLE) - bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) - mcr p15, 0, r2, c1, c0, 0 - nop - nop - nop - CPWAIT(r0) - -#if ARM_MMU_V6 - bl armv6_idcache_inv_all /* Modifies r0 only */ -#elif ARM_MMU_V7 - bl armv7_idcache_inv_all /* Modifies r0-r3, ip */ -#endif - - /* Load the page table physical address */ - adr r0, Lstartup_pagetable_secondary - bl translate_va_to_pa - /* Load the address the secondary page table */ - ldr r0, [r0] - - orr r0, r0, #2 /* Set TTB shared memory flag */ - mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ - mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ - - mov r0, #0 - mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */ - - /* Set the Domain Access register. Very important! */ - mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) - mcr p15, 0, r0, c3, c0, 0 - /* Enable MMU */ - mrc p15, 0, r0, c1, c0, 0 - orr r0, r0, #CPU_CONTROL_V6_EXTPAGE - orr r0, r0, #CPU_CONTROL_AF_ENABLE - orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ - CPU_CONTROL_WBUF_ENABLE) - orr r0, r0, #(CPU_CONTROL_IC_ENABLE) - orr r0, r0, #(CPU_CONTROL_BPRD_ENABLE) - mcr p15, 0, r0, c1, c0, 0 - nop - nop - nop - CPWAIT(r0) - - adr r1, .Lstart - ldmia r1, {r1, r2, sp} /* Set initial stack and */ - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - mov r1, #2048 - mul r2, r1, r0 - sub sp, sp, r2 - str r1, [sp] - ldr pc, .Lmpvirt_done - -mpvirt_done: - - mov fp, #0 /* trace back starts here */ - bl _C_LABEL(init_secondary) /* Off we go */ - - adr r0, .Lmpreturned - b _C_LABEL(panic) - /* NOTREACHED */ - -.Lmpreturned: - .asciz "init_secondary() returned" - .align 2 -END(mpentry) -#endif - ENTRY_NP(cpu_halt) - mrs r2, cpsr + mrs r2, cpsr bic r2, r2, #(PSR_MODE) - orr r2, r2, #(PSR_SVC32_MODE) + orr r2, r2, #(PSR_SVC32_MODE) orr r2, r2, #(PSR_I | PSR_F) - msr cpsr_fsxc, r2 + msr cpsr_fsxc, r2 ldr r4, .Lcpu_reset_address ldr r4, [r4] @@ -511,9 +398,9 @@ ENTRY_NP(cpu_halt) * Hurl ourselves into the ROM */ mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) - mcr p15, 0, r0, c1, c0, 0 - mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ - mov pc, r4 + mcr p15, 0, r0, c1, c0, 0 + mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ + mov pc, r4 /* * _cpu_reset_address contains the address to branch to, to complete @@ -550,7 +437,7 @@ ENTRY(longjmp) END(longjmp) .data - .global _C_LABEL(esym) + .global _C_LABEL(esym) _C_LABEL(esym): .word _C_LABEL(end) ENTRY_NP(abort) @@ -563,7 +450,7 @@ ENTRY_NP(sigcode) /* * Call the sigreturn system call. - * + * * We have to load r7 manually rather than using * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is * correct. Using the alternative places esigcode at the address diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index 55b4311..510af6c 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); -#ifndef ARM_NEW_PMAP +#ifndef ARM_NEW_PMAP #define PTE1_OFFSET L1_S_OFFSET #define PTE1_SHIFT L1_S_SHIFT #define PTE1_SIZE L1_S_SIZE @@ -52,13 +52,13 @@ __FBSDID("$FreeBSD$"); .align 2 /* - * On entry for FreeBSD boot ABI: - * r0 - metadata pointer or 0 (boothowto on AT91's boot2) - * r1 - if (r0 == 0) then metadata pointer - * On entry for Linux boot ABI: + * On entry for FreeBSD boot ABI: + * r0 - metadata pointer or 0 (boothowto on AT91's boot2) + * r1 - if (r0 == 0) then metadata pointer + * On entry for Linux boot ABI: * r0 - 0 * r1 - machine type (passed as arg2 to initarm) - * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) + * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) * * For both types of boot we gather up the args, put them in a struct arm_boot_params * structure and pass that to initarm. @@ -66,17 +66,17 @@ __FBSDID("$FreeBSD$"); .globl btext btext: ASENTRY_NP(_start) - STOP_UNWINDING /* Can't unwind into the bootloader! */ + STOP_UNWINDING /* Can't unwind into the bootloader! */ - /* Make sure interrupts are disabled. */ + /* Make sure interrupts are disabled. */ cpsid ifa - mov r8, r0 /* 0 or boot mode from boot2 */ - mov r9, r1 /* Save Machine type */ - mov r10, r2 /* Save meta data */ + mov r8, r0 /* 0 or boot mode from boot2 */ + mov r9, r1 /* Save Machine type */ + mov r10, r2 /* Save meta data */ mov r11, r3 /* Future expansion */ - /* + /* * Check whether data cache is enabled. If it is, then we know * current tags are valid (not power-on garbage values) and there * might be dirty lines that need cleaning. Disable cache to prevent @@ -93,7 +93,7 @@ ASENTRY_NP(_start) * valid. Disable all caches and the MMU, and invalidate everything * before setting up new page tables and re-enabling the mmu. */ -1: +1: bic r7, #CPU_CONTROL_DC_ENABLE bic r7, #CPU_CONTROL_MMU_ENABLE bic r7, #CPU_CONTROL_IC_ENABLE @@ -103,80 +103,94 @@ ASENTRY_NP(_start) orr r7, #CPU_CONTROL_AFLT_ENABLE orr r7, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r7) + DSB ISB bl dcache_inv_poc_all mcr CP15_ICIALLU + DSB ISB /* * 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 - /* - * 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. */ - /* 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 */ - mov r3, #64 + mov r1, #0 + mov r2, #0 + mov r3, #4096 bl build_pagetables - /* Create the kernel map to jump to */ + /* + * Next we do 64MiB starting at the physical load address, mapped to + * the VA the kernel is linked for. + */ mov r1, r5 ldr r2, =(KERNVIRTADDR) + mov r3, #64 bl build_pagetables + /* Create a device mapping for early_printf if specified. */ #if defined(SOCDEV_PA) && defined(SOCDEV_VA) - /* Create the custom map used for early_printf(). */ ldr r1, =SOCDEV_PA ldr r2, =SOCDEV_VA - bl build_pagetables + mov r3, #1 + bl build_device_pagetables #endif bl init_mmu - /* Switch to virtual addresses. */ + /* Transition the PC from physical to virtual addressing. */ ldr pc, =1f 1: - /* Setup stack, clear BSS */ + /* Setup stack, clear BSS */ ldr r1, =.Lstart ldmia r1, {r1, r2, sp} /* Set initial stack and */ add sp, sp, #INIT_ARM_STACK_SIZE - sub r2, r2, r1 /* get zero init data */ + sub r2, r2, r1 /* get zero init data */ mov r3, #0 2: str r3, [r1], #0x0004 /* get zero init data */ - subs r2, r2, #4 + subs r2, r2, #4 bgt 2b - mov r1, #28 /* loader info size is 28 bytes also second arg */ - subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ - mov r0, sp /* loader info pointer is first arg */ - bic sp, sp, #7 /* align stack to 8 bytes */ - str r1, [r0] /* Store length of loader info */ + mov r1, #28 /* loader info size is 28 bytes also second arg */ + subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ + mov r0, sp /* loader info pointer is first arg */ + bic sp, sp, #7 /* align stack to 8 bytes */ + str r1, [r0] /* Store length of loader info */ str r8, [r0, #4] /* Store r0 from boot loader */ str r9, [r0, #8] /* Store r1 from boot loader */ str r10, [r0, #12] /* store r2 from boot loader */ str r11, [r0, #16] /* store r3 from boot loader */ str r5, [r0, #20] /* store the physical address */ - adr r4, Lpagetable /* load the pagetable address */ + adr r4, Lpagetable /* load the pagetable address */ ldr r5, [r4, #4] str r5, [r0, #24] /* store the pagetable address */ mov fp, #0 /* trace back starts here */ bl _C_LABEL(initarm) /* Off we go */ - /* init arm will return the new stack pointer. */ + /* init arm will return the new stack pointer. */ mov sp, r0 - bl _C_LABEL(mi_startup) /* call mi_startup()! */ + bl _C_LABEL(mi_startup) /* call mi_startup()! */ ldr r0, =.Lmainreturned b _C_LABEL(panic) @@ -219,8 +233,8 @@ translate_va_to_pa: mov pc, lr /* - * Init MMU - * r0 - The table base address + * Init MMU + * r0 - the table base address */ ASENTRY_NP(init_mmu) @@ -261,17 +275,19 @@ ASENTRY_NP(init_mmu) ISB mcr CP15_TLBIALL /* Flush TLB */ mcr CP15_BPIALL /* Flush Branch predictor */ + DSB ISB + mov pc, lr END(init_mmu) /* - * Init SMP coherent mode, enable caching and switch to final MMU table. - * Called with disabled caches - * r0 - The table base address - * r1 - clear bits for aux register - * r2 - set bits for aux register + * Init SMP coherent mode, enable caching and switch to final MMU table. + * Called with disabled caches + * r0 - The table base address + * r1 - clear bits for aux register + * r2 - set bits for aux register */ ASENTRY_NP(reinit_mmu) push {r4-r11, lr} @@ -289,6 +305,7 @@ ASENTRY_NP(reinit_mmu) bl dcache_inv_pou_all #endif mcr CP15_ICIALLU + DSB ISB /* Set auxiliary register */ @@ -297,6 +314,7 @@ ASENTRY_NP(reinit_mmu) eor r8, r8, r6 /* Set bits */ teq r7, r8 mcrne CP15_ACTLR(r8) + DSB ISB /* Enable caches. */ @@ -311,8 +329,8 @@ ASENTRY_NP(reinit_mmu) DSB ISB - /* Flush all TLBs */ - mcr CP15_TLBIALL + mcr CP15_TLBIALL /* Flush TLB */ + mcr CP15_BPIALL /* Flush Branch predictor */ DSB ISB @@ -323,6 +341,7 @@ ASENTRY_NP(reinit_mmu) bl dcache_inv_pou_all #endif mcr CP15_ICIALLU + DSB ISB pop {r4-r11, pc} @@ -331,14 +350,23 @@ END(reinit_mmu) /* * Builds the page table - * r0 - The table base address - * r1 - The physical address (trashed) - * r2 - The virtual address (trashed) - * r3 - The number of 1MiB sections - * r4 - Trashed + * r0 - The table base address + * r1 - The physical address (trashed) + * r2 - The virtual address (trashed) + * r3 - The number of 1MiB sections + * r4 - Trashed * * 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) @@ -348,18 +376,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 */ + /* 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 + add r2, r2, #4 + add r1, r1, #(PTE1_SIZE) + adds r4, r4, #-1 + bhi 2b mov pc, lr @@ -372,7 +401,7 @@ VA_TO_PA_POINTER(Lpagetable, boot_pt1) .word svcstk /* must remain in order together. */ .Lmainreturned: - .asciz "main() returned" + .asciz "main() returned" .align 2 .bss @@ -380,8 +409,8 @@ svcstk: .space INIT_ARM_STACK_SIZE * MAXCPU /* - * Memory for the initial pagetable. We are unable to place this in - * the bss as this will be cleared after the table is loaded. + * Memory for the initial pagetable. We are unable to place this in + * the bss as this will be cleared after the table is loaded. */ .section ".init_pagetable" .align 14 /* 16KiB aligned */ @@ -398,7 +427,7 @@ boot_pt1: #if defined(SMP) ASENTRY_NP(mpentry) - /* Make sure interrupts are disabled. */ + /* Make sure interrupts are disabled. */ cpsid ifa /* Setup core, disable all caches. */ @@ -412,17 +441,19 @@ ASENTRY_NP(mpentry) orr r0, #CPU_CONTROL_AFLT_ENABLE orr r0, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r0) + DSB ISB /* Invalidate L1 cache I+D cache */ bl dcache_inv_pou_all mcr CP15_ICIALLU + DSB ISB - /* Find the delta between VA and PA */ + /* Find the delta between VA and PA */ adr r0, Lpagetable bl translate_va_to_pa - + bl init_mmu adr r1, .Lstart+8 /* Get initstack pointer from */ @@ -433,7 +464,7 @@ ASENTRY_NP(mpentry) mul r2, r1, r0 /* Point sp to initstack */ add sp, sp, r2 /* area for this processor. */ - /* Switch to virtual addresses. */ + /* Switch to virtual addresses. */ ldr pc, =1f 1: mov fp, #0 /* trace back starts here */ @@ -459,14 +490,14 @@ ENTRY_NP(cpu_halt) ldr r4, [r4] teq r4, #0 movne pc, r4 -1: +1: WFI b 1b /* * _cpu_reset_address contains the address to branch to, to complete * the cpu reset after turning the MMU off - * This variable is provided by the hardware specific code + * This variable is provided by the hardware specific code */ .Lcpu_reset_address: .word _C_LABEL(cpu_reset_address) @@ -498,38 +529,37 @@ END(abort) ENTRY_NP(sigcode) mov r0, sp - add r0, r0, #SIGF_UC + add r0, r0, #SIGF_UC /* - * Call the sigreturn system call. + * Call the sigreturn system call. * * We have to load r7 manually rather than using - * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is + * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is * correct. Using the alternative places esigcode at the address - * of the data rather than the address one past the data. + * of the data rather than the address one past the data. */ - ldr r7, [pc, #12] /* Load SYS_sigreturn */ + ldr r7, [pc, #12] /* Load SYS_sigreturn */ swi SYS_sigreturn - /* Well if that failed we better exit quick ! */ + /* Well if that failed we better exit quick ! */ - ldr r7, [pc, #8] /* Load SYS_exit */ + ldr r7, [pc, #8] /* Load SYS_exit */ swi SYS_exit - /* Branch back to retry SYS_sigreturn */ + /* Branch back to retry SYS_sigreturn */ b . - 16 END(sigcode) - .word SYS_sigreturn .word SYS_exit .align 2 - .global _C_LABEL(esigcode) + .global _C_LABEL(esigcode) _C_LABEL(esigcode): .data - .global szsigcode + .global szsigcode szsigcode: .long esigcode-sigcode diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 66dae32..443cc5b 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -826,13 +826,15 @@ fake_preload_metadata(struct arm_boot_params *abp __unused) fake_preload[i] = 0; preload_metadata = (void *)fake_preload; + init_static_kenv(NULL, 0); + return (lastaddr); } void pcpu0_init(void) { -#if ARM_ARCH_6 || ARM_ARCH_7A || defined(CPU_MV_PJ4B) +#if __ARM_ARCH >= 6 set_curthread(&thread0); #endif pcpu_init(pcpup, 0, sizeof(struct pcpu)); @@ -901,6 +903,8 @@ linux_parse_boot_param(struct arm_boot_params *abp) bcopy(atag_list, atags, (char *)walker - (char *)atag_list + ATAG_SIZE(walker)); + init_static_kenv(NULL, 0); + return fake_preload_metadata(abp); } #endif @@ -929,7 +933,7 @@ freebsd_parse_boot_param(struct arm_boot_params *abp) return 0; boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); - kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0); lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); #ifdef DDB ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); diff --git a/sys/arm/arm/physmem.c b/sys/arm/arm/physmem.c index bc72ce2..8c41fbb 100644 --- a/sys/arm/arm/physmem.c +++ b/sys/arm/arm/physmem.c @@ -161,7 +161,7 @@ static size_t regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail) { size_t acnt, exi, hwi; - vm_paddr_t end, start, xend, xstart; + uint64_t end, start, xend, xstart; long availmem; const struct region *exp, *hwp; @@ -171,7 +171,7 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail) for (hwi = 0, hwp = hwregions; hwi < hwcnt; ++hwi, ++hwp) { start = hwp->addr; end = hwp->size + start; - realmem += arm32_btop(end - start); + realmem += arm32_btop((vm_offset_t)(end - start)); for (exi = 0, exp = exregions; exi < excnt; ++exi, ++exp) { /* * If the excluded region does not match given flags, @@ -212,9 +212,10 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail) * could affect the remainder of this hw region. */ if ((xstart > start) && (xend < end)) { - avail[acnt++] = start; - avail[acnt++] = xstart; - availmem += arm32_btop(xstart - start); + avail[acnt++] = (vm_paddr_t)start; + avail[acnt++] = (vm_paddr_t)xstart; + availmem += + arm32_btop((vm_offset_t)(xstart - start)); start = xend; continue; } @@ -233,9 +234,9 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail) * available entry for it. */ if (end > start) { - avail[acnt++] = start; - avail[acnt++] = end; - availmem += arm32_btop(end - start); + avail[acnt++] = (vm_paddr_t)start; + avail[acnt++] = (vm_paddr_t)end; + availmem += arm32_btop((vm_offset_t)(end - start)); } if (acnt >= MAX_AVAIL_ENTRIES) panic("Not enough space in the dump/phys_avail arrays"); @@ -279,10 +280,22 @@ arm_physmem_hardware_region(vm_paddr_t pa, vm_size_t sz) /* * Filter out the page at PA 0x00000000. The VM can't handle it, as * pmap_extract() == 0 means failure. + * + * Also filter out the page at the end of the physical address space -- + * if addr is non-zero and addr+size is zero we wrapped to the next byte + * beyond what vm_paddr_t can express. That leads to a NULL pointer + * deref early in startup; work around it by leaving the last page out. + * + * XXX This just in: subtract out a whole megabyte, not just 1 page. + * Reducing the size by anything less than 1MB results in the NULL + * pointer deref in _vm_map_lock_read(). Better to give up a megabyte + * than leave some folks with an unusable system while we investigate. */ if (pa == 0) { pa = PAGE_SIZE; sz -= PAGE_SIZE; + } else if (pa + sz == 0) { + sz -= 1024 * 1024; } /* diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index 82d2f0f..726b718 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_map.h> #include <vm/vm_extern.h> +#include <machine/acle-compat.h> #include <machine/cpu.h> #include <machine/frame.h> #include <machine/machdep.h> @@ -322,7 +323,7 @@ abort_handler(struct trapframe *tf, int type) * location, so we can deal with those quickly. Otherwise we need to * disassemble the faulting instruction to determine if it was a write. */ -#if ARM_ARCH_6 || ARM_ARCH_7A +#if __ARM_ARCH >= 6 ftype = (fsr & FAULT_WNR) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ; #else if (IS_PERMISSION_FAULT(fsr)) diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index 5d58228..a506715 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -446,6 +446,9 @@ at91_mci_attach(device_t dev) CTLFLAG_RW, &sc->allow_overclock, 0, "Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less."); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", + CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output"); + /* * Our real min freq is master_clock/512, but upper driver layers are * going to set the min speed during card discovery, and the right speed @@ -783,15 +786,6 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); } else { len = min(BBSIZE, remaining); - /* - * If this is MCI1 revision 2xx controller, apply - * a work-around for the "Data Write Operation and - * number of bytes" erratum. - */ - if ((sc->sc_cap & CAP_MCI1_REV2XX) && len < 12) { - len = 12; - memset(sc->bbuf_vaddr[0], 0, 12); - } at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len); err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0], sc->bbuf_vaddr[0], len, at91_mci_getaddr, @@ -800,8 +794,13 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) panic("IO write dmamap_load failed\n"); bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0], BUS_DMASYNC_PREWRITE); + /* + * Erratum workaround: PDC transfer length on a write + * must not be smaller than 12 bytes (3 words); only + * blklen bytes (set above) are actually transferred. + */ WR4(sc, PDC_TPR,paddr); - WR4(sc, PDC_TCR, len / 4); + WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4); sc->bbuf_len[0] = len; remaining -= len; if (remaining == 0) { @@ -818,7 +817,7 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd) bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1], BUS_DMASYNC_PREWRITE); WR4(sc, PDC_TNPR, paddr); - WR4(sc, PDC_TNCR, len / 4); + WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4); sc->bbuf_len[1] = len; remaining -= len; } diff --git a/sys/arm/freescale/imx/imx6_anatop.c b/sys/arm/freescale/imx/imx6_anatop.c index e7abb9e..d38d432 100644 --- a/sys/arm/freescale/imx/imx6_anatop.c +++ b/sys/arm/freescale/imx/imx6_anatop.c @@ -73,11 +73,10 @@ __FBSDID("$FreeBSD$"); #include <arm/freescale/fsl_ocotpreg.h> #include <arm/freescale/fsl_ocotpvar.h> #include <arm/freescale/imx/imx_ccmvar.h> +#include <arm/freescale/imx/imx_machdep.h> #include <arm/freescale/imx/imx6_anatopreg.h> #include <arm/freescale/imx/imx6_anatopvar.h> -static SYSCTL_NODE(_hw, OID_AUTO, imx6, CTLFLAG_RW, NULL, "i.MX6 container"); - static struct resource_spec imx6_anatop_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE }, @@ -396,23 +395,23 @@ cpufreq_initialize(struct imx6_anatop_softc *sc) uint32_t cfg3speed; struct oppt * op; - SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0, "CPU frequency"); - SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "cpu_minmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, cpufreq_sysctl_minmhz, "IU", "Minimum CPU frequency"); - SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "cpu_maxmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, cpufreq_sysctl_maxmhz, "IU", "Maximum CPU frequency"); - SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "cpu_maxmhz_hw", CTLFLAG_RD, &sc->cpu_maxmhz_hw, 0, "Maximum CPU frequency allowed by hardware"); - SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "cpu_overclock_enable", CTLFLAG_RWTUN, &sc->cpu_overclock_enable, 0, "Allow setting CPU frequency higher than cpu_maxmhz_hw"); @@ -630,10 +629,10 @@ initialize_tempmon(struct imx6_anatop_softc *sc) callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay, 0, tempmon_throttle_check, sc, 0); - SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0, temp_sysctl_handler, "IK", "Current die temperature"); - SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx), OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc, 0, temp_throttle_sysctl_handler, "IK", "Throttle CPU when exceeding this temperature"); diff --git a/sys/arm/freescale/imx/imx6_machdep.c b/sys/arm/freescale/imx/imx6_machdep.c index 2335f7d..a5539ea 100644 --- a/sys/arm/freescale/imx/imx6_machdep.c +++ b/sys/arm/freescale/imx/imx6_machdep.c @@ -99,7 +99,6 @@ initarm_lastaddr(void) void initarm_early_init(void) { - /* Inform the MPCore timer driver that its clock is variable. */ arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES); } @@ -113,6 +112,9 @@ initarm_gpio_init(void) void initarm_late_init(void) { + const uint32_t IMX6_WDOG_SR_PHYS = 0x020bc004; + + imx_wdog_init_last_reset(IMX6_WDOG_SR_PHYS); /* Cache the gpio1 node handle for imx6_decode_fdt() workaround code. */ gpio1_node = OF_node_from_xref( diff --git a/sys/arm/freescale/imx/imx_machdep.c b/sys/arm/freescale/imx/imx_machdep.c index 3618637..002651a 100644 --- a/sys/arm/freescale/imx/imx_machdep.c +++ b/sys/arm/freescale/imx/imx_machdep.c @@ -45,6 +45,15 @@ __FBSDID("$FreeBSD$"); #include <arm/freescale/imx/imx_machdep.h> #include <arm/freescale/imx/imx_wdogreg.h> +SYSCTL_NODE(_hw, OID_AUTO, imx, CTLFLAG_RW, NULL, "i.MX container"); + +static int last_reset_status; +SYSCTL_UINT(_hw_imx, OID_AUTO, last_reset_status, CTLFLAG_RD, + &last_reset_status, 0, "Last reset status register"); + +SYSCTL_STRING(_hw_imx, OID_AUTO, last_reset_reason, CTLFLAG_RD, + "unknown", 0, "Last reset reason"); + struct arm32_dma_range * bus_dma_get_range(void) { @@ -72,21 +81,36 @@ imx_wdog_cpu_reset(vm_offset_t wdcr_physaddr) volatile uint16_t * pcr; /* - * The deceptively simple write of WDOG_CR_WDE enables the watchdog, - * sets the timeout to its minimum value (half a second), and also - * clears the SRS bit which results in the SFTW (software-requested - * reset) bit being set in the watchdog status register after the reset. - * This is how software can distinguish a reset from a wdog timeout. + * Trigger an immediate reset by clearing the SRS bit in the watchdog + * control register. The reset happens on the next cycle of the wdog + * 32KHz clock, so hang out in a spin loop until the reset takes effect. */ if ((pcr = arm_devmap_ptov(wdcr_physaddr, sizeof(*pcr))) == NULL) { printf("cpu_reset() can't find its control register... locking up now."); } else { - *pcr = WDOG_CR_WDE; + *pcr &= ~WDOG_CR_SRS; } for (;;) continue; } +void +imx_wdog_init_last_reset(vm_offset_t wdsr_phys) +{ + volatile uint16_t * psr; + + if ((psr = arm_devmap_ptov(wdsr_phys, sizeof(*psr))) == NULL) + return; + last_reset_status = *psr; + if (last_reset_status & WDOG_RSR_SFTW) { + sysctl___hw_imx_last_reset_reason.oid_arg1 = "SoftwareReset"; + } else if (last_reset_status & WDOG_RSR_TOUT) { + sysctl___hw_imx_last_reset_reason.oid_arg1 = "WatchdogTimeout"; + } else if (last_reset_status & WDOG_RSR_POR) { + sysctl___hw_imx_last_reset_reason.oid_arg1 = "PowerOnReset"; + } +} + u_int imx_soc_family(void) { diff --git a/sys/arm/freescale/imx/imx_machdep.h b/sys/arm/freescale/imx/imx_machdep.h index 6909e51..2bb8bb3 100644 --- a/sys/arm/freescale/imx/imx_machdep.h +++ b/sys/arm/freescale/imx/imx_machdep.h @@ -30,10 +30,14 @@ #define IMX_MACHDEP_H #include <sys/types.h> +#include <sys/sysctl.h> + +SYSCTL_DECL(_hw_imx); /* Common functions, implemented in imx_machdep.c. */ void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__)); +void imx_wdog_init_last_reset(vm_offset_t _wdsr_phys); /* From here down, routines are implemented in imxNN_machdep.c. */ diff --git a/sys/arm/freescale/imx/imx_sdhci.c b/sys/arm/freescale/imx/imx_sdhci.c index 7d982c5..98d5e23 100644 --- a/sys/arm/freescale/imx/imx_sdhci.c +++ b/sys/arm/freescale/imx/imx_sdhci.c @@ -429,6 +429,7 @@ imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_ } else { imx_sdhc_set_clock(sc, false); } + return; } /* @@ -522,12 +523,19 @@ imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable) else freq = sc->baseclk_hz / (2 * divisor); - for (prescale = 2; prescale < freq / prescale / 16;) + for (prescale = 2; freq < sc->baseclk_hz / (prescale * 16);) prescale <<= 1; - for (divisor = 1; freq < freq / prescale / divisor;) + for (divisor = 1; freq < sc->baseclk_hz / (prescale * divisor);) ++divisor; +#ifdef DEBUG + device_printf(sc->dev, + "desired SD freq: %d, actual: %d; base %d prescale %d divisor %d\n", + freq, sc->baseclk_hz / (prescale * divisor), sc->baseclk_hz, + prescale, divisor); +#endif + prescale >>= 1; divisor -= 1; diff --git a/sys/arm/freescale/imx/imx_wdogreg.h b/sys/arm/freescale/imx/imx_wdogreg.h index 1bff106..030cee8 100644 --- a/sys/arm/freescale/imx/imx_wdogreg.h +++ b/sys/arm/freescale/imx/imx_wdogreg.h @@ -47,6 +47,7 @@ #define WDOG_SR_STEP2 0xaaaa #define WDOG_RSR_REG 0x04 /* Reset Status Register */ +#define WDOG_RSR_POR (1 << 4) /* Due to Power-On Reset */ #define WDOG_RSR_TOUT (1 << 1) /* Due WDog timeout reset */ #define WDOG_RSR_SFTW (1 << 0) /* Due Soft reset */ diff --git a/sys/arm/mv/std-pj4b.mv b/sys/arm/mv/std-pj4b.mv index 1053ff0..cc14abc 100644 --- a/sys/arm/mv/std-pj4b.mv +++ b/sys/arm/mv/std-pj4b.mv @@ -5,4 +5,8 @@ cpu CPU_MV_PJ4B machine arm armv6 makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" -options VM_MAXUSER_ADDRESS="(KERNBASE-(1024*1024*1024))" +# This was originally defined as "(KERNBASE-(1024*1024*1024))" but that +# (in opt_global.h) clashed with the value emitted by genassym which +# reduces the original macro text to its numeric value. The only way +# to avoid that is to define it here as the numeric value genassym emits. +options VM_MAXUSER_ADDRESS="0x80000000" diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index b1d6734..e72798a 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -223,8 +223,8 @@ initarm(struct arm_boot_params *abp) pcpu_init(pcpup, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); - if (envmode == 1) - kern_envp = static_env; + init_static_kenv(NULL, 0); + /* Do basic tuning, hz etc */ init_param1(); @@ -420,10 +420,6 @@ initarm(struct arm_boot_params *abp) init_param2(physmem); kdb_init(); - /* use static kernel environment if so configured */ - if (envmode == 1) - kern_envp = static_env; - return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - sizeof(struct pcb))); #undef next_page diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index c9bcc52..de77c7b 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -231,9 +231,9 @@ int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]); int mod_loadkld(const char *name, int argc, char *argv[]); struct preloaded_file *file_alloc(void); -struct preloaded_file *file_findfile(char *name, char *type); +struct preloaded_file *file_findfile(const char *name, const char *type); struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); -struct preloaded_file *file_loadraw(char *name, char *type); +struct preloaded_file *file_loadraw(char *name, char *type, int insert); void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, @@ -257,6 +257,9 @@ int __elfN(obj_loadfile)(char *filename, u_int64_t dest, int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, int reltype, Elf_Addr relbase, Elf_Addr dataaddr, void *data, size_t len); +int __elfN(loadfile_raw)(char *filename, u_int64_t dest, + struct preloaded_file **result, int multiboot); +int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest); #endif /* diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index edbad05..200a29c 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -76,7 +76,8 @@ static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len); -static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef); +static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef, + Elf_Addr p_start, Elf_Addr p_end); static symaddr_fn __elfN(symaddr); static char *fake_modname(const char *name); @@ -85,6 +86,61 @@ const char *__elfN(moduletype) = "elf module"; u_int64_t __elfN(relocation_offset) = 0; +static int +__elfN(load_elf_header)(char *filename, elf_file_t ef) +{ + ssize_t bytes_read; + Elf_Ehdr *ehdr; + int err; + + /* + * Open the image, read and validate the ELF header + */ + if (filename == NULL) /* can't handle nameless */ + return (EFTYPE); + if ((ef->fd = open(filename, O_RDONLY)) == -1) + return (errno); + ef->firstpage = malloc(PAGE_SIZE); + if (ef->firstpage == NULL) { + close(ef->fd); + return (ENOMEM); + } + bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE); + ef->firstlen = (size_t)bytes_read; + if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) { + err = EFTYPE; /* could be EIO, but may be small file */ + goto error; + } + ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage; + + /* Is it ELF? */ + if (!IS_ELF(*ehdr)) { + err = EFTYPE; + goto error; + } + if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ + ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ + ehdr->e_version != EV_CURRENT || + ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ + err = EFTYPE; + goto error; + } + + return (0); + +error: + if (ef->firstpage != NULL) { + free(ef->firstpage); + ef->firstpage = NULL; + } + if (ef->fd != -1) { + close(ef->fd); + ef->fd = -1; + } + return (err); +} + /* * Attempt to load the file (file) as an ELF module. It will be stored at * (dest), and a pointer to a module structure describing the loaded object @@ -93,54 +149,32 @@ u_int64_t __elfN(relocation_offset) = 0; int __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) { + return (__elfN(loadfile_raw)(filename, dest, result, 0)); +} + +int +__elfN(loadfile_raw)(char *filename, u_int64_t dest, + struct preloaded_file **result, int multiboot) +{ struct preloaded_file *fp, *kfp; struct elf_file ef; Elf_Ehdr *ehdr; int err; - ssize_t bytes_read; fp = NULL; bzero(&ef, sizeof(struct elf_file)); + ef.fd = -1; - /* - * Open the image, read and validate the ELF header - */ - if (filename == NULL) /* can't handle nameless */ - return(EFTYPE); - if ((ef.fd = open(filename, O_RDONLY)) == -1) - return(errno); - ef.firstpage = malloc(PAGE_SIZE); - if (ef.firstpage == NULL) { - close(ef.fd); - return(ENOMEM); - } - bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE); - ef.firstlen = (size_t)bytes_read; - if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) { - err = EFTYPE; /* could be EIO, but may be small file */ - goto oerr; - } - ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage; - - /* Is it ELF? */ - if (!IS_ELF(*ehdr)) { - err = EFTYPE; - goto oerr; - } - if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ - ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || - ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ - ehdr->e_version != EV_CURRENT || - ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ - err = EFTYPE; - goto oerr; - } + err = __elfN(load_elf_header)(filename, &ef); + if (err != 0) + return (err); + ehdr = ef.ehdr; /* * Check to see what sort of module we are. */ - kfp = file_findfile(NULL, NULL); + kfp = file_findfile(NULL, __elfN(kerneltype)); #ifdef __powerpc__ /* * Kernels can be ET_DYN, so just assume the first loaded object is the @@ -177,6 +211,11 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) } else if (ehdr->e_type == ET_DYN) { /* Looks like a kld module */ + if (multiboot != 0) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n"); + err = EPERM; + goto oerr; + } if (kfp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n"); err = EPERM; @@ -209,10 +248,14 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) err = EPERM; goto out; } - if (ef.kernel) + if (ef.kernel == 1 && multiboot == 0) setenv("kernelname", filename, 1); fp->f_name = strdup(filename); - fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype)); + if (multiboot == 0) + fp->f_type = strdup(ef.kernel ? + __elfN(kerneltype) : __elfN(moduletype)); + else + fp->f_type = strdup("elf multiboot kernel"); #ifdef ELF_VERBOSE if (ef.kernel) @@ -240,7 +283,8 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) out: if (ef.firstpage) free(ef.firstpage); - close(ef.fd); + if (ef.fd != -1) + close(ef.fd); return(err); } @@ -269,6 +313,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) int symtabindex; Elf_Size size; u_int fpcopy; + Elf_Sym sym; + Elf_Addr p_start, p_end; dp = NULL; shdr = NULL; @@ -571,7 +617,15 @@ nosyms: COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); ef->buckets = ef->hashtab + 2; ef->chains = ef->buckets + ef->nbuckets; - if (__elfN(parse_modmetadata)(fp, ef) == 0) + + if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) + return 0; + p_start = sym.st_value + ef->off; + if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) + return ENOENT; + p_end = sym.st_value + ef->off; + + if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0) goto out; if (ef->kernel) /* kernel must not depend on anything */ @@ -634,7 +688,123 @@ struct mod_metadata32 { #endif int -__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef) +__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest) +{ + struct elf_file ef; + int err, i, j; + Elf_Shdr *sh_meta, *shdr = NULL; + Elf_Shdr *sh_data[2]; + char *shstrtab = NULL; + size_t size; + Elf_Addr p_start, p_end; + + bzero(&ef, sizeof(struct elf_file)); + ef.fd = -1; + + err = __elfN(load_elf_header)(fp->f_name, &ef); + if (err != 0) + goto out; + + if (ef.ehdr->e_type == ET_EXEC) { + ef.kernel = 1; + } else if (ef.ehdr->e_type != ET_DYN) { + err = EFTYPE; + goto out; + } + + size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize; + shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size); + if (shdr == NULL) { + err = ENOMEM; + goto out; + } + + /* Load shstrtab. */ + shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset, + shdr[ef.ehdr->e_shstrndx].sh_size); + if (shstrtab == NULL) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to load shstrtab\n"); + err = EFTYPE; + goto out; + } + + /* Find set_modmetadata_set and data sections. */ + sh_data[0] = sh_data[1] = sh_meta = NULL; + for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) { + if (strcmp(&shstrtab[shdr[i].sh_name], + "set_modmetadata_set") == 0) { + sh_meta = &shdr[i]; + } + if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) || + (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) { + sh_data[j++] = &shdr[i]; + } + } + if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to find set_modmetadata_set or data sections\n"); + err = EFTYPE; + goto out; + } + + /* Load set_modmetadata_set into memory */ + err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset); + if (err != 0) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to load set_modmetadata_set: %d\n", err); + goto out; + } + p_start = dest; + p_end = dest + sh_meta->sh_size; + dest += sh_meta->sh_size; + + /* Load data sections into memory. */ + err = kern_pread(ef.fd, dest, sh_data[0]->sh_size, + sh_data[0]->sh_offset); + if (err != 0) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to load data: %d\n", err); + goto out; + } + + /* + * We have to increment the dest, so that the offset is the same into + * both the .rodata and .data sections. + */ + ef.off = -(sh_data[0]->sh_addr - dest); + dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr); + + err = kern_pread(ef.fd, dest, sh_data[1]->sh_size, + sh_data[1]->sh_offset); + if (err != 0) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to load data: %d\n", err); + goto out; + } + + err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end); + if (err != 0) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "load_modmetadata: unable to parse metadata: %d\n", err); + goto out; + } + +out: + if (shstrtab != NULL) + free(shstrtab); + if (shdr != NULL) + free(shdr); + if (ef.firstpage != NULL) + free(ef.firstpage); + if (ef.fd != -1) + close(ef.fd); + return (err); +} + +int +__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, + Elf_Addr p_start, Elf_Addr p_end) { struct mod_metadata md; #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 @@ -644,20 +814,13 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef) #endif struct mod_depend *mdepend; struct mod_version mver; - Elf_Sym sym; char *s; int error, modcnt, minfolen; - Elf_Addr v, p, p_stop; - - if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) - return 0; - p = sym.st_value + ef->off; - if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) - return ENOENT; - p_stop = sym.st_value + ef->off; + Elf_Addr v, p; modcnt = 0; - while (p < p_stop) { + p = p_start; + while (p < p_end) { COPYOUT(p, &v, sizeof(v)); error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); if (error == EOPNOTSUPP) diff --git a/sys/boot/common/load_elf_obj.c b/sys/boot/common/load_elf_obj.c index 2c8e184..3d8b02a 100644 --- a/sys/boot/common/load_elf_obj.c +++ b/sys/boot/common/load_elf_obj.c @@ -129,20 +129,13 @@ __elfN(obj_loadfile)(char *filename, u_int64_t dest, goto oerr; } - kfp = file_findfile(NULL, NULL); + kfp = file_findfile(NULL, __elfN(obj_kerneltype)); if (kfp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadfile: can't load module before kernel\n"); err = EPERM; goto oerr; } - if (strcmp(__elfN(obj_kerneltype), kfp->f_type)) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadfile: can't load module with kernel type '%s'\n", - kfp->f_type); - err = EPERM; - goto oerr; - } if (archsw.arch_loadaddr != NULL) dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest); diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index c7d19d1..2af9c20 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -138,7 +138,7 @@ command_load(int argc, char *argv[]) command_errmsg = "invalid load type"; return(CMD_ERROR); } - return(file_loadraw(argv[1], typestr) ? CMD_OK : CMD_ERROR); + return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR); } /* * Do we have explicit KLD load ? @@ -193,7 +193,7 @@ command_load_geli(int argc, char *argv[]) argv += (optind - 1); argc -= (optind - 1); sprintf(typestr, "%s:geli_keyfile%d", argv[1], num); - return(file_loadraw(argv[2], typestr) ? CMD_OK : CMD_ERROR); + return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR); } COMMAND_SET(unload, "unload", "unload all modules", command_unload); @@ -362,7 +362,7 @@ file_load_dependencies(struct preloaded_file *base_file) * no arguments or anything. */ struct preloaded_file * -file_loadraw(char *name, char *type) +file_loadraw(char *name, char *type, int insert) { struct preloaded_file *fp; char *cp; @@ -421,7 +421,8 @@ file_loadraw(char *name, char *type) loadaddr = laddr; /* Add to the list of loaded files */ - file_insert_tail(fp); + if (insert != 0) + file_insert_tail(fp); close(fd); return(fp); } @@ -524,7 +525,7 @@ mod_loadkld(const char *kldname, int argc, char *argv[]) * NULL may be passed as a wildcard to either. */ struct preloaded_file * -file_findfile(char *name, char *type) +file_findfile(const char *name, const char *type) { struct preloaded_file *fp; diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile index ddf3147..8cb6c62 100644 --- a/sys/boot/efi/boot1/Makefile +++ b/sys/boot/efi/boot1/Makefile @@ -9,7 +9,7 @@ MAN= MK_SSP= no -PROG= loader.sym +PROG= boot1.sym INTERNALPROG= # architecture-specific loader code @@ -38,7 +38,7 @@ LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared LDFLAGS+= -Wl,-znocombreloc .endif -${PROG}: ${LDSCRIPT} +DPADD+= ${LDSCRIPT} OBJCOPY?= objcopy OBJDUMP?= objdump @@ -49,19 +49,19 @@ EFI_TARGET= efi-app-x86_64 EFI_TARGET= efi-app-ia32 .endif -boot1.efi: loader.sym +boot1.efi: ${PROG} if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ exit 1; \ fi ${OBJCOPY} -j .text -j .sdata -j .data \ -j .dynamic -j .dynsym -j .rel.dyn \ - -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \ + -j .rela.dyn -j .reloc -j .eh_frame \ --output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET} boot1.o: ${.CURDIR}/../../common/ufsread.c -# The following inserts out objects into a template FAT file system +# The following inserts our objects into a template FAT file system # created by generate-fat.sh .include "${.CURDIR}/Makefile.fat" @@ -73,7 +73,7 @@ boot1.efifat: boot1.efi bzip2 -f -d ${.TARGET}.bz2 dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc -CLEANFILES= boot1.efifat +CLEANFILES= boot1.efi boot1.efifat .endif # ${COMPILER_TYPE} != "gcc" @@ -82,7 +82,7 @@ CLEANFILES= boot1.efifat .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" beforedepend ${OBJS}: machine x86 -CLEANFILES+= machine x86 boot1.efi +CLEANFILES+= machine x86 machine: ln -sf ${.CURDIR}/../../../amd64/include machine diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index e0c26da..1e3821b 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$"); #define _PATH_LOADER "/boot/loader.efi" #define _PATH_KERNEL "/boot/kernel/kernel" - + #define BSIZEMAX 16384 typedef int putc_func_t(char c, void *arg); @@ -40,7 +40,7 @@ struct sp_data { u_int sp_len; u_int sp_size; }; - + static const char digits[] = "0123456789abcdef"; static void panic(const char *fmt, ...) __dead2; @@ -62,7 +62,7 @@ static void load(const char *fname); EFI_SYSTEM_TABLE *systab; EFI_HANDLE *image; -static void +static void bcopy(const void *src, void *dst, size_t len) { const char *s = src; @@ -71,12 +71,12 @@ bcopy(const void *src, void *dst, size_t len) while (len-- != 0) *d++ = *s++; } - + static void memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); -} +} static void bzero(void *b, size_t len) @@ -86,7 +86,7 @@ bzero(void *b, size_t len) while (len-- != 0) *p++ = 0; } - + static int strcmp(const char *s1, const char *s2) { @@ -134,7 +134,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) for (i = 0; i < nparts; i++) { status = systab->BootServices->HandleProtocol(handles[i], - &DevicePathGUID, (void **)&devpath); + &DevicePathGUID, (void **)&devpath); if (EFI_ERROR(status)) continue; @@ -142,7 +142,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) devpath = NextDevicePathNode(devpath); status = systab->BootServices->HandleProtocol(handles[i], - &BlockIoProtocolGUID, (void **)&blkio); + &BlockIoProtocolGUID, (void **)&blkio); if (EFI_ERROR(status)) continue; @@ -158,7 +158,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) bootdevhandle = handles[i]; load(path); - + panic("Load failed"); return EFI_SUCCESS; @@ -266,7 +266,7 @@ fsstat(ufs_ino_t inode) } static struct dmadat __dmadat; - + static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet) { @@ -278,7 +278,7 @@ domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet) if (!quiet) printf("domount: can't read superblock\n"); return (-1); - } + } if (!quiet) printf("Succesfully mounted UFS filesystem\n"); return (0); @@ -303,26 +303,26 @@ load(const char *fname) status = systab->BootServices->AllocatePool(EfiLoaderData, bufsize, &buffer); fsread(ino, buffer, bufsize); - + /* XXX: For secure boot, we need our own loader here */ status = systab->BootServices->LoadImage(TRUE, image, bootdevpath, buffer, bufsize, &loaderhandle); if (EFI_ERROR(status)) printf("LoadImage failed with error %lu\n", - status & ~EFI_ERROR_MASK); + EFI_ERROR_CODE(status)); status = systab->BootServices->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image); if (EFI_ERROR(status)) printf("HandleProtocol failed with error %lu\n", - status & ~EFI_ERROR_MASK); + EFI_ERROR_CODE(status)); loaded_image->DeviceHandle = bootdevhandle; status = systab->BootServices->StartImage(loaderhandle, NULL, NULL); if (EFI_ERROR(status)) printf("StartImage failed with error %lu\n", - status & ~EFI_ERROR_MASK); + EFI_ERROR_CODE(status)); } static void @@ -552,4 +552,3 @@ __ultoa(char *buf, u_long ul, int base) while ((ul /= base) != 0); return (p); } - diff --git a/sys/boot/efi/include/efierr.h b/sys/boot/efi/include/efierr.h index dc57f0e..921b297 100644 --- a/sys/boot/efi/include/efierr.h +++ b/sys/boot/efi/include/efierr.h @@ -30,7 +30,8 @@ Revision History #define EFIWARN(a) (a) -#define EFI_ERROR(a) (((INTN) a) < 0) +#define EFI_ERROR(a) (((INTN) a) < 0) +#define EFI_ERROR_CODE(a) (a & ~EFI_ERROR_MASK) #define EFI_SUCCESS 0 diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile index 8180d9e..900b230 100644 --- a/sys/boot/efi/libefi/Makefile +++ b/sys/boot/efi/libefi/Makefile @@ -19,5 +19,6 @@ CFLAGS+= -I${.CURDIR}/../../common # Suppress warning from clang for FreeBSD %b and %D formats CFLAGS+= -fformat-extensions +CFLAGS+= -DTERM_EMU .include <bsd.lib.mk> diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c index 3538994..52a3725 100644 --- a/sys/boot/efi/libefi/efi_console.c +++ b/sys/boot/efi/libefi/efi_console.c @@ -35,6 +35,69 @@ __FBSDID("$FreeBSD$"); static SIMPLE_TEXT_OUTPUT_INTERFACE *conout; static SIMPLE_INPUT_INTERFACE *conin; +#ifdef TERM_EMU +#define DEFAULT_FGCOLOR EFI_LIGHTGRAY +#define DEFAULT_BGCOLOR EFI_BLACK + +#define MAXARGS 8 +static int args[MAXARGS], argc; +static int fg_c, bg_c, curx, cury; +static int esc; + +void get_pos(int *x, int *y); +void curs_move(int *_x, int *_y, int x, int y); +static void CL(int); +#endif + +static void efi_cons_probe(struct console *); +static int efi_cons_init(int); +void efi_cons_putchar(int); +int efi_cons_getchar(void); +void efi_cons_efiputchar(int); +int efi_cons_poll(void); + +struct console efi_console = { + "efi", + "EFI console", + 0, + efi_cons_probe, + efi_cons_init, + efi_cons_putchar, + efi_cons_getchar, + efi_cons_poll +}; + +#ifdef TERM_EMU + +/* Get cursor position. */ +void +get_pos(int *x, int *y) +{ + *x = conout->Mode->CursorColumn; + *y = conout->Mode->CursorRow; +} + +/* Move cursor to x rows and y cols (0-based). */ +void +curs_move(int *_x, int *_y, int x, int y) +{ + conout->SetCursorPosition(conout, x, y); + if (_x != NULL) + *_x = conout->Mode->CursorColumn; + if (_y != NULL) + *_y = conout->Mode->CursorRow; +} + +/* Clear internal state of the terminal emulation code. */ +void +end_term(void) +{ + esc = 0; + argc = -1; +} + +#endif + static void efi_cons_probe(struct console *cp) { @@ -46,22 +109,314 @@ efi_cons_probe(struct console *cp) static int efi_cons_init(int arg) { - conout->SetAttribute(conout, EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK)); + conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR, + DEFAULT_BGCOLOR)); +#ifdef TERM_EMU + end_term(); + get_pos(&curx, &cury); + curs_move(&curx, &cury, curx, cury); + fg_c = DEFAULT_FGCOLOR; + bg_c = DEFAULT_BGCOLOR; +#endif + conout->EnableCursor(conout, TRUE); return 0; } +static void +efi_cons_rawputchar(int c) +{ + int i; + UINTN x, y; + conout->QueryMode(conout, conout->Mode->Mode, &x, &y); + + if (c == '\t') + /* XXX lame tab expansion */ + for (i = 0; i < 8; i++) + efi_cons_rawputchar(' '); + else { +#ifndef TERM_EMU + if (c == '\n') + efi_cons_efiputchar('\r'); + else + efi_cons_efiputchar(c); +#else + switch (c) { + case '\r': + curx = 0; + curs_move(&curx, &cury, curx, cury); + return; + case '\n': + cury++; + if (cury >= y) { + efi_cons_efiputchar('\n'); + cury--; + } else + curs_move(&curx, &cury, curx, cury); + return; + case '\b': + if (curx > 0) { + curx--; + curs_move(&curx, &cury, curx, cury); + } + return; + default: + efi_cons_efiputchar(c); + curx++; + if (curx > x-1) { + curx = 0; + cury++; + } + if (cury > y-1) { + curx = 0; + cury--; + } + } + curs_move(&curx, &cury, curx, cury); +#endif + } +} + +/* Gracefully exit ESC-sequence processing in case of misunderstanding. */ +static void +bail_out(int c) +{ + char buf[16], *ch; + int i; + + if (esc) { + efi_cons_rawputchar('\033'); + if (esc != '\033') + efi_cons_rawputchar(esc); + for (i = 0; i <= argc; ++i) { + sprintf(buf, "%d", args[i]); + ch = buf; + while (*ch) + efi_cons_rawputchar(*ch++); + } + } + efi_cons_rawputchar(c); + end_term(); +} + +/* Clear display from current position to end of screen. */ +static void +CD(void) { + int i; + UINTN x, y; + + get_pos(&curx, &cury); + if (curx == 0 && cury == 0) { + conout->ClearScreen(conout); + end_term(); + return; + } + + conout->QueryMode(conout, conout->Mode->Mode, &x, &y); + CL(0); /* clear current line from cursor to end */ + for (i = cury + 1; i < y-1; i++) { + curs_move(NULL, NULL, 0, i); + CL(0); + } + curs_move(NULL, NULL, curx, cury); + end_term(); +} + +/* + * Absolute cursor move to args[0] rows and args[1] columns + * (the coordinates are 1-based). + */ +static void +CM(void) +{ + if (args[0] > 0) + args[0]--; + if (args[1] > 0) + args[1]--; + curs_move(&curx, &cury, args[1], args[0]); + end_term(); +} + +/* Home cursor (left top corner), also called from mode command. */ void -efi_cons_putchar(int c) +HO(void) { - CHAR16 buf[2]; + argc = 1; + args[0] = args[1] = 1; + CM(); +} - if (c == '\n') - efi_cons_putchar('\r'); +/* Clear line from current position to end of line */ +static void +CL(int direction) +{ + int i, len; + UINTN x, y; + CHAR16 *line; - buf[0] = c; - buf[1] = 0; + conout->QueryMode(conout, conout->Mode->Mode, &x, &y); + switch (direction) { + case 0: /* from cursor to end */ + len = x - curx + 1; + break; + case 1: /* from beginning to cursor */ + len = curx; + break; + case 2: /* entire line */ + len = x; + break; + } - conout->OutputString(conout, buf); + if (cury == y - 1) + len--; + + line = malloc(len * sizeof (CHAR16)); + if (line == NULL) { + printf("out of memory\n"); + return; + } + for (i = 0; i < len; i++) + line[i] = ' '; + line[len-1] = 0; + + if (direction != 0) + curs_move(NULL, NULL, 0, cury); + + conout->OutputString(conout, line); + /* restore cursor position */ + curs_move(NULL, NULL, curx, cury); + free(line); + end_term(); +} + +static void +get_arg(int c) +{ + if (argc < 0) + argc = 0; + args[argc] *= 10; + args[argc] += c - '0'; +} + +/* Emulate basic capabilities of cons25 terminal */ +static void +efi_term_emu(int c) +{ + static int ansi_col[] = { + 0, 4, 2, 6, 1, 5, 3, 7 + }; + int t, i; + + switch (esc) { + case 0: + switch (c) { + case '\033': + esc = c; + break; + default: + efi_cons_rawputchar(c); + break; + } + break; + case '\033': + switch (c) { + case '[': + esc = c; + args[0] = 0; + argc = -1; + break; + default: + bail_out(c); + break; + } + break; + case '[': + switch (c) { + case ';': + if (argc < 0) + argc = 0; + else if (argc + 1 >= MAXARGS) + bail_out(c); + else + args[++argc] = 0; + break; + case 'H': /* ho = \E[H */ + if (argc < 0) + HO(); + else if (argc == 1) + CM(); + else + bail_out(c); + break; + case 'J': /* cd = \E[J */ + if (argc < 0) + CD(); + else + bail_out(c); + break; + case 'm': + if (argc < 0) { + fg_c = DEFAULT_FGCOLOR; + bg_c = DEFAULT_BGCOLOR; + } + for (i = 0; i <= argc; ++i) { + switch (args[i]) { + case 0: /* back to normal */ + fg_c = DEFAULT_FGCOLOR; + bg_c = DEFAULT_BGCOLOR; + break; + case 1: /* bold */ + fg_c |= 0x8; + break; + case 4: /* underline */ + case 5: /* blink */ + bg_c |= 0x8; + break; + case 7: /* reverse */ + t = fg_c; + fg_c = bg_c; + bg_c = t; + break; + case 30: case 31: case 32: case 33: + case 34: case 35: case 36: case 37: + fg_c = ansi_col[args[i] - 30]; + break; + case 39: /* normal */ + fg_c = DEFAULT_FGCOLOR; + break; + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + bg_c = ansi_col[args[i] - 40]; + break; + case 49: /* normal */ + bg_c = DEFAULT_BGCOLOR; + break; + } + } + conout->SetAttribute(conout, EFI_TEXT_ATTR(fg_c, bg_c)); + end_term(); + break; + default: + if (isdigit(c)) + get_arg(c); + else + bail_out(c); + break; + } + break; + default: + bail_out(c); + break; + } +} + +void +efi_cons_putchar(int c) +{ +#ifdef TERM_EMU + efi_term_emu(c); +#else + efi_cons_rawputchar(c); +#endif } int @@ -77,6 +432,12 @@ efi_cons_getchar() BS->WaitForEvent(1, &conin->WaitForKey, &junk); status = conin->ReadKeyStroke(conin, &key); } + switch (key.ScanCode) { + case 0x17: /* ESC */ + return (0x1b); /* esc */ + } + + /* this can return */ return (key.UnicodeChar); } @@ -87,13 +448,36 @@ efi_cons_poll() return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS); } -struct console efi_console = { - "efi", - "EFI console", - 0, - efi_cons_probe, - efi_cons_init, - efi_cons_putchar, - efi_cons_getchar, - efi_cons_poll -}; +/* Plain direct access to EFI OutputString(). */ +void +efi_cons_efiputchar(int c) +{ + CHAR16 buf[2]; + + /* + * translate box chars to unicode + */ + switch (c) { + /* single frame */ + case 0xb3: buf[0] = BOXDRAW_VERTICAL; break; + case 0xbf: buf[0] = BOXDRAW_DOWN_LEFT; break; + case 0xc0: buf[0] = BOXDRAW_UP_RIGHT; break; + case 0xc4: buf[0] = BOXDRAW_HORIZONTAL; break; + case 0xda: buf[0] = BOXDRAW_DOWN_RIGHT; break; + case 0xd9: buf[0] = BOXDRAW_UP_LEFT; break; + + /* double frame */ + case 0xba: buf[0] = BOXDRAW_DOUBLE_VERTICAL; break; + case 0xbb: buf[0] = BOXDRAW_DOUBLE_DOWN_LEFT; break; + case 0xbc: buf[0] = BOXDRAW_DOUBLE_UP_LEFT; break; + case 0xc8: buf[0] = BOXDRAW_DOUBLE_UP_RIGHT; break; + case 0xc9: buf[0] = BOXDRAW_DOUBLE_DOWN_RIGHT; break; + case 0xcd: buf[0] = BOXDRAW_DOUBLE_HORIZONTAL; break; + + default: + buf[0] = c; + } + buf[1] = 0; /* terminate string */ + + conout->OutputString(conout, buf); +} diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile index 8d3fe87..268edce 100644 --- a/sys/boot/efi/loader/Makefile +++ b/sys/boot/efi/loader/Makefile @@ -12,7 +12,6 @@ MK_SSP= no PROG= loader.sym INTERNALPROG= -.PATH: ${.CURDIR}/../../efi/loader # architecture-specific loader code SRCS= autoload.c \ bootinfo.c \ @@ -80,7 +79,7 @@ EFI_TARGET= efi-app-x86_64 EFI_TARGET= efi-app-ia32 .endif -loader.efi: loader.sym +loader.efi: ${PROG} if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ exit 1; \ diff --git a/sys/boot/efi/loader/bootinfo.c b/sys/boot/efi/loader/bootinfo.c index f3bb9cc..18837f8 100644 --- a/sys/boot/efi/loader/bootinfo.c +++ b/sys/boot/efi/loader/bootinfo.c @@ -275,7 +275,7 @@ bi_load_efi_data(struct preloaded_file *kfp) pages, &addr); if (EFI_ERROR(status)) { printf("%s: AllocatePages error %lu\n", __func__, - (unsigned long)(status & ~EFI_ERROR_MASK)); + EFI_ERROR_CODE(status)); return (ENOMEM); } @@ -291,7 +291,7 @@ bi_load_efi_data(struct preloaded_file *kfp) status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver); if (EFI_ERROR(status)) { printf("%s: GetMemoryMap error %lu\n", __func__, - (unsigned long)(status & ~EFI_ERROR_MASK)); + EFI_ERROR_CODE(status)); return (EINVAL); } status = BS->ExitBootServices(IH, efi_mapkey); @@ -305,8 +305,7 @@ bi_load_efi_data(struct preloaded_file *kfp) } BS->FreePages(addr, pages); } - printf("ExitBootServices error %lu\n", - (unsigned long)(status & ~EFI_ERROR_MASK)); + printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status)); return (EINVAL); } diff --git a/sys/boot/efi/loader/copy.c b/sys/boot/efi/loader/copy.c index a7d6bf1..363d95d 100644 --- a/sys/boot/efi/loader/copy.c +++ b/sys/boot/efi/loader/copy.c @@ -56,7 +56,7 @@ efi_copy_init(void) STAGE_PAGES, &staging); if (EFI_ERROR(status)) { printf("failed to allocate staging area: %lu\n", - (unsigned long)(status & EFI_ERROR_MASK)); + EFI_ERROR_CODE(status)); return (status); } staging_end = staging + STAGE_PAGES * EFI_PAGE_SIZE; diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index e6e13f1..ec9f9af 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -63,10 +63,10 @@ EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID; EFI_STATUS main(int argc, CHAR16 *argv[]) { - char vendor[128]; + char var[128]; EFI_LOADED_IMAGE *img; EFI_GUID *guid; - int i; + int i, j, vargood; /* * XXX Chicken-and-egg problem; we want to have console output @@ -76,6 +76,29 @@ main(int argc, CHAR16 *argv[]) */ cons_probe(); + /* + * Loop through the args, and for each one that contains an '=' that is + * not the first character, add it to the environment. This allows + * loader and kernel env vars to be passed on the command line. Convert + * args from UCS-2 to ASCII (16 to 8 bit) as they are copied. + */ + for (i = 1; i < argc; i++) { + vargood = 0; + for (j = 0; argv[i][j] != 0; j++) { + if (j == sizeof(var)) { + vargood = 0; + break; + } + if (j > 0 && argv[i][j] == '=') + vargood = 1; + var[j] = (char)argv[i][j]; + } + if (vargood) { + var[j] = 0; + putenv(var); + } + } + if (efi_copy_init()) { printf("failed to allocate staging area\n"); return (EFI_BUFFER_TOO_SMALL); @@ -203,50 +226,47 @@ command_memmap(int argc, char *argv[]) status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); if (status != EFI_BUFFER_TOO_SMALL) { printf("Can't determine memory map size\n"); - return CMD_ERROR; + return (CMD_ERROR); } map = malloc(sz); status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); if (EFI_ERROR(status)) { printf("Can't read memory map\n"); - return CMD_ERROR; + return (CMD_ERROR); } ndesc = sz / dsz; printf("%23s %12s %12s %8s %4s\n", - "Type", "Physical", "Virtual", "#Pages", "Attr"); + "Type", "Physical", "Virtual", "#Pages", "Attr"); for (i = 0, p = map; i < ndesc; i++, p = NextMemoryDescriptor(p, dsz)) { - printf("%23s %012lx %012lx %08lx ", - types[p->Type], - p->PhysicalStart, - p->VirtualStart, - p->NumberOfPages); - if (p->Attribute & EFI_MEMORY_UC) - printf("UC "); - if (p->Attribute & EFI_MEMORY_WC) - printf("WC "); - if (p->Attribute & EFI_MEMORY_WT) - printf("WT "); - if (p->Attribute & EFI_MEMORY_WB) - printf("WB "); - if (p->Attribute & EFI_MEMORY_UCE) - printf("UCE "); - if (p->Attribute & EFI_MEMORY_WP) - printf("WP "); - if (p->Attribute & EFI_MEMORY_RP) - printf("RP "); - if (p->Attribute & EFI_MEMORY_XP) - printf("XP "); - printf("\n"); + printf("%23s %012lx %012lx %08lx ", types[p->Type], + p->PhysicalStart, p->VirtualStart, p->NumberOfPages); + if (p->Attribute & EFI_MEMORY_UC) + printf("UC "); + if (p->Attribute & EFI_MEMORY_WC) + printf("WC "); + if (p->Attribute & EFI_MEMORY_WT) + printf("WT "); + if (p->Attribute & EFI_MEMORY_WB) + printf("WB "); + if (p->Attribute & EFI_MEMORY_UCE) + printf("UCE "); + if (p->Attribute & EFI_MEMORY_WP) + printf("WP "); + if (p->Attribute & EFI_MEMORY_RP) + printf("RP "); + if (p->Attribute & EFI_MEMORY_XP) + printf("XP "); + printf("\n"); } - return CMD_OK; + return (CMD_OK); } -COMMAND_SET(configuration, "configuration", - "print configuration tables", command_configuration); +COMMAND_SET(configuration, "configuration", "print configuration tables", + command_configuration); static const char * guid_to_string(EFI_GUID *guid) @@ -292,7 +312,7 @@ command_configuration(int argc, char *argv[]) printf(" at %p\n", ST->ConfigurationTable[i].VendorTable); } - return CMD_OK; + return (CMD_OK); } @@ -308,6 +328,7 @@ command_mode(int argc, char *argv[]) char rowenv[8]; EFI_STATUS status; SIMPLE_TEXT_OUTPUT_INTERFACE *conout; + extern void HO(void); conout = ST->ConOut; @@ -329,14 +350,15 @@ command_mode(int argc, char *argv[]) } sprintf(rowenv, "%u", (unsigned)rows); setenv("LINES", rowenv, 1); - + HO(); /* set cursor */ return (CMD_OK); } - for (i = 0; ; i++) { + printf("Current mode: %d\n", conout->Mode->Mode); + for (i = 0; i <= conout->Mode->MaxMode; i++) { status = conout->QueryMode(conout, i, &cols, &rows); if (EFI_ERROR(status)) - break; + continue; printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols, (unsigned)rows); } @@ -367,20 +389,17 @@ command_nvram(int argc, char *argv[]) status = RS->GetNextVariableName(&varsz, NULL, NULL); for (; status != EFI_NOT_FOUND; ) { - status = RS->GetNextVariableName(&varsz, var, - &varguid); + status = RS->GetNextVariableName(&varsz, var, &varguid); //if (EFI_ERROR(status)) //break; conout->OutputString(conout, var); printf("="); datasz = 0; - status = RS->GetVariable(var, &varguid, NULL, &datasz, - NULL); + status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL); /* XXX: check status */ data = malloc(datasz); - status = RS->GetVariable(var, &varguid, NULL, &datasz, - data); + status = RS->GetVariable(var, &varguid, NULL, &datasz, data); if (EFI_ERROR(status)) printf("<error retrieving variable>"); else { diff --git a/sys/boot/fdt/dts/arm/beaglebone-black.dts b/sys/boot/fdt/dts/arm/beaglebone-black.dts index ff25f9d..0e35a7a 100644 --- a/sys/boot/fdt/dts/arm/beaglebone-black.dts +++ b/sys/boot/fdt/dts/arm/beaglebone-black.dts @@ -146,9 +146,9 @@ }; i2c@44e0b000 { - pmic@48 { + pmic@24 { compatible = "ti,am335x-pmic"; - reg = <0x48>; + reg = <0x24>; }; }; }; diff --git a/sys/boot/fdt/dts/arm/beaglebone.dts b/sys/boot/fdt/dts/arm/beaglebone.dts index 83b948f..3f8e022 100644 --- a/sys/boot/fdt/dts/arm/beaglebone.dts +++ b/sys/boot/fdt/dts/arm/beaglebone.dts @@ -133,7 +133,7 @@ i2c@44e0b000 { pmic@24 { compatible = "ti,am335x-pmic"; - reg = <0x48>; + reg = <0x24>; }; }; }; diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c index 0f63776..98a0388 100644 --- a/sys/boot/fdt/fdt_loader_cmd.c +++ b/sys/boot/fdt/fdt_loader_cmd.c @@ -261,7 +261,7 @@ fdt_load_dtb_file(const char * filename) oldbfp = file_findfile(NULL, "dtb"); /* Attempt to load and validate a new dtb from a file. */ - if ((bfp = file_loadraw(filename, "dtb")) == NULL) { + if ((bfp = file_loadraw(filename, "dtb", 1)) == NULL) { sprintf(command_errbuf, "failed to load file '%s'", filename); return (1); } diff --git a/sys/boot/ficl/amd64/sysdep.c b/sys/boot/ficl/amd64/sysdep.c index 00b0d4a..6031094 100644 --- a/sys/boot/ficl/amd64/sysdep.c +++ b/sys/boot/ficl/amd64/sysdep.c @@ -55,7 +55,7 @@ void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) IGNORE(pVM); while(*msg != 0) - putchar(*(msg++)); + putchar((unsigned char)*(msg++)); if (fNewline) putchar('\n'); diff --git a/sys/boot/forth/beastie.4th b/sys/boot/forth/beastie.4th index 9ede592..752cce2 100644 --- a/sys/boot/forth/beastie.4th +++ b/sys/boot/forth/beastie.4th @@ -85,14 +85,10 @@ variable logoY also support-functions : beastie-start ( -- ) \ starts the menu - s" console" getenv dup -1 <> if - s" efi" 2swap contains? if - s" set beastie_disable=YES" evaluate - then - else drop then s" beastie_disable" getenv dup -1 <> if s" YES" compare-insensitive 0= if any_conf_read? if + load_xen_throw load_kernel load_modules then diff --git a/sys/boot/forth/beastie.4th.8 b/sys/boot/forth/beastie.4th.8 index 534a60c..70d8694 100644 --- a/sys/boot/forth/beastie.4th.8 +++ b/sys/boot/forth/beastie.4th.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 27, 2014 +.Dd January 20, 2016 .Dt BEASTIE.4TH 8 .Os .Sh NAME @@ -119,8 +119,7 @@ Sets the desired row position of the logo. Default is 4. If set to .Dq YES , the beastie boot menu will be skipped. -The beastie boot menu is always skipped if booting UEFI or running non-x86 -hardware. +The beastie boot menu is always skipped if running non-x86 hardware. .It Va loader_delay If set to a number higher than zero, introduces a delay before starting the beastie boot menu. During the delay the user can press either Ctrl-C to skip diff --git a/sys/boot/forth/loader.4th b/sys/boot/forth/loader.4th index 43d2a8e..ad4042e 100644 --- a/sys/boot/forth/loader.4th +++ b/sys/boot/forth/loader.4th @@ -147,13 +147,14 @@ only forth definitions also support-functions \ was succesfully loaded! any_conf_read? if s" loader_delay" getenv -1 = if + load_xen_throw load_kernel load_modules else drop ." Loading Kernel and Modules (Ctrl-C to Abort)" cr s" also support-functions" evaluate - s" set delay_command='load_kernel load_modules'" evaluate + s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate s" set delay_showdots" evaluate delay_execute then diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5 index 3c1ce1d..c574a92 100644 --- a/sys/boot/forth/loader.conf.5 +++ b/sys/boot/forth/loader.conf.5 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd April 27, 2014 +.Dd January 20, 2016 .Dt LOADER.CONF 5 .Os .Sh NAME @@ -236,8 +236,7 @@ be displayed. If set to .Dq YES , the beastie boot menu will be skipped. -The beastie boot menu is always skipped if booting UEFI or running non-x86 -hardware. +The beastie boot menu is always skipped if running non-x86 hardware. .It Va loader_logo Pq Dq Li orbbw Selects a desired logo in the beastie boot menu. Possible values are: diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th index 1acef70..3d9990d 100644 --- a/sys/boot/forth/support.4th +++ b/sys/boot/forth/support.4th @@ -1460,6 +1460,20 @@ also builtins abort" Unable to load a kernel!" ; +: load_xen ( -- ) + s" xen_kernel" getenv dup -1 <> if + 1 1 load + else + drop + 0 + then +; + +: load_xen_throw ( -- ) ( throws: abort ) + load_xen + abort" Unable to load Xen!" +; + : set_defaultoptions ( -- ) s" kernel_options" getenv dup -1 = if drop @@ -1578,12 +1592,15 @@ also builtins else drop then - r> if ( a path was passed ) - load_directory_or_file - else - standard_kernel_search + load_xen + ?dup 0= if ( success ) + r> if ( a path was passed ) + load_directory_or_file + else + standard_kernel_search + then + ?dup 0= if ['] load_modules catch then then - ?dup 0= if ['] load_modules catch then ; only forth definitions diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 1c4f049..d4fea80 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -6,7 +6,7 @@ INTERNALLIB= SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \ biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \ comconsole.c devicename.c elf32_freebsd.c \ - elf64_freebsd.c \ + elf64_freebsd.c multiboot.c multiboot_tramp.S \ i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \ smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c .PATH: ${.CURDIR}/../../zfs @@ -65,6 +65,7 @@ machine: # XXX: clang integrated-as doesn't grok .codeNN directives yet CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS} +CFLAGS.multiboot_tramp.S= ${CLANG_NO_IAS} CFLAGS+= ${CFLAGS.${.IMPSRC:T}} .if ${MACHINE_CPUARCH} == "amd64" diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c index 617414e..751e806 100644 --- a/sys/boot/i386/libi386/bootinfo64.c +++ b/sys/boot/i386/libi386/bootinfo64.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <machine/bootinfo.h> #include <machine/cpufunc.h> +#include <machine/metadata.h> #include <machine/psl.h> #include <machine/specialreg.h> #include "bootstrap.h" @@ -176,14 +177,15 @@ bi_checkcpu(void) * - Module metadata are formatted and placed in kernel space. */ int -bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) +bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep, + vm_offset_t *kernendp, int add_smap) { struct preloaded_file *xp, *kfp; struct i386_devdesc *rootdev; struct file_metadata *md; - vm_offset_t addr; u_int64_t kernend; u_int64_t envp; + u_int64_t module; vm_offset_t size; char *rootdevname; int howto; @@ -210,21 +212,18 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) /* Try reading the /etc/fstab file to select the root device */ getrootmount(i386_fmtdev((void *)rootdev)); - /* find the last module in the chain */ - addr = 0; - for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { - if (addr < (xp->f_addr + xp->f_size)) - addr = xp->f_addr + xp->f_size; + if (addr == 0) { + /* find the last module in the chain */ + for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { + if (addr < (xp->f_addr + xp->f_size)) + addr = xp->f_addr + xp->f_size; + } } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); - /* copy our environment */ - envp = addr; - addr = bi_copyenv(addr); - - /* pad to a page boundary */ - addr = roundup(addr, PAGE_SIZE); + /* place the metadata before anything */ + module = *modulep = addr; kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) @@ -235,20 +234,30 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); - bios_addsmapdata(kfp); + file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof module, &module); + if (add_smap != 0) + bios_addsmapdata(kfp); - /* Figure out the size and location of the metadata */ - *modulep = addr; size = bi_copymodules64(0); - kernend = roundup(addr + size, PAGE_SIZE); + + /* copy our environment */ + envp = roundup(addr + size, PAGE_SIZE); + addr = bi_copyenv(envp); + + /* set kernend */ + kernend = roundup(addr, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); + /* patch MODINFOMD_ENVP */ + md = file_findmetadata(kfp, MODINFOMD_ENVP); + bcopy(&envp, md->md_data, sizeof envp); + /* copy module list and metadata */ - (void)bi_copymodules64(addr); + (void)bi_copymodules64(*modulep); return(0); } diff --git a/sys/boot/i386/libi386/elf64_freebsd.c b/sys/boot/i386/libi386/elf64_freebsd.c index 627d416..338a745 100644 --- a/sys/boot/i386/libi386/elf64_freebsd.c +++ b/sys/boot/i386/libi386/elf64_freebsd.c @@ -81,7 +81,7 @@ elf64_exec(struct preloaded_file *fp) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); - err = bi_load64(fp->f_args, &modulep, &kernend); + err = bi_load64(fp->f_args, 0, &modulep, &kernend, 1); if (err != 0) return(err); diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h index 357b8fd..e8bdf65 100644 --- a/sys/boot/i386/libi386/libi386.h +++ b/sys/boot/i386/libi386/libi386.h @@ -117,6 +117,7 @@ void bi_setboothowto(int howto); vm_offset_t bi_copyenv(vm_offset_t addr); int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernend); -int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend); +int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep, + vm_offset_t *kernend, int add_smap); void pxe_enable(void *pxeinfo); diff --git a/sys/boot/i386/libi386/multiboot.c b/sys/boot/i386/libi386/multiboot.c new file mode 100644 index 0000000..00e36f2 --- /dev/null +++ b/sys/boot/i386/libi386/multiboot.c @@ -0,0 +1,425 @@ +/*- + * Copyright (c) 2014 Roger Pau Monné <royger@FreeBSD.org> + * 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. + */ + +/* + * This multiboot implementation only implements a subset of the full + * multiboot specification in order to be able to boot Xen and a + * FreeBSD Dom0. Trying to use it to boot other multiboot compliant + * kernels will most surely fail. + * + * The full multiboot specification can be found here: + * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/exec.h> +#include <sys/linker.h> +#include <sys/module.h> +#include <sys/stdint.h> +#define _MACHINE_ELF_WANT_32BIT +#include <machine/elf.h> +#include <string.h> +#include <stand.h> + +#include "bootstrap.h" +#include "multiboot.h" +#include "../i386/libi386/libi386.h" +#include "../i386/btx/lib/btxv86.h" + +#define MULTIBOOT_SUPPORTED_FLAGS \ + (MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO) +#define NUM_MODULES 2 +#define METADATA_FIXED_SIZE (PAGE_SIZE*4) +#define METADATA_MODULE_SIZE PAGE_SIZE + +#define METADATA_RESV_SIZE(mod_num) \ + roundup(METADATA_FIXED_SIZE + METADATA_MODULE_SIZE * mod_num, PAGE_SIZE) + +extern int elf32_loadfile_raw(char *filename, u_int64_t dest, + struct preloaded_file **result, int multiboot); +extern int elf64_load_modmetadata(struct preloaded_file *fp, u_int64_t dest); +extern int elf64_obj_loadfile(char *filename, u_int64_t dest, + struct preloaded_file **result); + +static int multiboot_loadfile(char *, u_int64_t, struct preloaded_file **); +static int multiboot_exec(struct preloaded_file *); + +static int multiboot_obj_loadfile(char *, u_int64_t, struct preloaded_file **); +static int multiboot_obj_exec(struct preloaded_file *fp); + +struct file_format multiboot = { multiboot_loadfile, multiboot_exec }; +struct file_format multiboot_obj = + { multiboot_obj_loadfile, multiboot_obj_exec }; + +extern void multiboot_tramp(); + +static const char mbl_name[] = "FreeBSD Loader"; + +static int +num_modules(struct preloaded_file *kfp) +{ + struct kernel_module *kmp; + int mod_num = 0; + + for (kmp = kfp->f_modules; kmp != NULL; kmp = kmp->m_next) + mod_num++; + + return (mod_num); +} + +static vm_offset_t +max_addr(void) +{ + struct preloaded_file *fp; + vm_offset_t addr = 0; + + for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { + if (addr < (fp->f_addr + fp->f_size)) + addr = fp->f_addr + fp->f_size; + } + + return (addr); +} + +static int +multiboot_loadfile(char *filename, u_int64_t dest, + struct preloaded_file **result) +{ + uint32_t *magic; + int i, error; + caddr_t header_search; + ssize_t search_size; + int fd; + struct multiboot_header *header; + char *cmdline; + + /* + * Read MULTIBOOT_SEARCH size in order to search for the + * multiboot magic header. + */ + if (filename == NULL) + return (EFTYPE); + if ((fd = open(filename, O_RDONLY)) == -1) + return (errno); + header_search = malloc(MULTIBOOT_SEARCH); + if (header_search == NULL) { + close(fd); + return (ENOMEM); + } + search_size = read(fd, header_search, MULTIBOOT_SEARCH); + magic = (uint32_t *)header_search; + + header = NULL; + for (i = 0; i < (search_size / sizeof(uint32_t)); i++) { + if (magic[i] == MULTIBOOT_HEADER_MAGIC) { + header = (struct multiboot_header *)&magic[i]; + break; + } + } + + if (header == NULL) { + error = EFTYPE; + goto out; + } + + /* Valid multiboot header has been found, validate checksum */ + if (header->magic + header->flags + header->checksum != 0) { + printf( + "Multiboot checksum failed, magic: 0x%x flags: 0x%x checksum: 0x%x\n", + header->magic, header->flags, header->checksum); + error = EFTYPE; + goto out; + } + + if ((header->flags & ~MULTIBOOT_SUPPORTED_FLAGS) != 0) { + printf("Unsupported multiboot flags found: 0x%x\n", + header->flags); + error = EFTYPE; + goto out; + } + + error = elf32_loadfile_raw(filename, dest, result, 1); + if (error != 0) { + printf( + "elf32_loadfile_raw failed: %d unable to load multiboot kernel\n", + error); + goto out; + } + + /* + * f_addr is already aligned to PAGE_SIZE, make sure + * f_size it's also aligned so when the modules are loaded + * they are aligned to PAGE_SIZE. + */ + (*result)->f_size = roundup((*result)->f_size, PAGE_SIZE); + +out: + free(header_search); + close(fd); + return (error); +} + +static int +multiboot_exec(struct preloaded_file *fp) +{ + vm_offset_t module_start, last_addr, metadata_size; + vm_offset_t modulep, kernend, entry; + struct file_metadata *md; + Elf_Ehdr *ehdr; + struct multiboot_info *mb_info = NULL; + struct multiboot_mod_list *mb_mod = NULL; + char *cmdline = NULL; + size_t len; + int error, mod_num; + + /* + * Don't pass the memory size found by the bootloader, the memory + * available to Dom0 will be lower than that. + */ + unsetenv("smbios.memory.enabled"); + + /* Allocate the multiboot struct and fill the basic details. */ + mb_info = malloc(sizeof(struct multiboot_info)); + if (mb_info == NULL) { + error = ENOMEM; + goto error; + } + bzero(mb_info, sizeof(struct multiboot_info)); + mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME; + mb_info->mem_lower = bios_basemem / 1024; + mb_info->mem_upper = bios_extmem / 1024; + mb_info->boot_loader_name = VTOP(mbl_name); + + /* Set the Xen command line. */ + if (fp->f_args == NULL) { + /* Add the Xen command line if it is set. */ + cmdline = getenv("xen_cmdline"); + if (cmdline != NULL) { + fp->f_args = strdup(cmdline); + if (fp->f_args == NULL) { + error = ENOMEM; + goto error; + } + } + } + if (fp->f_args != NULL) { + len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1; + cmdline = malloc(len); + if (cmdline == NULL) { + error = ENOMEM; + goto error; + } + snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args); + mb_info->cmdline = VTOP(cmdline); + mb_info->flags |= MULTIBOOT_INFO_CMDLINE; + } + + /* Find the entry point of the Xen kernel and save it for later */ + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { + printf("Unable to find %s entry point\n", fp->f_name); + error = EINVAL; + goto error; + } + ehdr = (Elf_Ehdr *)&(md->md_data); + entry = ehdr->e_entry & 0xffffff; + + /* + * Prepare the multiboot module list, Xen assumes the first + * module is the Dom0 kernel, and the second one is the initramfs. + * This is not optimal for FreeBSD, that doesn't have a initramfs + * but instead loads modules dynamically and creates the metadata + * info on-the-fly. + * + * As expected, the first multiboot module is going to be the + * FreeBSD kernel loaded as a raw file. The second module is going + * to contain the metadata info and the loaded modules. + * + * On native FreeBSD loads all the modules and then places the + * metadata info at the end, but this is painful when running on Xen, + * because it relocates the second multiboot module wherever it + * likes. In order to workaround this limitation the metadata + * information is placed at the start of the second module and + * the original modulep value is saved together with the other + * metadata, so we can relocate everything. + */ + fp = file_findfile(NULL, "elf kernel"); + if (fp == NULL) { + printf("No FreeBSD kernel provided, aborting\n"); + error = EINVAL; + goto error; + } + + mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES); + if (mb_mod == NULL) { + error = ENOMEM; + goto error; + } + + bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES); + + /* + * Calculate how much memory is needed for the metatdata. We did + * an approximation of the maximum size when loading the kernel, + * but now we know the exact size, so we can release some of this + * preallocated memory if not needed. + */ + last_addr = roundup(max_addr(), PAGE_SIZE); + mod_num = num_modules(fp); + + /* + * Place the metadata after the last used address in order to + * calculate it's size, this will not be used. + */ + error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0); + if (error != 0) { + printf("bi_load64 failed: %d\n", error); + goto error; + } + metadata_size = roundup(kernend - last_addr, PAGE_SIZE); + + /* Check that the size is not greater than what we have reserved */ + if (metadata_size > METADATA_RESV_SIZE(mod_num)) { + printf("Required memory for metadata is greater than reserved " + "space, please increase METADATA_FIXED_SIZE and " + "METADATA_MODULE_SIZE and rebuild the loader\n"); + error = ENOMEM; + goto error; + } + + /* + * This is the position where the second multiboot module + * will be placed. + */ + module_start = fp->f_addr + fp->f_size - metadata_size; + + error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0); + if (error != 0) { + printf("bi_load64 failed: %d\n", error); + goto error; + } + + mb_mod[0].mod_start = fp->f_addr; + mb_mod[0].mod_end = fp->f_addr + fp->f_size; + mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num); + + mb_mod[1].mod_start = module_start; + mb_mod[1].mod_end = last_addr; + + mb_info->mods_count = NUM_MODULES; + mb_info->mods_addr = VTOP(mb_mod); + mb_info->flags |= MULTIBOOT_INFO_MODS; + + dev_cleanup(); + __exec((void *)VTOP(multiboot_tramp), (void *)entry, + (void *)VTOP(mb_info)); + + panic("exec returned"); + +error: + if (mb_mod) + free(mb_mod); + if (mb_info) + free(mb_info); + if (cmdline) + free(cmdline); + return (error); +} + +static int +multiboot_obj_loadfile(char *filename, u_int64_t dest, + struct preloaded_file **result) +{ + struct preloaded_file *mfp, *kfp, *rfp; + struct kernel_module *kmp; + int error, mod_num; + + /* See if there's a multiboot kernel loaded */ + mfp = file_findfile(NULL, "elf multiboot kernel"); + if (mfp == NULL) + return (EFTYPE); + + /* + * We have a multiboot kernel loaded, see if there's a FreeBSD + * kernel loaded also. + */ + kfp = file_findfile(NULL, "elf kernel"); + if (kfp == NULL) { + /* + * No kernel loaded, this must be it. The kernel has to + * be loaded as a raw file, it will be processed by + * Xen and correctly loaded as an ELF file. + */ + rfp = file_loadraw(filename, "elf kernel", 0); + if (rfp == NULL) { + printf( + "Unable to load %s as a multiboot payload kernel\n", + filename); + return (EINVAL); + } + + /* Load kernel metadata... */ + setenv("kernelname", filename, 1); + error = elf64_load_modmetadata(rfp, rfp->f_addr + rfp->f_size); + if (error) { + printf("Unable to load kernel %s metadata error: %d\n", + rfp->f_name, error); + return (EINVAL); + } + + /* + * Save space at the end of the kernel in order to place + * the metadata information. We do an approximation of the + * max metadata size, this is not optimal but it's probably + * the best we can do at this point. Once all modules are + * loaded and the size of the metadata is known this + * space will be recovered if not used. + */ + mod_num = num_modules(rfp); + rfp->f_size = roundup(rfp->f_size, PAGE_SIZE); + rfp->f_size += METADATA_RESV_SIZE(mod_num); + *result = rfp; + } else { + /* The rest should be loaded as regular modules */ + error = elf64_obj_loadfile(filename, dest, result); + if (error != 0) { + printf("Unable to load %s as an object file, error: %d", + filename, error); + return (error); + } + } + + return (0); +} + +static int +multiboot_obj_exec(struct preloaded_file *fp) +{ + + return (EFTYPE); +} diff --git a/sys/boot/i386/libi386/multiboot.h b/sys/boot/i386/libi386/multiboot.h new file mode 100644 index 0000000..819fa2e --- /dev/null +++ b/sys/boot/i386/libi386/multiboot.h @@ -0,0 +1,225 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY +* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +* $FreeBSD$ +*/ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The bits in the required part of flags field we don't support. */ +#define MULTIBOOT_UNSUPPORTED 0x0000fffc + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the 'flags' member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the 'flags' member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 + +#ifndef ASM_FILE + +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ +/* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + +/* Feature flags. */ + multiboot_uint32_t flags; + +/* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + +/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + +/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ +/* Multiboot info version number */ + multiboot_uint32_t flags; + +/* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + +/* "root" partition */ + multiboot_uint32_t boot_device; + +/* Kernel command line */ + multiboot_uint32_t cmdline; + +/* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + +/* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + +/* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + +/* ROM configuration table */ + multiboot_uint32_t config_table; + +/* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + +/* APM table */ + multiboot_uint32_t apm_table; + +/* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ +/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + +/* Module command line */ + multiboot_uint32_t cmdline; + +/* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/sys/boot/i386/libi386/multiboot_tramp.S b/sys/boot/i386/libi386/multiboot_tramp.S new file mode 100644 index 0000000..0bd6043 --- /dev/null +++ b/sys/boot/i386/libi386/multiboot_tramp.S @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2014 Roger Pau Monné <royger@FreeBSD.org> + * 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$ + */ + +#define ASM_FILE +#include "multiboot.h" + +/* + * The multiboot specification requires the executable to be launched + * with %cs set to a flat read/execute segment with offset 0 and limit + * 0xFFFFFFFF, and the rest of the segment registers (%ds, %es, %fs, + * %gs, %ss) to flat read/write segments with the same offset and limit. + * This is already done by the BTX code before calling multiboot_tramp, + * so there is no need to do anything here. + */ + + .globl multiboot_tramp +multiboot_tramp: + /* Be sure that interrupts are disabled. */ + cli + + movl $MULTIBOOT_BOOTLOADER_MAGIC, %eax + /* Get the entry point and address of the multiboot_info parameter. */ + movl 8(%esp), %ebx + movl 4(%esp), %ecx + + call *%ecx diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c index fda6fd2..38df74d 100644 --- a/sys/boot/i386/loader/conf.c +++ b/sys/boot/i386/loader/conf.c @@ -107,8 +107,12 @@ extern struct file_format i386_elf; extern struct file_format i386_elf_obj; extern struct file_format amd64_elf; extern struct file_format amd64_elf_obj; +extern struct file_format multiboot; +extern struct file_format multiboot_obj; struct file_format *file_formats[] = { + &multiboot, + &multiboot_obj, #ifdef LOADER_PREFER_AMD64 &amd64_elf, &amd64_elf_obj, diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c index afb77b2..ca82c63 100644 --- a/sys/boot/i386/zfsboot/zfsboot.c +++ b/sys/boot/i386/zfsboot/zfsboot.c @@ -238,7 +238,7 @@ bios_getmem(void) v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); - if ((v86.efl & 1) || (v86.eax != SMAP_SIG)) + if (V86_CY(v86.efl) || (v86.eax != SMAP_SIG)) break; /* look for a low-memory segment that's large enough */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && @@ -285,7 +285,7 @@ bios_getmem(void) v86.addr = 0x15; /* int 0x15 function 0xe801*/ v86.eax = 0xe801; v86int(); - if (!(v86.efl & 1)) { + if (!V86_CY(v86.efl)) { bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; } } @@ -320,7 +320,7 @@ int13probe(int drive) v86.edx = drive; v86int(); - if (!(v86.efl & 0x1) && /* carry clear */ + if (!V86_CY(v86.efl) && /* carry clear */ ((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */ if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */ return(0); /* skip device */ diff --git a/sys/boot/ia64/efi/Makefile b/sys/boot/ia64/efi/Makefile index 6bb53b5..18b6d3a 100644 --- a/sys/boot/ia64/efi/Makefile +++ b/sys/boot/ia64/efi/Makefile @@ -37,7 +37,6 @@ FILESMODE_loader.efi= ${BINMODE} loader.efi: loader.sym if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ - rm ${.ALLSRC}; \ exit 1; \ fi ${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \ diff --git a/sys/boot/libstand32/Makefile b/sys/boot/libstand32/Makefile index 1fc04a2..4ee8690 100644 --- a/sys/boot/libstand32/Makefile +++ b/sys/boot/libstand32/Makefile @@ -63,8 +63,8 @@ SRCS+= ntoh.c .if ${MACHINE_CPUARCH} != "ia64" SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \ memmove.c memset.c qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \ - strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \ - strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c + strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \ + strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c .endif .if ${MACHINE_CPUARCH} == "arm" .PATH: ${LIBC}/arm/gen diff --git a/sys/boot/pc98/boot2/boot2.c b/sys/boot/pc98/boot2/boot2.c index 69a422e..72aae7d 100644 --- a/sys/boot/pc98/boot2/boot2.c +++ b/sys/boot/pc98/boot2/boot2.c @@ -326,7 +326,7 @@ bd_getbigeom(int bunit) v86.addr = 0x1b; v86.eax = 0x8400 | unit; v86int(); - if (v86.efl & 0x1) + if (V86_CY(v86.efl)) return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */ return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff); } diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c index 96dbd1f..b777d25 100644 --- a/sys/boot/pc98/libpc98/biosdisk.c +++ b/sys/boot/pc98/libpc98/biosdisk.c @@ -824,7 +824,7 @@ bd_chs_io(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest, int write) v86.es = VTOPSEG(dest); v86.ebp = VTOPOFF(dest); v86int(); - return (v86.efl & 0x1); + return (V86_CY(v86.efl)); } static int @@ -959,7 +959,7 @@ bd_getgeom(struct open_disk *od) od->od_cyl = v86.ecx; od->od_hds = (v86.edx >> 8) & 0xff; od->od_sec = v86.edx & 0xff; - if (v86.efl & 0x1) + if (V86_CY(v86.efl)) return(1); } @@ -1010,7 +1010,7 @@ bd_getbigeom(int bunit) v86.addr = 0x1b; v86.eax = 0x8400 | unit; v86int(); - if (v86.efl & 0x1) + if (V86_CY(v86.efl)) return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */ return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff); } diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c index b830354..d860d97 100644 --- a/sys/boot/uboot/common/main.c +++ b/sys/boot/uboot/common/main.c @@ -315,7 +315,7 @@ print_disk_probe_info() else strcpy(slice, "<auto>"); - if (currdev.d_disk.partition > 0) + if (currdev.d_disk.partition >= 0) sprintf(partition, "%d", currdev.d_disk.partition); else strcpy(partition, "<auto>"); @@ -382,7 +382,7 @@ probe_disks(int devidx, int load_type, int load_unit, int load_slice, printf("\n"); } - printf(" Requested disk type/unit not found\n"); + printf(" Requested disk type/unit/slice/partition not found\n"); return (-1); } @@ -392,7 +392,7 @@ main(void) struct api_signature *sig = NULL; int load_type, load_unit, load_slice, load_partition; int i; - const char * loaderdev; + const char *ldev; /* * If we can't find the magic signature and related info, exit with a @@ -485,10 +485,10 @@ main(void) return (0xbadef1ce); } - env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev), - uboot_setcurrdev, env_nounset); - env_setenv("loaddev", EV_VOLATILE, uboot_fmtdev(&currdev), - env_noset, env_nounset); + ldev = uboot_fmtdev(&currdev); + env_setenv("currdev", EV_VOLATILE, ldev, uboot_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, ldev, env_noset, env_nounset); + printf("Booting from %s\n", ldev); setenv("LINES", "24", 1); /* optional */ setenv("prompt", "loader>", 1); @@ -573,17 +573,47 @@ enum ubenv_action { static void handle_uboot_env_var(enum ubenv_action action, const char * var) { - const char * val; - char ubv[128]; + char ldvar[128]; + const char *val; + char *wrk; + int len; + + /* + * On an import with the variable name formatted as ldname=ubname, + * import the uboot variable ubname into the loader variable ldname, + * otherwise the historical behavior is to import to uboot.ubname. + */ + 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); + } else { + len = MIN(len, sizeof(ldvar) - 1); + strncpy(ldvar, var, len); + ldvar[len] = 0; + var = &var[len + 1]; + } + } /* * If the user prepended "uboot." (which is how they usually see these * names) strip it off as a convenience. */ if (strncmp(var, "uboot.", 6) == 0) { - snprintf(ubv, sizeof(ubv), "%s", &var[6]); - var = ubv; + var = &var[6]; } + + /* 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) { if (val == NULL) @@ -592,8 +622,7 @@ handle_uboot_env_var(enum ubenv_action action, const char * var) printf("uboot.%s=%s\n", var, val); } else if (action == UBENV_IMPORT) { if (val != NULL) { - snprintf(ubv, sizeof(ubv), "uboot.%s", var); - setenv(ubv, val, 1); + setenv(ldvar, val, 1); } } } diff --git a/sys/boot/uboot/lib/copy.c b/sys/boot/uboot/lib/copy.c index bb658e3..76f2faf 100644 --- a/sys/boot/uboot/lib/copy.c +++ b/sys/boot/uboot/lib/copy.c @@ -69,11 +69,11 @@ uint64_t uboot_loadaddr(u_int type, void *data, uint64_t addr) { struct sys_info *si; - uintptr_t sblock, eblock, subldr, eubldr; - uintptr_t biggest_block, this_block; - size_t biggest_size, this_size; + uint64_t sblock, eblock, subldr, eubldr; + uint64_t biggest_block, this_block; + uint64_t biggest_size, this_size; int i; - char * envstr; + char *envstr; if (addr == 0) { /* @@ -101,13 +101,14 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr) biggest_block = 0; biggest_size = 0; subldr = rounddown2((uintptr_t)_start, KERN_ALIGN); - eubldr = roundup2(uboot_heap_end, KERN_ALIGN); + eubldr = roundup2((uint64_t)uboot_heap_end, KERN_ALIGN); for (i = 0; i < si->mr_no; i++) { if (si->mr[i].flags != MR_ATTR_DRAM) continue; - sblock = roundup2(si->mr[i].start, KERN_ALIGN); - eblock = rounddown2(si->mr[i].start + si->mr[i].size, + sblock = roundup2((uint64_t)si->mr[i].start, KERN_ALIGN); + eblock = rounddown2((uint64_t)si->mr[i].start + + si->mr[i].size, KERN_ALIGN); if (biggest_size == 0) sblock += KERN_MINADDR; if (subldr >= sblock && subldr < eblock) { @@ -127,9 +128,10 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr) if (biggest_size == 0) panic("Not enough DRAM to load kernel\n"); #if 0 - printf("Loading kernel into region 0x%08x-0x%08x (%u MiB)\n", - biggest_block, biggest_block + biggest_size - 1, - biggest_size / 1024 / 1024); + printf("Loading kernel into region 0x%08jx-0x%08jx (%ju MiB)\n", + (uintmax_t)biggest_block, + (uintmax_t)biggest_block + biggest_size - 1, + (uintmax_t)biggest_size / 1024 / 1024); #endif return (biggest_block); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index fd3e537..ee0b52f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -607,7 +607,6 @@ spa_prop_validate(spa_t *spa, nvlist_t *props) error = SET_ERROR(EINVAL); break; } - check++; } if (strlen(strval) > ZPROP_MAX_COMMENT) error = E2BIG; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c index 49d87e6..9f83abb 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c @@ -520,7 +520,7 @@ vdev_queue_class_min_active(zio_priority_t p) } } -static int +static __noinline int vdev_queue_max_async_writes(spa_t *spa) { int writes; diff --git a/sys/cddl/dev/systrace/systrace.c b/sys/cddl/dev/systrace/systrace.c index 921393c..1796091 100644 --- a/sys/cddl/dev/systrace/systrace.c +++ b/sys/cddl/dev/systrace/systrace.c @@ -60,24 +60,37 @@ #ifdef LINUX_SYSTRACE #if defined(__amd64__) -#include <amd64/linux32/linux.h> -#include <amd64/linux32/linux32_proto.h> -#include <amd64/linux32/linux32_syscalls.c> -#include <amd64/linux32/linux32_systrace_args.c> -#define MODNAME "linux32" +#include <amd64/linux/linux.h> +#include <amd64/linux/linux_proto.h> +#include <amd64/linux/linux_syscalls.c> +#include <amd64/linux/linux_systrace_args.c> #elif defined(__i386__) #include <i386/linux/linux.h> #include <i386/linux/linux_proto.h> #include <i386/linux/linux_syscalls.c> #include <i386/linux/linux_systrace_args.c> -#define MODNAME "linux" #else #error Only i386 and amd64 are supported. #endif +#define MODNAME "linux" extern struct sysent linux_sysent[]; #define MAXSYSCALL LINUX_SYS_MAXSYSCALL #define SYSCALLNAMES linux_syscallnames #define SYSENT linux_sysent +#elif defined(LINUX32_SYSTRACE) +#if defined(__amd64__) +#include <amd64/linux32/linux.h> +#include <amd64/linux32/linux32_proto.h> +#include <amd64/linux32/linux32_syscalls.c> +#include <amd64/linux32/linux32_systrace_args.c> +#else +#error Only amd64 is supported. +#endif +#define MODNAME "linux32" +extern struct sysent linux32_sysent[]; +#define MAXSYSCALL LINUX32_SYS_MAXSYSCALL +#define SYSCALLNAMES linux32_syscallnames +#define SYSENT linux32_sysent #elif defined(FREEBSD32_SYSTRACE) /* * The syscall arguments are processed into a DTrace argument array @@ -103,6 +116,7 @@ extern const char *freebsd32_syscallnames[]; #define MAXSYSCALL SYS_MAXSYSCALL #define SYSCALLNAMES syscallnames #define SYSENT sysent +#define NATIVE_ABI #endif #define PROVNAME "syscall" @@ -132,7 +146,7 @@ static void systrace_load(void *); static struct cdevsw systrace_cdevsw = { .d_version = D_VERSION, .d_open = systrace_open, -#ifdef LINUX_SYSTRACE +#ifndef NATIVE_ABI .d_name = "systrace_" MODNAME, #else .d_name = "systrace", @@ -171,7 +185,7 @@ static dtrace_provider_id_t systrace_id; typedef void (*systrace_dtrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); -#if !defined(LINUX_SYSTRACE) +#ifdef NATIVE_ABI /* * Probe callback function. * @@ -314,7 +328,7 @@ systrace_load(void *dummy) NULL, &systrace_pops, NULL, &systrace_id) != 0) return; -#if !defined(LINUX_SYSTRACE) +#ifdef NATIVE_ABI systrace_probe_func = systrace_probe; #endif } @@ -328,7 +342,7 @@ systrace_unload() if ((error = dtrace_unregister(systrace_id)) != 0) return (error); -#if !defined(LINUX_SYSTRACE) +#ifdef NATIVE_ABI systrace_probe_func = NULL; #endif @@ -370,6 +384,16 @@ SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_load, NULL SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_unload, NULL); #ifdef LINUX_SYSTRACE +DEV_MODULE(systrace_linux, systrace_modevent, NULL); +MODULE_VERSION(systrace_linux, 1); +#ifdef __amd64__ +MODULE_DEPEND(systrace_linux, linux64, 1, 1, 1); +#else +MODULE_DEPEND(systrace_linux, linux, 1, 1, 1); +#endif +MODULE_DEPEND(systrace_linux, dtrace, 1, 1, 1); +MODULE_DEPEND(systrace_linux, opensolaris, 1, 1, 1); +#elif defined(LINUX32_SYSTRACE) DEV_MODULE(systrace_linux32, systrace_modevent, NULL); MODULE_VERSION(systrace_linux32, 1); MODULE_DEPEND(systrace_linux32, linux, 1, 1, 1); diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c index 206935a..d2870ce 100644 --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -140,6 +140,7 @@ struct sysentvec ia32_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec); diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 8f2a687..538b9dc 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -2362,7 +2362,13 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args) #if defined(DEBUG) || defined(KTR) /* XXX: can be removed when every ldebug(...) and KTR stuff are removed. */ -u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))]; +#ifdef COMPAT_LINUX32 +#define L_MAXSYSCALL LINUX32_SYS_MAXSYSCALL +#else +#define L_MAXSYSCALL LINUX_SYS_MAXSYSCALL +#endif + +u_char linux_debug_map[howmany(L_MAXSYSCALL, sizeof(u_char))]; static int linux_debug(int syscall, int toggle, int global) @@ -2374,7 +2380,7 @@ linux_debug(int syscall, int toggle, int global) memset(linux_debug_map, c, sizeof(linux_debug_map)); return (0); } - if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL) + if (syscall < 0 || syscall >= L_MAXSYSCALL) return (EINVAL); if (toggle) clrbit(linux_debug_map, syscall); @@ -2382,6 +2388,7 @@ linux_debug(int syscall, int toggle, int global) setbit(linux_debug_map, syscall); return (0); } +#undef L_MAXSYSCALL /* * Usage: sysctl linux.debug=<syscall_nr>.<0/1> diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 34af9da..dee4093 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -1164,6 +1164,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, msg.msg_iov = iov; msg.msg_flags = 0; error = linux_sendit(td, s, &msg, flags, control, UIO_USERSPACE); + control = NULL; bad: m_freem(control); diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 125a7d8..8b339c8 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -197,6 +197,7 @@ struct sysentvec svr4_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; const char svr4_emul_path[] = "/compat/svr4"; diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 268892b..445912a 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -322,6 +322,7 @@ dev/sfxge/common/efx_ev.c optional sfxge pci dev/sfxge/common/efx_filter.c optional sfxge pci dev/sfxge/common/efx_hash.c optional sfxge pci dev/sfxge/common/efx_intr.c optional sfxge pci +dev/sfxge/common/efx_lic.c optional sfxge pci dev/sfxge/common/efx_mac.c optional sfxge pci dev/sfxge/common/efx_mcdi.c optional sfxge pci dev/sfxge/common/efx_mon.c optional sfxge pci diff --git a/sys/dev/drm2/i915/intel_iic.c b/sys/dev/drm2/i915/intel_iic.c index 36a5b9e..30be2efb 100644 --- a/sys/dev/drm2/i915/intel_iic.c +++ b/sys/dev/drm2/i915/intel_iic.c @@ -467,8 +467,7 @@ timeout: * Try GPIO bitbanging instead. */ sc->force_bit_dev = true; - error = -IICBUS_TRANSFER(idev, msgs, nmsgs); - goto out; + error = -IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, nmsgs); out: sx_xunlock(&dev_priv->gmbus_sx); diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 088ba1e..c4dc51d 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -1313,7 +1313,8 @@ igb_init_locked(struct adapter *adapter) if (ifp->if_capenable & IFCAP_TXCSUM) { ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); #if __FreeBSD_version >= 800000 - if (adapter->hw.mac.type == e1000_82576) + if ((adapter->hw.mac.type == e1000_82576) || + (adapter->hw.mac.type == e1000_82580)) ifp->if_hwassist |= CSUM_SCTP; #endif } @@ -4587,8 +4588,9 @@ igb_initialize_receive_units(struct adapter *adapter) rxcsum |= E1000_RXCSUM_PCSD; #if __FreeBSD_version >= 800000 /* For SCTP Offload */ - if ((hw->mac.type == e1000_82576) - && (ifp->if_capenable & IFCAP_RXCSUM)) + if (((hw->mac.type == e1000_82576) || + (hw->mac.type == e1000_82580)) && + (ifp->if_capenable & IFCAP_RXCSUM)) rxcsum |= E1000_RXCSUM_CRCOFL; #endif } else { @@ -4596,7 +4598,8 @@ igb_initialize_receive_units(struct adapter *adapter) if (ifp->if_capenable & IFCAP_RXCSUM) { rxcsum |= E1000_RXCSUM_IPPCSE; #if __FreeBSD_version >= 800000 - if (adapter->hw.mac.type == e1000_82576) + if ((adapter->hw.mac.type == e1000_82576) || + (adapter->hw.mac.type == e1000_82580)) rxcsum |= E1000_RXCSUM_CRCOFL; #endif } else diff --git a/sys/dev/iicbus/icee.c b/sys/dev/iicbus/icee.c index 800ec4c..fffb356 100644 --- a/sys/dev/iicbus/icee.c +++ b/sys/dev/iicbus/icee.c @@ -27,6 +27,9 @@ __FBSDID("$FreeBSD$"); /* * Generic IIC eeprom support, modeled after the AT24C family of products. */ + +#include "opt_platform.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -37,26 +40,73 @@ __FBSDID("$FreeBSD$"); #include <sys/sx.h> #include <sys/uio.h> #include <machine/bus.h> + +#ifdef FDT +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#endif + #include <dev/iicbus/iiconf.h> #include <dev/iicbus/iicbus.h> #include "iicbus_if.h" -#define IIC_M_WR 0 /* write operation */ +/* + * AT24 parts have a "write page size" that differs per-device, and a "read page + * size" that is always equal to the full device size. We define maximum values + * here to limit how long we occupy the bus with a single transfer, and because + * there are temporary buffers of these sizes allocated on the stack. + */ #define MAX_RD_SZ 256 /* Largest read size we support */ -#define MAX_WR_SZ 256 /* Largest write size we support */ +#define MAX_WR_SZ 256 /* Largest write size we support */ struct icee_softc { - device_t sc_dev; /* Myself */ - device_t sc_busdev; /* Parent bus */ + device_t dev; /* Myself */ struct cdev *cdev; /* user interface */ - int addr; + int addr; /* Slave address on the bus */ int size; /* How big am I? */ - int type; /* What type 8 or 16 bit? */ - int rd_sz; /* What's the read page size */ + int type; /* What address type 8 or 16 bit? */ int wr_sz; /* What's the write page size */ }; +#ifdef FDT +struct eeprom_desc { + int type; + int size; + int wr_sz; + const char *name; +}; + +static struct eeprom_desc type_desc[] = { + { 8, 128, 8, "AT24C01"}, + { 8, 256, 8, "AT24C02"}, + { 8, 512, 16, "AT24C04"}, + { 8, 1024, 16, "AT24C08"}, + { 8, 2 * 1024, 16, "AT24C16"}, + {16, 4 * 1024, 32, "AT24C32"}, + {16, 8 * 1024, 32, "AT24C64"}, + {16, 16 * 1024, 64, "AT24C128"}, + {16, 32 * 1024, 64, "AT24C256"}, + {16, 64 * 1024, 128, "AT24C512"}, + {16, 128 * 1024, 256, "AT24CM01"}, +}; + +static struct ofw_compat_data compat_data[] = { + {"atmel,24c01", (uintptr_t)(&type_desc[0])}, + {"atmel,24c02", (uintptr_t)(&type_desc[1])}, + {"atmel,24c04", (uintptr_t)(&type_desc[2])}, + {"atmel,24c08", (uintptr_t)(&type_desc[3])}, + {"atmel,24c16", (uintptr_t)(&type_desc[4])}, + {"atmel,24c32", (uintptr_t)(&type_desc[5])}, + {"atmel,24c64", (uintptr_t)(&type_desc[6])}, + {"atmel,24c128", (uintptr_t)(&type_desc[7])}, + {"atmel,24c256", (uintptr_t)(&type_desc[8])}, + {"atmel,24c512", (uintptr_t)(&type_desc[9])}, + {"atmel,24c1024", (uintptr_t)(&type_desc[10])}, + {NULL, (uintptr_t)NULL}, +}; +#endif + #define CDEV2SOFTC(dev) ((dev)->si_drv1) /* cdev routines */ @@ -75,6 +125,39 @@ static struct cdevsw icee_cdevsw = .d_write = icee_write }; +#ifdef FDT +static int +icee_probe(device_t dev) +{ + struct eeprom_desc *d; + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + d = (struct eeprom_desc *) + ofw_bus_search_compatible(dev, compat_data)->ocd_data; + if (d == NULL) + return (ENXIO); + + device_set_desc(dev, d->name); + return (BUS_PROBE_DEFAULT); +} + +static void +icee_init(struct icee_softc *sc) +{ + struct eeprom_desc *d; + + d = (struct eeprom_desc *) + ofw_bus_search_compatible(sc->dev, compat_data)->ocd_data; + if (d == NULL) + return; /* attach will see sc->size == 0 and return error */ + + sc->size = d->size; + sc->type = d->type; + sc->wr_sz = d->wr_sz; +} +#else /* !FDT */ static int icee_probe(device_t dev) { @@ -83,37 +166,44 @@ icee_probe(device_t dev) return (BUS_PROBE_NOWILDCARD); } -static int -icee_attach(device_t dev) +static void +icee_init(struct icee_softc *sc) { - struct icee_softc *sc = device_get_softc(dev); const char *dname; - int dunit, err; + int dunit; - sc->sc_dev = dev; - sc->sc_busdev = device_get_parent(sc->sc_dev); - sc->addr = iicbus_get_addr(dev); - err = 0; - dname = device_get_name(dev); - dunit = device_get_unit(dev); + dname = device_get_name(sc->dev); + dunit = device_get_unit(sc->dev); resource_int_value(dname, dunit, "size", &sc->size); resource_int_value(dname, dunit, "type", &sc->type); - resource_int_value(dname, dunit, "rd_sz", &sc->rd_sz); - if (sc->rd_sz > MAX_RD_SZ) - sc->rd_sz = MAX_RD_SZ; resource_int_value(dname, dunit, "wr_sz", &sc->wr_sz); +} +#endif /* FDT */ + +static int +icee_attach(device_t dev) +{ + struct icee_softc *sc = device_get_softc(dev); + + sc->dev = dev; + sc->addr = iicbus_get_addr(dev); + icee_init(sc); + if (sc->size == 0 || sc->type == 0 || sc->wr_sz == 0) { + device_printf(sc->dev, "Missing config data, " + "these cannot be zero: size %d type %d wr_sz %d\n", + sc->size, sc->type, sc->wr_sz); + return (EINVAL); + } if (bootverbose) - device_printf(dev, "size: %d bytes bus_width: %d-bits\n", + device_printf(dev, "size: %d bytes, addressing: %d-bits\n", sc->size, sc->type); sc->cdev = make_dev(&icee_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "icee%d", device_get_unit(dev)); if (sc->cdev == NULL) { - err = ENOMEM; - goto out; + return (ENOMEM); } sc->cdev->si_drv1 = sc; -out: - return (err); + return (0); } static int @@ -149,14 +239,11 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag) return (EIO); if (sc->type != 8 && sc->type != 16) return (EINVAL); - error = iicbus_request_bus(sc->sc_busdev, sc->sc_dev, IIC_INTRWAIT); - if (error!= 0) - return (iic2errno(error)); slave = error = 0; while (uio->uio_resid > 0) { if (uio->uio_offset >= sc->size) break; - len = MIN(sc->rd_sz - (uio->uio_offset & (sc->rd_sz - 1)), + len = MIN(MAX_RD_SZ - (uio->uio_offset & (MAX_RD_SZ - 1)), uio->uio_resid); switch (sc->type) { case 8: @@ -175,7 +262,7 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag) } for (i = 0; i < 2; i++) msgs[i].slave = slave; - error = iicbus_transfer(sc->sc_dev, msgs, 2); + error = iicbus_transfer_excl(sc->dev, msgs, 2, IIC_INTRWAIT); if (error) { error = iic2errno(error); break; @@ -184,7 +271,6 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag) if (error) break; } - iicbus_release_bus(sc->sc_busdev, sc->sc_dev); return (error); } @@ -213,9 +299,6 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag) if (sc->type != 8 && sc->type != 16) return (EINVAL); - error = iicbus_request_bus(sc->sc_busdev, sc->sc_dev, IIC_INTRWAIT); - if (error!= 0) - return (iic2errno(error)); slave = error = 0; while (uio->uio_resid > 0) { if (uio->uio_offset >= sc->size) @@ -239,7 +322,7 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag) error = uiomove(data + sc->type / 8, len, uio); if (error) break; - error = iicbus_transfer(sc->sc_dev, wr, 1); + error = iicbus_transfer_excl(sc->dev, wr, 1, IIC_INTRWAIT); if (error) { error = iic2errno(error); break; @@ -248,14 +331,14 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag) waitlimit = 10000; rd[0].slave = slave; do { - error = iicbus_transfer(sc->sc_dev, rd, 1); + error = iicbus_transfer_excl(sc->dev, rd, 1, + IIC_INTRWAIT); } while (waitlimit-- > 0 && error != 0); if (error) { error = iic2errno(error); break; } } - iicbus_release_bus(sc->sc_busdev, sc->sc_dev); return error; } diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index 977d52a..ed1d7b8 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -149,22 +149,9 @@ iicbb_attach(device_t dev) static int iicbb_detach(device_t dev) { - struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev); - device_t child; - - /* - * We need to save child because the detach indirectly causes - * sc->iicbus to be zeroed. Since we added the device - * unconditionally in iicbb_attach, we need to make sure we - * delete it here. See iicbb_child_detached. We need that - * callback in case newbus detached our children w/o detaching - * us (say iicbus is a module and unloaded w/o iicbb being - * unloaded). - */ - child = sc->iicbus; + bus_generic_detach(dev); - if (child) - device_delete_child(dev, child); + device_delete_children(dev); return (0); } diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c index dc56760..e377383 100644 --- a/sys/dev/iicbus/iicbus.c +++ b/sys/dev/iicbus/iicbus.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/mutex.h> #include <sys/sysctl.h> -#include <sys/bus.h> +#include <sys/bus.h> #include <dev/iicbus/iiconf.h> #include <dev/iicbus/iicbus.h> @@ -60,7 +60,7 @@ iicbus_probe(device_t dev) } #if SCAN_IICBUS -static int +static int iic_probe_device(device_t dev, u_char addr) { int count; @@ -126,7 +126,7 @@ iicbus_attach(device_t dev) bus_generic_attach(dev); return (0); } - + static int iicbus_detach(device_t dev) { @@ -134,10 +134,11 @@ iicbus_detach(device_t dev) iicbus_reset(dev, IIC_FASTEST, 0, NULL); bus_generic_detach(dev); + device_delete_children(dev); mtx_destroy(&sc->lock); return (0); } - + static int iicbus_print_child(device_t dev, device_t child) { diff --git a/sys/dev/iicbus/iicoc.c b/sys/dev/iicbus/iicoc.c index 45f1692..c55d6fe 100644 --- a/sys/dev/iicbus/iicoc.c +++ b/sys/dev/iicbus/iicoc.c @@ -229,6 +229,7 @@ static int iicoc_detach(device_t dev) { bus_generic_detach(dev); + device_delete_children(dev); return (0); } diff --git a/sys/dev/iicbus/iiconf.c b/sys/dev/iicbus/iiconf.c index e28d341..8ac8a47 100644 --- a/sys/dev/iicbus/iiconf.c +++ b/sys/dev/iicbus/iiconf.c @@ -395,6 +395,21 @@ iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); } +int +iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, + int how) +{ + device_t bus; + int error; + + bus = device_get_parent(dev); + error = iicbus_request_bus(bus, dev, how); + if (error == 0) + error = IICBUS_TRANSFER(bus, msgs, nmsgs); + iicbus_release_bus(bus, dev); + return (error); +} + /* * Generic version of iicbus_transfer that calls the appropriate * routines to accomplish this. See note above about acceptable diff --git a/sys/dev/iicbus/iiconf.h b/sys/dev/iicbus/iiconf.h index aca0137..12ac0d7 100644 --- a/sys/dev/iicbus/iiconf.h +++ b/sys/dev/iicbus/iiconf.h @@ -129,6 +129,8 @@ extern int iicbus_block_read(device_t, u_char, char *, int, int *); /* vectors of iic operations to pass to bridge */ int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs); +int iicbus_transfer_excl(device_t bus, struct iic_msg *msgs, uint32_t nmsgs, + int how); int iicbus_transfer_gen(device_t bus, struct iic_msg *msgs, uint32_t nmsgs); #define IICBUS_MODVER 1 diff --git a/sys/dev/iicbus/iicsmb.c b/sys/dev/iicbus/iicsmb.c index 27f1d2b..d8f35c6 100644 --- a/sys/dev/iicbus/iicsmb.c +++ b/sys/dev/iicbus/iicsmb.c @@ -167,11 +167,9 @@ static int iicsmb_detach(device_t dev) { struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); - + bus_generic_detach(dev); - if (sc->smbus) { - device_delete_child(dev, sc->smbus); - } + device_delete_children(dev); mtx_destroy(&sc->lock); return (0); diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index 63abafc..b0c9448 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -102,6 +102,9 @@ static int fail_on_disconnection = 0; TUNABLE_INT("kern.iscsi.fail_on_disconnection", &fail_on_disconnection); SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN, &fail_on_disconnection, 0, "Destroy CAM SIM on connection failure"); +static int fail_on_shutdown = 1; +SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_shutdown, CTLFLAG_RWTUN, + &fail_on_shutdown, 0, "Fail disconnected sessions on shutdown"); static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator"); static uma_zone_t iscsi_outstanding_zone; @@ -421,8 +424,6 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is) sc = is->is_softc; sx_xlock(&sc->sc_lock); - TAILQ_REMOVE(&sc->sc_sessions, is, is_next); - sx_xunlock(&sc->sc_lock); icl_conn_close(is->is_conn); callout_drain(&is->is_callout); @@ -454,6 +455,9 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is) #ifdef ICL_KERNEL_PROXY cv_destroy(&is->is_login_cv); #endif + TAILQ_REMOVE(&sc->sc_sessions, is, is_next); + sx_xunlock(&sc->sc_lock); + ISCSI_SESSION_DEBUG(is, "terminated"); free(is, M_ISCSI); @@ -477,12 +481,7 @@ iscsi_maintenance_thread(void *arg) STAILQ_EMPTY(&is->is_postponed)) cv_wait(&is->is_maintenance_cv, &is->is_lock); - if (is->is_reconnecting) { - ISCSI_SESSION_UNLOCK(is); - iscsi_maintenance_thread_reconnect(is); - continue; - } - + /* Terminate supersedes reconnect. */ if (is->is_terminating) { ISCSI_SESSION_UNLOCK(is); iscsi_maintenance_thread_terminate(is); @@ -490,6 +489,12 @@ iscsi_maintenance_thread(void *arg) return; } + if (is->is_reconnecting) { + ISCSI_SESSION_UNLOCK(is); + iscsi_maintenance_thread_reconnect(is); + continue; + } + iscsi_session_send_postponed(is); ISCSI_SESSION_UNLOCK(is); } @@ -609,6 +614,11 @@ iscsi_callout(void *context) return; out: + if (is->is_terminating) { + ISCSI_SESSION_UNLOCK(is); + return; + } + ISCSI_SESSION_UNLOCK(is); if (reconnect_needed) @@ -2320,30 +2330,62 @@ iscsi_poll(struct cam_sim *sim) } static void -iscsi_shutdown(struct iscsi_softc *sc) +iscsi_terminate_sessions(struct iscsi_softc *sc) { struct iscsi_session *is; - /* - * Trying to reconnect during system shutdown would lead to hang. - */ - fail_on_disconnection = 1; + sx_slock(&sc->sc_lock); + TAILQ_FOREACH(is, &sc->sc_sessions, is_next) + iscsi_session_terminate(is); + while(!TAILQ_EMPTY(&sc->sc_sessions)) { + ISCSI_DEBUG("waiting for sessions to terminate"); + cv_wait(&sc->sc_cv, &sc->sc_lock); + } + ISCSI_DEBUG("all sessions terminated"); + sx_sunlock(&sc->sc_lock); +} + +static void +iscsi_shutdown_pre(struct iscsi_softc *sc) +{ + struct iscsi_session *is; + + if (!fail_on_shutdown) + return; /* * If we have any sessions waiting for reconnection, request * maintenance thread to fail them immediately instead of waiting * for reconnect timeout. + * + * This prevents LUNs with mounted filesystems that are supported + * by disconnected iSCSI sessions from hanging, however it will + * fail all queued BIOs. */ + ISCSI_DEBUG("forcing failing all disconnected sessions due to shutdown"); + + fail_on_disconnection = 1; + sx_slock(&sc->sc_lock); TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { ISCSI_SESSION_LOCK(is); - if (is->is_waiting_for_iscsid) + if (!is->is_connected) { + ISCSI_SESSION_DEBUG(is, "force failing disconnected session early"); iscsi_session_reconnect(is); + } ISCSI_SESSION_UNLOCK(is); } sx_sunlock(&sc->sc_lock); } +static void +iscsi_shutdown_post(struct iscsi_softc *sc) +{ + + ISCSI_DEBUG("removing all sessions due to shutdown"); + iscsi_terminate_sessions(sc); +} + static int iscsi_load(void) { @@ -2366,8 +2408,16 @@ iscsi_load(void) } sc->sc_cdev->si_drv1 = sc; - sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, - iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST); + sc->sc_shutdown_pre_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, + iscsi_shutdown_pre, sc, SHUTDOWN_PRI_FIRST); + /* + * shutdown_post_sync needs to run after filesystem shutdown and before + * CAM shutdown - otherwise when rebooting with an iSCSI session that is + * disconnected but has outstanding requests, dashutdown() will hang on + * cam_periph_runccb(). + */ + sc->sc_shutdown_post_eh = EVENTHANDLER_REGISTER(shutdown_post_sync, + iscsi_shutdown_post, sc, SHUTDOWN_PRI_DEFAULT - 1); return (0); } @@ -2375,7 +2425,6 @@ iscsi_load(void) static int iscsi_unload(void) { - struct iscsi_session *is, *tmp; if (sc->sc_cdev != NULL) { ISCSI_DEBUG("removing device node"); @@ -2383,18 +2432,12 @@ iscsi_unload(void) ISCSI_DEBUG("device node removed"); } - if (sc->sc_shutdown_eh != NULL) - EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh); + if (sc->sc_shutdown_pre_eh != NULL) + EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_pre_eh); + if (sc->sc_shutdown_post_eh != NULL) + EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_post_eh); - sx_slock(&sc->sc_lock); - TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) - iscsi_session_terminate(is); - while(!TAILQ_EMPTY(&sc->sc_sessions)) { - ISCSI_DEBUG("waiting for sessions to terminate"); - cv_wait(&sc->sc_cv, &sc->sc_lock); - } - ISCSI_DEBUG("all sessions terminated"); - sx_sunlock(&sc->sc_lock); + iscsi_terminate_sessions(sc); uma_zdestroy(iscsi_outstanding_zone); sx_destroy(&sc->sc_lock); diff --git a/sys/dev/iscsi/iscsi.h b/sys/dev/iscsi/iscsi.h index 0fe1515..11ecc42 100644 --- a/sys/dev/iscsi/iscsi.h +++ b/sys/dev/iscsi/iscsi.h @@ -130,7 +130,8 @@ struct iscsi_softc { TAILQ_HEAD(, iscsi_session) sc_sessions; struct cv sc_cv; unsigned int sc_last_session_id; - eventhandler_tag sc_shutdown_eh; + eventhandler_tag sc_shutdown_pre_eh; + eventhandler_tag sc_shutdown_post_eh; }; #endif /* !ISCSI_H */ diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c index 7be8a18..24ee075 100644 --- a/sys/dev/nvd/nvd.c +++ b/sys/dev/nvd/nvd.c @@ -295,7 +295,7 @@ nvd_new_disk(struct nvme_namespace *ns, void *ctrlr_arg) disk->d_sectorsize = nvme_ns_get_sector_size(ns); disk->d_mediasize = (off_t)nvme_ns_get_size(ns); disk->d_delmaxsize = (off_t)nvme_ns_get_size(ns); - disk->d_stripesize = nvme_ns_get_stripesize(ns); + disk->d_stripesize = nvme_ns_get_optimal_sector_size(ns); if (TAILQ_EMPTY(&disk_head)) disk->d_unit = 0; diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h index 7e41e77..227a89e 100644 --- a/sys/dev/nvme/nvme.h +++ b/sys/dev/nvme/nvme.h @@ -870,6 +870,7 @@ const char * nvme_ns_get_serial_number(struct nvme_namespace *ns); const char * nvme_ns_get_model_number(struct nvme_namespace *ns); const struct nvme_namespace_data * nvme_ns_get_data(struct nvme_namespace *ns); +uint32_t nvme_ns_get_optimal_sector_size(struct nvme_namespace *ns); uint32_t nvme_ns_get_stripesize(struct nvme_namespace *ns); int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c index 754d074..4580e66 100644 --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include "nvme_private.h" +extern int nvme_max_optimal_sectorsize; + static void nvme_bio_child_inbed(struct bio *parent, int bio_error); static void nvme_bio_child_done(void *arg, const struct nvme_completion *cpl); @@ -217,6 +219,22 @@ nvme_ns_get_stripesize(struct nvme_namespace *ns) return (ns->stripesize); } +uint32_t +nvme_ns_get_optimal_sector_size(struct nvme_namespace *ns) +{ + uint32_t stripesize; + + stripesize = nvme_ns_get_stripesize(ns); + + if (stripesize == 0) + return nvme_ns_get_sector_size(ns); + + if (nvme_max_optimal_sectorsize == 0) + return (stripesize); + + return (MIN(stripesize, nvme_max_optimal_sectorsize)); +} + static void nvme_ns_bio_done(void *arg, const struct nvme_completion *status) { diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c index 44b0ab7..08cd15e 100644 --- a/sys/dev/nvme/nvme_sysctl.c +++ b/sys/dev/nvme/nvme_sysctl.c @@ -33,6 +33,22 @@ __FBSDID("$FreeBSD$"); #include "nvme_private.h" +SYSCTL_NODE(_kern, OID_AUTO, nvme, CTLFLAG_RD, 0, "NVM Express"); +/* + * Intel NVMe controllers have a slow path for I/Os that span a 128KB + * stripe boundary but ZFS limits ashift, which is derived from + * d_stripesize, to 13 (8KB) so we limit the stripesize reported to + * geom(8) to 4KB by default. + * + * This may result in a small number of additional I/Os to require + * splitting in nvme(4), however the NVMe I/O path is very efficient + * so these additional I/Os will cause very minimal (if any) difference + * in performance or CPU utilisation. + */ +int nvme_max_optimal_sectorsize = 1<<12; +SYSCTL_INT(_kern_nvme, OID_AUTO, max_optimal_sectorsize, CTLFLAG_RWTUN, + &nvme_max_optimal_sectorsize, 0, "The maximum optimal sectorsize reported"); + /* * CTLTYPE_S64 and sysctl_handle_64 were added in r217616. Define these * explicitly here for older kernels that don't include the r217616 diff --git a/sys/dev/ofw/ofw_iicbus.c b/sys/dev/ofw/ofw_iicbus.c index f6d1be5..98fc060 100644 --- a/sys/dev/ofw/ofw_iicbus.c +++ b/sys/dev/ofw/ofw_iicbus.c @@ -147,7 +147,11 @@ ofw_iicbus_attach(device_t dev) M_NOWAIT | M_ZERO); if (dinfo == NULL) continue; - dinfo->opd_dinfo.addr = paddr; + /* + * OFW uses 7-bit I2C address format (see ePAPR), + * but system expect 8-bit. + */ + dinfo->opd_dinfo.addr = paddr << 1; if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 0) { free(dinfo, M_DEVBUF); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index e08237b..cef2db4 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -182,6 +182,8 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_release_msi, pci_release_msi_method), DEVMETHOD(pci_msi_count, pci_msi_count_method), DEVMETHOD(pci_msix_count, pci_msix_count_method), + DEVMETHOD(pci_msix_pba_bar, pci_msix_pba_bar_method), + DEVMETHOD(pci_msix_table_bar, pci_msix_table_bar_method), DEVMETHOD(pci_get_rid, pci_get_rid_method), DEVMETHOD(pci_child_added, pci_child_added_method), @@ -1827,6 +1829,28 @@ pci_msix_count_method(device_t dev, device_t child) return (0); } +int +pci_msix_pba_bar_method(device_t dev, device_t child) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + struct pcicfg_msix *msix = &dinfo->cfg.msix; + + if (pci_do_msix && msix->msix_location != 0) + return (msix->msix_pba_bar); + return (-1); +} + +int +pci_msix_table_bar_method(device_t dev, device_t child) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + struct pcicfg_msix *msix = &dinfo->cfg.msix; + + if (pci_do_msix && msix->msix_location != 0) + return (msix->msix_table_bar); + return (-1); +} + /* * HyperTransport MSI mapping control */ diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index 227d362..a44a641 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -36,6 +36,12 @@ CODE { { return (0); } + + static int + null_msix_bar(device_t dev, device_t child) + { + return (-1); + } }; @@ -180,6 +186,16 @@ METHOD int msix_count { device_t child; } DEFAULT null_msi_count; +METHOD int msix_pba_bar { + device_t dev; + device_t child; +} DEFAULT null_msix_bar; + +METHOD int msix_table_bar { + device_t dev; + device_t child; +} DEFAULT null_msix_bar; + METHOD uint16_t get_rid { device_t dev; device_t child; diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 5a90ce9..e446dc5 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -100,6 +100,8 @@ int pci_remap_msix_method(device_t dev, device_t child, int pci_release_msi_method(device_t dev, device_t child); int pci_msi_count_method(device_t dev, device_t child); int pci_msix_count_method(device_t dev, device_t child); +int pci_msix_pba_bar_method(device_t dev, device_t child); +int pci_msix_table_bar_method(device_t dev, device_t child); struct resource *pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index 73ce5e9..5453a53 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -260,6 +260,11 @@ #define PCIR_BIOS_1 0x38 #define PCIR_BRIDGECTL_1 0x3e +#define PCI_PPBMEMBASE(h,l) ((((uint64_t)(h) << 32) + ((l)<<16)) & ~0xfffff) +#define PCI_PPBMEMLIMIT(h,l) ((((uint64_t)(h) << 32) + ((l)<<16)) | 0xfffff) +#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff) +#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff) + /* config registers for header type 2 (CardBus) devices */ #define PCIR_MAX_BAR_2 0 @@ -279,6 +284,9 @@ #define PCIR_IOLIMIT0_2 0x30 #define PCIR_IOBASE1_2 0x34 #define PCIR_IOLIMIT1_2 0x38 +#define PCIM_CBBIO_16 0x0 +#define PCIM_CBBIO_32 0x1 +#define PCIM_CBBIO_MASK 0x3 #define PCIR_BRIDGECTL_2 0x3e @@ -287,6 +295,11 @@ #define PCIR_PCCARDIF_2 0x44 +#define PCI_CBBMEMBASE(l) ((l) & ~0xfffff) +#define PCI_CBBMEMLIMIT(l) ((l) | 0xfffff) +#define PCI_CBBIOBASE(l) ((l) & ~0x3) +#define PCI_CBBIOLIMIT(l) ((l) | 0x3) + /* PCI device class, subclass and programming interface definitions */ #define PCIC_OLD 0x00 @@ -474,6 +487,17 @@ #define PCIB_BCR_DISCARD_TIMER_STATUS 0x0400 #define PCIB_BCR_DISCARD_TIMER_SERREN 0x0800 +#define CBB_BCR_PERR_ENABLE 0x0001 +#define CBB_BCR_SERR_ENABLE 0x0002 +#define CBB_BCR_ISA_ENABLE 0x0004 +#define CBB_BCR_VGA_ENABLE 0x0008 +#define CBB_BCR_MASTER_ABORT_MODE 0x0020 +#define CBB_BCR_CARDBUS_RESET 0x0040 +#define CBB_BCR_IREQ_INT_ENABLE 0x0080 +#define CBB_BCR_PREFETCH_0_ENABLE 0x0100 +#define CBB_BCR_PREFETCH_1_ENABLE 0x0200 +#define CBB_BCR_WRITE_POSTING_ENABLE 0x0400 + /* PCI power manangement */ #define PCIR_POWER_CAP 0x2 #define PCIM_PCAP_SPEC 0x0007 diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 2bb26bd..14132bf 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -190,11 +190,6 @@ typedef struct pcicfg { /* additional type 1 device config header information (PCI to PCI bridge) */ -#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff) -#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff) -#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff) -#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff) - typedef struct { pci_addr_t pmembase; /* base address of prefetchable memory */ pci_addr_t pmemlimit; /* topmost address of prefetchable memory */ @@ -500,6 +495,18 @@ pci_msix_count(device_t dev) return (PCI_MSIX_COUNT(device_get_parent(dev), dev)); } +static __inline int +pci_msix_pba_bar(device_t dev) +{ + return (PCI_MSIX_PBA_BAR(device_get_parent(dev), dev)); +} + +static __inline int +pci_msix_table_bar(device_t dev) +{ + return (PCI_MSIX_TABLE_BAR(device_get_parent(dev), dev)); +} + static __inline uint16_t pci_get_rid(device_t dev) { diff --git a/sys/dev/rt/if_rt.c b/sys/dev/rt/if_rt.c index ea252d1..814698c 100644 --- a/sys/dev/rt/if_rt.c +++ b/sys/dev/rt/if_rt.c @@ -176,20 +176,6 @@ macaddr_atoi(const char *str, uint8_t *mac) } #ifdef USE_GENERATED_MAC_ADDRESS -static char * -kernenv_next(char *cp) -{ - - if (cp != NULL) { - while (*cp != 0) - cp++; - cp++; - if (*cp == 0) - cp = NULL; - } - return (cp); -} - /* * generate_mac(uin8_t *mac) * This is MAC address generator for cases when real device MAC address @@ -208,14 +194,8 @@ generate_mac(uint8_t *mac) uint32_t crc = 0xffffffff; /* Generate CRC32 on kenv */ - if (dynamic_kenv) { - for (cp = kenvp[0]; cp != NULL; cp = kenvp[++i]) { - crc = calculate_crc32c(crc, cp, strlen(cp) + 1); - } - } else { - for (cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) { - crc = calculate_crc32c(crc, cp, strlen(cp) + 1); - } + for (cp = kenvp[0]; cp != NULL; cp = kenvp[++i]) { + crc = calculate_crc32c(crc, cp, strlen(cp) + 1); } crc = ~crc; diff --git a/sys/dev/sfxge/common/ef10_impl.h b/sys/dev/sfxge/common/ef10_impl.h index 9b9f0aa..0c687ae 100644 --- a/sys/dev/sfxge/common/ef10_impl.h +++ b/sys/dev/sfxge/common/ef10_impl.h @@ -45,6 +45,52 @@ extern "C" { #define EF10_MAX_PIOBUF_NBUFS MEDFORD_PIOBUF_NBUFS #endif +extern __checkReturn efx_rc_t +efx_mcdi_get_port_assignment( + __in efx_nic_t *enp, + __out uint32_t *portp); + +extern __checkReturn efx_rc_t +efx_mcdi_get_port_modes( + __in efx_nic_t *enp, + __out uint32_t *modesp); + +extern __checkReturn efx_rc_t +efx_mcdi_get_mac_address_pf( + __in efx_nic_t *enp, + __out_ecount_opt(6) uint8_t mac_addrp[6]); + +extern __checkReturn efx_rc_t +efx_mcdi_get_mac_address_vf( + __in efx_nic_t *enp, + __out_ecount_opt(6) uint8_t mac_addrp[6]); + +extern __checkReturn efx_rc_t +efx_mcdi_get_clock( + __in efx_nic_t *enp, + __out uint32_t *sys_freqp); + +extern __checkReturn efx_rc_t +efx_mcdi_get_vector_cfg( + __in efx_nic_t *enp, + __out_opt uint32_t *vec_basep, + __out_opt uint32_t *pf_nvecp, + __out_opt uint32_t *vf_nvecp); + +extern __checkReturn efx_rc_t +ef10_get_datapath_caps( + __in efx_nic_t *enp); + +extern __checkReturn efx_rc_t +ef10_get_privilege_mask( + __in efx_nic_t *enp, + __out uint32_t *maskp); + +extern __checkReturn efx_rc_t +ef10_external_port_mapping( + __in efx_nic_t *enp, + __in uint32_t port, + __out uint8_t *external_portp); #ifdef __cplusplus diff --git a/sys/dev/sfxge/common/ef10_tlv_layout.h b/sys/dev/sfxge/common/ef10_tlv_layout.h index 4063165..80364ce 100644 --- a/sys/dev/sfxge/common/ef10_tlv_layout.h +++ b/sys/dev/sfxge/common/ef10_tlv_layout.h @@ -113,7 +113,11 @@ struct tlv_partition_header { uint32_t tag; uint32_t length; uint16_t type_id; - uint16_t reserved; +/* 0 indicates the default segment (always located at offset 0), while other values + * are for RFID-selectable presets that should immediately follow the default segment. + * The default segment may also have preset > 0, which means that it is a preset + * selected through an RFID command and copied by FW to the location at offset 0. */ + uint16_t preset; uint32_t generation; uint32_t total_length; }; @@ -376,7 +380,7 @@ struct tlv_tmp_gubbins { int8_t with_rmon; /* 0 -> off, 1 -> on, -1 -> leave alone */ /* Consumed by clocks_hunt.c */ int8_t clk_mode; /* 0 -> off, 1 -> on, -1 -> leave alone */ - /* Consumed by sram.c */ + /* No longer used, superseded by TLV_TAG_DESCRIPTOR_CACHE_CONFIG. */ int8_t rx_dc_size; /* -1 -> leave alone */ int8_t tx_dc_size; int16_t num_q_allocs; @@ -690,7 +694,6 @@ struct tlv_mcast_filter_chaining { #define TLV_MCAST_FILTER_CHAINING_ENABLED (1) }; - /* Pacer rate limit per PF */ #define TLV_TAG_RATE_LIMIT(pf) (0x101b0000 + (pf)) @@ -700,7 +703,6 @@ struct tlv_rate_limit { uint32_t rate_mbps; }; - /* OCSD Enable/Disable * * This setting allows OCSD to be disabled. This is a requirement for HP diff --git a/sys/dev/sfxge/common/efsys.h b/sys/dev/sfxge/common/efsys.h index 7bc1fe0..14238ad 100644 --- a/sys/dev/sfxge/common/efsys.h +++ b/sys/dev/sfxge/common/efsys.h @@ -211,6 +211,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define __out_ecount_opt(_n) #define __out_bcount(_n) #define __out_bcount_opt(_n) +#define __out_bcount_part(_n, _l) +#define __out_bcount_part_opt(_n, _l) #define __deref_out @@ -293,6 +295,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define EFSYS_OPT_DECODE_INTR_FATAL 1 +#define EFSYS_OPT_LICENSING 0 + /* ID */ typedef struct __efsys_identifier_s efsys_identifier_t; diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 0483c9a..ce70546 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -1071,6 +1071,7 @@ efx_bist_stop( #define EFX_FEATURE_TX_SRC_FILTERS 0x00000400 #define EFX_FEATURE_PIO_BUFFERS 0x00000800 #define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000 +#define EFX_FEATURE_FW_ASSISTED_TSO_V2 0x00002000 typedef struct efx_nic_cfg_s { uint32_t enc_board_type; @@ -1152,14 +1153,18 @@ typedef struct efx_nic_cfg_s { */ uint32_t enc_tx_tso_tcp_header_offset_limit; boolean_t enc_fw_assisted_tso_enabled; + boolean_t enc_fw_assisted_tso_v2_enabled; boolean_t enc_hw_tx_insert_vlan_enabled; /* Datapath firmware vadapter/vport/vswitch support */ boolean_t enc_datapath_cap_evb; boolean_t enc_rx_disable_scatter_supported; boolean_t enc_allow_set_mac_with_installed_filters; + boolean_t enc_enhanced_set_mac_supported; /* External port identifier */ uint8_t enc_external_port; uint32_t enc_mcdi_max_payload_length; + /* VPD may be per-PF or global */ + boolean_t enc_vpd_is_global; } efx_nic_cfg_t; #define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff) @@ -1315,6 +1320,7 @@ typedef enum efx_nvram_type_e { EFX_NVRAM_CPLD, EFX_NVRAM_FPGA_BACKUP, EFX_NVRAM_DYNAMIC_CFG, + EFX_NVRAM_LICENSE, EFX_NVRAM_NTYPES, } efx_nvram_type_t; @@ -2002,6 +2008,7 @@ efx_tx_fini( #define EFX_TXQ_CKSUM_IPV4 0x0001 #define EFX_TXQ_CKSUM_TCPUDP 0x0002 +#define EFX_TXQ_FATSOV2 0x0004 extern __checkReturn efx_rc_t efx_tx_qcreate( @@ -2089,6 +2096,21 @@ efx_tx_qdesc_tso_create( __in uint8_t tcp_flags, __out efx_desc_t *edp); +/* Number of FATSOv2 option descriptors */ +#define EFX_TX_FATSOV2_OPT_NDESCS 2 + +/* Maximum number of DMA segments per TSO packet (not superframe) */ +#define EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX 24 + +extern void +efx_tx_qdesc_tso2_create( + __in efx_txq_t *etp, + __in uint16_t ipv4_id, + __in uint32_t tcp_seq, + __in uint16_t tcp_mss, + __out_ecount(count) efx_desc_t *edp, + __in int count); + extern void efx_tx_qdesc_vlantci_create( __in efx_txq_t *etp, @@ -2291,6 +2313,57 @@ efx_hash_bytes( __in size_t length, __in uint32_t init); +#if EFSYS_OPT_LICENSING + +/* LICENSING */ + +typedef struct efx_key_stats_s { + uint32_t eks_valid; + uint32_t eks_invalid; + uint32_t eks_blacklisted; + uint32_t eks_unverifiable; + uint32_t eks_wrong_node; + uint32_t eks_licensed_apps_lo; + uint32_t eks_licensed_apps_hi; + uint32_t eks_licensed_features_lo; + uint32_t eks_licensed_features_hi; +} efx_key_stats_t; + +extern __checkReturn efx_rc_t +efx_lic_init( + __in efx_nic_t *enp); + +extern void +efx_lic_fini( + __in efx_nic_t *enp); + +extern __checkReturn efx_rc_t +efx_lic_update_licenses( + __in efx_nic_t *enp); + +extern __checkReturn efx_rc_t +efx_lic_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *ksp); + +extern __checkReturn efx_rc_t +efx_lic_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp); + +extern __checkReturn efx_rc_t +efx_lic_get_id( + __in efx_nic_t *enp, + __in size_t buffer_size, + __out uint32_t *typep, + __out size_t *lengthp, + __out_opt uint8_t *bufferp); + + +#endif /* EFSYS_OPT_LICENSING */ + + #ifdef __cplusplus } diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h index 199fab0..d6b7cf4 100644 --- a/sys/dev/sfxge/common/efx_check.h +++ b/sys/dev/sfxge/common/efx_check.h @@ -401,4 +401,15 @@ # endif #endif /* EFSYS_OPT_BIST */ +/* Support MCDI licensing API */ +#if EFSYS_OPT_LICENSING +# if !EFSYS_OPT_MCDI +# error "LICENSING requires MCDI" +# endif +# if !EFSYS_HAS_UINT64 +# error "LICENSING requires UINT64" +# endif +#endif /* EFSYS_OPT_LICENSING */ + + #endif /* _SYS_EFX_CHECK_H */ diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h index 5397ffe..5495b15 100644 --- a/sys/dev/sfxge/common/efx_impl.h +++ b/sys/dev/sfxge/common/efx_impl.h @@ -84,6 +84,7 @@ extern "C" { #define EFX_MOD_WOL 0x00000800 #define EFX_MOD_FILTER 0x00001000 #define EFX_MOD_PKTFILTER 0x00002000 +#define EFX_MOD_LIC 0x00004000 #define EFX_RESET_MAC 0x00000001 #define EFX_RESET_PHY 0x00000002 @@ -96,6 +97,7 @@ typedef enum efx_mac_type_e { EFX_MAC_FALCON_XMAC, EFX_MAC_SIENA, EFX_MAC_HUNTINGTON, + EFX_MAC_MEDFORD, EFX_MAC_NTYPES } efx_mac_type_t; @@ -146,6 +148,9 @@ typedef struct efx_tx_ops_s { void (*etxo_qdesc_tso_create)(efx_txq_t *, uint16_t, uint32_t, uint8_t, efx_desc_t *); + void (*etxo_qdesc_tso2_create)(efx_txq_t *, uint16_t, + uint32_t, uint16_t, + efx_desc_t *, int); void (*etxo_qdesc_vlantci_create)(efx_txq_t *, uint16_t, efx_desc_t *); #if EFSYS_OPT_QSTATS @@ -189,6 +194,7 @@ typedef struct efx_mac_ops_s { efx_rc_t (*emo_poll)(efx_nic_t *, efx_link_mode_t *); efx_rc_t (*emo_up)(efx_nic_t *, boolean_t *); efx_rc_t (*emo_addr_set)(efx_nic_t *); + efx_rc_t (*emo_pdu_set)(efx_nic_t *); efx_rc_t (*emo_reconfigure)(efx_nic_t *); efx_rc_t (*emo_multicast_list_set)(efx_nic_t *); efx_rc_t (*emo_filter_default_rxq_set)(efx_nic_t *, @@ -358,6 +364,7 @@ typedef struct efx_intr_s { typedef struct efx_nic_ops_s { efx_rc_t (*eno_probe)(efx_nic_t *); + efx_rc_t (*eno_board_cfg)(efx_nic_t *); efx_rc_t (*eno_set_drv_limits)(efx_nic_t *, efx_drv_limits_t*); efx_rc_t (*eno_reset)(efx_nic_t *); efx_rc_t (*eno_init)(efx_nic_t *); @@ -456,9 +463,8 @@ falconsiena_filter_tbl_clear( typedef struct efx_mcdi_ops_s { efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *); - void (*emco_request_copyin)(efx_nic_t *, efx_mcdi_req_t *, - unsigned int, boolean_t, boolean_t); - void (*emco_request_copyout)(efx_nic_t *, efx_mcdi_req_t *); + void (*emco_send_request)(efx_nic_t *, void *, size_t, + void *, size_t); efx_rc_t (*emco_poll_reboot)(efx_nic_t *); boolean_t (*emco_poll_response)(efx_nic_t *); void (*emco_read_response)(efx_nic_t *, void *, size_t, size_t); @@ -479,21 +485,21 @@ typedef struct efx_nvram_ops_s { #if EFSYS_OPT_DIAG efx_rc_t (*envo_test)(efx_nic_t *); #endif /* EFSYS_OPT_DIAG */ - efx_rc_t (*envo_size)(efx_nic_t *, efx_nvram_type_t, size_t *); - efx_rc_t (*envo_get_version)(efx_nic_t *, efx_nvram_type_t, - uint32_t *, uint16_t *); - efx_rc_t (*envo_rw_start)(efx_nic_t *, efx_nvram_type_t, size_t *); - efx_rc_t (*envo_read_chunk)(efx_nic_t *, efx_nvram_type_t, + efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t, + uint32_t *); + efx_rc_t (*envo_partn_size)(efx_nic_t *, uint32_t, size_t *); + efx_rc_t (*envo_partn_rw_start)(efx_nic_t *, uint32_t, size_t *); + efx_rc_t (*envo_partn_read)(efx_nic_t *, uint32_t, unsigned int, caddr_t, size_t); - efx_rc_t (*envo_erase)(efx_nic_t *, efx_nvram_type_t); - efx_rc_t (*envo_write_chunk)(efx_nic_t *, efx_nvram_type_t, + efx_rc_t (*envo_partn_erase)(efx_nic_t *, uint32_t, + unsigned int, size_t); + efx_rc_t (*envo_partn_write)(efx_nic_t *, uint32_t, unsigned int, caddr_t, size_t); - void (*envo_rw_finish)(efx_nic_t *, efx_nvram_type_t); - efx_rc_t (*envo_set_version)(efx_nic_t *, efx_nvram_type_t, + void (*envo_partn_rw_finish)(efx_nic_t *, uint32_t); + efx_rc_t (*envo_partn_get_version)(efx_nic_t *, uint32_t, + uint32_t *, uint16_t *); + efx_rc_t (*envo_partn_set_version)(efx_nic_t *, uint32_t, uint16_t *); - - efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t, - uint32_t *); } efx_nvram_ops_t; #endif /* EFSYS_OPT_NVRAM */ @@ -553,7 +559,8 @@ efx_mcdi_nvram_read( __in uint32_t partn, __in uint32_t offset, __out_bcount(size) caddr_t data, - __in size_t size); + __in size_t size, + __in uint32_t mode); __checkReturn efx_rc_t efx_mcdi_nvram_erase( @@ -587,6 +594,18 @@ efx_mcdi_nvram_test( #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ +#if EFSYS_OPT_LICENSING + +typedef struct efx_lic_ops_s { + efx_rc_t (*elo_update_licenses)(efx_nic_t *); + efx_rc_t (*elo_get_key_stats)(efx_nic_t *, efx_key_stats_t *); + efx_rc_t (*elo_app_state)(efx_nic_t *, uint64_t, boolean_t *); + efx_rc_t (*elo_get_id)(efx_nic_t *, size_t, uint32_t *, + size_t *, uint8_t *); +} efx_lic_ops_t; + +#endif + typedef struct efx_drv_cfg_s { uint32_t edc_min_vi_count; uint32_t edc_max_vi_count; @@ -636,6 +655,9 @@ struct efx_nic_s { uint32_t en_rss_context; #endif /* EFSYS_OPT_RX_SCALE */ uint32_t en_vport_id; +#if EFSYS_OPT_LICENSING + efx_lic_ops_t *en_elop; +#endif union { #if EFSYS_OPT_FALCON struct { diff --git a/sys/dev/sfxge/common/efx_lic.c b/sys/dev/sfxge/common/efx_lic.c new file mode 100644 index 0000000..33c8aba --- /dev/null +++ b/sys/dev/sfxge/common/efx_lic.c @@ -0,0 +1,792 @@ +/*- + * Copyright (c) 2009-2015 Solarflare Communications Inc. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + * The views and conclusions contained in the software and documentation are + * those of the authors and should not be interpreted as representing official + * policies, either expressed or implied, of the FreeBSD Project. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "efx.h" +#include "efx_impl.h" + +#if EFSYS_OPT_LICENSING + +#if EFSYS_OPT_SIENA + +static __checkReturn efx_rc_t +efx_mcdi_fc_license_update_license( + __in efx_nic_t *enp); + +static __checkReturn efx_rc_t +efx_mcdi_fc_license_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp); + +static efx_lic_ops_t __efx_lic_v1_ops = { + efx_mcdi_fc_license_update_license, /* elo_update_licenses */ + efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */ + NULL, /* elo_app_state */ + NULL, /* elo_get_id */ +}; + +#endif /* EFSYS_OPT_SIENA */ + +#if EFSYS_OPT_HUNTINGTON + +static __checkReturn efx_rc_t +efx_mcdi_licensing_update_licenses( + __in efx_nic_t *enp); + +static __checkReturn efx_rc_t +efx_mcdi_licensing_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp); + +static __checkReturn efx_rc_t +efx_mcdi_licensed_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp); + +static efx_lic_ops_t __efx_lic_v2_ops = { + efx_mcdi_licensing_update_licenses, /* elo_update_licenses */ + efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */ + efx_mcdi_licensed_app_state, /* elo_app_state */ + NULL, /* elo_get_id */ +}; + +#endif /* EFSYS_OPT_HUNTINGTON */ + +#if EFSYS_OPT_MEDFORD + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_update_licenses( + __in efx_nic_t *enp); + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_report_license( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp); + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp); + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_get_id( + __in efx_nic_t *enp, + __in size_t buffer_size, + __out uint32_t *typep, + __out size_t *lengthp, + __out_bcount_part_opt(buffer_size, *lengthp) + uint8_t *bufferp); + +static efx_lic_ops_t __efx_lic_v3_ops = { + efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */ + efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */ + efx_mcdi_licensing_v3_app_state, /* elo_app_state */ + efx_mcdi_licensing_v3_get_id, /* elo_get_id */ +}; + +#endif /* EFSYS_OPT_MEDFORD */ + + +/* V1 Licensing - used in Siena Modena only */ + +#if EFSYS_OPT_SIENA + +static __checkReturn efx_rc_t +efx_mcdi_fc_license_update_license( + __in efx_nic_t *enp) +{ + efx_mcdi_req_t req; + uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_FC_OP_LICENSE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; + req.emr_out_buf = payload; + req.emr_out_length = 0; + + MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, + MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used != 0) { + rc = EIO; + goto fail2; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_fc_license_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN, + MC_CMD_FC_OUT_LICENSE_LEN)]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_FC_OP_LICENSE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN; + + MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP, + MC_CMD_FC_IN_LICENSE_GET_KEY_STATS); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + eksp->eks_valid = + MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS); + eksp->eks_invalid = + MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS); + eksp->eks_blacklisted = + MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS); + eksp->eks_unverifiable = 0; + eksp->eks_wrong_node = 0; + eksp->eks_licensed_apps_lo = 0; + eksp->eks_licensed_apps_hi = 0; + eksp->eks_licensed_features_lo = 0; + eksp->eks_licensed_features_hi = 0; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +#endif /* EFSYS_OPT_SIENA */ + +/* V2 Licensing - used by Huntington family only. See SF-113611-TC */ + +#if EFSYS_OPT_HUNTINGTON + +static __checkReturn efx_rc_t +efx_mcdi_licensed_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN, + MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)]; + uint32_t app_state; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); + + /* V2 licensing supports 32bit app id only */ + if ((app_id >> 32) != 0) { + rc = EINVAL; + goto fail1; + } + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN; + + MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID, + app_id & 0xffffffff); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail2; + } + + if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) { + rc = EMSGSIZE; + goto fail3; + } + + app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE)); + if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) { + *licensedp = B_TRUE; + } else { + *licensedp = B_FALSE; + } + + return (0); + +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_licensing_update_licenses( + __in efx_nic_t *enp) +{ + efx_mcdi_req_t req; + uint8_t payload[MC_CMD_LICENSING_IN_LEN]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_LICENSING; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_LICENSING_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = 0; + + MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, + MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used != 0) { + rc = EIO; + goto fail2; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_licensing_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN, + MC_CMD_LICENSING_OUT_LEN)]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_LICENSING; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_LICENSING_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_LICENSING_OUT_LEN; + + MCDI_IN_SET_DWORD(req, LICENSING_IN_OP, + MC_CMD_LICENSING_IN_OP_GET_KEY_STATS); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + eksp->eks_valid = + MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS); + eksp->eks_invalid = + MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS); + eksp->eks_blacklisted = + MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS); + eksp->eks_unverifiable = + MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS); + eksp->eks_wrong_node = + MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS); + eksp->eks_licensed_apps_lo = 0; + eksp->eks_licensed_apps_hi = 0; + eksp->eks_licensed_features_lo = 0; + eksp->eks_licensed_features_hi = 0; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +#endif /* EFSYS_OPT_HUNTINGTON */ + +/* V3 Licensing - used starting from Medford family. See SF-114884-SW */ + +#if EFSYS_OPT_MEDFORD + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_update_licenses( + __in efx_nic_t *enp) +{ + efx_mcdi_req_t req; + uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_LICENSING_V3; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; + req.emr_out_buf = NULL; + req.emr_out_length = 0; + + MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, + MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_report_license( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN, + MC_CMD_LICENSING_V3_OUT_LEN)]; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_LICENSING_V3; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN; + + MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP, + MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + eksp->eks_valid = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS); + eksp->eks_invalid = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS); + eksp->eks_blacklisted = 0; + eksp->eks_unverifiable = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS); + eksp->eks_wrong_node = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS); + eksp->eks_licensed_apps_lo = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO); + eksp->eks_licensed_apps_hi = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI); + eksp->eks_licensed_features_lo = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO); + eksp->eks_licensed_features_hi = + MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI); + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN, + MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)]; + uint32_t app_state; + efx_rc_t rc; + + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD); + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN; + + MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO, + app_id & 0xffffffff); + MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI, + app_id >> 32); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE)); + if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) { + *licensedp = B_TRUE; + } else { + *licensedp = B_FALSE; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +static __checkReturn efx_rc_t +efx_mcdi_licensing_v3_get_id( + __in efx_nic_t *enp, + __in size_t buffer_size, + __out uint32_t *typep, + __out size_t *lengthp, + __out_bcount_part_opt(buffer_size, *lengthp) + uint8_t *bufferp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN, + MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)]; + efx_rc_t rc; + + req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3; + + if (bufferp == NULL) { + /* Request id type and length only */ + req.emr_in_buf = bufferp; + req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; + req.emr_out_buf = bufferp; + req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; + (void) memset(payload, 0, sizeof (payload)); + } else { + /* Request full buffer */ + req.emr_in_buf = bufferp; + req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN; + req.emr_out_buf = bufferp; + req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN); + (void) memset(bufferp, 0, req.emr_out_length); + } + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) { + rc = EMSGSIZE; + goto fail2; + } + + *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE); + *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH); + + if (bufferp == NULL) { + /* modify length requirements to indicate to caller the extra buffering + ** needed to read the complete output. + */ + *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN; + } else { + /* Shift ID down to start of buffer */ + memmove(bufferp, + bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST, + *lengthp); + memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST); + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + +#endif /* EFSYS_OPT_MEDFORD */ + + __checkReturn efx_rc_t +efx_lic_init( + __in efx_nic_t *enp) +{ + efx_lic_ops_t *elop; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); + EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC)); + + switch (enp->en_family) { + +#if EFSYS_OPT_SIENA + case EFX_FAMILY_SIENA: + elop = (efx_lic_ops_t *)&__efx_lic_v1_ops; + break; +#endif /* EFSYS_OPT_SIENA */ + +#if EFSYS_OPT_HUNTINGTON + case EFX_FAMILY_HUNTINGTON: + elop = (efx_lic_ops_t *)&__efx_lic_v2_ops; + break; +#endif /* EFSYS_OPT_HUNTINGTON */ + +#if EFSYS_OPT_MEDFORD + case EFX_FAMILY_MEDFORD: + elop = (efx_lic_ops_t *)&__efx_lic_v3_ops; + break; +#endif /* EFSYS_OPT_MEDFORD */ + + default: + EFSYS_ASSERT(0); + rc = ENOTSUP; + goto fail1; + } + + enp->en_elop = elop; + enp->en_mod_flags |= EFX_MOD_LIC; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + void +efx_lic_fini( + __in efx_nic_t *enp) +{ + efx_lic_ops_t *elop = enp->en_elop; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); + + enp->en_elop = NULL; + enp->en_mod_flags &= ~EFX_MOD_LIC; +} + + + __checkReturn efx_rc_t +efx_lic_update_licenses( + __in efx_nic_t *enp) +{ + efx_lic_ops_t *elop = enp->en_elop; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); + + if ((rc = elop->elo_update_licenses(enp)) != 0) + goto fail1; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_lic_get_key_stats( + __in efx_nic_t *enp, + __out efx_key_stats_t *eksp) +{ + efx_lic_ops_t *elop = enp->en_elop; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); + + if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0) + goto fail1; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_lic_app_state( + __in efx_nic_t *enp, + __in uint64_t app_id, + __out boolean_t *licensedp) +{ + efx_lic_ops_t *elop = enp->en_elop; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); + + if (elop->elo_app_state == NULL) { + rc = ENOTSUP; + goto fail1; + } + if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_lic_get_id( + __in efx_nic_t *enp, + __in size_t buffer_size, + __out uint32_t *typep, + __out size_t *lengthp, + __out_opt uint8_t *bufferp + ) +{ + efx_lic_ops_t *elop = enp->en_elop; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC); + + if (elop->elo_get_id == NULL) { + rc = ENOTSUP; + goto fail1; + } + + if ((rc = elop->elo_get_id(enp, buffer_size, typep, + lengthp, bufferp)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +#endif /* EFSYS_OPT_LICENSING */ diff --git a/sys/dev/sfxge/common/efx_mac.c b/sys/dev/sfxge/common/efx_mac.c index c8794a6..4868c4b 100644 --- a/sys/dev/sfxge/common/efx_mac.c +++ b/sys/dev/sfxge/common/efx_mac.c @@ -56,6 +56,7 @@ static efx_mac_ops_t __efx_falcon_gmac_ops = { falcon_mac_poll, /* emo_poll */ falcon_mac_up, /* emo_up */ falcon_gmac_reconfigure, /* emo_addr_set */ + falcon_gmac_reconfigure, /* emo_pdu_set */ falcon_gmac_reconfigure, /* emo_reconfigure */ falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ NULL, /* emo_filter_set_default_rxq */ @@ -77,6 +78,7 @@ static efx_mac_ops_t __efx_falcon_xmac_ops = { falcon_mac_poll, /* emo_poll */ falcon_mac_up, /* emo_up */ falcon_xmac_reconfigure, /* emo_addr_set */ + falcon_xmac_reconfigure, /* emo_pdu_set */ falcon_xmac_reconfigure, /* emo_reconfigure */ falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ NULL, /* emo_filter_set_default_rxq */ @@ -98,6 +100,7 @@ static efx_mac_ops_t __efx_siena_mac_ops = { siena_mac_poll, /* emo_poll */ siena_mac_up, /* emo_up */ siena_mac_reconfigure, /* emo_addr_set */ + siena_mac_reconfigure, /* emo_pdu_set */ siena_mac_reconfigure, /* emo_reconfigure */ falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ NULL, /* emo_filter_set_default_rxq */ @@ -113,27 +116,28 @@ static efx_mac_ops_t __efx_siena_mac_ops = { }; #endif /* EFSYS_OPT_SIENA */ -#if EFSYS_OPT_HUNTINGTON -static efx_mac_ops_t __efx_hunt_mac_ops = { +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD +static efx_mac_ops_t __efx_ef10_mac_ops = { NULL, /* emo_reset */ - hunt_mac_poll, /* emo_poll */ - hunt_mac_up, /* emo_up */ - hunt_mac_addr_set, /* emo_addr_set */ - hunt_mac_reconfigure, /* emo_reconfigure */ - hunt_mac_multicast_list_set, /* emo_multicast_list_set */ - hunt_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ - hunt_mac_filter_default_rxq_clear, + ef10_mac_poll, /* emo_poll */ + ef10_mac_up, /* emo_up */ + ef10_mac_addr_set, /* emo_addr_set */ + ef10_mac_pdu_set, /* emo_pdu_set */ + ef10_mac_reconfigure, /* emo_reconfigure */ + ef10_mac_multicast_list_set, /* emo_multicast_list_set */ + ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ + ef10_mac_filter_default_rxq_clear, /* emo_filter_default_rxq_clear */ #if EFSYS_OPT_LOOPBACK - hunt_mac_loopback_set, /* emo_loopback_set */ + ef10_mac_loopback_set, /* emo_loopback_set */ #endif /* EFSYS_OPT_LOOPBACK */ #if EFSYS_OPT_MAC_STATS efx_mcdi_mac_stats_upload, /* emo_stats_upload */ efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ - hunt_mac_stats_update /* emo_stats_update */ + ef10_mac_stats_update /* emo_stats_update */ #endif /* EFSYS_OPT_MAC_STATS */ }; -#endif /* EFSYS_OPT_HUNTINGTON */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ static efx_mac_ops_t *__efx_mac_ops[] = { /* [EFX_MAC_INVALID] */ @@ -158,7 +162,13 @@ static efx_mac_ops_t *__efx_mac_ops[] = { #endif /* [EFX_MAC_HUNTINGTON] */ #if EFSYS_OPT_HUNTINGTON - &__efx_hunt_mac_ops, + &__efx_ef10_mac_ops, +#else + NULL, +#endif + /* [EFX_MAC_MEDFORD] */ +#if EFSYS_OPT_MEDFORD + &__efx_ef10_mac_ops, #else NULL, #endif @@ -190,7 +200,7 @@ efx_mac_pdu_set( old_pdu = epp->ep_mac_pdu; epp->ep_mac_pdu = (uint32_t)pdu; - if ((rc = emop->emo_reconfigure(enp)) != 0) + if ((rc = emop->emo_pdu_set(enp)) != 0) goto fail3; return (0); @@ -781,6 +791,13 @@ efx_mac_select( efx_mac_ops_t *emop; int rc = EINVAL; +#if EFSYS_OPT_SIENA + if (enp->en_family == EFX_FAMILY_SIENA) { + type = EFX_MAC_SIENA; + goto chosen; + } +#endif + #if EFSYS_OPT_HUNTINGTON if (enp->en_family == EFX_FAMILY_HUNTINGTON) { type = EFX_MAC_HUNTINGTON; @@ -788,9 +805,9 @@ efx_mac_select( } #endif -#if EFSYS_OPT_SIENA - if (enp->en_family == EFX_FAMILY_SIENA) { - type = EFX_MAC_SIENA; +#if EFSYS_OPT_MEDFORD + if (enp->en_family == EFX_FAMILY_MEDFORD) { + type = EFX_MAC_MEDFORD; goto chosen; } #endif diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index 07224c7..9f7a9ff 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -36,13 +36,32 @@ __FBSDID("$FreeBSD$"); #if EFSYS_OPT_MCDI +/* + * There are three versions of the MCDI interface: + * - MCDIv0: Siena BootROM. Transport uses MCDIv1 headers. + * - MCDIv1: Siena firmware and Huntington BootROM. + * - MCDIv2: EF10 firmware (Huntington/Medford) and Medford BootROM. + * Transport uses MCDIv2 headers. + * + * MCDIv2 Header NOT_EPOCH flag + * ---------------------------- + * A new epoch begins at initial startup or after an MC reboot, and defines when + * the MC should reject stale MCDI requests. + * + * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all + * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1. + * + * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a + * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0. + */ + + #if EFSYS_OPT_SIENA static efx_mcdi_ops_t __efx_mcdi_siena_ops = { siena_mcdi_init, /* emco_init */ - siena_mcdi_request_copyin, /* emco_request_copyin */ - siena_mcdi_request_copyout, /* emco_request_copyout */ + siena_mcdi_send_request, /* emco_send_request */ siena_mcdi_poll_reboot, /* emco_poll_reboot */ siena_mcdi_poll_response, /* emco_poll_response */ siena_mcdi_read_response, /* emco_read_response */ @@ -56,8 +75,7 @@ static efx_mcdi_ops_t __efx_mcdi_siena_ops = { static efx_mcdi_ops_t __efx_mcdi_ef10_ops = { ef10_mcdi_init, /* emco_init */ - ef10_mcdi_request_copyin, /* emco_request_copyin */ - ef10_mcdi_request_copyout, /* emco_request_copyout */ + ef10_mcdi_send_request, /* emco_send_request */ ef10_mcdi_poll_reboot, /* emco_poll_reboot */ ef10_mcdi_poll_response, /* emco_poll_response */ ef10_mcdi_read_response, /* emco_read_response */ @@ -179,26 +197,16 @@ efx_mcdi_new_epoch( } static void -efx_mcdi_request_copyin( +efx_mcdi_send_request( __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp, - __in unsigned int seq, - __in boolean_t ev_cpl, - __in boolean_t new_epoch) -{ - efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - - emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch); -} - -static void -efx_mcdi_request_copyout( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp) + __in void *hdrp, + __in size_t hdr_len, + __in void *sdup, + __in size_t sdu_len) { efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - emcop->emco_request_copyout(enp, emrp); + emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len); } static efx_rc_t @@ -241,8 +249,15 @@ efx_mcdi_request_start( __in efx_mcdi_req_t *emrp, __in boolean_t ev_cpl) { +#if EFSYS_OPT_MCDI_LOGGING + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; +#endif efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + efx_dword_t hdr[2]; + size_t hdr_len; + unsigned int max_version; unsigned int seq; + unsigned int xflags; boolean_t new_epoch; int state; @@ -269,13 +284,64 @@ efx_mcdi_request_start( emip->emi_poll_cnt = 0; seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ); new_epoch = emip->emi_new_epoch; + max_version = emip->emi_max_version; EFSYS_UNLOCK(enp->en_eslp, state); - efx_mcdi_request_copyin(enp, emrp, seq, ev_cpl, new_epoch); + xflags = 0; + if (ev_cpl) + xflags |= MCDI_HEADER_XFLAGS_EVREQ; + + /* + * Huntington firmware supports MCDIv2, but the Huntington BootROM only + * supports MCDIv1. Use MCDIv1 headers for MCDIv1 commands where + * possible to support this. + */ + if ((max_version >= 2) && + ((emrp->emr_cmd > MC_CMD_CMD_SPACE_ESCAPE_7) || + (emrp->emr_in_length > MCDI_CTL_SDU_LEN_MAX_V1))) { + /* Construct MCDI v2 header */ + hdr_len = sizeof (hdr); + EFX_POPULATE_DWORD_8(hdr[0], + MCDI_HEADER_CODE, MC_CMD_V2_EXTN, + MCDI_HEADER_RESYNC, 1, + MCDI_HEADER_DATALEN, 0, + MCDI_HEADER_SEQ, seq, + MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, + MCDI_HEADER_ERROR, 0, + MCDI_HEADER_RESPONSE, 0, + MCDI_HEADER_XFLAGS, xflags); + + EFX_POPULATE_DWORD_2(hdr[1], + MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd, + MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length); + } else { + /* Construct MCDI v1 header */ + hdr_len = sizeof (hdr[0]); + EFX_POPULATE_DWORD_8(hdr[0], + MCDI_HEADER_CODE, emrp->emr_cmd, + MCDI_HEADER_RESYNC, 1, + MCDI_HEADER_DATALEN, emrp->emr_in_length, + MCDI_HEADER_SEQ, seq, + MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, + MCDI_HEADER_ERROR, 0, + MCDI_HEADER_RESPONSE, 0, + MCDI_HEADER_XFLAGS, xflags); + } + +#if EFSYS_OPT_MCDI_LOGGING + if (emtp->emt_logger != NULL) { + emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST, + &hdr, hdr_len, + emrp->emr_in_buf, emrp->emr_in_length); + } +#endif /* EFSYS_OPT_MCDI_LOGGING */ + + efx_mcdi_send_request(enp, &hdr[0], hdr_len, + emrp->emr_in_buf, emrp->emr_in_length); } - void +static void efx_mcdi_read_response_header( __in efx_nic_t *enp, __inout efx_mcdi_req_t *emrp) @@ -384,19 +450,56 @@ efx_mcdi_read_response_header( return; fail3: - if (!emrp->emr_quiet) - EFSYS_PROBE(fail3); fail2: - if (!emrp->emr_quiet) - EFSYS_PROBE(fail2); fail1: - if (!emrp->emr_quiet) - EFSYS_PROBE1(fail1, efx_rc_t, rc); - emrp->emr_rc = rc; emrp->emr_out_length_used = 0; } +static void +efx_mcdi_finish_response( + __in efx_nic_t *enp, + __in efx_mcdi_req_t *emrp) +{ +#if EFSYS_OPT_MCDI_LOGGING + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; +#endif /* EFSYS_OPT_MCDI_LOGGING */ + efx_dword_t hdr[2]; + unsigned int hdr_len; + size_t bytes; + + if (emrp->emr_out_buf == NULL) + return; + + /* Read the command header to detect MCDI response format */ + hdr_len = sizeof (hdr[0]); + efx_mcdi_read_response(enp, &hdr[0], 0, hdr_len); + if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { + /* + * Read the actual payload length. The length given in the event + * is only correct for responses with the V1 format. + */ + efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); + hdr_len += sizeof (hdr[1]); + + emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], + MC_CMD_V2_EXTN_IN_ACTUAL_LEN); + } + + /* Copy payload out into caller supplied buffer */ + bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); + efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); + +#if EFSYS_OPT_MCDI_LOGGING + if (emtp->emt_logger != NULL) { + emtp->emt_logger(emtp->emt_context, + EFX_LOG_MCDI_RESPONSE, + &hdr, hdr_len, + emrp->emr_out_buf, bytes); + } +#endif /* EFSYS_OPT_MCDI_LOGGING */ +} + __checkReturn boolean_t efx_mcdi_request_poll( @@ -444,7 +547,7 @@ efx_mcdi_request_poll( if ((rc = emrp->emr_rc) != 0) goto fail2; - efx_mcdi_request_copyout(enp, emrp); + efx_mcdi_finish_response(enp, emrp); return (B_TRUE); fail2: @@ -638,7 +741,6 @@ efx_mcdi_ev_cpl( { efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; - efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; efx_mcdi_req_t *emrp; int state; @@ -680,7 +782,7 @@ efx_mcdi_ev_cpl( } } if (errcode == 0) { - emcop->emco_request_copyout(enp, emrp); + efx_mcdi_finish_response(enp, emrp); } emtp->emt_ev_cpl(emtp->emt_context); diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h index 36b3d8d..dd1d76e 100644 --- a/sys/dev/sfxge/common/efx_mcdi.h +++ b/sys/dev/sfxge/common/efx_mcdi.h @@ -88,11 +88,6 @@ efx_mcdi_execute_quiet( __in efx_nic_t *enp, __inout efx_mcdi_req_t *emrp); - extern void -efx_mcdi_read_response_header( - __in efx_nic_t *enp, - __inout efx_mcdi_req_t *emrp); - extern void efx_mcdi_ev_cpl( __in efx_nic_t *enp, diff --git a/sys/dev/sfxge/common/efx_nic.c b/sys/dev/sfxge/common/efx_nic.c index 07acc56..dd28ece 100644 --- a/sys/dev/sfxge/common/efx_nic.c +++ b/sys/dev/sfxge/common/efx_nic.c @@ -244,6 +244,7 @@ fail1: static efx_nic_ops_t __efx_nic_falcon_ops = { falcon_nic_probe, /* eno_probe */ + NULL, /* eno_board_cfg */ NULL, /* eno_set_drv_limits */ falcon_nic_reset, /* eno_reset */ falcon_nic_init, /* eno_init */ @@ -263,6 +264,7 @@ static efx_nic_ops_t __efx_nic_falcon_ops = { static efx_nic_ops_t __efx_nic_siena_ops = { siena_nic_probe, /* eno_probe */ + NULL, /* eno_board_cfg */ NULL, /* eno_set_drv_limits */ siena_nic_reset, /* eno_reset */ siena_nic_init, /* eno_init */ @@ -282,6 +284,7 @@ static efx_nic_ops_t __efx_nic_siena_ops = { static efx_nic_ops_t __efx_nic_hunt_ops = { ef10_nic_probe, /* eno_probe */ + hunt_board_cfg, /* eno_board_cfg */ ef10_nic_set_drv_limits, /* eno_set_drv_limits */ ef10_nic_reset, /* eno_reset */ ef10_nic_init, /* eno_init */ @@ -297,6 +300,27 @@ static efx_nic_ops_t __efx_nic_hunt_ops = { #endif /* EFSYS_OPT_HUNTINGTON */ +#if EFSYS_OPT_MEDFORD + +static efx_nic_ops_t __efx_nic_medford_ops = { + ef10_nic_probe, /* eno_probe */ + medford_board_cfg, /* eno_board_cfg */ + ef10_nic_set_drv_limits, /* eno_set_drv_limits */ + ef10_nic_reset, /* eno_reset */ + ef10_nic_init, /* eno_init */ + ef10_nic_get_vi_pool, /* eno_get_vi_pool */ + ef10_nic_get_bar_region, /* eno_get_bar_region */ +#if EFSYS_OPT_DIAG + ef10_sram_test, /* eno_sram_test */ + ef10_nic_register_test, /* eno_register_test */ +#endif /* EFSYS_OPT_DIAG */ + ef10_nic_fini, /* eno_fini */ + ef10_nic_unprobe, /* eno_unprobe */ +}; + +#endif /* EFSYS_OPT_MEDFORD */ + + __checkReturn efx_rc_t efx_nic_create( __in efx_family_t family, @@ -357,10 +381,29 @@ efx_nic_create( EFX_FEATURE_MAC_HEADER_FILTERS | EFX_FEATURE_MCDI_DMA | EFX_FEATURE_PIO_BUFFERS | - EFX_FEATURE_FW_ASSISTED_TSO; + EFX_FEATURE_FW_ASSISTED_TSO | + EFX_FEATURE_FW_ASSISTED_TSO_V2; break; #endif /* EFSYS_OPT_HUNTINGTON */ +#if EFSYS_OPT_MEDFORD + case EFX_FAMILY_MEDFORD: + enp->en_enop = (efx_nic_ops_t *)&__efx_nic_medford_ops; + /* + * FW_ASSISTED_TSO ommitted as Medford only supports firmware + * assisted TSO version 2, not the v1 scheme used on Huntington. + */ + enp->en_features = + EFX_FEATURE_IPV6 | + EFX_FEATURE_LINK_EVENTS | + EFX_FEATURE_PERIODIC_MAC_STATS | + EFX_FEATURE_MCDI | + EFX_FEATURE_MAC_HEADER_FILTERS | + EFX_FEATURE_MCDI_DMA | + EFX_FEATURE_PIO_BUFFERS; + break; +#endif /* EFSYS_OPT_MEDFORD */ + default: rc = ENOTSUP; goto fail2; @@ -665,8 +708,9 @@ efx_nic_reset( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE); /* - * All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we - * do not reset here) must have been shut down or never initialized. + * All modules except the MCDI, PROBE, NVRAM, VPD, MON, LIC + * (which we do not reset here) must have been shut down or never + * initialized. * * A rule of thumb here is: If the controller or MC reboots, is *any* * state lost. If it's lost and needs reapplying, then the module @@ -674,7 +718,7 @@ efx_nic_reset( */ mod_flags = enp->en_mod_flags; mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM | - EFX_MOD_VPD | EFX_MOD_MON); + EFX_MOD_VPD | EFX_MOD_MON | EFX_MOD_LIC); EFSYS_ASSERT3U(mod_flags, ==, 0); if (mod_flags != 0) { rc = EINVAL; diff --git a/sys/dev/sfxge/common/efx_nvram.c b/sys/dev/sfxge/common/efx_nvram.c index 7597636..272e6c7 100644 --- a/sys/dev/sfxge/common/efx_nvram.c +++ b/sys/dev/sfxge/common/efx_nvram.c @@ -42,15 +42,15 @@ static efx_nvram_ops_t __efx_nvram_falcon_ops = { #if EFSYS_OPT_DIAG falcon_nvram_test, /* envo_test */ #endif /* EFSYS_OPT_DIAG */ - falcon_nvram_size, /* envo_size */ - falcon_nvram_get_version, /* envo_get_version */ - falcon_nvram_rw_start, /* envo_rw_start */ - falcon_nvram_read_chunk, /* envo_read_chunk */ - falcon_nvram_erase, /* envo_erase */ - falcon_nvram_write_chunk, /* envo_write_chunk */ - falcon_nvram_rw_finish, /* envo_rw_finish */ - falcon_nvram_set_version, /* envo_set_version */ falcon_nvram_type_to_partn, /* envo_type_to_partn */ + falcon_nvram_partn_size, /* envo_partn_size */ + falcon_nvram_partn_rw_start, /* envo_partn_rw_start */ + falcon_nvram_partn_read, /* envo_partn_read */ + falcon_nvram_partn_erase, /* envo_partn_erase */ + falcon_nvram_partn_write, /* envo_partn_write */ + falcon_nvram_partn_rw_finish, /* envo_partn_rw_finish */ + falcon_nvram_partn_get_version, /* envo_partn_get_version */ + falcon_nvram_partn_set_version, /* envo_partn_set_version */ }; #endif /* EFSYS_OPT_FALCON */ @@ -61,15 +61,15 @@ static efx_nvram_ops_t __efx_nvram_siena_ops = { #if EFSYS_OPT_DIAG siena_nvram_test, /* envo_test */ #endif /* EFSYS_OPT_DIAG */ - siena_nvram_size, /* envo_size */ - siena_nvram_get_version, /* envo_get_version */ - siena_nvram_rw_start, /* envo_rw_start */ - siena_nvram_read_chunk, /* envo_read_chunk */ - siena_nvram_erase, /* envo_erase */ - siena_nvram_write_chunk, /* envo_write_chunk */ - siena_nvram_rw_finish, /* envo_rw_finish */ - siena_nvram_set_version, /* envo_set_version */ siena_nvram_type_to_partn, /* envo_type_to_partn */ + siena_nvram_partn_size, /* envo_partn_size */ + siena_nvram_partn_rw_start, /* envo_partn_rw_start */ + siena_nvram_partn_read, /* envo_partn_read */ + siena_nvram_partn_erase, /* envo_partn_erase */ + siena_nvram_partn_write, /* envo_partn_write */ + siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ + siena_nvram_partn_get_version, /* envo_partn_get_version */ + siena_nvram_partn_set_version, /* envo_partn_set_version */ }; #endif /* EFSYS_OPT_SIENA */ @@ -80,15 +80,15 @@ static efx_nvram_ops_t __efx_nvram_ef10_ops = { #if EFSYS_OPT_DIAG ef10_nvram_test, /* envo_test */ #endif /* EFSYS_OPT_DIAG */ - ef10_nvram_size, /* envo_size */ - ef10_nvram_get_version, /* envo_get_version */ - ef10_nvram_rw_start, /* envo_rw_start */ - ef10_nvram_read_chunk, /* envo_read_chunk */ - ef10_nvram_erase, /* envo_erase */ - ef10_nvram_write_chunk, /* envo_write_chunk */ - ef10_nvram_rw_finish, /* envo_rw_finish */ - ef10_nvram_set_version, /* envo_set_version */ ef10_nvram_type_to_partn, /* envo_type_to_partn */ + ef10_nvram_partn_size, /* envo_partn_size */ + ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ + ef10_nvram_partn_read, /* envo_partn_read */ + ef10_nvram_partn_erase, /* envo_partn_erase */ + ef10_nvram_partn_write, /* envo_partn_write */ + ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ + ef10_nvram_partn_get_version, /* envo_partn_get_version */ + ef10_nvram_partn_set_version, /* envo_partn_set_version */ }; #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ @@ -178,6 +178,7 @@ efx_nvram_size( __out size_t *sizep) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -185,13 +186,19 @@ efx_nvram_size( EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - if ((rc = envop->envo_size(enp, type, sizep)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) + goto fail2; + return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); + *sizep = 0; return (rc); } @@ -204,6 +211,7 @@ efx_nvram_get_version( __out_ecount(4) uint16_t version[4]) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -212,11 +220,17 @@ efx_nvram_get_version( EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_get_version(enp, partn, + subtypep, version)) != 0) + goto fail2; + return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -230,6 +244,7 @@ efx_nvram_rw_start( __out_opt size_t *chunk_sizep) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -240,13 +255,18 @@ efx_nvram_rw_start( EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); - if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) + goto fail2; + enp->en_nvram_locked = type; return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -262,6 +282,7 @@ efx_nvram_read_chunk( __in size_t size) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -272,11 +293,16 @@ efx_nvram_read_chunk( EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) + goto fail2; + return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -289,6 +315,9 @@ efx_nvram_erase( __in efx_nvram_type_t type) { efx_nvram_ops_t *envop = enp->en_envop; + unsigned int offset = 0; + size_t size = 0; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -299,11 +328,21 @@ efx_nvram_erase( EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_erase(enp, type)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) + goto fail2; + + if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) + goto fail3; + return (0); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -319,6 +358,7 @@ efx_nvram_write_chunk( __in size_t size) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -329,11 +369,16 @@ efx_nvram_write_chunk( EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) + goto fail2; + return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -346,6 +391,7 @@ efx_nvram_rw_finish( __in efx_nvram_type_t type) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); @@ -355,7 +401,8 @@ efx_nvram_rw_finish( EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - envop->envo_rw_finish(enp, type); + if (envop->envo_type_to_partn(enp, type, &partn) == 0) + envop->envo_partn_rw_finish(enp, partn); enp->en_nvram_locked = EFX_NVRAM_INVALID; } @@ -367,6 +414,7 @@ efx_nvram_set_version( __in_ecount(4) uint16_t version[4]) { efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); @@ -382,11 +430,16 @@ efx_nvram_set_version( */ EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); - if ((rc = envop->envo_set_version(enp, type, version)) != 0) + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) + goto fail2; + return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -668,10 +721,11 @@ efx_mcdi_nvram_read( __in uint32_t partn, __in uint32_t offset, __out_bcount(size) caddr_t data, - __in size_t size) + __in size_t size, + __in uint32_t mode) { efx_mcdi_req_t req; - uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, + uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN, MC_CMD_NVRAM_READ_OUT_LENMAX)]; efx_rc_t rc; @@ -683,13 +737,14 @@ efx_mcdi_nvram_read( (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_NVRAM_READ; req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; + req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN; req.emr_out_buf = payload; req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; - MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); - MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); - MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size); + MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn); + MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset); + MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size); + MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode); efx_mcdi_execute(enp, &req); diff --git a/sys/dev/sfxge/common/efx_phy.c b/sys/dev/sfxge/common/efx_phy.c index dd966be..51e1ccb 100644 --- a/sys/dev/sfxge/common/efx_phy.c +++ b/sys/dev/sfxge/common/efx_phy.c @@ -265,33 +265,34 @@ static efx_phy_ops_t __efx_phy_siena_ops = { }; #endif /* EFSYS_OPT_SIENA */ -#if EFSYS_OPT_HUNTINGTON -static efx_phy_ops_t __efx_phy_hunt_ops = { - hunt_phy_power, /* epo_power */ +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD +static efx_phy_ops_t __efx_phy_ef10_ops = { + ef10_phy_power, /* epo_power */ NULL, /* epo_reset */ - hunt_phy_reconfigure, /* epo_reconfigure */ - hunt_phy_verify, /* epo_verify */ + ef10_phy_reconfigure, /* epo_reconfigure */ + ef10_phy_verify, /* epo_verify */ NULL, /* epo_uplink_check */ NULL, /* epo_downlink_check */ - hunt_phy_oui_get, /* epo_oui_get */ + ef10_phy_oui_get, /* epo_oui_get */ #if EFSYS_OPT_PHY_STATS - hunt_phy_stats_update, /* epo_stats_update */ + ef10_phy_stats_update, /* epo_stats_update */ #endif /* EFSYS_OPT_PHY_STATS */ #if EFSYS_OPT_PHY_PROPS #if EFSYS_OPT_NAMES - hunt_phy_prop_name, /* epo_prop_name */ + ef10_phy_prop_name, /* epo_prop_name */ #endif - hunt_phy_prop_get, /* epo_prop_get */ - hunt_phy_prop_set, /* epo_prop_set */ + ef10_phy_prop_get, /* epo_prop_get */ + ef10_phy_prop_set, /* epo_prop_set */ #endif /* EFSYS_OPT_PHY_PROPS */ #if EFSYS_OPT_BIST + /* FIXME: Are these BIST methods appropriate for Medford? */ hunt_bist_enable_offline, /* epo_bist_enable_offline */ hunt_bist_start, /* epo_bist_start */ hunt_bist_poll, /* epo_bist_poll */ hunt_bist_stop, /* epo_bist_stop */ #endif /* EFSYS_OPT_BIST */ }; -#endif /* EFSYS_OPT_HUNTINGTON */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ __checkReturn efx_rc_t efx_phy_probe( @@ -356,9 +357,14 @@ efx_phy_probe( #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON case EFX_FAMILY_HUNTINGTON: - epop = (efx_phy_ops_t *)&__efx_phy_hunt_ops; + epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops; break; #endif /* EFSYS_OPT_HUNTINGTON */ +#if EFSYS_OPT_MEDFORD + case EFX_FAMILY_MEDFORD: + epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops; + break; +#endif /* EFSYS_OPT_MEDFORD */ default: rc = ENOTSUP; goto fail1; diff --git a/sys/dev/sfxge/common/efx_regs_ef10.h b/sys/dev/sfxge/common/efx_regs_ef10.h index bd7619a..43745e5 100644 --- a/sys/dev/sfxge/common/efx_regs_ef10.h +++ b/sys/dev/sfxge/common/efx_regs_ef10.h @@ -50,7 +50,7 @@ extern "C" { */ #define ER_DZ_BIU_HW_REV_ID_REG_OFST 0x00000000 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_BIU_HW_REV_ID_REG_RESET 0xeb14face @@ -64,7 +64,7 @@ extern "C" { */ #define ER_DZ_BIU_MC_SFT_STATUS_REG_OFST 0x00000010 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_BIU_MC_SFT_STATUS_REG_STEP 4 #define ER_DZ_BIU_MC_SFT_STATUS_REG_ROWS 8 #define ER_DZ_BIU_MC_SFT_STATUS_REG_RESET 0x1111face @@ -80,7 +80,7 @@ extern "C" { */ #define ER_DZ_BIU_INT_ISR_REG_OFST 0x00000090 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_BIU_INT_ISR_REG_RESET 0x0 @@ -94,7 +94,7 @@ extern "C" { */ #define ER_DZ_MC_DB_LWRD_REG_OFST 0x00000200 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_MC_DB_LWRD_REG_RESET 0x0 @@ -108,7 +108,7 @@ extern "C" { */ #define ER_DZ_MC_DB_HWRD_REG_OFST 0x00000204 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_MC_DB_HWRD_REG_RESET 0x0 @@ -122,7 +122,7 @@ extern "C" { */ #define ER_DZ_EVQ_RPTR_REG_OFST 0x00000400 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_EVQ_RPTR_REG_STEP 8192 #define ER_DZ_EVQ_RPTR_REG_ROWS 2048 #define ER_DZ_EVQ_RPTR_REG_RESET 0x0 @@ -140,7 +140,7 @@ extern "C" { */ #define ER_DZ_EVQ_TMR_REG_OFST 0x00000420 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_EVQ_TMR_REG_STEP 8192 #define ER_DZ_EVQ_TMR_REG_ROWS 2048 #define ER_DZ_EVQ_TMR_REG_RESET 0x0 @@ -158,7 +158,7 @@ extern "C" { */ #define ER_DZ_RX_DESC_UPD_REG_OFST 0x00000830 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_RX_DESC_UPD_REG_STEP 8192 #define ER_DZ_RX_DESC_UPD_REG_ROWS 2048 #define ER_DZ_RX_DESC_UPD_REG_RESET 0x0 @@ -174,7 +174,7 @@ extern "C" { */ #define ER_DZ_TX_DESC_UPD_REG_OFST 0x00000a10 -/* hunta0=pcie_pf_bar2 */ +/* hunta0,medforda0=pcie_pf_bar2 */ #define ER_DZ_TX_DESC_UPD_REG_STEP 8192 #define ER_DZ_TX_DESC_UPD_REG_ROWS 2048 #define ER_DZ_TX_DESC_UPD_REG_RESET 0x0 @@ -248,8 +248,14 @@ extern "C" { #define ESF_DZ_RX_OVERRIDE_HOLDOFF_WIDTH 1 #define ESF_DZ_RX_DROP_EVENT_LBN 58 #define ESF_DZ_RX_DROP_EVENT_WIDTH 1 -#define ESF_DZ_RX_EV_RSVD2_LBN 54 -#define ESF_DZ_RX_EV_RSVD2_WIDTH 4 +#define ESF_DD_RX_EV_RSVD2_LBN 54 +#define ESF_DD_RX_EV_RSVD2_WIDTH 4 +#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_LBN 57 +#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1 +#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_LBN 56 +#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_WIDTH 1 +#define ESF_EZ_RX_EV_RSVD2_LBN 54 +#define ESF_EZ_RX_EV_RSVD2_WIDTH 2 #define ESF_DZ_RX_EV_SOFT2_LBN 52 #define ESF_DZ_RX_EV_SOFT2_WIDTH 2 #define ESF_DZ_RX_DSC_PTR_LBITS_LBN 48 @@ -293,10 +299,21 @@ extern "C" { #define ESF_DZ_RX_MAC_CLASS_WIDTH 1 #define ESE_DZ_MAC_CLASS_MCAST 1 #define ESE_DZ_MAC_CLASS_UCAST 0 -#define ESF_DZ_RX_EV_SOFT1_LBN 32 -#define ESF_DZ_RX_EV_SOFT1_WIDTH 3 -#define ESF_DZ_RX_EV_RSVD1_LBN 30 -#define ESF_DZ_RX_EV_RSVD1_WIDTH 2 +#define ESF_DD_RX_EV_SOFT1_LBN 32 +#define ESF_DD_RX_EV_SOFT1_WIDTH 3 +#define ESF_EZ_RX_EV_SOFT1_LBN 34 +#define ESF_EZ_RX_EV_SOFT1_WIDTH 1 +#define ESF_EZ_RX_ENCAP_HDR_LBN 32 +#define ESF_EZ_RX_ENCAP_HDR_WIDTH 2 +#define ESE_EZ_ENCAP_HDR_GRE 2 +#define ESE_EZ_ENCAP_HDR_VXLAN 1 +#define ESE_EZ_ENCAP_HDR_NONE 0 +#define ESF_DD_RX_EV_RSVD1_LBN 30 +#define ESF_DD_RX_EV_RSVD1_WIDTH 2 +#define ESF_EZ_RX_EV_RSVD1_LBN 31 +#define ESF_EZ_RX_EV_RSVD1_WIDTH 1 +#define ESF_EZ_RX_ABORT_LBN 30 +#define ESF_EZ_RX_ABORT_WIDTH 1 #define ESF_DZ_RX_ECC_ERR_LBN 29 #define ESF_DZ_RX_ECC_ERR_WIDTH 1 #define ESF_DZ_RX_CRC1_ERR_LBN 28 @@ -369,12 +386,22 @@ extern "C" { #define ESF_DZ_TX_OVERRIDE_HOLDOFF_WIDTH 1 #define ESF_DZ_TX_DROP_EVENT_LBN 58 #define ESF_DZ_TX_DROP_EVENT_WIDTH 1 -#define ESF_DZ_TX_EV_RSVD_LBN 48 -#define ESF_DZ_TX_EV_RSVD_WIDTH 10 +#define ESF_DD_TX_EV_RSVD_LBN 48 +#define ESF_DD_TX_EV_RSVD_WIDTH 10 +#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_LBN 57 +#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1 +#define ESF_EZ_IP_INNER_CHKSUM_ERR_LBN 56 +#define ESF_EZ_IP_INNER_CHKSUM_ERR_WIDTH 1 +#define ESF_EZ_TX_EV_RSVD_LBN 48 +#define ESF_EZ_TX_EV_RSVD_WIDTH 8 #define ESF_DZ_TX_SOFT2_LBN 32 #define ESF_DZ_TX_SOFT2_WIDTH 16 -#define ESF_DZ_TX_SOFT1_LBN 24 -#define ESF_DZ_TX_SOFT1_WIDTH 8 +#define ESF_DD_TX_SOFT1_LBN 24 +#define ESF_DD_TX_SOFT1_WIDTH 8 +#define ESF_EZ_TX_CAN_MERGE_LBN 31 +#define ESF_EZ_TX_CAN_MERGE_WIDTH 1 +#define ESF_EZ_TX_SOFT1_LBN 24 +#define ESF_EZ_TX_SOFT1_WIDTH 7 #define ESF_DZ_TX_QLABEL_LBN 16 #define ESF_DZ_TX_QLABEL_WIDTH 5 #define ESF_DZ_TX_DESCR_INDX_LBN 0 diff --git a/sys/dev/sfxge/common/efx_rx.c b/sys/dev/sfxge/common/efx_rx.c index a0b143f..8ebe205 100644 --- a/sys/dev/sfxge/common/efx_rx.c +++ b/sys/dev/sfxge/common/efx_rx.c @@ -78,14 +78,14 @@ falconsiena_rx_prefix_hash( __in efx_rx_hash_alg_t func, __in uint8_t *buffer); +#endif /* EFSYS_OPT_RX_SCALE */ + static __checkReturn efx_rc_t falconsiena_rx_prefix_pktlen( __in efx_nic_t *enp, __in uint8_t *buffer, __out uint16_t *lengthp); -#endif /* EFSYS_OPT_RX_SCALE */ - static void falconsiena_rx_qpost( __in efx_rxq_t *erp, diff --git a/sys/dev/sfxge/common/efx_tx.c b/sys/dev/sfxge/common/efx_tx.c index cff7742..168fde4 100644 --- a/sys/dev/sfxge/common/efx_tx.c +++ b/sys/dev/sfxge/common/efx_tx.c @@ -142,6 +142,7 @@ static efx_tx_ops_t __efx_tx_falcon_ops = { falconsiena_tx_qdesc_post, /* etxo_qdesc_post */ falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ NULL, /* etxo_qdesc_tso_create */ + NULL, /* etxo_qdesc_tso2_create */ NULL, /* etxo_qdesc_vlantci_create */ #if EFSYS_OPT_QSTATS falconsiena_tx_qstats_update, /* etxo_qstats_update */ @@ -167,6 +168,7 @@ static efx_tx_ops_t __efx_tx_siena_ops = { falconsiena_tx_qdesc_post, /* etxo_qdesc_post */ falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ NULL, /* etxo_qdesc_tso_create */ + NULL, /* etxo_qdesc_tso2_create */ NULL, /* etxo_qdesc_vlantci_create */ #if EFSYS_OPT_QSTATS falconsiena_tx_qstats_update, /* etxo_qstats_update */ @@ -192,6 +194,7 @@ static efx_tx_ops_t __efx_tx_hunt_ops = { ef10_tx_qdesc_post, /* etxo_qdesc_post */ ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ hunt_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */ + ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */ ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */ #if EFSYS_OPT_QSTATS ef10_tx_qstats_update, /* etxo_qstats_update */ @@ -217,6 +220,7 @@ static efx_tx_ops_t __efx_tx_medford_ops = { ef10_tx_qdesc_post, /* etxo_qdesc_post */ ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ NULL, /* etxo_qdesc_tso_create */ + ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */ ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */ #if EFSYS_OPT_QSTATS ef10_tx_qstats_update, /* etxo_qstats_update */ @@ -641,6 +645,24 @@ efx_tx_qdesc_tso_create( } void +efx_tx_qdesc_tso2_create( + __in efx_txq_t *etp, + __in uint16_t ipv4_id, + __in uint32_t tcp_seq, + __in uint16_t mss, + __out_ecount(count) efx_desc_t *edp, + __in int count) +{ + efx_nic_t *enp = etp->et_enp; + efx_tx_ops_t *etxop = enp->en_etxop; + + EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); + EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL); + + etxop->etxo_qdesc_tso2_create(etp, ipv4_id, tcp_seq, mss, edp, count); +} + + void efx_tx_qdesc_vlantci_create( __in efx_txq_t *etp, __in uint16_t tci, diff --git a/sys/dev/sfxge/common/efx_vpd.c b/sys/dev/sfxge/common/efx_vpd.c index c1762e6..ebeddfe 100644 --- a/sys/dev/sfxge/common/efx_vpd.c +++ b/sys/dev/sfxge/common/efx_vpd.c @@ -669,7 +669,7 @@ efx_vpd_hunk_next( __in size_t size, __out efx_vpd_tag_t *tagp, __out efx_vpd_keyword_t *keywordp, - __out_bcount_opt(*paylenp) unsigned int *payloadp, + __out_opt unsigned int *payloadp, __out_opt uint8_t *paylenp, __inout unsigned int *contp) { @@ -689,12 +689,18 @@ efx_vpd_hunk_next( if ((rc = efx_vpd_next_tag(data, size, &offset, &tag, &taglen)) != 0) goto fail1; - if (tag == EFX_VPD_END) + + if (tag == EFX_VPD_END) { + keyword = 0; + paylen = 0; + index = 0; break; + } if (tag == EFX_VPD_ID) { - if (index == *contp) { + if (index++ == *contp) { EFSYS_ASSERT3U(taglen, <, 0x100); + keyword = 0; paylen = (uint8_t)MIN(taglen, 0xff); goto done; @@ -705,7 +711,7 @@ efx_vpd_hunk_next( taglen, pos, &keyword, &keylen)) != 0) goto fail2; - if (index == *contp) { + if (index++ == *contp) { offset += pos + 3; paylen = keylen; @@ -717,9 +723,6 @@ efx_vpd_hunk_next( offset += taglen; } - *contp = 0; - return (0); - done: *tagp = tag; *keywordp = keyword; @@ -728,7 +731,7 @@ done: if (paylenp != NULL) *paylenp = paylen; - ++(*contp); + *contp = index; return (0); fail2: diff --git a/sys/dev/sfxge/common/hunt_ev.c b/sys/dev/sfxge/common/hunt_ev.c index 2cea2e0..1a41b49 100644 --- a/sys/dev/sfxge/common/hunt_ev.c +++ b/sys/dev/sfxge/common/hunt_ev.c @@ -444,9 +444,9 @@ ef10_ev_qmoderate( eep->ee_index, &dword, 0); } else { EFX_POPULATE_DWORD_2(dword, - FRF_CZ_TC_TIMER_MODE, mode, - FRF_CZ_TC_TIMER_VAL, timer_val); - EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0, + ERF_DZ_TC_TIMER_MODE, mode, + ERF_DZ_TC_TIMER_VAL, timer_val); + EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG, eep->ee_index, &dword, 0); } @@ -486,17 +486,14 @@ ef10_ev_rx( { efx_nic_t *enp = eep->ee_enp; uint32_t size; -#if 0 - boolean_t parse_err; -#endif uint32_t label; - uint32_t mcast; - uint32_t eth_base_class; + uint32_t mac_class; uint32_t eth_tag_class; uint32_t l3_class; uint32_t l4_class; uint32_t next_read_lbits; uint16_t flags; + boolean_t cont; boolean_t should_abort; efx_evq_rxq_state_t *eersp; unsigned int desc_count; @@ -508,10 +505,15 @@ ef10_ev_rx( if (enp->en_reset_flags & (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR)) return (B_FALSE); - /* - * FIXME: likely to be incomplete, incorrect and inefficient. - * Improvements in all three areas are required. - */ + /* Basic packet information */ + size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES); + next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS); + label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL); + eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS); + mac_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS); + l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS); + l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS); + cont = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT); if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DROP_EVENT) != 0) { /* Drop this event */ @@ -519,9 +521,7 @@ ef10_ev_rx( } flags = 0; - size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES); - - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT) != 0) { + if (cont != 0) { /* * This may be part of a scattered frame, or it may be a * truncated frame if scatter is disabled on this RXQ. @@ -534,41 +534,9 @@ ef10_ev_rx( flags |= EFX_PKT_CONT; } -#if 0 - /* TODO What to do if the packet is flagged with parsing error */ - parse_err = (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE) != 0); -#endif - label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL); - - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) { - /* Ethernet frame CRC bad */ - flags |= EFX_DISCARD; - } - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC0_ERR) != 0) { - /* IP+TCP, bad CRC in iSCSI header */ - flags |= EFX_DISCARD; - } - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC1_ERR) != 0) { - /* IP+TCP, bad CRC in iSCSI payload or FCoE or FCoIP */ - flags |= EFX_DISCARD; - } - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) { - /* ECC memory error */ - flags |= EFX_DISCARD; - } - - mcast = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS); - if (mcast == ESE_DZ_MAC_CLASS_UCAST) + if (mac_class == ESE_DZ_MAC_CLASS_UCAST) flags |= EFX_PKT_UNICAST; - eth_base_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_BASE_CLASS); - eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS); - l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS); - l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS); - - /* bottom 4 bits of incremented index (not last desc consumed) */ - next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS); - /* Increment the count of descriptors read */ eersp = &eep->ee_rxq_state[label]; desc_count = (next_read_lbits - eersp->eers_rx_read_ptr) & @@ -587,88 +555,84 @@ ef10_ev_rx( /* Calculate the index of the the last descriptor consumed */ last_used_id = (eersp->eers_rx_read_ptr - 1) & eersp->eers_rx_mask; - /* EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_OVERRIDE_HOLDOFF); */ - - switch (eth_base_class) { - case ESE_DZ_ETH_BASE_CLASS_LLC_SNAP: - case ESE_DZ_ETH_BASE_CLASS_LLC: - case ESE_DZ_ETH_BASE_CLASS_ETH2: - default: - break; + /* Check for errors that invalidate checksum and L3/L4 fields */ + if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) { + /* RX frame truncated (error flag is misnamed) */ + EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC); + flags |= EFX_DISCARD; + goto deliver; + } + if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) { + /* Bad Ethernet frame CRC */ + EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR); + flags |= EFX_DISCARD; + goto deliver; + } + if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE)) { + /* + * Hardware parse failed, due to malformed headers + * or headers that are too long for the parser. + * Headers and checksums must be validated by the host. + */ + // TODO: EFX_EV_QSTAT_INCR(eep, EV_RX_PARSE_INCOMPLETE); + goto deliver; } - switch (eth_tag_class) { - case ESE_DZ_ETH_TAG_CLASS_RSVD7: - case ESE_DZ_ETH_TAG_CLASS_RSVD6: - case ESE_DZ_ETH_TAG_CLASS_RSVD5: - case ESE_DZ_ETH_TAG_CLASS_RSVD4: - break; - - case ESE_DZ_ETH_TAG_CLASS_RSVD3: /* Triple tagged */ - case ESE_DZ_ETH_TAG_CLASS_VLAN2: /* Double tagged */ - case ESE_DZ_ETH_TAG_CLASS_VLAN1: /* VLAN tagged */ + if ((eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN1) || + (eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN2)) { flags |= EFX_PKT_VLAN_TAGGED; - break; - - case ESE_DZ_ETH_TAG_CLASS_NONE: - default: - break; } switch (l3_class) { - case ESE_DZ_L3_CLASS_RSVD7: /* Used by firmware for packet overrun */ -#if 0 - parse_err = B_TRUE; -#endif - flags |= EFX_DISCARD; - break; + case ESE_DZ_L3_CLASS_IP4: + case ESE_DZ_L3_CLASS_IP4_FRAG: + flags |= EFX_PKT_IPV4; + if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR)) { + EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR); + } else { + flags |= EFX_CKSUM_IPV4; + } - case ESE_DZ_L3_CLASS_ARP: - case ESE_DZ_L3_CLASS_FCOE: + if (l4_class == ESE_DZ_L4_CLASS_TCP) { + EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4); + flags |= EFX_PKT_TCP; + } else if (l4_class == ESE_DZ_L4_CLASS_UDP) { + EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4); + flags |= EFX_PKT_UDP; + } else { + EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4); + } break; - case ESE_DZ_L3_CLASS_IP6_FRAG: case ESE_DZ_L3_CLASS_IP6: + case ESE_DZ_L3_CLASS_IP6_FRAG: flags |= EFX_PKT_IPV6; - break; - case ESE_DZ_L3_CLASS_IP4_FRAG: - case ESE_DZ_L3_CLASS_IP4: - flags |= EFX_PKT_IPV4; - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR) == 0) - flags |= EFX_CKSUM_IPV4; + if (l4_class == ESE_DZ_L4_CLASS_TCP) { + EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6); + flags |= EFX_PKT_TCP; + } else if (l4_class == ESE_DZ_L4_CLASS_UDP) { + EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6); + flags |= EFX_PKT_UDP; + } else { + EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6); + } break; - case ESE_DZ_L3_CLASS_UNKNOWN: default: + EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP); break; } - switch (l4_class) { - case ESE_DZ_L4_CLASS_RSVD7: - case ESE_DZ_L4_CLASS_RSVD6: - case ESE_DZ_L4_CLASS_RSVD5: - case ESE_DZ_L4_CLASS_RSVD4: - case ESE_DZ_L4_CLASS_RSVD3: - break; - - case ESE_DZ_L4_CLASS_UDP: - flags |= EFX_PKT_UDP; - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0) - flags |= EFX_CKSUM_TCPUDP; - break; - - case ESE_DZ_L4_CLASS_TCP: - flags |= EFX_PKT_TCP; - if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0) + if (flags & (EFX_PKT_TCP | EFX_PKT_UDP)) { + if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR)) { + EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR); + } else { flags |= EFX_CKSUM_TCPUDP; - break; - - case ESE_DZ_L4_CLASS_UNKNOWN: - default: - break; + } } +deliver: /* If we're not discarding the packet then it is ok */ if (~flags & EFX_DISCARD) EFX_EV_QSTAT_INCR(eep, EV_RX_OK); @@ -835,7 +799,7 @@ ef10_ev_mcdi( case MCDI_EVENT_CODE_LINKCHANGE: { efx_link_mode_t link_mode; - hunt_phy_link_ev(enp, eqp, &link_mode); + ef10_phy_link_ev(enp, eqp, &link_mode); should_abort = eecp->eec_link_change(arg, link_mode); break; } diff --git a/sys/dev/sfxge/common/hunt_impl.h b/sys/dev/sfxge/common/hunt_impl.h index f8c3b5e..49ecbea 100644 --- a/sys/dev/sfxge/common/hunt_impl.h +++ b/sys/dev/sfxge/common/hunt_impl.h @@ -54,6 +54,13 @@ extern "C" { */ #define EF10_RX_WPTR_ALIGN 8 +/* + * Max byte offset into the packet the TCP header must start for the hardware + * to be able to parse the packet correctly. + * FIXME: Move to ef10_impl.h when it is included in all driver builds. + */ +#define EF10_TCP_HEADER_OFFSET_LIMIT 208 + /* Invalid RSS context handle */ #define EF10_RSS_CONTEXT_INVALID (0xffffffff) @@ -165,6 +172,10 @@ ef10_nic_probe( __in efx_nic_t *enp); extern __checkReturn efx_rc_t +hunt_board_cfg( + __in efx_nic_t *enp); + +extern __checkReturn efx_rc_t ef10_nic_set_drv_limits( __inout efx_nic_t *enp, __in efx_drv_limits_t *edlp); @@ -209,41 +220,45 @@ ef10_nic_unprobe( /* MAC */ extern __checkReturn efx_rc_t -hunt_mac_poll( +ef10_mac_poll( __in efx_nic_t *enp, __out efx_link_mode_t *link_modep); extern __checkReturn efx_rc_t -hunt_mac_up( +ef10_mac_up( __in efx_nic_t *enp, __out boolean_t *mac_upp); extern __checkReturn efx_rc_t -hunt_mac_addr_set( +ef10_mac_addr_set( __in efx_nic_t *enp); extern __checkReturn efx_rc_t -hunt_mac_reconfigure( +ef10_mac_pdu_set( __in efx_nic_t *enp); extern __checkReturn efx_rc_t -hunt_mac_multicast_list_set( +ef10_mac_reconfigure( + __in efx_nic_t *enp); + +extern __checkReturn efx_rc_t +ef10_mac_multicast_list_set( __in efx_nic_t *enp); extern __checkReturn efx_rc_t -hunt_mac_filter_default_rxq_set( +ef10_mac_filter_default_rxq_set( __in efx_nic_t *enp, __in efx_rxq_t *erp, __in boolean_t using_rss); extern void -hunt_mac_filter_default_rxq_clear( +ef10_mac_filter_default_rxq_clear( __in efx_nic_t *enp); #if EFSYS_OPT_LOOPBACK extern __checkReturn efx_rc_t -hunt_mac_loopback_set( +ef10_mac_loopback_set( __in efx_nic_t *enp, __in efx_link_mode_t link_mode, __in efx_loopback_type_t loopback_type); @@ -253,7 +268,7 @@ hunt_mac_loopback_set( #if EFSYS_OPT_MAC_STATS extern __checkReturn efx_rc_t -hunt_mac_stats_update( +ef10_mac_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat, @@ -276,12 +291,12 @@ ef10_mcdi_fini( __in efx_nic_t *enp); extern void -ef10_mcdi_request_copyin( +ef10_mcdi_send_request( __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp, - __in unsigned int seq, - __in boolean_t ev_cpl, - __in boolean_t new_epoch); + __in void *hdrp, + __in size_t hdr_len, + __in void *sdup, + __in size_t sdu_len); extern __checkReturn boolean_t ef10_mcdi_poll_response( @@ -294,11 +309,6 @@ ef10_mcdi_read_response( __in size_t offset, __in size_t length); -extern void -ef10_mcdi_request_copyout( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp); - extern efx_rc_t ef10_mcdi_poll_reboot( __in efx_nic_t *enp); @@ -359,39 +369,10 @@ ef10_nvram_partn_write_segment_tlv( __in boolean_t all_segments); extern __checkReturn efx_rc_t -ef10_nvram_partn_size( - __in efx_nic_t *enp, - __in uint32_t partn, - __out size_t *sizep); - -extern __checkReturn efx_rc_t ef10_nvram_partn_lock( __in efx_nic_t *enp, __in uint32_t partn); -extern __checkReturn efx_rc_t -ef10_nvram_partn_read( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size); - -extern __checkReturn efx_rc_t -ef10_nvram_partn_erase( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __in size_t size); - -extern __checkReturn efx_rc_t -ef10_nvram_partn_write( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size); - extern void ef10_nvram_partn_unlock( __in efx_nic_t *enp, @@ -410,117 +391,122 @@ ef10_nvram_test( #endif /* EFSYS_OPT_DIAG */ extern __checkReturn efx_rc_t -ef10_nvram_size( +ef10_nvram_type_to_partn( __in efx_nic_t *enp, __in efx_nvram_type_t type, + __out uint32_t *partnp); + +extern __checkReturn efx_rc_t +ef10_nvram_partn_size( + __in efx_nic_t *enp, + __in uint32_t partn, __out size_t *sizep); extern __checkReturn efx_rc_t -ef10_nvram_get_version( +ef10_nvram_partn_rw_start( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out uint32_t *subtypep, - __out_ecount(4) uint16_t version[4]); + __in uint32_t partn, + __out size_t *chunk_sizep); extern __checkReturn efx_rc_t -ef10_nvram_rw_start( +ef10_nvram_partn_read_mode( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out size_t *pref_chunkp); + __in uint32_t partn, + __in unsigned int offset, + __out_bcount(size) caddr_t data, + __in size_t size, + __in uint32_t mode); extern __checkReturn efx_rc_t -ef10_nvram_read_chunk( +ef10_nvram_partn_read( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __in unsigned int offset, __out_bcount(size) caddr_t data, __in size_t size); -extern __checkReturn efx_rc_t -ef10_nvram_erase( +extern __checkReturn efx_rc_t +ef10_nvram_partn_erase( __in efx_nic_t *enp, - __in efx_nvram_type_t type); + __in uint32_t partn, + __in unsigned int offset, + __in size_t size); extern __checkReturn efx_rc_t -ef10_nvram_write_chunk( +ef10_nvram_partn_write( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __in unsigned int offset, - __in_bcount(size) caddr_t data, + __out_bcount(size) caddr_t data, __in size_t size); extern void -ef10_nvram_rw_finish( +ef10_nvram_partn_rw_finish( __in efx_nic_t *enp, - __in efx_nvram_type_t type); + __in uint32_t partn); extern __checkReturn efx_rc_t -ef10_nvram_partn_set_version( +ef10_nvram_partn_get_version( __in efx_nic_t *enp, __in uint32_t partn, - __in_ecount(4) uint16_t version[4]); + __out uint32_t *subtypep, + __out_ecount(4) uint16_t version[4]); extern __checkReturn efx_rc_t -ef10_nvram_set_version( +ef10_nvram_partn_set_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __in_ecount(4) uint16_t version[4]); -extern __checkReturn efx_rc_t -ef10_nvram_type_to_partn( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out uint32_t *partnp); - #endif /* EFSYS_OPT_NVRAM */ /* PHY */ -typedef struct hunt_link_state_s { - uint32_t hls_adv_cap_mask; - uint32_t hls_lp_cap_mask; - unsigned int hls_fcntl; - efx_link_mode_t hls_link_mode; +typedef struct ef10_link_state_s { + uint32_t els_adv_cap_mask; + uint32_t els_lp_cap_mask; + unsigned int els_fcntl; + efx_link_mode_t els_link_mode; #if EFSYS_OPT_LOOPBACK - efx_loopback_type_t hls_loopback; + efx_loopback_type_t els_loopback; #endif - boolean_t hls_mac_up; -} hunt_link_state_t; + boolean_t els_mac_up; +} ef10_link_state_t; extern void -hunt_phy_link_ev( +ef10_phy_link_ev( __in efx_nic_t *enp, __in efx_qword_t *eqp, __out efx_link_mode_t *link_modep); extern __checkReturn efx_rc_t -hunt_phy_get_link( +ef10_phy_get_link( __in efx_nic_t *enp, - __out hunt_link_state_t *hlsp); + __out ef10_link_state_t *elsp); extern __checkReturn efx_rc_t -hunt_phy_power( +ef10_phy_power( __in efx_nic_t *enp, __in boolean_t on); extern __checkReturn efx_rc_t -hunt_phy_reconfigure( +ef10_phy_reconfigure( __in efx_nic_t *enp); extern __checkReturn efx_rc_t -hunt_phy_verify( +ef10_phy_verify( __in efx_nic_t *enp); extern __checkReturn efx_rc_t -hunt_phy_oui_get( +ef10_phy_oui_get( __in efx_nic_t *enp, __out uint32_t *ouip); #if EFSYS_OPT_PHY_STATS extern __checkReturn efx_rc_t -hunt_phy_stats_update( +ef10_phy_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat); @@ -532,21 +518,21 @@ hunt_phy_stats_update( #if EFSYS_OPT_NAMES extern const char * -hunt_phy_prop_name( +ef10_phy_prop_name( __in efx_nic_t *enp, __in unsigned int id); #endif /* EFSYS_OPT_NAMES */ extern __checkReturn efx_rc_t -hunt_phy_prop_get( +ef10_phy_prop_get( __in efx_nic_t *enp, __in unsigned int id, __in uint32_t flags, __out uint32_t *valp); extern __checkReturn efx_rc_t -hunt_phy_prop_set( +ef10_phy_prop_set( __in efx_nic_t *enp, __in unsigned int id, __in uint32_t val); @@ -696,6 +682,15 @@ hunt_tx_qdesc_tso_create( __out efx_desc_t *edp); extern void +ef10_tx_qdesc_tso2_create( + __in efx_txq_t *etp, + __in uint16_t ipv4_id, + __in uint32_t tcp_seq, + __in uint16_t tcp_mss, + __out_ecount(count) efx_desc_t *edp, + __in int count); + +extern void ef10_tx_qdesc_vlantci_create( __in efx_txq_t *etp, __in uint16_t vlan_tci, @@ -733,7 +728,7 @@ ef10_tx_qstats_update( #define HUNT_MIN_PIO_ALLOC_SIZE (HUNT_PIOBUF_SIZE / 32) -#define HUNT_LEGACY_PF_PRIVILEGE_MASK \ +#define EF10_LEGACY_PF_PRIVILEGE_MASK \ (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \ MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \ MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \ @@ -746,7 +741,7 @@ ef10_tx_qstats_update( MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \ MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS) -#define HUNT_LEGACY_VF_PRIVILEGE_MASK 0 +#define EF10_LEGACY_VF_PRIVILEGE_MASK 0 typedef uint32_t efx_piobuf_handle_t; @@ -886,14 +881,14 @@ ef10_rx_prefix_hash( __in efx_rx_hash_alg_t func, __in uint8_t *buffer); +#endif /* EFSYS_OPT_RX_SCALE */ + extern __checkReturn efx_rc_t ef10_rx_prefix_pktlen( __in efx_nic_t *enp, __in uint8_t *buffer, __out uint16_t *lengthp); -#endif /* EFSYS_OPT_RX_SCALE */ - extern void ef10_rx_qpost( __in efx_rxq_t *erp, diff --git a/sys/dev/sfxge/common/hunt_mac.c b/sys/dev/sfxge/common/hunt_mac.c index 358c4d9..a36a11a 100644 --- a/sys/dev/sfxge/common/hunt_mac.c +++ b/sys/dev/sfxge/common/hunt_mac.c @@ -38,26 +38,21 @@ __FBSDID("$FreeBSD$"); #if EFSYS_OPT_HUNTINGTON __checkReturn efx_rc_t -hunt_mac_poll( +ef10_mac_poll( __in efx_nic_t *enp, __out efx_link_mode_t *link_modep) { - /* - * TBD: Consider a common Siena/Huntington function. The code is - * essentially identical. - */ - efx_port_t *epp = &(enp->en_port); - hunt_link_state_t hls; + ef10_link_state_t els; efx_rc_t rc; - if ((rc = hunt_phy_get_link(enp, &hls)) != 0) + if ((rc = ef10_phy_get_link(enp, &els)) != 0) goto fail1; - epp->ep_adv_cap_mask = hls.hls_adv_cap_mask; - epp->ep_fcntl = hls.hls_fcntl; + epp->ep_adv_cap_mask = els.els_adv_cap_mask; + epp->ep_fcntl = els.els_fcntl; - *link_modep = hls.hls_link_mode; + *link_modep = els.els_link_mode; return (0); @@ -70,26 +65,21 @@ fail1: } __checkReturn efx_rc_t -hunt_mac_up( +ef10_mac_up( __in efx_nic_t *enp, __out boolean_t *mac_upp) { - /* - * TBD: Consider a common Siena/Huntington function. The code is - * essentially identical. - */ - - hunt_link_state_t hls; + ef10_link_state_t els; efx_rc_t rc; /* - * Because Huntington doesn't *require* polling, we can't rely on - * hunt_mac_poll() being executed to populate epp->ep_mac_up. + * Because EF10 doesn't *require* polling, we can't rely on + * ef10_mac_poll() being executed to populate epp->ep_mac_up. */ - if ((rc = hunt_phy_get_link(enp, &hls)) != 0) + if ((rc = ef10_phy_get_link(enp, &els)) != 0) goto fail1; - *mac_upp = hls.hls_mac_up; + *mac_upp = els.els_mac_up; return (0); @@ -100,7 +90,7 @@ fail1: } /* - * Huntington uses MC_CMD_VADAPTOR_SET_MAC to set the + * EF10 adapters use MC_CMD_VADAPTOR_SET_MAC to set the * MAC address; the address field in MC_CMD_SET_MAC has no * effect. * MC_CMD_VADAPTOR_SET_MAC requires mac-spoofing privilege and @@ -144,7 +134,7 @@ fail1: } __checkReturn efx_rc_t -hunt_mac_addr_set( +ef10_mac_addr_set( __in efx_nic_t *enp) { efx_rc_t rc; @@ -153,8 +143,11 @@ hunt_mac_addr_set( if (rc != ENOTSUP) goto fail1; - /* Fallback for older firmware without Vadapter support */ - if ((rc = hunt_mac_reconfigure(enp)) != 0) + /* + * Fallback for older Huntington firmware without Vadapter + * support. + */ + if ((rc = ef10_mac_reconfigure(enp)) != 0) goto fail2; } @@ -169,8 +162,76 @@ fail1: return (rc); } +static __checkReturn efx_rc_t +efx_mcdi_mtu_set( + __in efx_nic_t *enp, + __in uint32_t mtu) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_SET_MAC_EXT_IN_LEN, + MC_CMD_SET_MAC_OUT_LEN)]; + efx_rc_t rc; + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_SET_MAC; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_SET_MAC_EXT_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN; + + /* Only configure the MTU in this call to MC_CMD_SET_MAC */ + MCDI_IN_SET_DWORD(req, SET_MAC_EXT_IN_MTU, mtu); + MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_EXT_IN_CONTROL, + SET_MAC_EXT_IN_CFG_MTU, 1); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +ef10_mac_pdu_set( + __in efx_nic_t *enp) +{ + efx_port_t *epp = &(enp->en_port); + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); + efx_rc_t rc; + + if (encp->enc_enhanced_set_mac_supported) { + if ((rc = efx_mcdi_mtu_set(enp, epp->ep_mac_pdu)) != 0) + goto fail1; + } else { + /* + * Fallback for older Huntington firmware, which always + * configure all of the parameters to MC_CMD_SET_MAC. This isn't + * suitable for setting the MTU on unpriviliged functions. + */ + if ((rc = ef10_mac_reconfigure(enp)) != 0) + goto fail2; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + __checkReturn efx_rc_t -hunt_mac_reconfigure( +ef10_mac_reconfigure( __in efx_nic_t *enp) { efx_port_t *epp = &(enp->en_port); @@ -197,6 +258,8 @@ hunt_mac_reconfigure( * from reaching the filters. As Huntington filters drop any * traffic that does not match a filter it is ok to leave the * MAC running in promiscuous mode. See bug41141. + * + * FIXME: Does REJECT_UNCST behave the same way on Medford? */ MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT, SET_MAC_IN_REJECT_UNCST, 0, @@ -247,16 +310,15 @@ fail1: } __checkReturn efx_rc_t -hunt_mac_multicast_list_set( +ef10_mac_multicast_list_set( __in efx_nic_t *enp) { efx_port_t *epp = &(enp->en_port); efx_mac_ops_t *emop = epp->ep_emop; efx_rc_t rc; - EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON); - - /* FIXME: Insert filters for multicast list */ + EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || + enp->en_family == EFX_FAMILY_MEDFORD); if ((rc = emop->emo_reconfigure(enp)) != 0) goto fail1; @@ -270,7 +332,7 @@ fail1: } __checkReturn efx_rc_t -hunt_mac_filter_default_rxq_set( +ef10_mac_filter_default_rxq_set( __in efx_nic_t *enp, __in efx_rxq_t *erp, __in boolean_t using_rss) @@ -304,7 +366,7 @@ fail1: } void -hunt_mac_filter_default_rxq_clear( +ef10_mac_filter_default_rxq_clear( __in efx_nic_t *enp) { efx_port_t *epp = &(enp->en_port); @@ -322,23 +384,18 @@ hunt_mac_filter_default_rxq_clear( #if EFSYS_OPT_LOOPBACK __checkReturn efx_rc_t -hunt_mac_loopback_set( +ef10_mac_loopback_set( __in efx_nic_t *enp, __in efx_link_mode_t link_mode, __in efx_loopback_type_t loopback_type) { - /* - * TBD: Consider a common Siena/Huntington function. The code is - * essentially identical. - */ - efx_port_t *epp = &(enp->en_port); efx_phy_ops_t *epop = epp->ep_epop; efx_loopback_type_t old_loopback_type; efx_link_mode_t old_loopback_link_mode; efx_rc_t rc; - /* The PHY object handles this on Huntington */ + /* The PHY object handles this on EF10 */ old_loopback_type = epp->ep_loopback_type; old_loopback_link_mode = epp->ep_loopback_link_mode; epp->ep_loopback_type = loopback_type; @@ -362,12 +419,12 @@ fail1: #if EFSYS_OPT_MAC_STATS -#define HUNT_MAC_STAT_READ(_esmp, _field, _eqp) \ +#define EF10_MAC_STAT_READ(_esmp, _field, _eqp) \ EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp) __checkReturn efx_rc_t -hunt_mac_stats_update( +ef10_mac_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat, @@ -381,301 +438,301 @@ hunt_mac_stats_update( /* Read END first so we don't race with the MC */ EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END, &generation_end); EFSYS_MEM_READ_BARRIER(); /* TX */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value); EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value); EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value); /* RX */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value); EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value); EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]), &(value.eq_dword[0])); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]), &(value.eq_dword[1])); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]), &(value.eq_dword[0])); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]), &(value.eq_dword[1])); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]), &(value.eq_dword[0])); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]), &(value.eq_dword[1])); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]), &(value.eq_dword[0])); EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]), &(value.eq_dword[1])); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value); /* Packet memory (EF10 only) */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_BB_OVERFLOW]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_BB_OVERFLOW]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_VFIFO_FULL, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_VFIFO_FULL, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_VFIFO_FULL]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_VFIFO_FULL, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_VFIFO_FULL, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_VFIFO_FULL]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_QBB, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_QBB, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_QBB]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_QBB, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_QBB, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_QBB]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_MAPPING, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_MAPPING, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_MAPPING]), &value); /* RX datapath */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_Q_DISABLED_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_Q_DISABLED_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_Q_DISABLED_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_DI_DROPPED_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_DI_DROPPED_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_DI_DROPPED_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_STREAMING_PKTS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_STREAMING_PKTS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_STREAMING_PKTS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_FETCH_CONDITIONS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_FETCH_CONDITIONS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_FETCH]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_WAIT_CONDITIONS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_WAIT_CONDITIONS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_WAIT]), &value); /* VADAPTER RX */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_UNICAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_UNICAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_MULTICAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_MULTICAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BROADCAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BROADCAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BAD_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_BYTES, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BAD_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_OVERFLOW, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_OVERFLOW, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_OVERFLOW]), &value); /* VADAPTER TX */ - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_UNICAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_UNICAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_MULTICAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_MULTICAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_PACKETS, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BROADCAST_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_BYTES, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BROADCAST_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_PACKETS, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_PACKETS, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BAD_PACKETS]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_BYTES, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_BYTES, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BAD_BYTES]), &value); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_OVERFLOW, &value); + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_OVERFLOW, &value); EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_OVERFLOW]), &value); EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE); EFSYS_MEM_READ_BARRIER(); - HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START, + EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START, &generation_start); /* Check that we didn't read the stats in the middle of a DMA */ diff --git a/sys/dev/sfxge/common/hunt_mcdi.c b/sys/dev/sfxge/common/hunt_mcdi.c index 1cccb23..f39e977 100644 --- a/sys/dev/sfxge/common/hunt_mcdi.c +++ b/sys/dev/sfxge/common/hunt_mcdi.c @@ -43,37 +43,6 @@ __FBSDID("$FreeBSD$"); #error "WITH_MCDI_V2 required for EF10 MCDIv2 commands." #endif -typedef enum efx_mcdi_header_type_e { - EFX_MCDI_HEADER_TYPE_V1, /* MCDIv0 (BootROM), MCDIv1 commands */ - EFX_MCDI_HEADER_TYPE_V2, /* MCDIv2 commands */ -} efx_mcdi_header_type_t; - -/* - * Return the header format to use for sending an MCDI request. - * - * An MCDIv1 (Siena compatible) command should use MCDIv2 encapsulation if the - * request input buffer or response output buffer are too large for the MCDIv1 - * format. An MCDIv2 command must always be sent using MCDIv2 encapsulation. - */ -#define EFX_MCDI_HEADER_TYPE(_cmd, _length) \ - ((((_cmd) & ~EFX_MASK32(MCDI_HEADER_CODE)) || \ - ((_length) & ~EFX_MASK32(MCDI_HEADER_DATALEN))) ? \ - EFX_MCDI_HEADER_TYPE_V2 : EFX_MCDI_HEADER_TYPE_V1) - - -/* - * MCDI Header NOT_EPOCH flag - * ========================== - * A new epoch begins at initial startup or after an MC reboot, and defines when - * the MC should reject stale MCDI requests. - * - * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all - * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1. - * - * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a - * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0. - */ - __checkReturn efx_rc_t ef10_mcdi_init( @@ -139,7 +108,7 @@ ef10_mcdi_fini( emip->emi_new_epoch = B_FALSE; } -static void + void ef10_mcdi_send_request( __in efx_nic_t *enp, __in void *hdrp, @@ -181,118 +150,6 @@ ef10_mcdi_send_request( EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE); } - void -ef10_mcdi_request_copyin( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp, - __in unsigned int seq, - __in boolean_t ev_cpl, - __in boolean_t new_epoch) -{ -#if EFSYS_OPT_MCDI_LOGGING - const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; -#endif /* EFSYS_OPT_MCDI_LOGGING */ - efx_mcdi_header_type_t hdr_type; - efx_dword_t hdr[2]; - size_t hdr_len; - unsigned int xflags; - - EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || - enp->en_family == EFX_FAMILY_MEDFORD); - - xflags = 0; - if (ev_cpl) - xflags |= MCDI_HEADER_XFLAGS_EVREQ; - - hdr_type = EFX_MCDI_HEADER_TYPE(emrp->emr_cmd, - MAX(emrp->emr_in_length, emrp->emr_out_length)); - - if (hdr_type == EFX_MCDI_HEADER_TYPE_V2) { - /* Construct MCDI v2 header */ - hdr_len = sizeof (hdr); - EFX_POPULATE_DWORD_8(hdr[0], - MCDI_HEADER_CODE, MC_CMD_V2_EXTN, - MCDI_HEADER_RESYNC, 1, - MCDI_HEADER_DATALEN, 0, - MCDI_HEADER_SEQ, seq, - MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, - MCDI_HEADER_ERROR, 0, - MCDI_HEADER_RESPONSE, 0, - MCDI_HEADER_XFLAGS, xflags); - - EFX_POPULATE_DWORD_2(hdr[1], - MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd, - MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length); - } else { - /* Construct MCDI v1 header */ - hdr_len = sizeof (hdr[0]); - EFX_POPULATE_DWORD_8(hdr[0], - MCDI_HEADER_CODE, emrp->emr_cmd, - MCDI_HEADER_RESYNC, 1, - MCDI_HEADER_DATALEN, emrp->emr_in_length, - MCDI_HEADER_SEQ, seq, - MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, - MCDI_HEADER_ERROR, 0, - MCDI_HEADER_RESPONSE, 0, - MCDI_HEADER_XFLAGS, xflags); - } - -#if EFSYS_OPT_MCDI_LOGGING - if (emtp->emt_logger != NULL) { - emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST, - &hdr, hdr_len, - emrp->emr_in_buf, emrp->emr_in_length); - } -#endif /* EFSYS_OPT_MCDI_LOGGING */ - - ef10_mcdi_send_request(enp, &hdr[0], hdr_len, - emrp->emr_in_buf, emrp->emr_in_length); -} - - void -ef10_mcdi_request_copyout( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp) -{ -#if EFSYS_OPT_MCDI_LOGGING - const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; -#endif /* EFSYS_OPT_MCDI_LOGGING */ - efx_dword_t hdr[2]; - unsigned int hdr_len; - size_t bytes; - - if (emrp->emr_out_buf == NULL) - return; - - /* Read the command header to detect MCDI response format */ - hdr_len = sizeof (hdr[0]); - ef10_mcdi_read_response(enp, &hdr[0], 0, hdr_len); - if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { - /* - * Read the actual payload length. The length given in the event - * is only correct for responses with the V1 format. - */ - ef10_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); - hdr_len += sizeof (hdr[1]); - - emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], - MC_CMD_V2_EXTN_IN_ACTUAL_LEN); - } - - /* Copy payload out into caller supplied buffer */ - bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); - ef10_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); - -#if EFSYS_OPT_MCDI_LOGGING - if (emtp->emt_logger != NULL) { - emtp->emt_logger(emtp->emt_context, - EFX_LOG_MCDI_RESPONSE, - &hdr, hdr_len, - emrp->emr_out_buf, bytes); - } -#endif /* EFSYS_OPT_MCDI_LOGGING */ -} - __checkReturn boolean_t ef10_mcdi_poll_response( __in efx_nic_t *enp) diff --git a/sys/dev/sfxge/common/hunt_nic.c b/sys/dev/sfxge/common/hunt_nic.c index d87f3cd..7f0c068 100644 --- a/sys/dev/sfxge/common/hunt_nic.c +++ b/sys/dev/sfxge/common/hunt_nic.c @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$"); #include "ef10_tlv_layout.h" -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_port_assignment( __in efx_nic_t *enp, __out uint32_t *portp) @@ -85,7 +85,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_port_modes( __in efx_nic_t *enp, __out uint32_t *modesp) @@ -112,7 +112,10 @@ efx_mcdi_get_port_modes( goto fail1; } - /* Accept pre-Medford size (8 bytes - no CurrentMode field) */ + /* + * Require only Modes and DefaultMode fields. + * (CurrentMode field was added for Medford) + */ if (req.emr_out_length_used < MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) { rc = EMSGSIZE; @@ -205,7 +208,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_mac_address_pf( __in efx_nic_t *enp, __out_ecount_opt(6) uint8_t mac_addrp[6]) @@ -263,7 +266,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_mac_address_vf( __in efx_nic_t *enp, __out_ecount_opt(6) uint8_t mac_addrp[6]) @@ -326,7 +329,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_clock( __in efx_nic_t *enp, __out uint32_t *sys_freqp) @@ -376,7 +379,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_get_vector_cfg( __in efx_nic_t *enp, __out_opt uint32_t *vec_basep, @@ -427,8 +430,8 @@ fail1: static __checkReturn efx_rc_t efx_mcdi_get_capabilities( __in efx_nic_t *enp, - __out efx_dword_t *flagsp, - __out efx_dword_t *flags2p) + __out uint32_t *flagsp, + __out uint32_t *flags2p) { efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, @@ -454,13 +457,12 @@ efx_mcdi_get_capabilities( goto fail2; } - *flagsp = *MCDI_OUT2(req, efx_dword_t, GET_CAPABILITIES_OUT_FLAGS1); + *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1); if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) - EFX_ZERO_DWORD(*flags2p); + *flags2p = 0; else - *flags2p = *MCDI_OUT2(req, efx_dword_t, - GET_CAPABILITIES_V2_OUT_FLAGS2); + *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2); return (0); @@ -889,76 +891,75 @@ ef10_nic_pio_unlink( return (efx_mcdi_unlink_piobuf(enp, vi_index)); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t ef10_get_datapath_caps( __in efx_nic_t *enp) { efx_nic_cfg_t *encp = &(enp->en_nic_cfg); - efx_dword_t datapath_capabilities; - efx_dword_t datapath_capabilities_v2; + uint32_t flags; + uint32_t flags2; efx_rc_t rc; - if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities, - &datapath_capabilities_v2)) != 0) + if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2)) != 0) goto fail1; +#define CAP_FLAG(flags1, field) \ + ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN))) + +#define CAP_FLAG2(flags2, field) \ + ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN))) + /* * Huntington RXDP firmware inserts a 0 or 14 byte prefix. * We only support the 14 byte prefix here. */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) { + if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) { rc = ENOTSUP; goto fail2; } encp->enc_rx_prefix_size = 14; /* Check if the firmware supports TSO */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_TX_TSO) == 1) - encp->enc_fw_assisted_tso_enabled = B_TRUE; - else - encp->enc_fw_assisted_tso_enabled = B_FALSE; + encp->enc_fw_assisted_tso_enabled = + CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE; + + /* Check if the firmware supports FATSOv2 */ + encp->enc_fw_assisted_tso_v2_enabled = + CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE; /* Check if the firmware has vadapter/vport/vswitch support */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_EVB) == 1) - encp->enc_datapath_cap_evb = B_TRUE; - else - encp->enc_datapath_cap_evb = B_FALSE; + encp->enc_datapath_cap_evb = + CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE; /* Check if the firmware supports VLAN insertion */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1) - encp->enc_hw_tx_insert_vlan_enabled = B_TRUE; - else - encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; + encp->enc_hw_tx_insert_vlan_enabled = + CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE; /* Check if the firmware supports RX event batching */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_RX_BATCHING) == 1) { - encp->enc_rx_batching_enabled = B_TRUE; + encp->enc_rx_batching_enabled = + CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE; + + if (encp->enc_rx_batching_enabled) encp->enc_rx_batch_max = 16; - } else { - encp->enc_rx_batching_enabled = B_FALSE; - } /* Check if the firmware supports disabling scatter on RXQs */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) { - encp->enc_rx_disable_scatter_supported = B_TRUE; - } else { - encp->enc_rx_disable_scatter_supported = B_FALSE; - } + encp->enc_rx_disable_scatter_supported = + CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE; /* Check if the firmware supports set mac with running filters */ - if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, - GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) - == 1) { - encp->enc_allow_set_mac_with_installed_filters = B_TRUE; - } else { - encp->enc_allow_set_mac_with_installed_filters = B_FALSE; - } + encp->enc_allow_set_mac_with_installed_filters = + CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ? + B_TRUE : B_FALSE; + + /* + * Check if firmware supports the extended MC_CMD_SET_MAC, which allows + * specifying which parameters to configure. + */ + encp->enc_enhanced_set_mac_supported = + CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE; + +#undef CAP_FLAG +#undef CAP_FLAG2 return (0); @@ -970,6 +971,42 @@ fail1: return (rc); } + + __checkReturn efx_rc_t +ef10_get_privilege_mask( + __in efx_nic_t *enp, + __out uint32_t *maskp) +{ + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); + uint32_t mask; + efx_rc_t rc; + + if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf, + &mask)) != 0) { + if (rc != ENOTSUP) + goto fail1; + + /* Fallback for old firmware without privilege mask support */ + if (EFX_PCI_FUNCTION_IS_PF(encp)) { + /* Assume PF has admin privilege */ + mask = EF10_LEGACY_PF_PRIVILEGE_MASK; + } else { + /* VF is always unprivileged by default */ + mask = EF10_LEGACY_VF_PRIVILEGE_MASK; + } + } + + *maskp = mask; + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + /* * The external port mapping is a one-based numbering of the external * connectors on the board. It does not distinguish off-board separated @@ -992,6 +1029,13 @@ static struct { (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1 }, + { + EFX_FAMILY_MEDFORD, + (1 << TLV_PORT_MODE_10G) | + (1 << TLV_PORT_MODE_10G_10G) | + (1 << TLV_PORT_MODE_10G_10G_10G_10G), + 1 + }, /* Supported modes requiring 2 outputs per port */ { EFX_FAMILY_HUNTINGTON, @@ -1000,18 +1044,25 @@ static struct { (1 << TLV_PORT_MODE_40G_10G_10G) | (1 << TLV_PORT_MODE_10G_10G_40G), 2 - } - /* - * NOTE: Medford modes will require 4 outputs per port: - * TLV_PORT_MODE_10G_10G_10G_10G_Q - * TLV_PORT_MODE_10G_10G_10G_10G_Q2 - * The Q2 mode routes outputs to external port 2. Support for this - * will require a new field specifying the number to add after - * scaling by stride. This is fixed at 1 currently. - */ + }, + { + EFX_FAMILY_MEDFORD, + (1 << TLV_PORT_MODE_40G) | + (1 << TLV_PORT_MODE_40G_40G) | + (1 << TLV_PORT_MODE_40G_10G_10G) | + (1 << TLV_PORT_MODE_10G_10G_40G), + 2 + }, + /* Supported modes requiring 4 outputs per port */ + { + EFX_FAMILY_MEDFORD, + (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) | + (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2), + 4 + }, }; -static __checkReturn efx_rc_t + __checkReturn efx_rc_t ef10_external_port_mapping( __in efx_nic_t *enp, __in uint32_t port, @@ -1064,7 +1115,7 @@ fail1: return (rc); } -static __checkReturn efx_rc_t + __checkReturn efx_rc_t hunt_board_cfg( __in efx_nic_t *enp) { @@ -1072,7 +1123,7 @@ hunt_board_cfg( efx_nic_cfg_t *encp = &(enp->en_nic_cfg); uint8_t mac_addr[6]; uint32_t board_type = 0; - hunt_link_state_t hls; + ef10_link_state_t els; efx_port_t *epp = &(enp->en_port); uint32_t port; uint32_t pf; @@ -1146,10 +1197,10 @@ hunt_board_cfg( goto fail6; /* Obtain the default PHY advertised capabilities */ - if ((rc = hunt_phy_get_link(enp, &hls)) != 0) + if ((rc = ef10_phy_get_link(enp, &els)) != 0) goto fail7; - epp->ep_default_adv_cap_mask = hls.hls_adv_cap_mask; - epp->ep_adv_cap_mask = hls.hls_adv_cap_mask; + epp->ep_default_adv_cap_mask = els.els_adv_cap_mask; + epp->ep_adv_cap_mask = els.els_adv_cap_mask; /* * Enable firmware workarounds for hardware errata. @@ -1288,20 +1339,8 @@ hunt_board_cfg( * the privilege mask to check for sufficient privileges, as that * can result in time-of-check/time-of-use bugs. */ - if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) { - if (rc != ENOTSUP) - goto fail13; - - /* Fallback for old firmware without privilege mask support */ - if (EFX_PCI_FUNCTION_IS_PF(encp)) { - /* Assume PF has admin privilege */ - mask = HUNT_LEGACY_PF_PRIVILEGE_MASK; - } else { - /* VF is always unprivileged by default */ - mask = HUNT_LEGACY_VF_PRIVILEGE_MASK; - } - } - + if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0) + goto fail13; encp->enc_privilege_mask = mask; /* Get interrupt vector limits */ @@ -1320,7 +1359,7 @@ hunt_board_cfg( * Maximum number of bytes into the frame the TCP header can start for * firmware assisted TSO to work. */ - encp->enc_tx_tso_tcp_header_offset_limit = 208; + encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT; return (0); @@ -1361,6 +1400,7 @@ fail1: ef10_nic_probe( __in efx_nic_t *enp) { + efx_nic_ops_t *enop = enp->en_enop; efx_nic_cfg_t *encp = &(enp->en_nic_cfg); efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); efx_rc_t rc; @@ -1380,7 +1420,7 @@ ef10_nic_probe( if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) goto fail3; - if ((rc = hunt_board_cfg(enp)) != 0) + if ((rc = enop->eno_board_cfg(enp)) != 0) if (rc != EACCES) goto fail4; diff --git a/sys/dev/sfxge/common/hunt_nvram.c b/sys/dev/sfxge/common/hunt_nvram.c index 35c5ddd..dd471f4 100644 --- a/sys/dev/sfxge/common/hunt_nvram.c +++ b/sys/dev/sfxge/common/hunt_nvram.c @@ -598,8 +598,9 @@ ef10_nvram_read_tlv_segment( } /* Read initial chunk of the segment, starting at offset */ - if ((rc = ef10_nvram_partn_read(enp, partn, seg_offset, seg_data, - EF10_NVRAM_CHUNK)) != 0) { + if ((rc = ef10_nvram_partn_read_mode(enp, partn, seg_offset, seg_data, + EF10_NVRAM_CHUNK, + MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT)) != 0) { goto fail2; } @@ -624,10 +625,11 @@ ef10_nvram_read_tlv_segment( /* Read the remaining segment content */ if (total_length > EF10_NVRAM_CHUNK) { - if ((rc = ef10_nvram_partn_read(enp, partn, + if ((rc = ef10_nvram_partn_read_mode(enp, partn, seg_offset + EF10_NVRAM_CHUNK, seg_data + EF10_NVRAM_CHUNK, - total_length - EF10_NVRAM_CHUNK)) != 0) + total_length - EF10_NVRAM_CHUNK, + MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT)) != 0) goto fail6; } @@ -1321,12 +1323,13 @@ fail1: } __checkReturn efx_rc_t -ef10_nvram_partn_read( +ef10_nvram_partn_read_mode( __in efx_nic_t *enp, __in uint32_t partn, __in unsigned int offset, __out_bcount(size) caddr_t data, - __in size_t size) + __in size_t size, + __in uint32_t mode) { size_t chunk; efx_rc_t rc; @@ -1335,7 +1338,7 @@ ef10_nvram_partn_read( chunk = MIN(size, EF10_NVRAM_CHUNK); if ((rc = efx_mcdi_nvram_read(enp, partn, offset, - data, chunk)) != 0) { + data, chunk, mode)) != 0) { goto fail1; } @@ -1353,6 +1356,22 @@ fail1: } __checkReturn efx_rc_t +ef10_nvram_partn_read( + __in efx_nic_t *enp, + __in uint32_t partn, + __in unsigned int offset, + __out_bcount(size) caddr_t data, + __in size_t size) +{ + /* + * Read requests which come in through the EFX API expect to + * read the current, active partition. + */ + return ef10_nvram_partn_read_mode(enp, partn, offset, data, size, + MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT); +} + + __checkReturn efx_rc_t ef10_nvram_partn_erase( __in efx_nic_t *enp, __in uint32_t partn, @@ -1541,7 +1560,11 @@ static ef10_parttbl_entry_t hunt_parttbl[] = { {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP}, {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP}, {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 3, EFX_NVRAM_FPGA_BACKUP}, - {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP} + {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP}, + {NVRAM_PARTITION_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 3, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 4, EFX_NVRAM_LICENSE} }; static ef10_parttbl_entry_t medford_parttbl[] = { @@ -1572,7 +1595,11 @@ static ef10_parttbl_entry_t medford_parttbl[] = { {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP}, {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP}, {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 3, EFX_NVRAM_FPGA_BACKUP}, - {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP} + {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP}, + {NVRAM_PARTITION_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 3, EFX_NVRAM_LICENSE}, + {NVRAM_PARTITION_TYPE_LICENSE, 4, EFX_NVRAM_LICENSE} }; static __checkReturn efx_rc_t @@ -1707,56 +1734,23 @@ fail1: #endif /* EFSYS_OPT_DIAG */ __checkReturn efx_rc_t -ef10_nvram_size( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out size_t *sizep) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = ef10_nvram_partn_size(enp, partn, sizep)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - *sizep = 0; - - return (rc); -} - - __checkReturn efx_rc_t -ef10_nvram_get_version( +ef10_nvram_partn_get_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __out uint32_t *subtypep, __out_ecount(4) uint16_t version[4]) { - uint32_t partn; efx_rc_t rc; - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - /* FIXME: get highest partn version from all ports */ /* FIXME: return partn description if available */ if ((rc = efx_mcdi_nvram_metadata(enp, partn, subtypep, version, NULL, 0)) != 0) - goto fail2; + goto fail1; return (0); -fail2: - EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -1764,111 +1758,21 @@ fail1: } __checkReturn efx_rc_t -ef10_nvram_rw_start( +ef10_nvram_partn_rw_start( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __out size_t *chunk_sizep) { - uint32_t partn; efx_rc_t rc; - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - if ((rc = ef10_nvram_partn_lock(enp, partn)) != 0) - goto fail2; + goto fail1; if (chunk_sizep != NULL) *chunk_sizep = EF10_NVRAM_CHUNK; return (0); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -ef10_nvram_read_chunk( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = ef10_nvram_partn_read(enp, partn, offset, data, size)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -ef10_nvram_erase( - __in efx_nic_t *enp, - __in efx_nvram_type_t type) -{ - uint32_t partn; - size_t size; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = ef10_nvram_partn_size(enp, partn, &size)) != 0) - goto fail2; - - if ((rc = ef10_nvram_partn_erase(enp, partn, 0, size)) != 0) - goto fail3; - - return (0); - -fail3: - EFSYS_PROBE(fail3); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -ef10_nvram_write_chunk( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in unsigned int offset, - __in_bcount(size) caddr_t data, - __in size_t size) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = ef10_nvram_partn_write(enp, partn, offset, data, size)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -1876,40 +1780,11 @@ fail1: } void -ef10_nvram_rw_finish( - __in efx_nic_t *enp, - __in efx_nvram_type_t type) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) == 0) - ef10_nvram_partn_unlock(enp, partn); -} - - __checkReturn efx_rc_t -ef10_nvram_set_version( +ef10_nvram_partn_rw_finish( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in_ecount(4) uint16_t version[4]) + __in uint32_t partn) { - uint32_t partn; - efx_rc_t rc; - - if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = ef10_nvram_partn_set_version(enp, partn, version)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); + ef10_nvram_partn_unlock(enp, partn); } #endif /* EFSYS_OPT_NVRAM */ diff --git a/sys/dev/sfxge/common/hunt_phy.c b/sys/dev/sfxge/common/hunt_phy.c index c25e820..a6b7faa 100644 --- a/sys/dev/sfxge/common/hunt_phy.c +++ b/sys/dev/sfxge/common/hunt_phy.c @@ -37,15 +37,10 @@ __FBSDID("$FreeBSD$"); #if EFSYS_OPT_HUNTINGTON static void -hunt_phy_decode_cap( +mcdi_phy_decode_cap( __in uint32_t mcdi_cap, __out uint32_t *maskp) { - /* - * TBD: consider common Siena/Hunt function: Hunt is a superset of - * Siena here (adds 40G) - */ - uint32_t mask; mask = 0; @@ -76,7 +71,7 @@ hunt_phy_decode_cap( } static void -hunt_phy_decode_link_mode( +mcdi_phy_decode_link_mode( __in efx_nic_t *enp, __in uint32_t link_flags, __in unsigned int speed, @@ -84,11 +79,6 @@ hunt_phy_decode_link_mode( __out efx_link_mode_t *link_modep, __out unsigned int *fcntlp) { - /* - * TBD: consider common Siena/Hunt function: Hunt is a superset of - * Siena here (adds 40G and generate-only flow control) - */ - boolean_t fd = !!(link_flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN)); boolean_t up = !!(link_flags & @@ -127,16 +117,11 @@ hunt_phy_decode_link_mode( void -hunt_phy_link_ev( +ef10_phy_link_ev( __in efx_nic_t *enp, __in efx_qword_t *eqp, __out efx_link_mode_t *link_modep) { - /* - * TBD: consider common Siena/Hunt function: Hunt is a superset of - * Siena here (adds 40G) - */ - efx_port_t *epp = &(enp->en_port); unsigned int link_flags; unsigned int speed; @@ -167,10 +152,10 @@ hunt_phy_link_ev( } link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS); - hunt_phy_decode_link_mode(enp, link_flags, speed, + mcdi_phy_decode_link_mode(enp, link_flags, speed, MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL), &link_mode, &fcntl); - hunt_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP), + mcdi_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP), &lp_cap_mask); /* @@ -191,19 +176,17 @@ hunt_phy_link_ev( } __checkReturn efx_rc_t -hunt_phy_power( +ef10_phy_power( __in efx_nic_t *enp, __in boolean_t power) { - /* TBD: consider common Siena/Hunt function: essentially identical */ - efx_rc_t rc; if (!power) return (0); /* Check if the PHY is a zombie */ - if ((rc = hunt_phy_verify(enp)) != 0) + if ((rc = ef10_phy_verify(enp)) != 0) goto fail1; enp->en_reset_flags |= EFX_RESET_PHY; @@ -217,16 +200,10 @@ fail1: } __checkReturn efx_rc_t -hunt_phy_get_link( +ef10_phy_get_link( __in efx_nic_t *enp, - __out hunt_link_state_t *hlsp) + __out ef10_link_state_t *elsp) { - /* - * TBD: consider common Siena/Hunt function: Hunt is very similar - * (at least for now; not clear that the loopbacks should necessarily - * be quite the same...) - */ - efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_LINK_IN_LEN, MC_CMD_GET_LINK_OUT_LEN)]; @@ -251,15 +228,15 @@ hunt_phy_get_link( goto fail2; } - hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP), - &hlsp->hls_adv_cap_mask); - hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP), - &hlsp->hls_lp_cap_mask); + mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP), + &elsp->els_adv_cap_mask); + mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP), + &elsp->els_lp_cap_mask); - hunt_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS), + mcdi_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS), MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED), MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL), - &hlsp->hls_link_mode, &hlsp->hls_fcntl); + &elsp->els_link_mode, &elsp->els_fcntl); #if EFSYS_OPT_LOOPBACK /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */ @@ -282,10 +259,10 @@ hunt_phy_get_link( EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS); EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD); - hlsp->hls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE); + elsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE); #endif /* EFSYS_OPT_LOOPBACK */ - hlsp->hls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0; + elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0; return (0); @@ -298,15 +275,9 @@ fail1: } __checkReturn efx_rc_t -hunt_phy_reconfigure( +ef10_phy_reconfigure( __in efx_nic_t *enp) { - /* - * TBD: this is a little different for now (no LED support for Hunt - * yet), but ultimately should consider common Siena/Hunt function: - * Hunt should be a superset of Siena here (adds 40G) - */ - efx_nic_cfg_t *encp = &(enp->en_nic_cfg); efx_port_t *epp = &(enp->en_port); efx_mcdi_req_t req; @@ -428,11 +399,9 @@ fail1: } __checkReturn efx_rc_t -hunt_phy_verify( +ef10_phy_verify( __in efx_nic_t *enp) { - /* TBD: consider common Siena/Hunt function: essentially identical */ - efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_PHY_STATE_IN_LEN, MC_CMD_GET_PHY_STATE_OUT_LEN)]; @@ -479,7 +448,7 @@ fail1: } __checkReturn efx_rc_t -hunt_phy_oui_get( +ef10_phy_oui_get( __in efx_nic_t *enp, __out uint32_t *ouip) { @@ -491,7 +460,7 @@ hunt_phy_oui_get( #if EFSYS_OPT_PHY_STATS __checkReturn efx_rc_t -hunt_phy_stats_update( +ef10_phy_stats_update( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) @@ -509,8 +478,8 @@ hunt_phy_stats_update( #if EFSYS_OPT_NAMES -extern const char * -hunt_phy_prop_name( + const char * +ef10_phy_prop_name( __in efx_nic_t *enp, __in unsigned int id) { @@ -521,8 +490,8 @@ hunt_phy_prop_name( #endif /* EFSYS_OPT_NAMES */ -extern __checkReturn efx_rc_t -hunt_phy_prop_get( + __checkReturn efx_rc_t +ef10_phy_prop_get( __in efx_nic_t *enp, __in unsigned int id, __in uint32_t flags, @@ -533,8 +502,8 @@ hunt_phy_prop_get( return (ENOTSUP); } -extern __checkReturn efx_rc_t -hunt_phy_prop_set( + __checkReturn efx_rc_t +ef10_phy_prop_set( __in efx_nic_t *enp, __in unsigned int id, __in uint32_t val) diff --git a/sys/dev/sfxge/common/hunt_tx.c b/sys/dev/sfxge/common/hunt_tx.c index 593db88..baa7444 100755 --- a/sys/dev/sfxge/common/hunt_tx.c +++ b/sys/dev/sfxge/common/hunt_tx.c @@ -87,12 +87,13 @@ efx_mcdi_init_txq( MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label); MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance); - MCDI_IN_POPULATE_DWORD_6(req, INIT_TXQ_IN_FLAGS, + MCDI_IN_POPULATE_DWORD_7(req, INIT_TXQ_IN_FLAGS, INIT_TXQ_IN_FLAG_BUFF_MODE, 0, INIT_TXQ_IN_FLAG_IP_CSUM_DIS, (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1, INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1, + INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0, INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0, INIT_TXQ_IN_CRC_MODE, 0, INIT_TXQ_IN_FLAG_TIMESTAMP, 0); @@ -589,6 +590,38 @@ hunt_tx_qdesc_tso_create( } void +ef10_tx_qdesc_tso2_create( + __in efx_txq_t *etp, + __in uint16_t ipv4_id, + __in uint32_t tcp_seq, + __in uint16_t tcp_mss, + __out_ecount(count) efx_desc_t *edp, + __in int count) +{ + EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index, + uint16_t, ipv4_id, uint32_t, tcp_seq, + uint16_t, tcp_mss); + + EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS); + + EFX_POPULATE_QWORD_5(edp[0].ed_eq, + ESF_DZ_TX_DESC_IS_OPT, 1, + ESF_DZ_TX_OPTION_TYPE, + ESE_DZ_TX_OPTION_DESC_TSO, + ESF_DZ_TX_TSO_OPTION_TYPE, + ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A, + ESF_DZ_TX_TSO_IP_ID, ipv4_id, + ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq); + EFX_POPULATE_QWORD_4(edp[1].ed_eq, + ESF_DZ_TX_DESC_IS_OPT, 1, + ESF_DZ_TX_OPTION_TYPE, + ESE_DZ_TX_OPTION_DESC_TSO, + ESF_DZ_TX_TSO_OPTION_TYPE, + ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B, + ESF_DZ_TX_TSO_TCP_MSS, tcp_mss); +} + + void ef10_tx_qdesc_vlantci_create( __in efx_txq_t *etp, __in uint16_t tci, diff --git a/sys/dev/sfxge/common/hunt_vpd.c b/sys/dev/sfxge/common/hunt_vpd.c index 58e9a66..41b4b83 100644 --- a/sys/dev/sfxge/common/hunt_vpd.c +++ b/sys/dev/sfxge/common/hunt_vpd.c @@ -48,13 +48,20 @@ ef10_vpd_init( caddr_t svpd; size_t svpd_size; uint32_t pci_pf; + uint32_t tag; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || enp->en_family == EFX_FAMILY_MEDFORD); - pci_pf = enp->en_nic_cfg.enc_pf; + if (enp->en_nic_cfg.enc_vpd_is_global) { + tag = TLV_TAG_GLOBAL_STATIC_VPD; + } else { + pci_pf = enp->en_nic_cfg.enc_pf; + tag = TLV_TAG_PF_STATIC_VPD(pci_pf); + } + /* * The VPD interface exposes VPD resources from the combined static and * dynamic VPD storage. As the static VPD configuration should *never* @@ -64,8 +71,7 @@ ef10_vpd_init( svpd_size = 0; rc = ef10_nvram_partn_read_tlv(enp, NVRAM_PARTITION_TYPE_STATIC_CONFIG, - TLV_TAG_PF_STATIC_VPD(pci_pf), - &svpd, &svpd_size); + tag, &svpd, &svpd_size); if (rc != 0) { if (rc == EACCES) { /* Unpriviledged functions cannot access VPD */ @@ -132,17 +138,22 @@ ef10_vpd_read( caddr_t dvpd; size_t dvpd_size; uint32_t pci_pf; + uint32_t tag; efx_rc_t rc; EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || enp->en_family == EFX_FAMILY_MEDFORD); - pci_pf = enp->en_nic_cfg.enc_pf; + if (enp->en_nic_cfg.enc_vpd_is_global) { + tag = TLV_TAG_GLOBAL_DYNAMIC_VPD; + } else { + pci_pf = enp->en_nic_cfg.enc_pf; + tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf); + } if ((rc = ef10_nvram_partn_read_tlv(enp, NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, - TLV_TAG_PF_DYNAMIC_VPD(pci_pf), - &dvpd, &dvpd_size)) != 0) + tag, &dvpd, &dvpd_size)) != 0) goto fail1; if (dvpd_size > size) { @@ -210,6 +221,13 @@ ef10_vpd_verify( if (dcont == 0) break; + /* + * Skip the RV keyword. It should be present in both the static + * and dynamic cfg sectors. + */ + if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V')) + continue; + scont = 0; _NOTE(CONSTANTCONDITION) while (1) { @@ -389,12 +407,18 @@ ef10_vpd_write( { size_t vpd_length; uint32_t pci_pf; + uint32_t tag; efx_rc_t rc; EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || enp->en_family == EFX_FAMILY_MEDFORD); - pci_pf = enp->en_nic_cfg.enc_pf; + if (enp->en_nic_cfg.enc_vpd_is_global) { + tag = TLV_TAG_GLOBAL_DYNAMIC_VPD; + } else { + pci_pf = enp->en_nic_cfg.enc_pf; + tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf); + } /* Determine total length of new dynamic VPD */ if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0) @@ -403,8 +427,7 @@ ef10_vpd_write( /* Store new dynamic VPD in all segments in DYNAMIC_CONFIG partition */ if ((rc = ef10_nvram_partn_write_segment_tlv(enp, NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, - TLV_TAG_PF_DYNAMIC_VPD(pci_pf), - data, vpd_length, B_TRUE)) != 0) { + tag, data, vpd_length, B_TRUE)) != 0) { goto fail2; } diff --git a/sys/dev/sfxge/common/medford_impl.h b/sys/dev/sfxge/common/medford_impl.h index 11084dc..59ea35f 100644 --- a/sys/dev/sfxge/common/medford_impl.h +++ b/sys/dev/sfxge/common/medford_impl.h @@ -37,7 +37,29 @@ extern "C" { #endif +/* Alignment requirement for value written to RX WPTR: + * the WPTR must be aligned to an 8 descriptor boundary + * + * FIXME: Is this the same on Medford as Huntington? + */ +#define MEDFORD_RX_WPTR_ALIGN 8 + + + +#ifndef ER_EZ_TX_PIOBUF_SIZE +#define ER_EZ_TX_PIOBUF_SIZE 4096 +#endif + + #define MEDFORD_PIOBUF_NBUFS (16) +#define MEDFORD_PIOBUF_SIZE (ER_EZ_TX_PIOBUF_SIZE) + +#define MEDFORD_MIN_PIO_ALLOC_SIZE (MEDFORD_PIOBUF_SIZE / 32) + + +extern __checkReturn efx_rc_t +medford_board_cfg( + __in efx_nic_t *enp); #ifdef __cplusplus diff --git a/sys/dev/sfxge/common/medford_nic.c b/sys/dev/sfxge/common/medford_nic.c index 68c8184..7c176b5 100644 --- a/sys/dev/sfxge/common/medford_nic.c +++ b/sys/dev/sfxge/common/medford_nic.c @@ -39,7 +39,273 @@ __FBSDID("$FreeBSD$"); #include "ef10_tlv_layout.h" +static __checkReturn efx_rc_t +efx_mcdi_get_rxdp_config( + __in efx_nic_t *enp, + __out uint32_t *end_paddingp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_GET_RXDP_CONFIG_IN_LEN, + MC_CMD_GET_RXDP_CONFIG_OUT_LEN)]; + uint32_t end_padding; + efx_rc_t rc; + memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_GET_RXDP_CONFIG; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_GET_RXDP_CONFIG_OUT_LEN; + efx_mcdi_execute(enp, &req); + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA, + GET_RXDP_CONFIG_OUT_PAD_HOST_DMA) == 0) { + /* RX DMA end padding is disabled */ + end_padding = 0; + } else { + switch(MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA, + GET_RXDP_CONFIG_OUT_PAD_HOST_LEN)) { + case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_64: + end_padding = 64; + break; + case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_128: + end_padding = 128; + break; + case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_256: + end_padding = 256; + break; + default: + rc = ENOTSUP; + goto fail2; + } + } + + *end_paddingp = end_padding; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +medford_board_cfg( + __in efx_nic_t *enp) +{ + efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); + uint8_t mac_addr[6] = { 0 }; + uint32_t board_type = 0; + ef10_link_state_t els; + efx_port_t *epp = &(enp->en_port); + uint32_t port; + uint32_t pf; + uint32_t vf; + uint32_t mask; + uint32_t flags; + uint32_t sysclk; + uint32_t base, nvec; + uint32_t end_padding; + efx_rc_t rc; + + /* + * FIXME: Likely to be incomplete and incorrect. + * Parts of this should be shared with Huntington. + */ + + if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0) + goto fail1; + + /* + * NOTE: The MCDI protocol numbers ports from zero. + * The common code MCDI interface numbers ports from one. + */ + emip->emi_port = port + 1; + + if ((rc = ef10_external_port_mapping(enp, port, + &encp->enc_external_port)) != 0) + goto fail2; + + /* + * Get PCIe function number from firmware (used for + * per-function privilege and dynamic config info). + * - PCIe PF: pf = PF number, vf = 0xffff. + * - PCIe VF: pf = parent PF, vf = VF number. + */ + if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0) + goto fail3; + + encp->enc_pf = pf; + encp->enc_vf = vf; + + /* MAC address for this function */ + if (EFX_PCI_FUNCTION_IS_PF(encp)) { + rc = efx_mcdi_get_mac_address_pf(enp, mac_addr); + if ((rc == 0) && (mac_addr[0] & 0x02)) { + /* + * If the static config does not include a global MAC + * address pool then the board may return a locally + * administered MAC address (this should only happen on + * incorrectly programmed boards). + */ + rc = EINVAL; + } + } else { + rc = efx_mcdi_get_mac_address_vf(enp, mac_addr); + } + if (rc != 0) + goto fail4; + + EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); + + /* Board configuration */ + rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL); + if (rc != 0) { + /* Unprivileged functions may not be able to read board cfg */ + if (rc == EACCES) + board_type = 0; + else + goto fail5; + } + + encp->enc_board_type = board_type; + encp->enc_clk_mult = 1; /* not used for Medford */ + + /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ + if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) + goto fail6; + + /* Obtain the default PHY advertised capabilities */ + if ((rc = ef10_phy_get_link(enp, &els)) != 0) + goto fail7; + epp->ep_default_adv_cap_mask = els.els_adv_cap_mask; + epp->ep_adv_cap_mask = els.els_adv_cap_mask; + + if (EFX_PCI_FUNCTION_IS_VF(encp)) { + /* + * Interrupt testing does not work for VFs. See bug50084. + * FIXME: Does this still apply to Medford? + */ + encp->enc_bug41750_workaround = B_TRUE; + } + + /* Chained multicast is always enabled on Medford */ + encp->enc_bug26807_workaround = B_TRUE; + + /* Get sysclk frequency (in MHz). */ + if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0) + goto fail8; + + /* + * The timer quantum is 1536 sysclk cycles, documented for the + * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units. + */ + encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */ + encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << + FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; + + /* Check capabilities of running datapath firmware */ + if ((rc = ef10_get_datapath_caps(enp)) != 0) + goto fail9; + + /* Alignment for receive packet DMA buffers */ + encp->enc_rx_buf_align_start = 1; + + /* Get the RX DMA end padding alignment configuration */ + if ((rc = efx_mcdi_get_rxdp_config(enp, &end_padding)) != 0) + goto fail10; + encp->enc_rx_buf_align_end = end_padding; + + /* Alignment for WPTR updates */ + encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN; + + /* + * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use + * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available + * resources (allocated to this PCIe function), which is zero until + * after we have allocated VIs. + */ + encp->enc_evq_limit = 1024; + encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; + encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; + + encp->enc_buftbl_limit = 0xFFFFFFFF; + + encp->enc_piobuf_limit = MEDFORD_PIOBUF_NBUFS; + encp->enc_piobuf_size = MEDFORD_PIOBUF_SIZE; + encp->enc_piobuf_min_alloc_size = MEDFORD_MIN_PIO_ALLOC_SIZE; + + /* + * Get the current privilege mask. Note that this may be modified + * dynamically, so this value is informational only. DO NOT use + * the privilege mask to check for sufficient privileges, as that + * can result in time-of-check/time-of-use bugs. + */ + if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0) + goto fail11; + encp->enc_privilege_mask = mask; + + /* Get interrupt vector limits */ + if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) { + if (EFX_PCI_FUNCTION_IS_PF(encp)) + goto fail12; + + /* Ignore error (cannot query vector limits from a VF). */ + base = 0; + nvec = 1024; + } + encp->enc_intr_vec_base = base; + encp->enc_intr_limit = nvec; + + /* + * Maximum number of bytes into the frame the TCP header can start for + * firmware assisted TSO to work. + */ + encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT; + + /* + * Medford stores a single global copy of VPD, not per-PF as on + * Huntington. + */ + encp->enc_vpd_is_global = B_TRUE; + + return (0); + +fail12: + EFSYS_PROBE(fail12); +fail11: + EFSYS_PROBE(fail11); +fail10: + EFSYS_PROBE(fail10); +fail9: + EFSYS_PROBE(fail9); +fail8: + EFSYS_PROBE(fail8); +fail7: + EFSYS_PROBE(fail7); +fail6: + EFSYS_PROBE(fail6); +fail5: + EFSYS_PROBE(fail5); +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} #endif /* EFSYS_OPT_MEDFORD */ diff --git a/sys/dev/sfxge/common/siena_flash.h b/sys/dev/sfxge/common/siena_flash.h index 48ddfac..143a14e 100644 --- a/sys/dev/sfxge/common/siena_flash.h +++ b/sys/dev/sfxge/common/siena_flash.h @@ -115,14 +115,14 @@ typedef struct siena_mc_boot_hdr_s { /* GENERATED BY scripts/genfwdef */ efx_word_t checksum; /* of whole header area + firmware image */ efx_word_t firmware_version_d; efx_byte_t mcfw_subtype; - efx_byte_t reserved_a[1]; /* (set to 0) */ + efx_byte_t generation; /* Valid for medford, SBZ for earlier chips */ efx_dword_t firmware_text_offset; /* offset to firmware .text */ efx_dword_t firmware_text_size; /* length of firmware .text, in bytes */ efx_dword_t firmware_data_offset; /* offset to firmware .data */ efx_dword_t firmware_data_size; /* length of firmware .data, in bytes */ efx_byte_t spi_rate; /* SPI rate for reading image, 0 is BootROM default */ efx_byte_t spi_phase_adj; /* SPI SDO/SCL phase adjustment, 0 is default (no adj) */ - efx_word_t reserved_b[1]; /* (set to 0) */ + efx_word_t xpm_sector; /* The sector that contains the key, or 0xffff if unsigned (medford) SBZ (earlier) */ efx_dword_t reserved_c[7]; /* (set to 0) */ } siena_mc_boot_hdr_t; diff --git a/sys/dev/sfxge/common/siena_impl.h b/sys/dev/sfxge/common/siena_impl.h index 639ac6b..4c80cd6 100644 --- a/sys/dev/sfxge/common/siena_impl.h +++ b/sys/dev/sfxge/common/siena_impl.h @@ -114,12 +114,12 @@ siena_mcdi_init( __in const efx_mcdi_transport_t *mtp); extern void -siena_mcdi_request_copyin( +siena_mcdi_send_request( __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp, - __in unsigned int seq, - __in boolean_t ev_cpl, - __in boolean_t new_epoch); + __in void *hdrp, + __in size_t hdr_len, + __in void *sdup, + __in size_t sdu_len); extern __checkReturn boolean_t siena_mcdi_poll_response( @@ -132,11 +132,6 @@ siena_mcdi_read_response( __in size_t offset, __in size_t length); -extern void -siena_mcdi_request_copyout( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp); - extern efx_rc_t siena_mcdi_poll_reboot( __in efx_nic_t *enp); @@ -156,39 +151,10 @@ siena_mcdi_feature_supported( #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD extern __checkReturn efx_rc_t -siena_nvram_partn_size( - __in efx_nic_t *enp, - __in uint32_t partn, - __out size_t *sizep); - -extern __checkReturn efx_rc_t siena_nvram_partn_lock( __in efx_nic_t *enp, __in uint32_t partn); -extern __checkReturn efx_rc_t -siena_nvram_partn_read( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size); - -extern __checkReturn efx_rc_t -siena_nvram_partn_erase( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __in size_t size); - -extern __checkReturn efx_rc_t -siena_nvram_partn_write( - __in efx_nic_t *enp, - __in uint32_t partn, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size); - extern void siena_nvram_partn_unlock( __in efx_nic_t *enp, @@ -215,67 +181,69 @@ siena_nvram_test( #endif /* EFSYS_OPT_DIAG */ extern __checkReturn efx_rc_t -siena_nvram_size( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out size_t *sizep); - -extern __checkReturn efx_rc_t siena_nvram_get_subtype( __in efx_nic_t *enp, __in uint32_t partn, __out uint32_t *subtypep); extern __checkReturn efx_rc_t -siena_nvram_get_version( +siena_nvram_type_to_partn( __in efx_nic_t *enp, __in efx_nvram_type_t type, - __out uint32_t *subtypep, - __out_ecount(4) uint16_t version[4]); + __out uint32_t *partnp); extern __checkReturn efx_rc_t -siena_nvram_rw_start( +siena_nvram_partn_size( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out size_t *pref_chunkp); + __in uint32_t partn, + __out size_t *sizep); extern __checkReturn efx_rc_t -siena_nvram_read_chunk( +siena_nvram_partn_rw_start( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, + __out size_t *chunk_sizep); + +extern __checkReturn efx_rc_t +siena_nvram_partn_read( + __in efx_nic_t *enp, + __in uint32_t partn, __in unsigned int offset, __out_bcount(size) caddr_t data, __in size_t size); -extern __checkReturn efx_rc_t -siena_nvram_erase( +extern __checkReturn efx_rc_t +siena_nvram_partn_erase( __in efx_nic_t *enp, - __in efx_nvram_type_t type); + __in uint32_t partn, + __in unsigned int offset, + __in size_t size); extern __checkReturn efx_rc_t -siena_nvram_write_chunk( +siena_nvram_partn_write( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __in unsigned int offset, - __in_bcount(size) caddr_t data, + __out_bcount(size) caddr_t data, __in size_t size); extern void -siena_nvram_rw_finish( +siena_nvram_partn_rw_finish( __in efx_nic_t *enp, - __in efx_nvram_type_t type); + __in uint32_t partn); extern __checkReturn efx_rc_t -siena_nvram_set_version( +siena_nvram_partn_get_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in_ecount(4) uint16_t version[4]); + __in uint32_t partn, + __out uint32_t *subtypep, + __out_ecount(4) uint16_t version[4]); extern __checkReturn efx_rc_t -siena_nvram_type_to_partn( +siena_nvram_partn_set_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out uint32_t *partnp); + __in uint32_t partn, + __in_ecount(4) uint16_t version[4]); #endif /* EFSYS_OPT_NVRAM */ diff --git a/sys/dev/sfxge/common/siena_mcdi.c b/sys/dev/sfxge/common/siena_mcdi.c index f3af2bf6f..4fb2b6c 100644 --- a/sys/dev/sfxge/common/siena_mcdi.c +++ b/sys/dev/sfxge/common/siena_mcdi.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); : MC_SMEM_P1_STATUS_OFST >> 2) -static void + void siena_mcdi_send_request( __in efx_nic_t *enp, __in void *hdrp, @@ -89,79 +89,6 @@ siena_mcdi_send_request( EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE); } - void -siena_mcdi_request_copyin( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp, - __in unsigned int seq, - __in boolean_t ev_cpl, - __in boolean_t new_epoch) -{ -#if EFSYS_OPT_MCDI_LOGGING - const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; -#endif - efx_dword_t hdr; - size_t hdr_len; - unsigned int xflags; - - EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); - _NOTE(ARGUNUSED(new_epoch)) - - xflags = 0; - if (ev_cpl) - xflags |= MCDI_HEADER_XFLAGS_EVREQ; - - /* Construct the header */ - hdr_len = sizeof (hdr); - EFX_POPULATE_DWORD_6(hdr, - MCDI_HEADER_CODE, emrp->emr_cmd, - MCDI_HEADER_RESYNC, 1, - MCDI_HEADER_DATALEN, emrp->emr_in_length, - MCDI_HEADER_SEQ, seq, - MCDI_HEADER_RESPONSE, 0, - MCDI_HEADER_XFLAGS, xflags); - -#if EFSYS_OPT_MCDI_LOGGING - if (emtp->emt_logger != NULL) { - emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST, - &hdr, sizeof (hdr), - emrp->emr_in_buf, emrp->emr_in_length); - } -#endif /* EFSYS_OPT_MCDI_LOGGING */ - - siena_mcdi_send_request(enp, &hdr, hdr_len, - emrp->emr_in_buf, emrp->emr_in_length); -} - - void -siena_mcdi_request_copyout( - __in efx_nic_t *enp, - __in efx_mcdi_req_t *emrp) -{ -#if EFSYS_OPT_MCDI_LOGGING - const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; - efx_dword_t hdr; -#endif - size_t bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); - - /* Copy payload out if caller supplied buffer */ - if (emrp->emr_out_buf != NULL) { - siena_mcdi_read_response(enp, emrp->emr_out_buf, - sizeof (efx_dword_t), bytes); - } - -#if EFSYS_OPT_MCDI_LOGGING - if (emtp->emt_logger != NULL) { - siena_mcdi_read_response(enp, &hdr, 0, sizeof (hdr)); - - emtp->emt_logger(emtp->emt_context, - EFX_LOG_MCDI_RESPONSE, - &hdr, sizeof (hdr), - emrp->emr_out_buf, bytes); - } -#endif /* EFSYS_OPT_MCDI_LOGGING */ -} - efx_rc_t siena_mcdi_poll_reboot( __in efx_nic_t *enp) diff --git a/sys/dev/sfxge/common/siena_nic.c b/sys/dev/sfxge/common/siena_nic.c index 70e7b5d..59e1283 100644 --- a/sys/dev/sfxge/common/siena_nic.c +++ b/sys/dev/sfxge/common/siena_nic.c @@ -169,6 +169,7 @@ siena_board_cfg( encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; encp->enc_fw_assisted_tso_enabled = B_FALSE; + encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; encp->enc_allow_set_mac_with_installed_filters = B_TRUE; return (0); diff --git a/sys/dev/sfxge/common/siena_nvram.c b/sys/dev/sfxge/common/siena_nvram.c index 8f107b4..9708e0c 100644 --- a/sys/dev/sfxge/common/siena_nvram.c +++ b/sys/dev/sfxge/common/siena_nvram.c @@ -99,8 +99,8 @@ siena_nvram_partn_read( while (size > 0) { chunk = MIN(size, SIENA_NVRAM_CHUNK); - if ((rc = efx_mcdi_nvram_read(enp, partn, offset, - data, chunk)) != 0) { + if ((rc = efx_mcdi_nvram_read(enp, partn, offset, data, chunk, + MC_CMD_NVRAM_READ_IN_V2_DEFAULT)) != 0) { goto fail1; } @@ -227,6 +227,8 @@ static siena_parttbl_entry_t siena_parttbl[] = { {MC_CMD_NVRAM_TYPE_FC_FW, 2, EFX_NVRAM_FCFW}, {MC_CMD_NVRAM_TYPE_CPLD, 1, EFX_NVRAM_CPLD}, {MC_CMD_NVRAM_TYPE_CPLD, 2, EFX_NVRAM_CPLD}, + {MC_CMD_NVRAM_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE}, + {MC_CMD_NVRAM_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE} }; __checkReturn efx_rc_t @@ -291,32 +293,6 @@ fail1: #endif /* EFSYS_OPT_DIAG */ - __checkReturn efx_rc_t -siena_nvram_size( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __out size_t *sizep) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - *sizep = 0; - - return (rc); -} #define SIENA_DYNAMIC_CFG_SIZE(_nitems) \ (sizeof (siena_mc_dynamic_config_hdr_t) + ((_nitems) * \ @@ -506,29 +482,25 @@ fail1: } __checkReturn efx_rc_t -siena_nvram_get_version( +siena_nvram_partn_get_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __out uint32_t *subtypep, __out_ecount(4) uint16_t version[4]) { siena_mc_dynamic_config_hdr_t *dcfg; siena_parttbl_entry_t *entry; uint32_t dcfg_partn; - uint32_t partn; unsigned int i; efx_rc_t rc; - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) { rc = ENOTSUP; - goto fail2; + goto fail1; } if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0) - goto fail3; + goto fail2; /* * Some partitions are accessible from both ports (for instance BOOTROM) @@ -537,6 +509,7 @@ siena_nvram_get_version( */ version[0] = version[1] = version[2] = version[3] = 0; for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) { + siena_mc_fw_version_t *verp; unsigned int nitems; uint16_t temp[4]; size_t length; @@ -559,32 +532,27 @@ siena_nvram_get_version( if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn, B_FALSE, &dcfg, &length)) != 0) - goto fail4; + goto fail3; nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items, EFX_DWORD_0); if (nitems < entry->partn) goto done; - temp[0] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_w, - EFX_WORD_0); - temp[1] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_x, - EFX_WORD_0); - temp[2] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_y, - EFX_WORD_0); - temp[3] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_z, - EFX_WORD_0); + verp = &dcfg->fw_version[partn]; + temp[0] = EFX_WORD_FIELD(verp->version_w, EFX_WORD_0); + temp[1] = EFX_WORD_FIELD(verp->version_x, EFX_WORD_0); + temp[2] = EFX_WORD_FIELD(verp->version_y, EFX_WORD_0); + temp[3] = EFX_WORD_FIELD(verp->version_z, EFX_WORD_0); if (memcmp(version, temp, sizeof (temp)) < 0) memcpy(version, temp, sizeof (temp)); - done: +done: EFSYS_KMEM_FREE(enp->en_esip, length, dcfg); } return (0); -fail4: - EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: @@ -596,111 +564,21 @@ fail1: } __checkReturn efx_rc_t -siena_nvram_rw_start( +siena_nvram_partn_rw_start( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __out size_t *chunk_sizep) { - uint32_t partn; efx_rc_t rc; - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - if ((rc = siena_nvram_partn_lock(enp, partn)) != 0) - goto fail2; + goto fail1; if (chunk_sizep != NULL) *chunk_sizep = SIENA_NVRAM_CHUNK; return (0); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -siena_nvram_read_chunk( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in unsigned int offset, - __out_bcount(size) caddr_t data, - __in size_t size) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = siena_nvram_partn_read(enp, partn, offset, data, size)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -siena_nvram_erase( - __in efx_nic_t *enp, - __in efx_nvram_type_t type) -{ - size_t size; - uint32_t partn; - efx_rc_t rc; - - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0) - goto fail2; - - if ((rc = siena_nvram_partn_erase(enp, partn, 0, size)) != 0) - goto fail3; - - return (0); - -fail3: - EFSYS_PROBE(fail3); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t -siena_nvram_write_chunk( - __in efx_nic_t *enp, - __in efx_nvram_type_t type, - __in unsigned int offset, - __in_bcount(size) caddr_t data, - __in size_t size) -{ - uint32_t partn; - efx_rc_t rc; - - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - - if ((rc = siena_nvram_partn_write(enp, partn, offset, data, size)) != 0) - goto fail2; - - return (0); - -fail2: - EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -708,27 +586,23 @@ fail1: } void -siena_nvram_rw_finish( +siena_nvram_partn_rw_finish( __in efx_nic_t *enp, - __in efx_nvram_type_t type) + __in uint32_t partn) { - uint32_t partn; - efx_rc_t rc; - - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) == 0) - siena_nvram_partn_unlock(enp, partn); + siena_nvram_partn_unlock(enp, partn); } __checkReturn efx_rc_t -siena_nvram_set_version( +siena_nvram_partn_set_version( __in efx_nic_t *enp, - __in efx_nvram_type_t type, + __in uint32_t partn, __in_ecount(4) uint16_t version[4]) { efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); siena_mc_dynamic_config_hdr_t *dcfg = NULL; siena_mc_fw_version_t *fwverp; - uint32_t dcfg_partn, partn; + uint32_t dcfg_partn; size_t dcfg_size; unsigned int hdr_length; unsigned int vpd_length; @@ -741,15 +615,12 @@ siena_nvram_set_version( size_t length; efx_rc_t rc; - if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0) - goto fail1; - dcfg_partn = (emip->emi_port == 1) ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &dcfg_size)) != 0) - goto fail2; + goto fail1; if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0) goto fail2; diff --git a/sys/dev/sfxge/common/siena_vpd.c b/sys/dev/sfxge/common/siena_vpd.c index 9a07f91..7a7ce67 100644 --- a/sys/dev/sfxge/common/siena_vpd.c +++ b/sys/dev/sfxge/common/siena_vpd.c @@ -326,6 +326,13 @@ siena_vpd_verify( if (dcont == 0) break; + /* + * Skip the RV keyword. It should be present in both the static + * and dynamic cfg sectors. + */ + if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V')) + continue; + scont = 0; _NOTE(CONSTANTCONDITION) while (1) { diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h index bea1eba..9cf8f07 100644 --- a/sys/dev/sfxge/sfxge.h +++ b/sys/dev/sfxge/sfxge.h @@ -283,7 +283,10 @@ struct sfxge_softc { unsigned int rxq_count; unsigned int txq_count; - int tso_fw_assisted; + unsigned int tso_fw_assisted; +#define SFXGE_FATSOV1 (1 << 0) +#define SFXGE_FATSOV2 (1 << 1) + #if EFSYS_OPT_MCDI_LOGGING int mcdi_logging; #endif diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c index 780ed26..6ae5a07 100644 --- a/sys/dev/sfxge/sfxge_tx.c +++ b/sys/dev/sfxge/sfxge_tx.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/sysctl.h> #include <sys/syslog.h> +#include <sys/limits.h> #include <net/bpf.h> #include <net/ethernet.h> @@ -96,11 +97,11 @@ SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_dpl_put_max, CTLFLAG_RDTUN, "Maximum number of any packets in deferred packet put-list"); #define SFXGE_PARAM_TSO_FW_ASSISTED SFXGE_PARAM(tso_fw_assisted) -static int sfxge_tso_fw_assisted = 1; +static int sfxge_tso_fw_assisted = (SFXGE_FATSOV1 | SFXGE_FATSOV2); TUNABLE_INT(SFXGE_PARAM_TSO_FW_ASSISTED, &sfxge_tso_fw_assisted); SYSCTL_INT(_hw_sfxge, OID_AUTO, tso_fw_assisted, CTLFLAG_RDTUN, &sfxge_tso_fw_assisted, 0, - "Use FW-assisted TSO if supported by NIC firmware"); + "Bitmask of FW-assisted TSO allowed to use if supported by NIC firmware"); static const struct { @@ -850,6 +851,8 @@ struct sfxge_tso_state { unsigned out_len; /* Remaining length in current segment */ unsigned seqnum; /* Current sequence number */ unsigned packet_space; /* Remaining space in current packet */ + unsigned segs_space; /* Remaining number of DMA segments + for the packet (FATSOv2 only) */ /* Input position */ uint64_t dma_addr; /* DMA address of current position */ @@ -952,7 +955,7 @@ static void tso_start(struct sfxge_txq *txq, struct sfxge_tso_state *tso, struct tcphdr th_copy; #endif - tso->fw_assisted = txq->sc->tso_fw_assisted; + tso->fw_assisted = txq->tso_fw_assisted; tso->mbuf = mbuf; /* Find network protocol and header */ @@ -1059,6 +1062,8 @@ static void tso_fill_packet_with_fragment(struct sfxge_txq *txq, { efx_desc_t *desc; int n; + uint64_t dma_addr = tso->dma_addr; + boolean_t eop; if (tso->in_len == 0 || tso->packet_space == 0) return; @@ -1066,20 +1071,38 @@ static void tso_fill_packet_with_fragment(struct sfxge_txq *txq, KASSERT(tso->in_len > 0, ("TSO input length went negative")); KASSERT(tso->packet_space > 0, ("TSO packet space went negative")); - n = min(tso->in_len, tso->packet_space); + if (tso->fw_assisted & SFXGE_FATSOV2) { + n = tso->in_len; + tso->out_len -= n; + tso->seqnum += n; + tso->in_len = 0; + if (n < tso->packet_space) { + tso->packet_space -= n; + tso->segs_space--; + } else { + tso->packet_space = tso->seg_size - + (n - tso->packet_space) % tso->seg_size; + tso->segs_space = + EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1 - + (tso->packet_space != tso->seg_size); + } + } else { + n = min(tso->in_len, tso->packet_space); + tso->packet_space -= n; + tso->out_len -= n; + tso->dma_addr += n; + tso->in_len -= n; + } - tso->packet_space -= n; - tso->out_len -= n; - tso->in_len -= n; + /* + * It is OK to use binary OR below to avoid extra branching + * since all conditions may always be checked. + */ + eop = (tso->out_len == 0) | (tso->packet_space == 0) | + (tso->segs_space == 0); desc = &txq->pend_desc[txq->n_pend_desc++]; - efx_tx_qdesc_dma_create(txq->common, - tso->dma_addr, - n, - tso->out_len == 0 || tso->packet_space == 0, - desc); - - tso->dma_addr += n; + efx_tx_qdesc_dma_create(txq->common, dma_addr, n, eop, desc); } /* Callback from bus_dmamap_load() for long TSO headers. */ @@ -1112,28 +1135,47 @@ static int tso_start_new_packet(struct sfxge_txq *txq, int rc; if (tso->fw_assisted) { - uint8_t tcp_flags = tso->tcp_flags; - - if (tso->out_len > tso->seg_size) - tcp_flags &= ~(TH_FIN | TH_PUSH); - - /* TSO option descriptor */ - desc = &txq->pend_desc[txq->n_pend_desc++]; - efx_tx_qdesc_tso_create(txq->common, - tso->packet_id, - tso->seqnum, - tcp_flags, - desc++); - KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0")); - id = (id + 1) & txq->ptr_mask; + if (tso->fw_assisted & SFXGE_FATSOV2) { + /* Add 2 FATSOv2 option descriptors */ + desc = &txq->pend_desc[txq->n_pend_desc]; + efx_tx_qdesc_tso2_create(txq->common, + tso->packet_id, + tso->seqnum, + tso->seg_size, + desc, + EFX_TX_FATSOV2_OPT_NDESCS); + desc += EFX_TX_FATSOV2_OPT_NDESCS; + txq->n_pend_desc += EFX_TX_FATSOV2_OPT_NDESCS; + KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0")); + id = (id + EFX_TX_FATSOV2_OPT_NDESCS) & txq->ptr_mask; + + tso->segs_space = + EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1; + } else { + uint8_t tcp_flags = tso->tcp_flags; + + if (tso->out_len > tso->seg_size) + tcp_flags &= ~(TH_FIN | TH_PUSH); + + /* Add FATSOv1 option descriptor */ + desc = &txq->pend_desc[txq->n_pend_desc++]; + efx_tx_qdesc_tso_create(txq->common, + tso->packet_id, + tso->seqnum, + tcp_flags, + desc++); + KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0")); + id = (id + 1) & txq->ptr_mask; + + tso->seqnum += tso->seg_size; + tso->segs_space = UINT_MAX; + } /* Header DMA descriptor */ *desc = tso->header_desc; txq->n_pend_desc++; KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0")); id = (id + 1) & txq->ptr_mask; - - tso->seqnum += tso->seg_size; } else { /* Allocate a DMA-mapped header buffer. */ if (__predict_true(tso->header_len <= TSOH_STD_SIZE)) { @@ -1215,6 +1257,8 @@ static int tso_start_new_packet(struct sfxge_txq *txq, 0, desc); id = (id + 1) & txq->ptr_mask; + + tso->segs_space = UINT_MAX; } tso->packet_space = tso->seg_size; txq->tso_packets++; @@ -1264,15 +1308,19 @@ sfxge_tx_queue_tso(struct sfxge_txq *txq, struct mbuf *mbuf, } /* End of packet? */ - if (tso.packet_space == 0) { + if ((tso.packet_space == 0) | (tso.segs_space == 0)) { + unsigned int n_fatso_opt_desc = + (tso.fw_assisted & SFXGE_FATSOV2) ? + EFX_TX_FATSOV2_OPT_NDESCS : + (tso.fw_assisted & SFXGE_FATSOV1) ? 1 : 0; + /* If the queue is now full due to tiny MSS, * or we can't create another header, discard * the remainder of the input mbuf but do not * roll back the work we have done. */ - if (txq->n_pend_desc + tso.fw_assisted + - 1 /* header */ + n_dma_seg > - txq->max_pkt_desc) { + if (txq->n_pend_desc + n_fatso_opt_desc + + 1 /* header */ + n_dma_seg > txq->max_pkt_desc) { txq->tso_pdrop_too_many++; break; } @@ -1407,12 +1455,67 @@ sfxge_tx_qstop(struct sfxge_softc *sc, unsigned int index) SFXGE_TXQ_UNLOCK(txq); } +/* + * Estimate maximum number of Tx descriptors required for TSO packet. + * With minimum MSS and maximum mbuf length we might need more (even + * than a ring-ful of descriptors), but this should not happen in + * practice except due to deliberate attack. In that case we will + * truncate the output at a packet boundary. + */ +static unsigned int +sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type, + unsigned int tso_fw_assisted) +{ + /* One descriptor for every input fragment */ + unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG; + unsigned int sw_tso_max_descs; + unsigned int fa_tso_v1_max_descs = 0; + unsigned int fa_tso_v2_max_descs = 0; + + /* VLAN tagging Tx option descriptor may be required */ + if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled) + max_descs++; + + if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) { + /* + * Plus header and payload descriptor for each output segment. + * Minus one since header fragment is already counted. + * Even if FATSO is used, we should be ready to fallback + * to do it in the driver. + */ + sw_tso_max_descs = SFXGE_TSO_MAX_SEGS * 2 - 1; + + /* FW assisted TSOv1 requires one more descriptor per segment + * in comparison to SW TSO */ + if (tso_fw_assisted & SFXGE_FATSOV1) + fa_tso_v1_max_descs = + sw_tso_max_descs + SFXGE_TSO_MAX_SEGS; + + /* FW assisted TSOv2 requires 3 (2 FATSO plus header) extra + * descriptors per superframe limited by number of DMA fetches + * per packet. The first packet header is already counted. + */ + if (tso_fw_assisted & SFXGE_FATSOV2) { + fa_tso_v2_max_descs = + howmany(SFXGE_TX_MAPPING_MAX_SEG, + EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1) * + (EFX_TX_FATSOV2_OPT_NDESCS + 1) - 1; + } + + max_descs += MAX(sw_tso_max_descs, + MAX(fa_tso_v1_max_descs, fa_tso_v2_max_descs)); + } + + return (max_descs); +} + static int sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index) { struct sfxge_txq *txq; efsys_mem_t *esmp; uint16_t flags; + unsigned int tso_fw_assisted; struct sfxge_evq *evq; unsigned int desc_index; int rc; @@ -1434,6 +1537,7 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index) return (rc); /* Determine the kind of queue we are creating. */ + tso_fw_assisted = 0; switch (txq->type) { case SFXGE_TXQ_NON_CKSUM: flags = 0; @@ -1443,6 +1547,9 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index) break; case SFXGE_TXQ_IP_TCP_UDP_CKSUM: flags = EFX_TXQ_CKSUM_IPV4 | EFX_TXQ_CKSUM_TCPUDP; + tso_fw_assisted = sc->tso_fw_assisted; + if (tso_fw_assisted & SFXGE_FATSOV2) + flags |= EFX_TXQ_FATSOV2; break; default: KASSERT(0, ("Impossible TX queue")); @@ -1453,8 +1560,19 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index) /* Create the common code transmit queue. */ if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp, sc->txq_entries, txq->buf_base_id, flags, evq->common, - &txq->common, &desc_index)) != 0) - goto fail; + &txq->common, &desc_index)) != 0) { + /* Retry if no FATSOv2 resources, otherwise fail */ + if ((rc != ENOSPC) || (~flags & EFX_TXQ_FATSOV2)) + goto fail; + + /* Looks like all FATSOv2 contexts are used */ + flags &= ~EFX_TXQ_FATSOV2; + tso_fw_assisted &= ~SFXGE_FATSOV2; + if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp, + sc->txq_entries, txq->buf_base_id, flags, evq->common, + &txq->common, &desc_index)) != 0) + goto fail; + } /* Initialise queue descriptor indexes */ txq->added = txq->pending = txq->completed = txq->reaped = desc_index; @@ -1466,6 +1584,10 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index) txq->init_state = SFXGE_TXQ_STARTED; txq->flush_state = SFXGE_FLUSH_REQUIRED; + txq->tso_fw_assisted = tso_fw_assisted; + + txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, txq->type, + tso_fw_assisted); SFXGE_TXQ_UNLOCK(txq); @@ -1574,38 +1696,6 @@ sfxge_tx_qfini(struct sfxge_softc *sc, unsigned int index) free(txq, M_SFXGE); } -/* - * Estimate maximum number of Tx descriptors required for TSO packet. - * With minimum MSS and maximum mbuf length we might need more (even - * than a ring-ful of descriptors), but this should not happen in - * practice except due to deliberate attack. In that case we will - * truncate the output at a packet boundary. - */ -static unsigned int -sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type) -{ - /* One descriptor for every input fragment */ - unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG; - - /* VLAN tagging Tx option descriptor may be required */ - if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled) - max_descs++; - - if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) { - /* - * Plus header and payload descriptor for each output segment. - * Minus one since header fragment is already counted. - */ - max_descs += SFXGE_TSO_MAX_SEGS * 2 - 1; - - /* FW assisted TSO requires one more descriptor per segment */ - if (sc->tso_fw_assisted) - max_descs += SFXGE_TSO_MAX_SEGS; - } - - return (max_descs); -} - static int sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index, enum sfxge_txq_type type, unsigned int evq_index) @@ -1735,8 +1825,6 @@ sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index, txq->init_state = SFXGE_TXQ_INITIALIZED; txq->hw_vlan_tci = 0; - txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, type); - return (0); fail_txq_stat_init: @@ -1852,10 +1940,12 @@ sfxge_tx_init(struct sfxge_softc *sc) sc->txq_count = SFXGE_TXQ_NTYPES - 1 + sc->intr.n_alloc; sc->tso_fw_assisted = sfxge_tso_fw_assisted; - if (sc->tso_fw_assisted) - sc->tso_fw_assisted = - (encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) && - (encp->enc_fw_assisted_tso_enabled); + if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) || + (!encp->enc_fw_assisted_tso_enabled)) + sc->tso_fw_assisted &= ~SFXGE_FATSOV1; + if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO_V2) || + (!encp->enc_fw_assisted_tso_v2_enabled)) + sc->tso_fw_assisted &= ~SFXGE_FATSOV2; sc->txqs_node = SYSCTL_ADD_NODE( device_get_sysctl_ctx(sc->dev), diff --git a/sys/dev/sfxge/sfxge_tx.h b/sys/dev/sfxge/sfxge_tx.h index 816856a..ce5d3c4 100644 --- a/sys/dev/sfxge/sfxge_tx.h +++ b/sys/dev/sfxge/sfxge_tx.h @@ -170,6 +170,7 @@ struct sfxge_txq { struct sfxge_softc *sc; enum sfxge_txq_state init_state; enum sfxge_flush_state flush_state; + unsigned int tso_fw_assisted; enum sfxge_txq_type type; unsigned int txq_index; unsigned int evq_index; diff --git a/sys/dev/sfxge/sfxge_version.h b/sys/dev/sfxge/sfxge_version.h index 9d93e79..dbc23ba 100644 --- a/sys/dev/sfxge/sfxge_version.h +++ b/sys/dev/sfxge/sfxge_version.h @@ -36,6 +36,6 @@ #ifndef _SFXGE_VERSION_H #define _SFXGE_VERSION_H -#define SFXGE_VERSION_STRING "v4.5.3.1002" +#define SFXGE_VERSION_STRING "v4.8.0.1019" #endif /* _SFXGE_DRIVER_VERSION_H */ diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index 4a2ab91..3422269 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -112,6 +112,7 @@ struct uart_softc { /* Pulse capturing support (PPS). */ struct pps_state sc_pps; int sc_pps_mode; + sbintime_t sc_pps_captime; /* Upper layer data. */ void *sc_softih; diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index 3da37e0..b9cffe3 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_bus.h> #include <dev/uart/uart_cpu.h> +#include <dev/uart/uart_ppstypes.h> #include "uart_if.h" @@ -65,47 +66,47 @@ static MALLOC_DEFINE(M_UART, "UART", "UART driver"); static int uart_poll_freq = UART_POLL_FREQ; TUNABLE_INT("debug.uart_poll_freq", &uart_poll_freq); -#define PPS_MODE_DISABLED 0 -#define PPS_MODE_CTS 1 -#define PPS_MODE_DCD 2 - -static inline int -uart_pps_signal(int pps_mode) -{ - - switch(pps_mode) { - case PPS_MODE_CTS: - return (SER_CTS); - case PPS_MODE_DCD: - return (SER_DCD); - } - return (0); -} static inline int uart_pps_mode_valid(int pps_mode) { - - switch(pps_mode) { - case PPS_MODE_DISABLED: - case PPS_MODE_CTS: - case PPS_MODE_DCD: - return (true); + int opt; + + switch(pps_mode & UART_PPS_SIGNAL_MASK) { + case UART_PPS_DISABLED: + case UART_PPS_CTS: + case UART_PPS_DCD: + break; + default: + return (false); } - return (false); + + opt = pps_mode & UART_PPS_OPTION_MASK; + if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0) + return (false); + + return (true); } -static const char * -uart_pps_mode_name(int pps_mode) +static void +uart_pps_print_mode(struct uart_softc *sc) { - switch(pps_mode) { - case PPS_MODE_DISABLED: - return ("disabled"); - case PPS_MODE_CTS: - return ("CTS"); - case PPS_MODE_DCD: - return ("DCD"); + + device_printf(sc->sc_dev, "PPS capture mode: "); + switch(sc->sc_pps_mode) { + case UART_PPS_DISABLED: + printf("disabled"); + case UART_PPS_CTS: + printf("CTS"); + case UART_PPS_DCD: + printf("DCD"); + default: + printf("invalid"); } - return ("invalid"); + if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE) + printf("-Inverted"); + if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) + printf("-NarrowPulse"); + printf("\n"); } static int @@ -126,6 +127,55 @@ uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS) } static void +uart_pps_process(struct uart_softc *sc, int ser_sig) +{ + sbintime_t now; + int is_assert, pps_sig; + + /* Which signal is configured as PPS? Early out if none. */ + switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) { + case UART_PPS_CTS: + pps_sig = SER_CTS; + break; + case UART_PPS_DCD: + pps_sig = SER_DCD; + break; + default: + return; + } + + /* Early out if there is no change in the signal configured as PPS. */ + if ((ser_sig & SER_DELTA(pps_sig)) == 0) + return; + + /* + * In narrow-pulse mode we need to synthesize both capture and clear + * events from a single "delta occurred" indication from the uart + * hardware because the pulse width is too narrow to reliably detect + * both edges. However, when the pulse width is close to our interrupt + * processing latency we might intermittantly catch both edges. To + * guard against generating spurious events when that happens, we use a + * separate timer to ensure at least half a second elapses before we + * generate another event. + */ + pps_capture(&sc->sc_pps); + if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) { + now = getsbinuptime(); + if (now > sc->sc_pps_captime + 500 * SBT_1MS) { + sc->sc_pps_captime = now; + pps_event(&sc->sc_pps, PPS_CAPTUREASSERT); + pps_event(&sc->sc_pps, PPS_CAPTURECLEAR); + } + } else { + is_assert = ser_sig & pps_sig; + if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE) + is_assert = !is_assert; + pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT : + PPS_CAPTURECLEAR); + } +} + +static void uart_pps_init(struct uart_softc *sc) { struct sysctl_ctx_list *ctx; @@ -142,23 +192,23 @@ uart_pps_init(struct uart_softc *sc) * for one specific device. */ #ifdef UART_PPS_ON_CTS - sc->sc_pps_mode = PPS_MODE_CTS; + sc->sc_pps_mode = UART_PPS_CTS; #else - sc->sc_pps_mode = PPS_MODE_DCD; + sc->sc_pps_mode = UART_PPS_DCD; #endif TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I", - "pulse capturing mode - 0/1/2 - disabled/CTS/DCD"); + "pulse mode: 0/1/2=disabled/CTS/DCD; " + "add 0x10 to invert, 0x20 for narrow pulse"); if (!uart_pps_mode_valid(sc->sc_pps_mode)) { device_printf(sc->sc_dev, - "Invalid pps_mode %d configured; disabling PPS capture\n", + "Invalid pps_mode 0x%02x configured; disabling PPS capture\n", sc->sc_pps_mode); - sc->sc_pps_mode = PPS_MODE_DISABLED; + sc->sc_pps_mode = UART_PPS_DISABLED; } else if (bootverbose) { - device_printf(sc->sc_dev, "PPS capture mode %d (%s)\n", - sc->sc_pps_mode, uart_pps_mode_name(sc->sc_pps_mode)); + uart_pps_print_mode(sc); } sc->sc_pps.ppscap = PPS_CAPTUREBOTH; @@ -302,23 +352,16 @@ static __inline int uart_intr_sigchg(void *arg) { struct uart_softc *sc = arg; - int new, old, pps_sig, sig; + int new, old, sig; sig = UART_GETSIG(sc); /* - * Time pulse counting support. Note that both CTS and DCD are - * active-low signals. The status bit is high to indicate that - * the signal on the line is low, which corresponds to a PPS - * clear event. + * Time pulse counting support, invoked whenever the PPS parameters are + * currently set to capture either edge of the signal. */ if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) { - pps_sig = uart_pps_signal(sc->sc_pps_mode); - if (sig & SER_DELTA(pps_sig)) { - pps_capture(&sc->sc_pps); - pps_event(&sc->sc_pps, (sig & pps_sig) ? - PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); - } + uart_pps_process(sc, sig); } /* diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 99692e6..67149d6 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #endif #include <dev/uart/uart_bus.h> #include <dev/uart/uart_dev_ns8250.h> +#include <dev/uart/uart_ppstypes.h> #include <dev/ic/ns16550.h> @@ -390,11 +391,40 @@ static struct ofw_compat_data compat_data[] = { UART_FDT_CLASS_AND_DEVICE(compat_data); #endif -#define SIGCHG(c, i, s, d) \ - if (c) { \ - i |= (i & s) ? s : s | d; \ - } else { \ - i = (i & s) ? (i & ~s) | d : i; \ +/* Use token-pasting to form SER_ and MSR_ named constants. */ +#define SER(sig) SER_##sig +#define SERD(sig) SER_D##sig +#define MSR(sig) MSR_##sig +#define MSRD(sig) MSR_D##sig + +/* + * Detect signal changes using software delta detection. The previous state of + * the signals is in 'var' the new hardware state is in 'msr', and 'sig' is the + * short name (DCD, CTS, etc) of the signal bit being processed; 'var' gets the + * new state of both the signal and the delta bits. + */ +#define SIGCHGSW(var, msr, sig) \ + if ((msr) & MSR(sig)) { \ + if ((var & SER(sig)) == 0) \ + var |= SERD(sig) | SER(sig); \ + } else { \ + if ((var & SER(sig)) != 0) \ + var = SERD(sig) | (var & ~SER(sig)); \ + } + +/* + * Detect signal changes using the hardware msr delta bits. This is currently + * used only when PPS timing information is being captured using the "narrow + * pulse" option. With a narrow PPS pulse the signal may not still be asserted + * by time the interrupt handler is invoked. The hardware will latch the fact + * that it changed in the delta bits. + */ +#define SIGCHGHW(var, msr, sig) \ + if ((msr) & MSRD(sig)) { \ + if (((msr) & MSR(sig)) != 0) \ + var |= SERD(sig) | SER(sig); \ + else \ + var = SERD(sig) | (var & ~SER(sig)); \ } int @@ -521,21 +551,37 @@ ns8250_bus_flush(struct uart_softc *sc, int what) int ns8250_bus_getsig(struct uart_softc *sc) { - uint32_t new, old, sig; + uint32_t old, sig; uint8_t msr; + /* + * The delta bits are reputed to be broken on some hardware, so use + * software delta detection by default. Use the hardware delta bits + * when capturing PPS pulses which are too narrow for software detection + * to see the edges. Hardware delta for RI doesn't work like the + * others, so always use software for it. Other threads may be changing + * other (non-MSR) bits in sc_hwsig, so loop until it can succesfully + * update without other changes happening. Note that the SIGCHGxx() + * macros carefully preserve the delta bits when we have to loop several + * times and a signal transitions between iterations. + */ do { old = sc->sc_hwsig; sig = old; uart_lock(sc->sc_hwmtx); msr = uart_getreg(&sc->sc_bas, REG_MSR); uart_unlock(sc->sc_hwmtx); - SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR); - SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS); - SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD); - SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI); - new = sig & ~SER_MASK_DELTA; - } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) { + SIGCHGHW(sig, msr, DSR); + SIGCHGHW(sig, msr, CTS); + SIGCHGHW(sig, msr, DCD); + } else { + SIGCHGSW(sig, msr, DSR); + SIGCHGSW(sig, msr, CTS); + SIGCHGSW(sig, msr, DCD); + } + SIGCHGSW(sig, msr, RI); + } while (!atomic_cmpset_32(&sc->sc_hwsig, old, sig & ~SER_MASK_DELTA)); return (sig); } @@ -889,12 +935,10 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig) old = sc->sc_hwsig; new = old; if (sig & SER_DDTR) { - SIGCHG(sig & SER_DTR, new, SER_DTR, - SER_DDTR); + new = (new & ~SER_DTR) | (sig & (SER_DTR | SER_DDTR)); } if (sig & SER_DRTS) { - SIGCHG(sig & SER_RTS, new, SER_RTS, - SER_DRTS); + new = (new & ~SER_RTS) | (sig & (SER_RTS | SER_DRTS)); } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); uart_lock(sc->sc_hwmtx); diff --git a/sys/dev/uart/uart_ppstypes.h b/sys/dev/uart/uart_ppstypes.h new file mode 100644 index 0000000..142d0f1 --- /dev/null +++ b/sys/dev/uart/uart_ppstypes.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2015 Ian Lepore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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 _DEV_UART_PPSTYPES_H_ +#define _DEV_UART_PPSTYPES_H_ + +/* + * These constants are shared by several drivers including uart and usb_serial. + */ + +#define UART_PPS_SIGNAL_MASK 0x0f +#define UART_PPS_OPTION_MASK 0xf0 + +#define UART_PPS_DISABLED 0x00 +#define UART_PPS_CTS 0x01 +#define UART_PPS_DCD 0x02 + +#define UART_PPS_INVERT_PULSE 0x10 +#define UART_PPS_NARROW_PULSE 0x20 + +#endif /* _DEV_UART_PPSTYPES_H_ */ diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c index 499d5c1..5bc23b8 100644 --- a/sys/dev/usb/serial/usb_serial.c +++ b/sys/dev/usb/serial/usb_serial.c @@ -81,6 +81,8 @@ __FBSDID("$FreeBSD$"); #include <sys/cons.h> #include <sys/kdb.h> +#include <dev/uart/uart_ppstypes.h> + #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> @@ -99,7 +101,8 @@ static SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom"); static int ucom_pps_mode; SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RWTUN, - &ucom_pps_mode, 0, "pulse capturing mode - 0/1/2 - disabled/CTS/DCD"); + &ucom_pps_mode, 0, + "pulse capture mode: 0/1/2=disabled/CTS/DCD; add 0x10 to invert"); #ifdef USB_DEBUG static int ucom_debug = 0; @@ -1074,10 +1077,12 @@ ucom_cfg_status_change(struct usb_proc_msg *_task) (struct ucom_cfg_task *)_task; struct ucom_softc *sc = task->sc; struct tty *tp; + int onoff; uint8_t new_msr; uint8_t new_lsr; uint8_t msr_delta; uint8_t lsr_delta; + uint8_t pps_signal; tp = sc->sc_tty; @@ -1107,35 +1112,33 @@ ucom_cfg_status_change(struct usb_proc_msg *_task) sc->sc_lsr = new_lsr; /* - * Time pulse counting support. Note that both CTS and DCD are - * active-low signals. The status bit is high to indicate that - * the signal on the line is low, which corresponds to a PPS - * clear event. + * Time pulse counting support. */ - switch(ucom_pps_mode) { - case 1: - if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && - (msr_delta & SER_CTS)) { - pps_capture(&sc->sc_pps); - pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ? - PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); - } + switch(ucom_pps_mode & UART_PPS_SIGNAL_MASK) { + case UART_PPS_CTS: + pps_signal = SER_CTS; break; - case 2: - if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && - (msr_delta & SER_DCD)) { - pps_capture(&sc->sc_pps); - pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ? - PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); - } + case UART_PPS_DCD: + pps_signal = SER_DCD; break; default: + pps_signal = 0; break; } + if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && + (msr_delta & pps_signal)) { + pps_capture(&sc->sc_pps); + onoff = (sc->sc_msr & pps_signal) ? 1 : 0; + if (ucom_pps_mode & UART_PPS_INVERT_PULSE) + onoff = !onoff; + pps_event(&sc->sc_pps, onoff ? PPS_CAPTUREASSERT : + PPS_CAPTURECLEAR); + } + if (msr_delta & SER_DCD) { - int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0; + onoff = (sc->sc_msr & SER_DCD) ? 1 : 0; DPRINTF("DCD changed to %d\n", onoff); diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index ba56e56..a45e07d 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -146,7 +146,7 @@ devfs_get_cdevpriv(void **datap) } int -devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t priv_dtr) +devfs_set_cdevpriv(void *priv, d_priv_dtor_t *priv_dtr) { struct file *fp; struct cdev_priv *cdp; @@ -239,18 +239,18 @@ devfs_populate_vp(struct vnode *vp) if (DEVFS_DMP_DROP(dmp)) { sx_xunlock(&dmp->dm_lock); devfs_unmount_final(dmp); - return (EBADF); + return (ERESTART); } if ((vp->v_iflag & VI_DOOMED) != 0) { sx_xunlock(&dmp->dm_lock); - return (EBADF); + return (ERESTART); } de = vp->v_data; KASSERT(de != NULL, ("devfs_populate_vp: vp->v_data == NULL but vnode not doomed")); if ((de->de_flags & DE_DOOMED) != 0) { sx_xunlock(&dmp->dm_lock); - return (EBADF); + return (ERESTART); } return (0); diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c index ada84c2..c5b8a68 100644 --- a/sys/fs/smbfs/smbfs_smb.c +++ b/sys/fs/smbfs/smbfs_smb.c @@ -333,18 +333,18 @@ smbfs_smb_flush(struct smbnode *np, struct smb_cred *scred) } int -smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred) +smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred) { struct smb_share *ssp = np->n_mount->sm_share; struct smb_rq *rqp; struct mbchain *mbp; int error; - if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) { + if (!smbfs_smb_seteof(np, newsize, scred)) { np->n_flag |= NFLUSHWIRE; return (0); } - + /* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return (error); @@ -352,7 +352,7 @@ smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred) smb_rq_wstart(rqp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, 0); - mb_put_uint32le(mbp, newsize); + mb_put_uint32le(mbp, (uint32_t)newsize); mb_put_uint16le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); diff --git a/sys/fs/smbfs/smbfs_subr.h b/sys/fs/smbfs/smbfs_subr.h index d22df08..4ee143c 100644 --- a/sys/fs/smbfs/smbfs_subr.h +++ b/sys/fs/smbfs/smbfs_subr.h @@ -128,7 +128,8 @@ int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, off_t start, off_t end, struct smb_cred *scred); int smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred); -int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred); +int smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, + struct smb_cred *scred); int smbfs_smb_query_info(struct smbnode *np, const char *name, int len, struct smbfattr *fap, struct smb_cred *scred); diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 8ea1198..c78ceb2 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -358,7 +358,8 @@ smbfs_setattr(ap) doclose = 1; } if (error == 0) - error = smbfs_smb_setfsize(np, vap->va_size, scred); + error = smbfs_smb_setfsize(np, + (int64_t)vap->va_size, scred); if (doclose) smbfs_smb_close(ssp, np->n_fid, NULL, scred); if (error) { diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 1a879f7..5d7965e 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -581,6 +581,23 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g indent, dp->d_fwheads); sbuf_printf(sb, "%s<fwsectors>%u</fwsectors>\n", indent, dp->d_fwsectors); + + /* + * "rotationrate" is a little complicated, because the value + * returned by the drive might not be the RPM; 0 and 1 are + * special cases, and there's also a valid range. + */ + sbuf_printf(sb, "%s<rotationrate>", indent); + if (dp->d_rotation_rate == 0) /* Old drives don't */ + sbuf_printf(sb, "unknown"); /* report RPM. */ + else if (dp->d_rotation_rate == 1) /* Since 0 is used */ + sbuf_printf(sb, "0"); /* above, SSDs use 1. */ + else if ((dp->d_rotation_rate >= 0x041) && + (dp->d_rotation_rate <= 0xfffe)) + sbuf_printf(sb, "%u", dp->d_rotation_rate); + else + sbuf_printf(sb, "invalid"); + sbuf_printf(sb, "</rotationrate>\n"); if (dp->d_getattr != NULL) { buf = g_malloc(DISK_IDENT_SIZE, M_WAITOK); bp = g_alloc_bio(); diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 0953d18..6644532 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -107,8 +107,9 @@ struct g_class g_multipath_class = { #define MP_NEW 0x00000004 #define MP_POSTED 0x00000008 #define MP_BAD (MP_FAIL | MP_LOST | MP_NEW) -#define MP_IDLE 0x00000010 -#define MP_IDLE_MASK 0xfffffff0 +#define MP_WITHER 0x00000010 +#define MP_IDLE 0x00000020 +#define MP_IDLE_MASK 0xffffffe0 static int g_multipath_good(struct g_geom *gp) @@ -204,6 +205,7 @@ g_mpd(void *arg, int flags __unused) g_access(cp, -cp->acr, -cp->acw, -cp->ace); if (w > 0 && cp->provider != NULL && (cp->provider->geom->flags & G_GEOM_WITHER) == 0) { + cp->index |= MP_WITHER; g_post_event(g_mpd, cp, M_WAITOK, NULL); return; } @@ -467,23 +469,37 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de) gp = pp->geom; + /* Error used if we have no valid consumers. */ + error = ENXIO; + LIST_FOREACH(cp, &gp->consumer, consumer) { + if (cp->index & MP_WITHER) + continue; + error = g_access(cp, dr, dw, de); if (error) { badcp = cp; goto fail; } } + + if (error != 0) + return (error); + sc = gp->softc; sc->sc_opened += dr + dw + de; if (sc->sc_stopping && sc->sc_opened == 0) g_multipath_destroy(gp); + return (0); fail: LIST_FOREACH(cp, &gp->consumer, consumer) { if (cp == badcp) break; + if (cp->index & MP_WITHER) + continue; + (void) g_access(cp, -dr, -dw, -de); } return (error); diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c index 81d6e35..29a8885 100644 --- a/sys/i386/i386/elf_machdep.c +++ b/sys/i386/i386/elf_machdep.c @@ -89,6 +89,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 36aeca5..f55900c 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -3190,10 +3190,11 @@ init386(first) } else { metadata_missing = 1; } - if (envmode == 1) - kern_envp = static_env; - else if (bootinfo.bi_envp) - kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE; + + if (bootinfo.bi_envp) + init_static_kenv((caddr_t)bootinfo.bi_envp + KERNBASE, 0); + else + init_static_kenv(NULL, 0); /* Init basic tunables, hz etc */ init_param1(); diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index 16507ee..372e5ea 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -90,6 +90,7 @@ struct sysentvec ibcs2_svr3_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static int diff --git a/sys/i386/include/metadata.h b/sys/i386/include/metadata.h index 73c9207..98d0272 100644 --- a/sys/i386/include/metadata.h +++ b/sys/i386/include/metadata.h @@ -1,36 +1,6 @@ /*- - * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org> - * 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$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_METADATA_H_ -#define _MACHINE_METADATA_H_ - -#define MODINFOMD_SMAP 0x1001 -#define MODINFOMD_SMAP_XATTR 0x1002 -#define MODINFOMD_DTBP 0x1003 - -#endif /* !_MACHINE_METADATA_H_ */ +#include <x86/metadata.h> diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index 4bfd603..558565b 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -44,13 +44,17 @@ #endif #include <machine/npx.h> +/* + * NB: The fields marked with (*) are used by kernel debuggers. Their + * ABI should be preserved. + */ struct pcb { - int pcb_edi; - int pcb_esi; - int pcb_ebp; - int pcb_esp; - int pcb_ebx; - int pcb_eip; + int pcb_edi; /* (*) */ + int pcb_esi; /* (*) */ + int pcb_ebp; /* (*) */ + int pcb_esp; /* (*) */ + int pcb_ebx; /* (*) */ + int pcb_eip; /* (*) */ struct segment_descriptor pcb_fsd; struct segment_descriptor pcb_gsd; int pcb_ds; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 7c980ce..df5441b 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -988,6 +988,7 @@ struct sysentvec linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; INIT_SYSENTVEC(aout_sysvec, &linux_sysvec); @@ -1027,6 +1028,7 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; static void diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index edd5f5f..553dc04 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -100,6 +100,7 @@ struct sysentvec aout_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; #elif defined(__amd64__) diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 6cb5017..201680a 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -415,6 +415,7 @@ struct sysentvec null_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; /* diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c index ff453cb..05c4f62 100644 --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -210,12 +210,44 @@ done: return (error); } +/* + * Populate the initial kernel environment. + * + * This is called very early in MD startup, either to provide a copy of the + * environment obtained from a boot loader, or to provide an empty buffer into + * which MD code can store an initial environment using kern_setenv() calls. + * + * If the global envmode is 1, the environment is initialized from the global + * static_env[], regardless of the arguments passed. This implements the env + * keyword described in config(5). In this case env_pos is set to env_len, + * causing kern_setenv() to return -1 (if len > 0) or panic (if len == 0) until + * the dynamic environment is available. The envmode and static_env variables + * are defined in env.c which is generated by config(8). + * + * If len is non-zero, the caller is providing an empty buffer. The caller will + * subsequently use kern_setenv() to add up to len bytes of initial environment + * before the dynamic environment is available. + * + * If len is zero, the caller is providing a pre-loaded buffer containing + * environment strings. Additional strings cannot be added until the dynamic + * environment is available. The memory pointed to must remain stable at least + * until sysinit runs init_dynamic_kenv(). If no initial environment is + * available from the boot loader, passing a NULL pointer allows the static_env + * to be installed if it is configured. + */ void init_static_kenv(char *buf, size_t len) { - kern_envp = buf; - env_len = len; - env_pos = 0; + + if (envmode == 1) { + kern_envp = static_env; + env_len = len; + env_pos = len; + } else { + kern_envp = buf; + env_len = len; + env_pos = 0; + } } /* diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index e379f5f..78eab87 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -71,6 +71,12 @@ SYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW | CTLFLAG_TUN, TUNABLE_INT("debug.kld_debug", &kld_debug); #endif +/* These variables are used by kernel debuggers to enumerate loaded files. */ +const int kld_off_address = offsetof(struct linker_file, address); +const int kld_off_filename = offsetof(struct linker_file, filename); +const int kld_off_pathname = offsetof(struct linker_file, pathname); +const int kld_off_next = offsetof(struct linker_file, link.tqe_next); + /* * static char *linker_search_path(const char *name, struct mod_depend * *verinfo); diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index 0307791..ccecbc9 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -574,6 +574,11 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, buf, CTLFLAG_RD, SYSCTL_INT(_debug_sizeof, OID_AUTO, kinfo_proc, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, sizeof(struct kinfo_proc), "sizeof(struct kinfo_proc)"); +/* Used by kernel debuggers. */ +const int pcb_size = sizeof(struct pcb); +SYSCTL_INT(_debug_sizeof, OID_AUTO, pcb, CTLFLAG_RD, + SYSCTL_NULL_INT_PTR, sizeof(struct pcb), "sizeof(struct pcb)"); + /* XXX compatibility, remove for 6.0 */ #include <sys/imgact.h> #include <sys/imgact_elf.h> diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index c9b7ca3..6b60840 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -139,6 +139,21 @@ struct sx proctree_lock; struct mtx ppeers_lock; uma_zone_t proc_zone; +/* + * The offset of various fields in struct proc and struct thread. + * These are used by kernel debuggers to enumerate kernel threads and + * processes. + */ +const int proc_off_p_pid = offsetof(struct proc, p_pid); +const int proc_off_p_comm = offsetof(struct proc, p_comm); +const int proc_off_p_list = offsetof(struct proc, p_list); +const int proc_off_p_threads = offsetof(struct proc, p_threads); +const int thread_off_td_tid = offsetof(struct thread, td_tid); +const int thread_off_td_name = offsetof(struct thread, td_name); +const int thread_off_td_oncpu = offsetof(struct thread, td_oncpu); +const int thread_off_td_pcb = offsetof(struct thread, td_pcb); +const int thread_off_td_plist = offsetof(struct thread, td_plist); + int kstack_pages = KSTACK_PAGES; SYSCTL_INT(_kern, OID_AUTO, kstack_pages, CTLFLAG_RD, &kstack_pages, 0, "Kernel stack size in pages"); diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 96f68609ca..c85813b 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sched.h> #include <sys/sleepqueue.h> #include <sys/selinfo.h> +#include <sys/syscallsubr.h> #include <sys/sysent.h> #include <sys/turnstile.h> #include <sys/ktr.h> @@ -885,7 +886,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 @@ -893,13 +893,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); diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 8be4896..1d3af65 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -410,6 +410,10 @@ s/\$//g printf("\t\tuarg[%d] = (intptr_t) p->%s; /* %s */\n", \ i - 1, \ argname[i], arg) > systrace + else if (arg == "union l_semun") + printf("\t\tuarg[%d] = p->%s.buf; /* %s */\n", \ + i - 1, \ + argname[i], arg) > systrace else if (substr(arg, 1, 1) == "u" || arg == "size_t") printf("\t\tuarg[%d] = p->%s; /* %s */\n", \ i - 1, \ diff --git a/sys/kern/subr_busdma_bufalloc.c b/sys/kern/subr_busdma_bufalloc.c index b0b1ba8..c8980e1 100644 --- a/sys/kern/subr_busdma_bufalloc.c +++ b/sys/kern/subr_busdma_bufalloc.c @@ -94,8 +94,8 @@ busdma_bufalloc_create(const char *name, bus_size_t minimum_alignment, for (i = 0, bz = ba->buf_zones, cursize = ba->min_size; i < nitems(ba->buf_zones) && cursize <= MAX_ZONE_BUFSIZE; ++i, ++bz, cursize <<= 1) { - snprintf(bz->name, sizeof(bz->name), "dma %.10s %lu", - name, cursize); + snprintf(bz->name, sizeof(bz->name), "dma %.10s %ju", + name, (uintmax_t)cursize); bz->size = cursize; bz->umazone = uma_zcreate(bz->name, bz->size, NULL, NULL, NULL, NULL, bz->size - 1, zcreate_flags); diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h index c1e792b..a33c090 100644 --- a/sys/mips/include/elf.h +++ b/sys/mips/include/elf.h @@ -238,39 +238,10 @@ __ElfType(Auxinfo); #define R_MIPS_COPY 126 #define R_MIPS_JUMP_SLOT 127 -/* mips dynamic tags */ - -#define DT_MIPS_RLD_VERSION 0x70000001 -#define DT_MIPS_TIME_STAMP 0x70000002 -#define DT_MIPS_ICHECKSUM 0x70000003 -#define DT_MIPS_IVERSION 0x70000004 -#define DT_MIPS_FLAGS 0x70000005 -#define DT_MIPS_BASE_ADDRESS 0x70000006 -#define DT_MIPS_CONFLICT 0x70000008 -#define DT_MIPS_LIBLIST 0x70000009 -#define DT_MIPS_CONFLICTNO 0x7000000b -#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* number of local got ents */ -#define DT_MIPS_LIBLISTNO 0x70000010 -#define DT_MIPS_SYMTABNO 0x70000011 /* number of .dynsym entries */ -#define DT_MIPS_UNREFEXTNO 0x70000012 -#define DT_MIPS_GOTSYM 0x70000013 /* first dynamic sym in got */ -#define DT_MIPS_HIPAGENO 0x70000014 -#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */ -#define DT_MIPS_PLTGOT 0x70000032 -#define DT_MIPS_RWPLT 0x70000034 - /* * ELF Flags */ -#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ -#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */ -#define EF_MIPS_ABI2 0x00000020 /* N32 */ - -#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural extensions */ -#define EF_MIPS_ARCH_MDMX 0x08000000 /* MDMX multimedia extension */ -#define EF_MIPS_ARCH_M16 0x04000000 /* MIPS-16 ISA extensions */ -#define EF_MIPS_ARCH 0xf0000000 /* Architecture field */ #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */ #define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */ #define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */ diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c index 626b5f8..db50a73 100644 --- a/sys/mips/mips/elf_machdep.c +++ b/sys/mips/mips/elf_machdep.c @@ -84,6 +84,7 @@ struct sysentvec elf64_freebsd_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf64_Brandinfo freebsd_brand_info = { @@ -141,6 +142,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf32_Brandinfo freebsd_brand_info = { diff --git a/sys/mips/mips/freebsd32_machdep.c b/sys/mips/mips/freebsd32_machdep.c index 5303420..87fda42 100644 --- a/sys/mips/mips/freebsd32_machdep.c +++ b/sys/mips/mips/freebsd32_machdep.c @@ -107,6 +107,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_syscallnames = freebsd32_syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile index 1b12371..9f3c993 100644 --- a/sys/modules/dtrace/Makefile +++ b/sys/modules/dtrace/Makefile @@ -16,7 +16,10 @@ SUBDIR= dtmalloc \ systrace .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" -SUBDIR+= fasttrap fbt systrace_linux32 +SUBDIR+= fasttrap fbt systrace_linux +.endif +.if ${MACHINE_CPUARCH} == "amd64" +SUBDIR+= systrace_linux32 .endif .if ${MACHINE_CPUARCH} == "powerpc" SUBDIR+= fbt fasttrap diff --git a/sys/modules/dtrace/systrace_linux/Makefile b/sys/modules/dtrace/systrace_linux/Makefile new file mode 100644 index 0000000..1cf5e31 --- /dev/null +++ b/sys/modules/dtrace/systrace_linux/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +SYSDIR?= ${.CURDIR}/../../.. + +.PATH: ${SYSDIR}/cddl/dev/systrace + +KMOD= systrace_linux + +SRCS= systrace.c +SRCS+= vnode_if.h + +CFLAGS+= -I${SYSDIR}/cddl/compat/opensolaris \ + -I${SYSDIR}/cddl/contrib/opensolaris/uts/common \ + -I${SYSDIR} -DLINUX_SYSTRACE + +.include <bsd.kmod.mk> + +CFLAGS+= -include ${SYSDIR}/cddl/compat/opensolaris/sys/debug_compat.h diff --git a/sys/modules/dtrace/systrace_linux32/Makefile b/sys/modules/dtrace/systrace_linux32/Makefile index a2bfc81..3183482 100644 --- a/sys/modules/dtrace/systrace_linux32/Makefile +++ b/sys/modules/dtrace/systrace_linux32/Makefile @@ -2,18 +2,14 @@ .PATH: ${.CURDIR}/../../../cddl/dev/systrace -.if ${MACHINE} == "amd64" KMOD= systrace_linux32 -.else -KMOD= systrace_linux -.endif SRCS= systrace.c SRCS+= vnode_if.h CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \ -I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/common \ - -I${.CURDIR}/../../.. -DLINUX_SYSTRACE + -I${.CURDIR}/../../.. -DLINUX32_SYSTRACE .include <bsd.kmod.mk> diff --git a/sys/modules/sfxge/Makefile b/sys/modules/sfxge/Makefile index c444152..ba4108b 100644 --- a/sys/modules/sfxge/Makefile +++ b/sys/modules/sfxge/Makefile @@ -16,7 +16,7 @@ SRCS+= sfxge_port.c sfxge_rx.c sfxge_tx.c SRCS+= sfxge.h sfxge_rx.h sfxge_tx.h sfxge_version.h .PATH: ${.CURDIR}/../../dev/sfxge/common -SRCS+= efx_bootcfg.c efx_crc32.c efx_ev.c efx_intr.c efx_mac.c +SRCS+= efx_bootcfg.c efx_crc32.c efx_ev.c efx_intr.c efx_lic.c efx_mac.c SRCS+= efx_mcdi.c efx_mon.c efx_nic.c SRCS+= efx_nvram.c efx_phy.c efx_port.c efx_rx.c efx_sram.c efx_tx.c SRCS+= efx_vpd.c efx_wol.c efx_filter.c efx_hash.c diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 914dad6..15ab5aa 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -2500,7 +2500,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp) bp->bif_hdrlen = hdrlen; - if (bootverbose) + if (bootverbose && IS_DEFAULT_VNET(curvnet)) if_printf(ifp, "bpf attached\n"); } diff --git a/sys/net/if.c b/sys/net/if.c index efaece7..288d944 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -176,7 +176,7 @@ static int if_getgroup(struct ifgroupreq *, struct ifnet *); static int if_getgroupmembers(struct ifgroupreq *); static void if_delgroups(struct ifnet *); static void if_attach_internal(struct ifnet *, int, struct if_clone *); -static void if_detach_internal(struct ifnet *, int, struct if_clone **); +static int if_detach_internal(struct ifnet *, int, struct if_clone **); #ifdef INET6 /* @@ -894,7 +894,7 @@ if_detach(struct ifnet *ifp) CURVNET_RESTORE(); } -static void +static int if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) { struct ifaddr *ifa; @@ -917,11 +917,19 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) #endif IFNET_WUNLOCK(); if (!found) { + /* + * While we would want to panic here, we cannot + * guarantee that the interface is indeed still on + * the list given we don't hold locks all the way. + */ + return (ENOENT); +#if 0 if (vmove) panic("%s: ifp=%p not on the ifnet tailq %p", __func__, ifp, &V_ifnet); else return; /* XXX this should panic as well? */ +#endif } /* Check if this is a cloned interface or not. */ @@ -1019,6 +1027,8 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) (*dp->dom_ifdetach)(ifp, ifp->if_afdata[dp->dom_family]); } + + return (0); } #ifdef VIMAGE @@ -1034,12 +1044,16 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { u_short idx; struct if_clone *ifc; + int rc; /* * Detach from current vnet, but preserve LLADDR info, do not * mark as dead etc. so that the ifnet can be reattached later. + * If we cannot find it, we lost the race to someone else. */ - if_detach_internal(ifp, 1, &ifc); + rc = if_detach_internal(ifp, 1, &ifc); + if (rc != 0) + return; /* * Unlink the ifnet from ifindex_table[] in current vnet, and shrink diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index 84ea6c6..11e415d 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -62,11 +62,10 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); -static VNET_DEFINE(SLIST_HEAD(, lltable), lltables); +static VNET_DEFINE(SLIST_HEAD(, lltable), lltables) = + SLIST_HEAD_INITIALIZER(lltables); #define V_lltables VNET(lltables) -static void vnet_lltable_init(void); - struct rwlock lltable_rwlock; RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); @@ -367,15 +366,6 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) return (error); } -static void -vnet_lltable_init() -{ - - SLIST_INIT(&V_lltables); -} -VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, - vnet_lltable_init, NULL); - #ifdef DDB struct llentry_sa { struct llentry base; diff --git a/sys/net/sff8436.h b/sys/net/sff8436.h index 97abe10..3399cce 100644 --- a/sys/net/sff8436.h +++ b/sys/net/sff8436.h @@ -131,7 +131,7 @@ enum { SFF_8436_CONNECTOR = 130, /* Connector type (Table 32) */ SFF_8436_TRANS_START = 131, /* Electric or Optical Compatibility * (Table 33) */ - SFF_8436_CODE_E1040G = 131, /* 10/40G Ethernet Compliance Code */ + SFF_8436_CODE_E1040100G = 131, /* 10/40/100G Ethernet Compliance Code */ SFF_8436_CODE_SONET = 132, /* SONET Compliance codes */ SFF_8436_CODE_SATA = 133, /* SAS/SATA compliance codes */ SFF_8436_CODE_E1G = 134, /* Gigabit Ethernet Compliant codes */ diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index 8a033d8..784c1d4 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -388,33 +388,32 @@ struct sctp_error_cause { } SCTP_PACKED; struct sctp_error_invalid_stream { - struct sctp_error_cause cause; /* code=SCTP_ERROR_INVALID_STREAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_INVALID_STREAM */ uint16_t stream_id; /* stream id of the DATA in error */ uint16_t reserved; } SCTP_PACKED; struct sctp_error_missing_param { - struct sctp_error_cause cause; /* code=SCTP_ERROR_MISSING_PARAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_MISSING_PARAM */ uint32_t num_missing_params; /* number of missing parameters */ - /* uint16_t param_type's follow */ + uint16_t type[]; } SCTP_PACKED; struct sctp_error_stale_cookie { - struct sctp_error_cause cause; /* code=SCTP_ERROR_STALE_COOKIE */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_STALE_COOKIE */ uint32_t stale_time; /* time in usec of staleness */ } SCTP_PACKED; struct sctp_error_out_of_resource { - struct sctp_error_cause cause; /* code=SCTP_ERROR_OUT_OF_RESOURCES */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_OUT_OF_RESOURCES */ } SCTP_PACKED; struct sctp_error_unresolv_addr { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRESOLVABLE_ADDR */ - + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRESOLVABLE_ADDR */ } SCTP_PACKED; struct sctp_error_unrecognized_chunk { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRECOG_CHUNK */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */ struct sctp_chunkhdr ch;/* header from chunk in error */ } SCTP_PACKED; @@ -423,6 +422,11 @@ struct sctp_error_no_user_data { uint32_t tsn; /* TSN of the empty data chunk */ } SCTP_PACKED; +struct sctp_error_auth_invalid_hmac { + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNSUPPORTED_HMACID */ + uint16_t hmac_id; +} SCTP_PACKED; + /* * Main SCTP chunk types we place these here so natd and f/w's in user land * can find them. diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index a64e7f9..540cc65 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -1680,8 +1680,14 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, * abort the asoc, since someone probably just hijacked us... */ if (serial_num == (asoc->asconf_seq_out + 1)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); - sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED); + snprintf(msg, sizeof(msg), "Never sent serial number %8.8x", + serial_num); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_no_unlock = 1; return; } diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index 7c2e194..07dbf8b 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -558,7 +558,7 @@ sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id) atomic_add_int(&skey->refcount, 1); SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u refcount acquire to %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); } } @@ -578,7 +578,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked if (skey) { SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u refcount release to %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); /* see if a notification should be generated */ if ((skey->refcount <= 2) && (skey->deactivated)) { @@ -587,7 +587,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked key_id, 0, so_locked); SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u no longer used, %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); } sctp_free_sharedkey(skey); } @@ -1651,8 +1651,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, /* is the indicated HMAC supported? */ if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) { - struct mbuf *m_err; - struct sctp_auth_invalid_hmac *err; + struct mbuf *op_err; + struct sctp_error_auth_invalid_hmac *cause; SCTP_STAT_INCR(sctps_recvivalhmacid); SCTPDBG(SCTP_DEBUG_AUTH1, @@ -1662,20 +1662,19 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, * report this in an Error Chunk: Unsupported HMAC * Identifier */ - m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT, - 1, MT_HEADER); - if (m_err != NULL) { + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_auth_invalid_hmac), + 0, M_NOWAIT, 1, MT_HEADER); + if (op_err != NULL) { /* pre-reserve some space */ - SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* fill in the error */ - err = mtod(m_err, struct sctp_auth_invalid_hmac *); - bzero(err, sizeof(*err)); - err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); - err->ph.param_length = htons(sizeof(*err)); - err->hmac_id = ntohs(hmac_id); - SCTP_BUF_LEN(m_err) = sizeof(*err); + cause = mtod(op_err, struct sctp_error_auth_invalid_hmac *); + cause->cause.code = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); + cause->cause.length = htons(sizeof(struct sctp_error_auth_invalid_hmac)); + cause->hmac_id = ntohs(hmac_id); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_auth_invalid_hmac); /* queue it */ - sctp_queue_op_err(stcb, m_err); + sctp_queue_op_err(stcb, op_err); } return (-1); } diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index d90bd25..a26bc5b 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$"); */ #define SCTP_LARGEST_INIT_ACCEPTED (65535 - 2048) +/* Largest length of a chunk */ +#define SCTP_MAX_CHUNK_LENGTH 0xffff /* Number of addresses where we just skip the counting */ #define SCTP_COUNT_LIMIT 40 @@ -458,7 +460,7 @@ __FBSDID("$FreeBSD$"); /* - * SCTP states for internal state machine XXX (should match "user" values) + * SCTP states for internal state machine */ #define SCTP_STATE_EMPTY 0x0000 #define SCTP_STATE_INUSE 0x0001 @@ -612,10 +614,6 @@ __FBSDID("$FreeBSD$"); /* 30 seconds + RTO (in ms) */ #define SCTP_HB_DEFAULT_MSEC 30000 -/* Max time I will wait for Shutdown to complete */ -#define SCTP_DEF_MAX_SHUTDOWN_SEC 180 - - /* * This is how long a secret lives, NOT how long a cookie lives how many * ticks the current secret will live. diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h index f322e04..dc05b3d 100644 --- a/sys/netinet/sctp_header.h +++ b/sys/netinet/sctp_header.h @@ -202,34 +202,6 @@ struct sctp_state_cookie { /* this is our definition... */ */ } SCTP_PACKED; - -/* Used for NAT state error cause */ -struct sctp_missing_nat_state { - uint16_t cause; - uint16_t length; - uint8_t data[]; -} SCTP_PACKED; - - -struct sctp_inv_mandatory_param { - uint16_t cause; - uint16_t length; - uint32_t num_param; - uint16_t param; - /* - * We include this to 0 it since only a missing cookie will cause - * this error. - */ - uint16_t resv; -} SCTP_PACKED; - -struct sctp_unresolv_addr { - uint16_t cause; - uint16_t length; - uint16_t addr_type; - uint16_t reserved; /* Only one invalid addr type */ -} SCTP_PACKED; - /* state cookie parameter */ struct sctp_state_cookie_param { struct sctp_paramhdr ph; @@ -370,28 +342,11 @@ struct sctp_shutdown_complete_chunk { struct sctp_chunkhdr ch; } SCTP_PACKED; -/* Oper error holding a stale cookie */ -struct sctp_stale_cookie_msg { - struct sctp_paramhdr ph;/* really an error cause */ - uint32_t time_usec; -} SCTP_PACKED; - struct sctp_adaptation_layer_indication { struct sctp_paramhdr ph; uint32_t indication; } SCTP_PACKED; -struct sctp_cookie_while_shutting_down { - struct sctphdr sh; - struct sctp_chunkhdr ch; - struct sctp_paramhdr ph;/* really an error cause */ -} SCTP_PACKED; - -struct sctp_shutdown_complete_msg { - struct sctphdr sh; - struct sctp_shutdown_complete_chunk shut_cmp; -} SCTP_PACKED; - /* * draft-ietf-tsvwg-addip-sctp */ @@ -554,12 +509,6 @@ struct sctp_auth_chunk { uint8_t hmac[]; } SCTP_PACKED; -struct sctp_auth_invalid_hmac { - struct sctp_paramhdr ph; - uint16_t hmac_id; - uint16_t padding; -} SCTP_PACKED; - /* * we pre-reserve enough room for a ECNE or CWR AND a SACK with no missing * pieces. If ENCE is missing we could have a couple of blocks. This way we diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 50a6628..75c1ac5 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -223,9 +223,9 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) } seinfo = (struct sctp_extrcvinfo *)sinfo; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) && - (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) { + (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) { provide_nxt = 1; - len += CMSG_SPACE(sizeof(struct sctp_rcvinfo)); + len += CMSG_SPACE(sizeof(struct sctp_nxtinfo)); } else { provide_nxt = 0; } @@ -276,20 +276,20 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo)); cmh->cmsg_type = SCTP_NXTINFO; nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh); - nxtinfo->nxt_sid = seinfo->sreinfo_next_stream; + nxtinfo->nxt_sid = seinfo->serinfo_next_stream; nxtinfo->nxt_flags = 0; - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { nxtinfo->nxt_flags |= SCTP_UNORDERED; } - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { nxtinfo->nxt_flags |= SCTP_NOTIFICATION; } - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { nxtinfo->nxt_flags |= SCTP_COMPLETE; } - nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid; - nxtinfo->nxt_length = seinfo->sreinfo_next_length; - nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid; + nxtinfo->nxt_ppid = seinfo->serinfo_next_ppid; + nxtinfo->nxt_length = seinfo->serinfo_next_length; + nxtinfo->nxt_assoc_id = seinfo->serinfo_next_aid; cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo))); SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo)); } @@ -578,10 +578,10 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD); } SCTPDBG(SCTP_DEBUG_INDATA1, - "queue to stream called for ssn:%u lastdel:%u nxt:%u\n", - (uint32_t) control->sinfo_stream, - (uint32_t) strm->last_sequence_delivered, - (uint32_t) nxt_todel); + "queue to stream called for sid:%u ssn:%u tsn:%u lastdel:%u nxt:%u\n", + (uint32_t) control->sinfo_stream, (uint32_t) control->sinfo_ssn, + (uint32_t) control->sinfo_tsn, + (uint32_t) strm->last_sequence_delivered, (uint32_t) nxt_todel); if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) { /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", @@ -602,6 +602,20 @@ protocol_error: return; } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + struct socket *so; + + so = SCTP_INP_SO(stcb->sctp_ep); + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_SOCKET_LOCK(so, 1); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { + SCTP_SOCKET_UNLOCK(so, 1); + return; + } +#endif if (nxt_todel == control->sinfo_ssn) { /* can be delivered right away? */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { @@ -617,7 +631,7 @@ protocol_error: sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, - SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); + SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED); TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) { /* all delivered */ nxt_todel = strm->last_sequence_delivered + 1; @@ -641,7 +655,7 @@ protocol_error: control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, - SCTP_SO_NOT_LOCKED); + SCTP_SO_LOCKED); continue; } break; @@ -653,6 +667,9 @@ protocol_error: * to put it on the queue. */ if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif goto protocol_error; } if (TAILQ_EMPTY(&strm->inqueue)) { @@ -699,6 +716,9 @@ protocol_error: control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif return; } else { if (TAILQ_NEXT(at, next) == NULL) { @@ -718,6 +738,9 @@ protocol_error: } } } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif } /* @@ -1403,30 +1426,25 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } strmno = ntohs(ch->dp.stream_id); if (strmno >= asoc->streamincnt) { - struct sctp_paramhdr *phdr; - struct mbuf *mb; + struct sctp_error_invalid_stream *cause; - mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream), 0, M_NOWAIT, 1, MT_DATA); - if (mb != NULL) { + if (op_err != NULL) { /* add some space up front so prepend will work well */ - SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr)); - phdr = mtod(mb, struct sctp_paramhdr *); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + cause = mtod(op_err, struct sctp_error_invalid_stream *); /* * Error causes are just param's and this one has * two back to back phdr, one with the error type * and size, the other with the streamid and a rsvd */ - SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2); - phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM); - phdr->param_length = - htons(sizeof(struct sctp_paramhdr) * 2); - phdr++; - /* We insert the stream in the type field */ - phdr->param_type = ch->dp.stream_id; - /* And set the length to 0 for the rsvd field */ - phdr->param_length = 0; - sctp_queue_op_err(stcb, mb); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream); + cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM); + cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream)); + cause->stream_id = ch->dp.stream_id; + cause->reserved = htons(0); + sctp_queue_op_err(stcb, op_err); } SCTP_STAT_INCR(sctps_badsid); SCTP_TCB_LOCK_ASSERT(stcb); @@ -1886,6 +1904,7 @@ finish_express_del: sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams); TAILQ_REMOVE(&asoc->resetHead, liste, next_resp); + sctp_send_deferred_reset_response(stcb, liste, SCTP_STREAM_RESET_RESULT_PERFORMED); SCTP_FREE(liste, SCTP_M_STRESET); /* sa_ignore FREED_MEMORY */ liste = TAILQ_FIRST(&asoc->resetHead); @@ -2288,11 +2307,8 @@ doit_again: int sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, - struct sockaddr *src, struct sockaddr *dst, - struct sctphdr *sh, struct sctp_inpcb *inp, - struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t * high_tsn, - uint8_t mflowtype, uint32_t mflowid, - uint32_t vrf_id, uint16_t port) + struct sctp_inpcb *inp, struct sctp_tcb *stcb, + struct sctp_nets *net, uint32_t * high_tsn) { struct sctp_data_chunk *ch, chunk_buf; struct sctp_association *asoc; @@ -2384,10 +2400,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, chk_length); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21; - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, - mflowtype, mflowid, - vrf_id, port); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) { @@ -2399,10 +2412,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, op_err = sctp_generate_no_user_data_cause(ch->dp.tsn); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22; - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, - mflowtype, mflowid, - vrf_id, port); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } #ifdef SCTP_AUDITING_ENABLED @@ -2464,14 +2474,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, */ if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) { struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, ""); - sctp_abort_association(inp, stcb, - m, iphlen, - src, dst, - sh, op_err, - mflowtype, mflowid, - vrf_id, port); + snprintf(msg, sizeof(msg), "DATA chunk followed by chunk of type %2.2x", + ch->ch.chunk_type); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } break; @@ -2479,34 +2487,21 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, /* unknown chunk type, use bit rules */ if (ch->ch.chunk_type & 0x40) { /* Add a error report to the queue */ - struct mbuf *merr; - struct sctp_paramhdr *phd; - - merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA); - if (merr) { - phd = mtod(merr, struct sctp_paramhdr *); - /* - * We cheat and use param - * type since we did not - * bother to define a error - * cause struct. They are - * the same basic format - * with different names. - */ - phd->param_type = - htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = - htons(chk_length + sizeof(*phd)); - SCTP_BUF_LEN(merr) = sizeof(*phd); - SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); - if (SCTP_BUF_NEXT(merr)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { - sctp_m_freem(merr); - } else { - sctp_queue_op_err(stcb, merr); - } + struct mbuf *op_err; + struct sctp_gen_error_cause *cause; + + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), + 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(merr); + sctp_m_freem(op_err); } } } @@ -2768,6 +2763,11 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); #endif } + if ((stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (stcb->asoc.strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&stcb->asoc.strmout[tp1->rec.data.stream_number].outqueue)) { + stcb->asoc.trigger_reset = 1; + } tp1->sent = SCTP_DATAGRAM_NR_ACKED; if (tp1->data) { /* @@ -3741,6 +3741,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, #endif } } + if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); if (tp1->data) { /* sa_ignore NO_NULL_CHK */ @@ -3989,6 +3994,7 @@ again: op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_26; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); + return; } else { struct sctp_nets *netp; @@ -4466,6 +4472,11 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, #endif } } + if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); if (PR_SCTP_ENABLED(tp1->flags)) { if (asoc->pr_sctp_cnt != 0) diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h index 79a86e2..94cd49c 100644 --- a/sys/netinet/sctp_indata.h +++ b/sys/netinet/sctp_indata.h @@ -112,12 +112,8 @@ void int sctp_process_data(struct mbuf **, int, int *, int, - struct sockaddr *src, struct sockaddr *dst, - struct sctphdr *, struct sctp_inpcb *, struct sctp_tcb *, - struct sctp_nets *, uint32_t *, - uint8_t, uint32_t, - uint32_t, uint16_t); + struct sctp_nets *, uint32_t *); void sctp_slide_mapping_arrays(struct sctp_tcb *stcb); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 0986293..3b50590 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -357,14 +357,17 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); /* sa_ignore FREED_MEMORY */ } + outs->state = SCTP_STREAM_CLOSED; } } /* cut back the count */ asoc->pre_open_streams = newcnt; } SCTP_TCB_SEND_UNLOCK(stcb); - asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; - + asoc->streamoutcnt = asoc->pre_open_streams; + for (i = 0; i < asoc->streamoutcnt; i++) { + asoc->strmout[i].state = SCTP_STREAM_OPEN; + } /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { @@ -518,7 +521,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, /* calculate the RTO */ net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, SCTP_RTT_FROM_NON_DATA); - retval = sctp_send_cookie_echo(m, offset, stcb, net); if (retval < 0) { /* @@ -527,25 +529,21 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, * abandon the peer, its broke. */ if (retval == -3) { + uint16_t len; + + len = (uint16_t) (sizeof(struct sctp_error_missing_param) + sizeof(uint16_t)); /* We abort with an error of missing mandatory param */ - op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); - if (op_err) { - /* - * Expand beyond to include the mandatory - * param cookie - */ - struct sctp_inv_mandatory_param *mp; + op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + struct sctp_error_missing_param *cause; - SCTP_BUF_LEN(op_err) = - sizeof(struct sctp_inv_mandatory_param); - mp = mtod(op_err, - struct sctp_inv_mandatory_param *); + SCTP_BUF_LEN(op_err) = len; + cause = mtod(op_err, struct sctp_error_missing_param *); /* Subtract the reserved param */ - mp->length = - htons(sizeof(struct sctp_inv_mandatory_param) - 2); - mp->num_param = htonl(1); - mp->param = htons(SCTP_STATE_COOKIE); - mp->resv = 0; + cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM); + cause->cause.length = htons(len); + cause->num_missing_params = htonl(1); + cause->type[0] = htons(SCTP_STATE_COOKIE); } sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, @@ -778,10 +776,10 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, * Need to check the cause codes for our two magic nat * aborts which don't kill the assoc necessarily. */ - struct sctp_missing_nat_state *natc; + struct sctp_gen_error_cause *cause; - natc = (struct sctp_missing_nat_state *)(abort + 1); - error = ntohs(natc->cause); + cause = (struct sctp_gen_error_cause *)(abort + 1); + error = ntohs(cause->code); if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", abort->ch.chunk_flags); @@ -864,6 +862,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, { struct sctp_association *asoc; int some_on_streamwheel; + int old_state; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -882,11 +881,11 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { /* Shutdown NOT the expected size */ return; - } else { - sctp_update_acked(stcb, cp, abort_flag); - if (*abort_flag) { - return; - } + } + old_state = SCTP_GET_STATE(asoc); + sctp_update_acked(stcb, cp, abort_flag); + if (*abort_flag) { + return; } if (asoc->control_pdapi) { /* @@ -956,12 +955,16 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_stop_timers_for_shutdown(stcb); - sctp_send_shutdown_ack(stcb, net); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, - stcb, net); + if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); + sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown_ack(stcb, net); + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, + stcb->sctp_ep, stcb, net); + } else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) { + sctp_send_shutdown_ack(stcb, net); + } } } @@ -2100,6 +2103,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, */ stcb = sctp_aloc_assoc(inp, init_src, &error, ntohl(initack_cp->init.initiate_tag), vrf_id, + ntohs(initack_cp->init.num_outbound_streams), (struct thread *)NULL ); if (stcb == NULL) { @@ -2343,12 +2347,17 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); } (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); - if ((netp) && (*netp)) { + if ((netp != NULL) && (*netp != NULL)) { /* calculate the RTT and set the encaps port */ (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, &cookie->time_entered, sctp_align_unsafe_makecopy, SCTP_RTT_FROM_NON_DATA); +#if defined(INET) || defined(INET6) + if (((*netp)->port == 0) && (port != 0)) { + sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr)); + } (*netp)->port = port; +#endif } /* respond with a COOKIE-ACK */ sctp_send_cookie_ack(stcb); @@ -2431,8 +2440,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, cookie_offset = offset + sizeof(struct sctp_chunkhdr); cookie_len = ntohs(cp->ch.chunk_length); - if ((cookie->peerport != sh->src_port) && - (cookie->myport != sh->dest_port) && + if ((cookie->peerport != sh->src_port) || + (cookie->myport != sh->dest_port) || (cookie->my_vtag != sh->v_tag)) { /* * invalid ports or bad tag. Note that we always leave the @@ -2550,27 +2559,27 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, if (timevalcmp(&now, &time_expires, >)) { /* cookie is stale! */ struct mbuf *op_err; - struct sctp_stale_cookie_msg *scm; + struct sctp_error_stale_cookie *cause; uint32_t tim; - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie), 0, M_NOWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); } /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); - scm = mtod(op_err, struct sctp_stale_cookie_msg *); - scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); - scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie); + cause = mtod(op_err, struct sctp_error_stale_cookie *); + cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE); + cause->cause.length = htons((sizeof(struct sctp_paramhdr) + (sizeof(uint32_t)))); /* seconds to usec */ tim = (now.tv_sec - time_expires.tv_sec) * 1000000; /* add in usec */ if (tim == 0) tim = now.tv_usec - cookie->time_entered.tv_usec; - scm->time_usec = htonl(tim); + cause->stale_time = htonl(tim); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, mflowtype, mflowid, l_inp->fibnum, vrf_id, port); @@ -3506,6 +3515,28 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); } +static void +sctp_reset_clear_pending(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) +{ + uint32_t i; + uint16_t temp; + + if (number_entries > 0) { + for (i = 0; i < number_entries; i++) { + temp = ntohs(list[i]); + if (temp >= stcb->asoc.streamoutcnt) { + /* no such stream */ + continue; + } + stcb->asoc.strmout[temp].state = SCTP_STREAM_OPEN; + } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].state = SCTP_STREAM_OPEN; + } + } +} + struct sctp_stream_reset_request * sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) @@ -3604,6 +3635,8 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, type = ntohs(req_param->ph.param_type); lparm_len = ntohs(req_param->ph.param_length); if (type == SCTP_STR_RESET_OUT_REQUEST) { + int no_clear = 0; + req_out_param = (struct sctp_stream_reset_out_request *)req_param; number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); asoc->stream_reset_out_is_outstanding = 0; @@ -3614,9 +3647,21 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams); } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); + } else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) { + /* + * Set it up so we don't stop + * retransmitting + */ + asoc->stream_reset_outstanding++; + stcb->asoc.str_reset_seq_out--; + asoc->stream_reset_out_is_outstanding = 1; + no_clear = 1; } else { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); } + if (no_clear == 0) { + sctp_reset_clear_pending(stcb, number_entries, req_out_param->list_of_streams); + } } else if (type == SCTP_STR_RESET_IN_REQUEST) { req_in_param = (struct sctp_stream_reset_in_request *)req_param; number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); @@ -3643,7 +3688,12 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, asoc->stream_reset_outstanding--; if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { /* Put the new streams into effect */ - stcb->asoc.streamoutcnt += num_stream; + int i; + + for (i = asoc->streamoutcnt; i < (asoc->streamoutcnt + num_stream); i++) { + asoc->strmout[i].state = SCTP_STREAM_OPEN; + } + asoc->streamoutcnt += num_stream; sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, @@ -3720,6 +3770,9 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, } } } + if (asoc->stream_reset_outstanding == 0) { + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); + } return (0); } @@ -3750,22 +3803,33 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { len = ntohs(req->ph.param_length); number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); - for (i = 0; i < number_entries; i++) { - temp = ntohs(req->list_of_streams[i]); - req->list_of_streams[i] = temp; + if (number_entries) { + for (i = 0; i < number_entries; i++) { + temp = ntohs(req->list_of_streams[i]); + if (temp >= stcb->asoc.streamoutcnt) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + goto bad_boy; + } + req->list_of_streams[i] = temp; + } + for (i = 0; i < number_entries; i++) { + if (stcb->asoc.strmout[req->list_of_streams[i]].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[req->list_of_streams[i]].state = SCTP_STREAM_RESET_PENDING; + } + } + } else { + /* Its all */ + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; + } } asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; - sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, - asoc->str_reset_seq_out, - seq, (asoc->sending_seq - 1)); - asoc->stream_reset_out_is_outstanding = 1; - asoc->str_reset = chk; - sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); - stcb->asoc.stream_reset_outstanding++; } else { /* Can't do it, since we have sent one out */ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; } +bad_boy: sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; } else if (asoc->str_reset_seq_in - 1 == seq) { @@ -3775,6 +3839,7 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, } else { sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); } static int @@ -3893,11 +3958,12 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb, sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); return; } + liste->seq = seq; liste->tsn = tsn; liste->number_entries = number_entries; memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); - asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_IN_PROGRESS; } sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; @@ -4034,7 +4100,7 @@ sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk mychk += num_stream; if (mychk < 0x10000) { stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; - if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { + if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, num_stream, 0, 1)) { stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } } else { @@ -4565,7 +4631,7 @@ __attribute__((noinline)) } } if (stcb == NULL) { - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); /* no association, so it's out of the blue... */ @@ -4609,7 +4675,7 @@ __attribute__((noinline)) if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); } - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, *offset, src, dst, @@ -4755,13 +4821,11 @@ process_control_chunks: /* The INIT chunk must be the only chunk. */ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { - op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), - "INIT not the only chunk"); - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, - mflowtype, mflowid, - vrf_id, port); + /* RFC 4960 requires that no ABORT is sent */ *offset = length; + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } /* Honor our resource limit. */ @@ -5519,39 +5583,27 @@ process_control_chunks: unknown_chunk: /* it's an unknown chunk! */ if ((ch->chunk_type & 0x40) && (stcb != NULL)) { - struct mbuf *mm; - struct sctp_paramhdr *phd; + struct sctp_gen_error_cause *cause; int len; - mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), 0, M_NOWAIT, 1, MT_DATA); - if (mm) { + if (op_err != NULL) { len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset)); - phd = mtod(mm, struct sctp_paramhdr *); - /* - * We cheat and use param type since - * we did not bother to define a - * error cause struct. They are the - * same basic format with different - * names. - */ - phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = htons(len + sizeof(*phd)); - SCTP_BUF_LEN(mm) = sizeof(*phd); - SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); - if (SCTP_BUF_NEXT(mm)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(len) - len, NULL) == NULL) { - sctp_m_freem(mm); - } else { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(len + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { #ifdef SCTP_MBUF_LOGGING - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { - sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY); - } -#endif - sctp_queue_op_err(stcb, mm); + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { + sctp_log_mbc(SCTP_BUF_NEXT(op_err), SCTP_MBUF_ICOPY); } +#endif + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(mm); + sctp_m_freem(op_err); } } } @@ -5589,30 +5641,6 @@ next_chunk: } -#ifdef INVARIANTS -#ifdef __GNUC__ -__attribute__((noinline)) -#endif - void - sctp_validate_no_locks(struct sctp_inpcb *inp) -{ - struct sctp_tcb *lstcb; - - LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { - if (mtx_owned(&lstcb->tcb_mtx)) { - panic("Own lock on stcb at return from input"); - } - } - if (mtx_owned(&inp->inp_create_mtx)) { - panic("Own create lock on inp"); - } - if (mtx_owned(&inp->inp_mtx)) { - panic("Own inp lock on inp"); - } -} - -#endif - /* * common input chunk processing (v4 and v6) */ @@ -5775,7 +5803,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ SCTP_TCB_UNLOCK(stcb); stcb = NULL; - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, @@ -5799,7 +5827,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ inp = stcb->sctp_ep; #if defined(INET) || defined(INET6) - if ((net) && (port)) { + if ((net != NULL) && (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } @@ -5827,7 +5855,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } if (stcb == NULL) { /* out of the blue DATA chunk */ - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, @@ -5899,7 +5927,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt /* * We consider OOTB any data sent during asoc setup. */ - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, @@ -5922,10 +5950,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } /* plow through the data chunks while length > offset */ retval = sctp_process_data(mm, iphlen, &offset, length, - src, dst, sh, - inp, stcb, net, &high_tsn, - mflowtype, mflowid, - vrf_id, port); + inp, stcb, net, &high_tsn); if (retval == 2) { /* * The association aborted, NO UNLOCK needed since @@ -5977,7 +6002,7 @@ trigger_send: if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; } - if (cnt_ctrl_ready || + if (cnt_ctrl_ready || stcb->asoc.trigger_reset || ((un_sent) && (stcb->asoc.peers_rwnd > 0 || (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { @@ -5999,11 +6024,6 @@ out: SCTP_INP_DECR_REF(inp_decr); SCTP_INP_WUNLOCK(inp_decr); } -#ifdef INVARIANTS - if (inp != NULL) { - sctp_validate_no_locks(inp); - } -#endif return; } diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 7ae332a..88ad978 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -95,7 +95,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_pcb.h> -#include <netinet/icmp6.h> #include <netinet6/ip6protosw.h> #include <netinet6/nd6.h> #include <netinet6/scope6_var.h> diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 0cdeb94..5328f49 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -2417,7 +2417,7 @@ sctp_is_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if (laddr->ifa == ifa) { @@ -2439,7 +2439,7 @@ sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if ((laddr->ifa == ifa) && laddr->action == 0) @@ -3652,6 +3652,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er #endif stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; + stcb->asoc.strmout[i].state = SCTP_STREAM_OPENING; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); } } @@ -5524,7 +5525,7 @@ do_a_abort: if (op_err == NULL) { char msg[SCTP_DIAG_INFO_LEN]; - snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); } @@ -5841,10 +5842,10 @@ do_a_abort: his_limit = ntohs(init_chk->init.num_inbound_streams); /* choose what I want */ if (asoc != NULL) { - if (asoc->streamoutcnt > inp->sctp_ep.pre_open_stream_count) { + if (asoc->streamoutcnt > asoc->pre_open_streams) { i_want = asoc->streamoutcnt; } else { - i_want = inp->sctp_ep.pre_open_stream_count; + i_want = asoc->pre_open_streams; } } else { i_want = inp->sctp_ep.pre_open_stream_count; @@ -6682,10 +6683,17 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + abort_anyway: + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); atomic_add_int(&stcb->asoc.refcnt, 1); sctp_abort_an_association(stcb->sctp_ep, stcb, - NULL, SCTP_SO_NOT_LOCKED); + op_err, SCTP_SO_NOT_LOCKED); atomic_add_int(&stcb->asoc.refcnt, -1); goto no_chunk_output; } @@ -7162,6 +7170,11 @@ one_more_time: } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); + if ((strq->state == SCTP_STREAM_RESET_PENDING) && + (strq->chunks_on_queues == 0) && + TAILQ_EMPTY(&strq->outqueue)) { + stcb->asoc.trigger_reset = 1; + } stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up); if (sp->net) { sctp_free_remote_addr(sp->net); @@ -7206,7 +7219,7 @@ one_more_time: } /* Whack down the size */ atomic_subtract_int(&stcb->asoc.total_output_queue_size, sp->length); - if ((stcb->sctp_socket != NULL) && \ + if ((stcb->sctp_socket != NULL) && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc, sp->length); @@ -7225,9 +7238,6 @@ one_more_time: } } some_taken = sp->some_taken; - if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { - sp->msg_is_complete = 1; - } re_look: length = sp->length; if (sp->msg_is_complete) { @@ -7560,6 +7570,11 @@ dont_do_it: send_lock_up = 1; } TAILQ_REMOVE(&strq->outqueue, sp, next); + if ((strq->state == SCTP_STREAM_RESET_PENDING) && + (strq->chunks_on_queues == 0) && + TAILQ_EMPTY(&strq->outqueue)) { + stcb->asoc.trigger_reset = 1; + } stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up); if (sp->net) { sctp_free_remote_addr(sp->net); @@ -7787,7 +7802,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, #endif SCTP_TCB_LOCK_ASSERT(stcb); hbflag = 0; - if ((control_only) || (asoc->stream_reset_outstanding)) + if (control_only) no_data_chunks = 1; else no_data_chunks = 0; @@ -8851,9 +8866,37 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) */ struct sctp_chunkhdr *hdr; struct sctp_tmit_chunk *chk; - struct mbuf *mat; + struct mbuf *mat, *last_mbuf; + uint32_t chunk_length; + uint16_t padding_length; SCTP_TCB_LOCK_ASSERT(stcb); + SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT); + if (op_err == NULL) { + return; + } + last_mbuf = NULL; + chunk_length = 0; + for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) { + chunk_length += SCTP_BUF_LEN(mat); + if (SCTP_BUF_NEXT(mat) == NULL) { + last_mbuf = mat; + } + } + if (chunk_length > SCTP_MAX_CHUNK_LENGTH) { + sctp_m_freem(op_err); + return; + } + padding_length = chunk_length % 4; + if (padding_length != 0) { + padding_length = 4 - padding_length; + } + if (padding_length != 0) { + if (sctp_add_pad_tombuf(last_mbuf, padding_length) == NULL) { + sctp_m_freem(op_err); + return; + } + } sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { /* no memory */ @@ -8861,15 +8904,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) return; } chk->copy_by_ref = 0; - SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT); - if (op_err == NULL) { - sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); - return; - } - chk->send_size = 0; - for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) { - chk->send_size += SCTP_BUF_LEN(mat); - } + chk->send_size = (uint16_t) chunk_length; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->asoc = &stcb->asoc; @@ -8879,9 +8914,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) hdr->chunk_type = SCTP_OPERATION_ERROR; hdr->chunk_flags = 0; hdr->chunk_length = htons(chk->send_size); - TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, - chk, - sctp_next); + TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next); chk->asoc->ctrl_queue_cnt++; } @@ -9462,12 +9495,16 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, } if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) && (chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) { - /* Gak, we have exceeded max unlucky retran, abort! */ - SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n", - chk->snd_count, - SCTP_BASE_SYSCTL(sctp_max_retran_chunk)); + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + + snprintf(msg, sizeof(msg), "TSN %8.8x retransmitted %d times, giving up", + chk->rec.data.TSN_seq, chk->snd_count); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); atomic_add_int(&stcb->asoc.refcnt, 1); - sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, so_locked); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, + so_locked); SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); return (SCTP_RETRAN_EXIT); @@ -9872,6 +9909,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, unsigned int tot_frs = 0; asoc = &stcb->asoc; +do_it_again: /* The Nagle algorithm is only applied when handling a send call. */ if (from_where == SCTP_OUTPUT_FROM_USR_SEND) { if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY)) { @@ -9889,7 +9927,8 @@ sctp_chunk_output(struct sctp_inpcb *inp, if ((un_sent <= 0) && (TAILQ_EMPTY(&asoc->control_send_queue)) && (TAILQ_EMPTY(&asoc->asconf_send_queue)) && - (asoc->sent_queue_retran_cnt == 0)) { + (asoc->sent_queue_retran_cnt == 0) && + (asoc->trigger_reset == 0)) { /* Nothing to do unless there is something to be sent left */ return; } @@ -10108,6 +10147,12 @@ sctp_chunk_output(struct sctp_inpcb *inp, */ if (stcb->asoc.ecn_echo_cnt_onq) sctp_fix_ecn_echo(asoc); + + if (stcb->asoc.trigger_reset) { + if (sctp_send_stream_reset_out_if_possible(stcb, so_locked) == 0) { + goto do_it_again; + } + } return; } @@ -11224,6 +11269,11 @@ sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked break; #endif default: + if (chk->data) { + sctp_m_freem(chk->data); + chk->data = NULL; + } + sctp_free_a_chunk(stcb, chk, so_locked); return; break; } @@ -11510,30 +11560,60 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u asoc->ctrl_queue_cnt++; } -void -sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, - int number_entries, uint16_t * list, +static int +sctp_add_stream_reset_out(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, uint32_t seq, uint32_t resp_seq, uint32_t last_sent) { uint16_t len, old_len, i; struct sctp_stream_reset_out_request *req_out; struct sctp_chunkhdr *ch; + int at; + int number_entries = 0; ch = mtod(chk->data, struct sctp_chunkhdr *); old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length)); - /* get to new offset for the param. */ req_out = (struct sctp_stream_reset_out_request *)((caddr_t)ch + len); /* now how long will this param be? */ + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) && + (stcb->asoc.strmout[i].chunks_on_queues == 0) && + TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + number_entries++; + } + } + if (number_entries == 0) { + return (0); + } + if (number_entries == stcb->asoc.streamoutcnt) { + number_entries = 0; + } + if (number_entries > SCTP_MAX_STREAMS_AT_ONCE_RESET) { + number_entries = SCTP_MAX_STREAMS_AT_ONCE_RESET; + } len = (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries)); req_out->ph.param_type = htons(SCTP_STR_RESET_OUT_REQUEST); req_out->ph.param_length = htons(len); req_out->request_seq = htonl(seq); req_out->response_seq = htonl(resp_seq); req_out->send_reset_at_tsn = htonl(last_sent); + at = 0; if (number_entries) { - for (i = 0; i < number_entries; i++) { - req_out->list_of_streams[i] = htons(list[i]); + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) && + (stcb->asoc.strmout[i].chunks_on_queues == 0) && + TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + req_out->list_of_streams[at] = htons(i); + at++; + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT; + if (at >= number_entries) { + break; + } + } + } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT; } } if (SCTP_SIZE32(len) > len) { @@ -11550,7 +11630,7 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, chk->book_size_scale = 0; chk->send_size = SCTP_SIZE32(chk->book_size); SCTP_BUF_LEN(chk->data) = chk->send_size; - return; + return (1); } static void @@ -11652,6 +11732,68 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk, } void +sctp_send_deferred_reset_response(struct sctp_tcb *stcb, + struct sctp_stream_reset_list *ent, + int response) +{ + struct sctp_association *asoc; + struct sctp_tmit_chunk *chk; + struct sctp_chunkhdr *ch; + + asoc = &stcb->asoc; + + /* + * Reset our last reset action to the new one IP -> response + * (PERFORMED probably). This assures that if we fail to send, a + * retran from the peer will get the new response. + */ + asoc->last_reset_action[0] = response; + if (asoc->stream_reset_outstanding) { + return; + } + sctp_alloc_a_chunk(stcb, chk); + if (chk == NULL) { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return; + } + chk->copy_by_ref = 0; + chk->rec.chunk_id.id = SCTP_STREAM_RESET; + chk->rec.chunk_id.can_take_data = 0; + chk->flags = 0; + chk->asoc = &stcb->asoc; + chk->book_size = sizeof(struct sctp_chunkhdr); + chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + if (chk->data == NULL) { + sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED); + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return; + } + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + sctp_add_stream_reset_result(chk, ent->seq, response); + /* setup chunk parameters */ + chk->sent = SCTP_DATAGRAM_UNSENT; + chk->snd_count = 0; + if (stcb->asoc.alternate) { + chk->whoTo = stcb->asoc.alternate; + } else { + chk->whoTo = stcb->asoc.primary_destination; + } + ch = mtod(chk->data, struct sctp_chunkhdr *); + ch->chunk_type = SCTP_STREAM_RESET; + ch->chunk_flags = 0; + ch->chunk_length = htons(chk->book_size); + atomic_add_int(&chk->whoTo->ref_count, 1); + SCTP_BUF_LEN(chk->data) = chk->send_size; + /* insert the chunk for sending */ + TAILQ_INSERT_TAIL(&asoc->control_send_queue, + chk, + sctp_next); + asoc->ctrl_queue_cnt++; +} + +void sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk, uint32_t resp_seq, uint32_t result, uint32_t send_una, uint32_t recv_next) @@ -11749,19 +11891,90 @@ sctp_add_an_in_stream(struct sctp_tmit_chunk *chk, } int +sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb, int so_locked) +{ + struct sctp_association *asoc; + struct sctp_tmit_chunk *chk; + struct sctp_chunkhdr *ch; + uint32_t seq; + + asoc = &stcb->asoc; + asoc->trigger_reset = 0; + if (asoc->stream_reset_outstanding) { + return (EALREADY); + } + sctp_alloc_a_chunk(stcb, chk); + if (chk == NULL) { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + chk->copy_by_ref = 0; + chk->rec.chunk_id.id = SCTP_STREAM_RESET; + chk->rec.chunk_id.can_take_data = 0; + chk->flags = 0; + chk->asoc = &stcb->asoc; + chk->book_size = sizeof(struct sctp_chunkhdr); + chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + if (chk->data == NULL) { + sctp_free_a_chunk(stcb, chk, so_locked); + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + + /* setup chunk parameters */ + chk->sent = SCTP_DATAGRAM_UNSENT; + chk->snd_count = 0; + if (stcb->asoc.alternate) { + chk->whoTo = stcb->asoc.alternate; + } else { + chk->whoTo = stcb->asoc.primary_destination; + } + ch = mtod(chk->data, struct sctp_chunkhdr *); + ch->chunk_type = SCTP_STREAM_RESET; + ch->chunk_flags = 0; + ch->chunk_length = htons(chk->book_size); + atomic_add_int(&chk->whoTo->ref_count, 1); + SCTP_BUF_LEN(chk->data) = chk->send_size; + seq = stcb->asoc.str_reset_seq_out; + if (sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1))) { + seq++; + asoc->stream_reset_outstanding++; + } else { + m_freem(chk->data); + chk->data = NULL; + sctp_free_a_chunk(stcb, chk, so_locked); + return (ENOENT); + } + asoc->str_reset = chk; + /* insert the chunk for sending */ + TAILQ_INSERT_TAIL(&asoc->control_send_queue, + chk, + sctp_next); + asoc->ctrl_queue_cnt++; + + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, so_locked); + } + sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); + return (0); +} + +int sctp_send_str_reset_req(struct sctp_tcb *stcb, uint16_t number_entries, uint16_t * list, - uint8_t send_out_req, uint8_t send_in_req, uint8_t send_tsn_req, uint8_t add_stream, uint16_t adding_o, uint16_t adding_i, uint8_t peer_asked) { - struct sctp_association *asoc; struct sctp_tmit_chunk *chk; struct sctp_chunkhdr *ch; + int can_send_out_req = 0; uint32_t seq; asoc = &stcb->asoc; @@ -11772,16 +11985,18 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EBUSY); return (EBUSY); } - if ((send_out_req == 0) && (send_in_req == 0) && (send_tsn_req == 0) && + if ((send_in_req == 0) && (send_tsn_req == 0) && (add_stream == 0)) { /* nothing to do */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } - if (send_tsn_req && (send_out_req || send_in_req)) { + if (send_tsn_req && send_in_req) { /* error, can't do that */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); + } else if (send_in_req) { + can_send_out_req = 1; } if (number_entries > (MCLBYTES - SCTP_MIN_OVERHEAD - @@ -11829,12 +12044,14 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, SCTP_BUF_LEN(chk->data) = chk->send_size; seq = stcb->asoc.str_reset_seq_out; - if (send_out_req) { - sctp_add_stream_reset_out(chk, number_entries, list, - seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); - asoc->stream_reset_out_is_outstanding = 1; - seq++; - asoc->stream_reset_outstanding++; + if (can_send_out_req) { + int ret; + + ret = sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); + if (ret) { + seq++; + asoc->stream_reset_outstanding++; + } } if ((add_stream & 1) && ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < adding_o)) { @@ -11851,7 +12068,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, oldstream = stcb->asoc.strmout; /* get some more */ SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *, - ((stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out)), + (stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out), SCTP_M_STRMO); if (stcb->asoc.strmout == NULL) { uint8_t x; @@ -11874,6 +12091,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send; stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete; stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].state = oldstream[i].state; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]); /* now anything on those queues? */ TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) { @@ -11906,6 +12124,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); + stcb->asoc.strmout[i].state = SCTP_STREAM_CLOSED; } stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o; SCTP_FREE(oldstream, SCTP_M_STRMO); @@ -11939,6 +12158,9 @@ skip_stuff: chk, sctp_next); asoc->ctrl_queue_cnt++; + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, SCTP_SO_LOCKED); + } sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); return (0); } @@ -12393,6 +12615,7 @@ sctp_lower_sosend(struct socket *so, } #endif stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, + inp->sctp_ep.pre_open_stream_count, p ); if (stcb == NULL) { @@ -12515,12 +12738,24 @@ sctp_lower_sosend(struct socket *so, SCTP_ASOC_CREATE_UNLOCK(inp); create_lock_applied = 0; } - if (asoc->stream_reset_outstanding) { + /* Is the stream no. valid? */ + if (srcv->sinfo_stream >= asoc->streamoutcnt) { + /* Invalid stream number */ + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; + } + if ((asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPEN) && + (asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPENING)) { /* * Can't queue any data while stream reset is underway. */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN); - error = EAGAIN; + if (asoc->strmout[srcv->sinfo_stream].state > SCTP_STREAM_OPEN) { + error = EAGAIN; + } else { + error = EINVAL; + } + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error); goto out_unlocked; } if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || @@ -12659,13 +12894,6 @@ sctp_lower_sosend(struct socket *so, SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } - /* Is the stream no. valid? */ - if (srcv->sinfo_stream >= asoc->streamoutcnt) { - /* Invalid stream number */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } if (asoc->strmout == NULL) { /* huh? software error */ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT); @@ -12961,7 +13189,7 @@ skip_preblock: /*- * Ok, Nagle is set on and we have data outstanding. * Don't send anything and let SACKs drive out the - * data unless wen have a "full" segment to send. + * data unless we have a "full" segment to send. */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_NAGLE_LOGGING_ENABLE) { sctp_log_nagle_event(stcb, SCTP_NAGLE_APPLIED); @@ -13170,13 +13398,20 @@ dataless_eof: if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + abort_anyway: if (free_cnt_applied) { atomic_add_int(&stcb->asoc.refcnt, -1); free_cnt_applied = 0; } + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb->sctp_ep, stcb, - NULL, SCTP_SO_LOCKED); + op_err, SCTP_SO_LOCKED); /* * now relock the stcb so everything * is sane @@ -13316,13 +13551,6 @@ out_unlocked: } } #endif -#ifdef INVARIANTS - if (inp) { - sctp_validate_no_locks(inp); - } else { - SCTP_PRINTF("Warning - inp is NULL so cant validate locks\n"); - } -#endif if (top) { sctp_m_freem(top); } diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index 8e45e5c..d7222c4 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -170,18 +170,21 @@ void sctp_send_cwr(struct sctp_tcb *, struct sctp_nets *, uint32_t, uint8_t); void -sctp_add_stream_reset_out(struct sctp_tmit_chunk *, - int, uint16_t *, uint32_t, uint32_t, uint32_t); + sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t); void - sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t); +sctp_send_deferred_reset_response(struct sctp_tcb *, + struct sctp_stream_reset_list *, + int); void sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *, uint32_t, uint32_t, uint32_t, uint32_t); +int + sctp_send_stream_reset_out_if_possible(struct sctp_tcb *, int); int -sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t, +sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t); void diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 344cdfc..39872e4 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -1115,7 +1115,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { - SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__); + SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __func__); continue; } if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { @@ -1773,7 +1773,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ", @@ -2269,8 +2269,12 @@ sctp_findassociation_addr(struct mbuf *m, int offset, } } find_tcp_pool = 0; - if ((ch->chunk_type != SCTP_INITIATION) && - (ch->chunk_type != SCTP_INITIATION_ACK) && + /* + * Don't consider INIT chunks since that breaks 1-to-1 sockets: When + * a server closes the listener, incoming INIT chunks are not + * responsed by an INIT-ACK chunk. + */ + if ((ch->chunk_type != SCTP_INITIATION_ACK) && (ch->chunk_type != SCTP_COOKIE_ACK) && (ch->chunk_type != SCTP_COOKIE_ECHO)) { /* Other chunk types go to the tcp pool. */ @@ -2343,7 +2347,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &parm_buf, sizeof(struct sctp_paramhdr)); if (phdr == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n", - __FUNCTION__); + __func__); return NULL; } ptype = (int)((uint32_t) ntohs(phdr->param_type)); @@ -2363,7 +2367,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &p6_buf.ph, sizeof(*p6)); if (p6 == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", - __FUNCTION__); + __func__); return (NULL); } sin6 = &remote_store.sin6; @@ -2390,7 +2394,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &p4_buf.ph, sizeof(*p4)); if (p4 == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", - __FUNCTION__); + __func__); return (NULL); } sin = &remote_store.sin; @@ -2499,14 +2503,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) return (ENOBUFS); } #ifdef IPSEC - { - struct inpcbpolicy *pcb_sp = NULL; - - error = ipsec_init_policy(so, &pcb_sp); - /* Arrange to share the policy */ - inp->ip_inp.inp.inp_sp = pcb_sp; - ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp; - } + error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp); if (error != 0) { crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); @@ -2540,6 +2537,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); so->so_pcb = NULL; crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); } @@ -2560,6 +2560,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); so->so_pcb = NULL; crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); } @@ -3644,13 +3647,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) * macro here since le_next will get freed as part of the * sctp_free_assoc() call. */ - if (so) { #ifdef IPSEC - ipsec_delete_pcbpolicy(ip_pcb); -#endif /* IPSEC */ - - /* Unlocks not needed since the socket is gone now */ - } + ipsec_delete_pcbpolicy(ip_pcb); +#endif if (ip_pcb->inp_options) { (void)sctp_m_free(ip_pcb->inp_options); ip_pcb->inp_options = 0; @@ -4169,6 +4168,7 @@ try_again: struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, int *error, uint32_t override_tag, uint32_t vrf_id, + uint16_t o_streams, struct thread *p ) { @@ -4327,7 +4327,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, /* setup back pointer's */ stcb->sctp_ep = inp; stcb->sctp_socket = inp->sctp_socket; - if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id))) { + if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id, o_streams))) { /* failed */ SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); @@ -5304,7 +5304,7 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { @@ -6254,12 +6254,20 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, */ if (stcb_tmp) { if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + /* * in setup state we * abort this guy */ + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb_tmp->sctp_ep, - stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); + stcb_tmp, op_err, + SCTP_SO_NOT_LOCKED); goto add_it_now; } SCTP_TCB_UNLOCK(stcb_tmp); @@ -6343,18 +6351,26 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, * strange, address is in another * assoc? straighten out locks. */ - if (stcb_tmp) + if (stcb_tmp) { if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + /* * in setup state we * abort this guy */ + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb_tmp->sctp_ep, - stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); + stcb_tmp, op_err, + SCTP_SO_NOT_LOCKED); goto add_it_now6; } - SCTP_TCB_UNLOCK(stcb_tmp); - + SCTP_TCB_UNLOCK(stcb_tmp); + } if (stcb->asoc.state == 0) { /* the assoc was freed? */ return (-21); diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index f5ede2a..165ef3b 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -584,7 +584,7 @@ void sctp_inpcb_free(struct sctp_inpcb *, int, int); struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *, - int *, uint32_t, uint32_t, struct thread *); + int *, uint32_t, uint32_t, uint16_t, struct thread *); int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int); @@ -654,11 +654,5 @@ void #endif -#ifdef INVARIANTS -void - sctp_validate_no_locks(struct sctp_inpcb *inp); - -#endif - #endif /* _KERNEL */ #endif /* !__sctp_pcb_h__ */ diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 8f61cd7..eda99fe 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -76,6 +76,7 @@ TAILQ_HEAD(sctpnetlisthead, sctp_nets); struct sctp_stream_reset_list { TAILQ_ENTRY(sctp_stream_reset_list) next_resp; + uint32_t seq; uint32_t tsn; uint32_t number_entries; uint16_t list_of_streams[]; @@ -580,11 +581,20 @@ union scheduling_parameters { struct ss_fb fb; }; +/* States for outgoing streams */ +#define SCTP_STREAM_CLOSED 0x00 +#define SCTP_STREAM_OPENING 0x01 +#define SCTP_STREAM_OPEN 0x02 +#define SCTP_STREAM_RESET_PENDING 0x03 +#define SCTP_STREAM_RESET_IN_FLIGHT 0x04 + +#define SCTP_MAX_STREAMS_AT_ONCE_RESET 200 + /* This struct is used to track the traffic on outbound streams */ struct sctp_stream_out { struct sctp_streamhead outqueue; union scheduling_parameters ss_params; - uint32_t chunks_on_queues; + uint32_t chunks_on_queues; /* send queue and sent queue */ #if defined(SCTP_DETAILED_STR_STATS) uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1]; uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1]; @@ -596,6 +606,7 @@ struct sctp_stream_out { uint16_t stream_no; uint16_t next_sequence_send; /* next one I expect to send out */ uint8_t last_msg_incomplete; + uint8_t state; }; /* used to keep track of the addresses yet to try to add/delete */ @@ -1148,7 +1159,7 @@ struct sctp_association { uint8_t hb_random_idx; uint8_t default_dscp; uint8_t asconf_del_pending; /* asconf delete last addr pending */ - + uint8_t trigger_reset; /* * This value, plus all other ack'd but above cum-ack is added * together to cross check against the bit that we have yet to diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index 997ee53..1b35af7 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -453,7 +453,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) if (stcb->asoc.primary_destination != NULL) xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr; xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay; - xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */ + xstcb.state = (uint32_t) sctp_map_assoc_state(stcb->asoc.state); /* 7.0 does not support these */ xstcb.assoc_id = sctp_get_associd(stcb); xstcb.peers_rwnd = stcb->asoc.peers_rwnd; @@ -511,6 +511,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) xraddr.mtu = net->mtu; xraddr.rtt = net->rtt / 1000; xraddr.heartbeat_interval = net->heart_beat_delay; + xraddr.ssthresh = net->ssthresh; xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec; xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec; SCTP_INP_RUNLOCK(inp); diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h index 857bda1..8233343 100644 --- a/sys/netinet/sctp_sysctl.h +++ b/sys/netinet/sctp_sysctl.h @@ -291,10 +291,10 @@ struct sctp_sysctl { #define SCTPCTL_PMTU_RAISE_TIME_DEFAULT SCTP_DEF_PMTU_RAISE_SEC /* shutdown_guard_time: Default shutdown guard timer in seconds */ -#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in seconds" +#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Shutdown guard timer in seconds (0 means 5 times RTO.Max)" #define SCTPCTL_SHUTDOWN_GUARD_TIME_MIN 0 #define SCTPCTL_SHUTDOWN_GUARD_TIME_MAX 0xFFFFFFFF -#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT SCTP_DEF_MAX_SHUTDOWN_SEC +#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT 0 /* secret_lifetime: Default secret lifetime in seconds */ #define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in seconds" diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 257d188..0d684b3 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -153,7 +153,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* Abort notification sends a ULP notify */ struct mbuf *op_err; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Association error counter exceeded"); inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); @@ -408,7 +408,11 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb, int num_marked, int num_abandoned) { if (net->RTO == 0) { - net->RTO = stcb->asoc.minrto; + if (net->RTO_measured) { + net->RTO = stcb->asoc.minrto; + } else { + net->RTO = stcb->asoc.initial_rto; + } } net->RTO <<= 1; if (net->RTO > stcb->asoc.maxrto) { @@ -438,6 +442,11 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; } } + if ((asoc->strmout[chk->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[chk->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[chk->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); if (PR_SCTP_ENABLED(chk->flags)) { if (asoc->pr_sctp_cnt != 0) @@ -1046,7 +1055,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp, /* FOOBAR! */ struct mbuf *op_err; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Cookie timer expired, but no cookie"); inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); @@ -1492,6 +1501,8 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp, #endif if (mtu > next_mtu) { net->mtu = next_mtu; + } else { + net->mtu = mtu; } } } diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index 9305413..ee31543 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -134,20 +134,27 @@ struct sctp_extrcvinfo { uint16_t sinfo_flags; uint32_t sinfo_ppid; uint32_t sinfo_context; - uint32_t sinfo_timetolive; + uint32_t sinfo_timetolive; /* should have been sinfo_pr_value */ uint32_t sinfo_tsn; uint32_t sinfo_cumtsn; sctp_assoc_t sinfo_assoc_id; - uint16_t sreinfo_next_flags; - uint16_t sreinfo_next_stream; - uint32_t sreinfo_next_aid; - uint32_t sreinfo_next_length; - uint32_t sreinfo_next_ppid; + uint16_t serinfo_next_flags; + uint16_t serinfo_next_stream; + uint32_t serinfo_next_aid; + uint32_t serinfo_next_length; + uint32_t serinfo_next_ppid; uint16_t sinfo_keynumber; uint16_t sinfo_keynumber_valid; uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT]; }; +#define sinfo_pr_value sinfo_timetolive +#define sreinfo_next_flags serinfo_next_flags +#define sreinfo_next_stream serinfo_next_stream +#define sreinfo_next_aid serinfo_next_aid +#define sreinfo_next_length serinfo_next_length +#define sreinfo_next_ppid serinfo_next_ppid + struct sctp_sndinfo { uint16_t snd_sid; uint16_t snd_flags; @@ -1229,7 +1236,8 @@ struct xsctp_raddr { struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */ uint32_t rtt; uint32_t heartbeat_interval; - uint32_t extra_padding[31]; /* future */ + uint32_t ssthresh; + uint32_t extra_padding[30]; /* future */ }; #define SCTP_MAX_LOGGING_SIZE 30000 diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 907412c..2ea4eed 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -487,11 +487,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS int error; uint32_t vrf_id = SCTP_DEFAULT_VRFID; -#ifdef IPSEC - uint32_t flags; - -#endif - inp = (struct sctp_inpcb *)so->so_pcb; if (inp != 0) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); @@ -513,33 +508,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS ip_inp = &inp->ip_inp.inp; ip_inp->inp_vflag |= INP_IPV4; ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl); -#ifdef IPSEC - error = ipsec_init_policy(so, &ip_inp->inp_sp); -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 17); -#endif - if (error != 0) { -try_again: - flags = inp->sctp_flags; - if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) { -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 15); -#endif - SCTP_INP_WUNLOCK(inp); - sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, - SCTP_CALLED_AFTER_CMPSET_OFCLOSE); - } else { - flags = inp->sctp_flags; - if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { - goto try_again; - } else { - SCTP_INP_WUNLOCK(inp); - } - } - return (error); - } -#endif /* IPSEC */ SCTP_INP_WUNLOCK(inp); return (0); } @@ -957,14 +925,15 @@ sctp_shutdown(struct socket *so) SCTP_INP_RUNLOCK(inp); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); return (EOPNOTSUPP); - } - /* - * Ok if we reach here its the TCP model and it is either a SHUT_WR - * or SHUT_RDWR. This means we put the shutdown flag against it. - */ - { + } else { + /* + * Ok, if we reach here its the TCP model and it is either a + * SHUT_WR or SHUT_RDWR. This means we put the shutdown flag + * against it. + */ struct sctp_tcb *stcb; struct sctp_association *asoc; + struct sctp_nets *netp; if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) { @@ -976,7 +945,7 @@ sctp_shutdown(struct socket *so) stcb = LIST_FIRST(&inp->sctp_asoc_list); if (stcb == NULL) { /* - * Ok we hit the case that the shutdown call was + * Ok, we hit the case that the shutdown call was * made after an abort or something. Nothing to do * now. */ @@ -985,53 +954,48 @@ sctp_shutdown(struct socket *so) } SCTP_TCB_LOCK(stcb); asoc = &stcb->asoc; - if (TAILQ_EMPTY(&asoc->send_queue) && + if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) { + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); + } + if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) && + (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) && + (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) { + /* + * If we are not in or before ESTABLISHED, there is + * no protocol action required. + */ + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); + } + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && + TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->stream_queue_cnt == 0)) { if (asoc->locked_on_sending) { goto abort_anyway; } /* there is nothing queued to send, so I'm done... */ - if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { - /* only send SHUTDOWN the first time through */ - struct sctp_nets *netp; - - if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || - (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { - SCTP_STAT_DECR_GAUGE32(sctps_currestab); - } - SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); - SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_stop_timers_for_shutdown(stcb); - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - sctp_send_shutdown(stcb, netp); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, - stcb->sctp_ep, stcb, netp); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, - stcb->sctp_ep, stcb, netp); - sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); - } + SCTP_STAT_DECR_GAUGE32(sctps_currestab); + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); + SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown(stcb, netp); + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, + stcb->sctp_ep, stcb, netp); } else { /* - * we still got (or just got) data to send, so set - * SHUTDOWN_PENDING + * We still got (or just got) data to send, so set + * SHUTDOWN_PENDING. */ - struct sctp_nets *netp; - - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - - asoc->state |= SCTP_STATE_SHUTDOWN_PENDING; - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, - netp); - + SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); if (asoc->locked_on_sending) { /* Locked to send out the data */ struct sctp_stream_queue_pending *sp; @@ -1042,7 +1006,7 @@ sctp_shutdown(struct socket *so) asoc->locked_on_sending->stream_no); } else { if ((sp->length == 0) && (sp->msg_is_complete == 0)) { - asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT; + SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT); } } } @@ -1056,16 +1020,20 @@ sctp_shutdown(struct socket *so) stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_LOCKED); - goto skip_unlock; - } else { - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); + SCTP_INP_RUNLOCK(inp); + return (0); } } + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp); + /* + * XXX: Why do this in the case where we have still data + * queued? + */ + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); } -skip_unlock: - SCTP_INP_RUNLOCK(inp); - return (0); } /* @@ -1533,6 +1501,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, /* We are GOOD to go */ stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id, + inp->sctp_ep.pre_open_stream_count, (struct thread *)p ); if (stcb == NULL) { @@ -1914,8 +1883,15 @@ flags_out: uint32_t *value, cnt; SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize); - cnt = 0; SCTP_INP_RLOCK(inp); + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { + /* Can't do this for a 1-1 socket */ + error = EINVAL; + SCTP_INP_RUNLOCK(inp); + break; + } + cnt = 0; LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { cnt++; } @@ -1930,9 +1906,16 @@ flags_out: unsigned int at, limit; SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize); + SCTP_INP_RLOCK(inp); + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { + /* Can't do this for a 1-1 socket */ + error = EINVAL; + SCTP_INP_RUNLOCK(inp); + break; + } at = 0; limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t); - SCTP_INP_RLOCK(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { if (at < limit) { ids->gaids_assoc_id[at++] = sctp_get_associd(stcb); @@ -2668,12 +2651,7 @@ flags_out: error = EINVAL; break; } - /* - * I think passing the state is fine since - * sctp_constants.h will be available to the user - * land. - */ - sstat->sstat_state = stcb->asoc.state; + sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state); sstat->sstat_assoc_id = sctp_get_associd(stcb); sstat->sstat_rwnd = stcb->asoc.peers_rwnd; sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt; @@ -4620,18 +4598,24 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - if (stcb->asoc.stream_reset_outstanding) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); - error = EALREADY; - SCTP_TCB_UNLOCK(stcb); - break; - } if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) { send_in = 1; + if (stcb->asoc.stream_reset_outstanding) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); + error = EALREADY; + SCTP_TCB_UNLOCK(stcb); + break; + } } if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) { send_out = 1; } + if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); + error = ENOMEM; + SCTP_TCB_UNLOCK(stcb); + break; + } if ((send_in == 0) && (send_out == 0)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; @@ -4656,11 +4640,46 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams, - strrst->srs_stream_list, - send_out, send_in, 0, 0, 0, 0, 0); - - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); + if (send_out) { + int cnt; + uint16_t strm; + + if (strrst->srs_number_streams) { + for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) { + strm = strrst->srs_stream_list[i]; + if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING; + cnt++; + } + } + } else { + /* Its all */ + for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) { + if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; + cnt++; + } + } + } + } + if (send_in) { + error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams, + strrst->srs_stream_list, + send_in, 0, 0, 0, 0, 0); + } else { + error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED); + } + if (error == 0) { + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); + } else { + /* + * For outgoing streams don't report any + * problems in sending the request to the + * application. XXX: Double check resetting + * incoming streams. + */ + error = 0; + } SCTP_TCB_UNLOCK(stcb); break; } @@ -4730,7 +4749,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, goto skip_stuff; } } - error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0); + error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); skip_stuff: SCTP_TCB_UNLOCK(stcb); @@ -4738,6 +4757,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } case SCTP_RESET_ASSOC: { + int i; uint32_t *value; SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize); @@ -4762,7 +4782,25 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0); + /* + * Is there any data pending in the send or sent + * queues? + */ + if (!TAILQ_EMPTY(&stcb->asoc.send_queue) || + !TAILQ_EMPTY(&stcb->asoc.sent_queue)) { + busy_out: + error = EBUSY; + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); + SCTP_TCB_UNLOCK(stcb); + break; + } + /* Do any streams have data queued? */ + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + goto busy_out; + } + } + error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); SCTP_TCB_UNLOCK(stcb); break; @@ -5769,7 +5807,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if (laddr->ifa == ifa) { @@ -6906,7 +6944,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) } vrf_id = inp->def_vrf_id; /* We are GOOD to go */ - stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p); + stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p); if (stcb == NULL) { /* Gak! no memory */ goto out_now; diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index c25ec39..4cf134b 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -893,9 +893,52 @@ sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int ch return (x); } +int32_t +sctp_map_assoc_state(int kernel_state) +{ + int32_t user_state; + + if (kernel_state & SCTP_STATE_WAS_ABORTED) { + user_state = SCTP_CLOSED; + } else if (kernel_state & SCTP_STATE_SHUTDOWN_PENDING) { + user_state = SCTP_SHUTDOWN_PENDING; + } else { + switch (kernel_state & SCTP_STATE_MASK) { + case SCTP_STATE_EMPTY: + user_state = SCTP_CLOSED; + break; + case SCTP_STATE_INUSE: + user_state = SCTP_CLOSED; + break; + case SCTP_STATE_COOKIE_WAIT: + user_state = SCTP_COOKIE_WAIT; + break; + case SCTP_STATE_COOKIE_ECHOED: + user_state = SCTP_COOKIE_ECHOED; + break; + case SCTP_STATE_OPEN: + user_state = SCTP_ESTABLISHED; + break; + case SCTP_STATE_SHUTDOWN_SENT: + user_state = SCTP_SHUTDOWN_SENT; + break; + case SCTP_STATE_SHUTDOWN_RECEIVED: + user_state = SCTP_SHUTDOWN_RECEIVED; + break; + case SCTP_STATE_SHUTDOWN_ACK_SENT: + user_state = SCTP_SHUTDOWN_ACK_SENT; + break; + default: + user_state = SCTP_CLOSED; + break; + } + } + return (user_state); +} + int sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, - uint32_t override_tag, uint32_t vrf_id) + uint32_t override_tag, uint32_t vrf_id, uint16_t o_strms) { struct sctp_association *asoc; @@ -1057,7 +1100,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * that we request by default. */ asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = - inp->sctp_ep.pre_open_stream_count; + o_strms; SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, asoc->streamoutcnt * sizeof(struct sctp_stream_out), SCTP_M_STRMO); @@ -1089,6 +1132,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, #endif asoc->strmout[i].stream_no = i; asoc->strmout[i].last_msg_incomplete = 0; + asoc->strmout[i].state = SCTP_STREAM_OPENING; asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); } asoc->ss_functions.sctp_ss_init(stcb, asoc, 0); @@ -1444,12 +1488,14 @@ sctp_timeout_handler(void *t) struct sctp_tcb *stcb; struct sctp_nets *net; struct sctp_timer *tmr; + struct mbuf *op_err; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif int did_output; + int type; tmr = (struct sctp_timer *)t; inp = (struct sctp_inpcb *)tmr->ep; @@ -1518,8 +1564,9 @@ sctp_timeout_handler(void *t) return; } } + type = tmr->type; tmr->stopped_from = 0xa005; - SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type); + SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", type); if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { if (inp) { SCTP_INP_DECR_REF(inp); @@ -1535,7 +1582,7 @@ sctp_timeout_handler(void *t) if (stcb) { SCTP_TCB_LOCK(stcb); atomic_add_int(&stcb->asoc.refcnt, -1); - if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) && + if ((type != SCTP_TIMER_TYPE_ASOCKILL) && ((stcb->asoc.state == 0) || (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) { SCTP_TCB_UNLOCK(stcb); @@ -1547,7 +1594,7 @@ sctp_timeout_handler(void *t) } } /* record in stopped what t-o occured */ - tmr->stopped_from = tmr->type; + tmr->stopped_from = type; /* mark as being serviced now */ if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { @@ -1565,7 +1612,7 @@ sctp_timeout_handler(void *t) SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); /* call the handler for the appropriate timer type */ - switch (tmr->type) { + switch (type) { case SCTP_TIMER_TYPE_ZERO_COPY: if (inp == NULL) { break; @@ -1755,7 +1802,9 @@ sctp_timeout_handler(void *t) break; } SCTP_STAT_INCR(sctps_timoshutdownguard); - sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Shutdown guard timer expired"); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); /* no need to unlock on tcb its gone */ goto out_decr; @@ -1847,11 +1896,11 @@ sctp_timeout_handler(void *t) goto out_no_decr; default: SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n", - tmr->type); + type); break; } #ifdef SCTP_AUDITING_ENABLED - sctp_audit_log(0xF1, (uint8_t) tmr->type); + sctp_audit_log(0xF1, (uint8_t) type); if (inp) sctp_auditing(5, inp, stcb, net); #endif @@ -1874,8 +1923,7 @@ out_decr: SCTP_INP_DECR_REF(inp); } out_no_decr: - SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", - tmr->type); + SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type = %d)\n", type); CURVNET_RESTORE(); } @@ -2076,7 +2124,11 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (stcb == NULL) { return; } - to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; + if (inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] == 0) { + to_ticks = 5 * MSEC_TO_TICKS(stcb->asoc.maxrto); + } else { + to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; + } tmr = &stcb->asoc.shut_guard_timer; break; case SCTP_TIMER_TYPE_STRRESET: @@ -2132,13 +2184,13 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", - __FUNCTION__, t_type); + __func__, t_type); return; break; } if ((to_ticks <= 0) || (tmr == NULL)) { SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n", - __FUNCTION__, t_type, to_ticks, (void *)tmr); + __func__, t_type, to_ticks, (void *)tmr); return; } if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { @@ -2294,7 +2346,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", - __FUNCTION__, t_type); + __func__, t_type); break; } if (tmr == NULL) { @@ -2616,6 +2668,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, #endif + if (stcb == NULL) { + return; + } if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { notif_len = sizeof(struct sctp_assoc_change); if (abort != NULL) { @@ -3723,7 +3778,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n", - __FUNCTION__, notification, notification); + __func__, notification, notification); break; } /* end switch */ } @@ -5600,20 +5655,20 @@ found_one: s_extra = (struct sctp_extrcvinfo *)sinfo; if ((nxt) && (nxt->length)) { - s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL; + s_extra->serinfo_next_flags = SCTP_NEXT_MSG_AVAIL; if (nxt->sinfo_flags & SCTP_UNORDERED) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; } if (nxt->spec_flags & M_NOTIFICATION) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; } - s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id; - s_extra->sreinfo_next_length = nxt->length; - s_extra->sreinfo_next_ppid = nxt->sinfo_ppid; - s_extra->sreinfo_next_stream = nxt->sinfo_stream; + s_extra->serinfo_next_aid = nxt->sinfo_assoc_id; + s_extra->serinfo_next_length = nxt->length; + s_extra->serinfo_next_ppid = nxt->sinfo_ppid; + s_extra->serinfo_next_stream = nxt->sinfo_stream; if (nxt->tail_mbuf != NULL) { if (nxt->end_added) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; } } } else { @@ -5624,11 +5679,11 @@ found_one: * :-D */ nxt = NULL; - s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; - s_extra->sreinfo_next_aid = 0; - s_extra->sreinfo_next_length = 0; - s_extra->sreinfo_next_ppid = 0; - s_extra->sreinfo_next_stream = 0; + s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; + s_extra->serinfo_next_aid = 0; + s_extra->serinfo_next_length = 0; + s_extra->serinfo_next_ppid = 0; + s_extra->serinfo_next_stream = 0; } } /* @@ -6111,7 +6166,7 @@ out: struct sctp_extrcvinfo *s_extra; s_extra = (struct sctp_extrcvinfo *)sinfo; - s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; + s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; } if (hold_rlock == 1) { SCTP_INP_READ_UNLOCK(inp); @@ -6855,7 +6910,7 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_ #endif static void -sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored, +sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp, const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED) { struct ip *iph; @@ -6903,6 +6958,18 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored, for (last = m; last->m_next; last = last->m_next); last->m_next = sp; m->m_pkthdr.len += sp->m_pkthdr.len; + /* + * The CSUM_DATA_VALID flags indicates that the HW checked the UDP + * checksum and it was valid. Since CSUM_DATA_VALID == + * CSUM_SCTP_VALID this would imply that the HW also verified the + * SCTP checksum. Therefore, clear the bit. + */ + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp_recv_udp_tunneled_packet(): Packet of length %d received on %s with csum_flags 0x%b.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + (int)m->m_pkthdr.csum_flags, CSUM_BITS); + m->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID; iph = mtod(m, struct ip *); switch (iph->ip_v) { #ifdef INET diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index 7df0a6c..354d40e 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -67,6 +67,9 @@ void /* * Function prototypes */ +int32_t +sctp_map_assoc_state(int); + uint32_t sctp_get_ifa_hash_val(struct sockaddr *addr); @@ -80,7 +83,7 @@ uint32_t sctp_select_initial_TSN(struct sctp_pcb *); uint32_t sctp_select_a_tag(struct sctp_inpcb *, uint16_t lport, uint16_t rport, int); -int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t); +int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t, uint16_t); void sctp_fill_random_store(struct sctp_pcb *); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 3ce21a9..c0add82 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -341,7 +341,7 @@ tcp_init(void) */ if (hashsize < 512) hashsize = 512; - if (bootverbose) + if (bootverbose && IS_DEFAULT_VNET(curvnet)) printf("%s: %s auto tuned to %d\n", __func__, tcbhash_tuneable, hashsize); } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 3baaa93..e3c3229 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2003,7 +2003,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; @@ -2013,7 +2013,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); } diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 7670289..6749875 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -39,9 +39,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctp_var.h> -#ifdef INET6 #include <netinet6/sctp6_var.h> -#endif #include <netinet/sctp_sysctl.h> #include <netinet/sctp_output.h> #include <netinet/sctp_uio.h> @@ -54,13 +52,12 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_output.h> #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_crc32.h> +#include <netinet/icmp6.h> #include <netinet/udp.h> #ifdef IPSEC #include <netipsec/ipsec.h> -#ifdef INET6 #include <netipsec/ipsec6.h> -#endif /* INET6 */ #endif /* IPSEC */ extern struct protosw inetsw[]; @@ -956,7 +953,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p) return (EALREADY); } /* We are GOOD to go */ - stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p); + stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p); SCTP_ASOC_CREATE_UNLOCK(inp); if (stcb == NULL) { /* Gak! no memory */ diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c index ef44c6d..92b6ac7 100644 --- a/sys/ofed/include/linux/linux_compat.c +++ b/sys/ofed/include/linux/linux_compat.c @@ -480,7 +480,7 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vma.vm_end = size; vma.vm_pgoff = *offset / PAGE_SIZE; vma.vm_pfn = 0; - vma.vm_page_prot = 0; + vma.vm_page_prot = VM_MEMATTR_DEFAULT; if (filp->f_op->mmap) { error = -filp->f_op->mmap(filp, &vma); if (error == 0) { diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c index 9ea51ce..1e57d92 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -514,14 +514,14 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* * XXX: - * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact + * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact * alignment guarantees of malloc need to be nailed down, and the * code below should be rewritten to take that into account. * * In the meantime, we'll warn the user if malloc gets it wrong. */ if ((dmat->maxsize <= PAGE_SIZE) && - (dmat->alignment < dmat->maxsize) && + (dmat->alignment <= dmat->maxsize) && dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) && attr == VM_MEMATTR_DEFAULT) { *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c index e8d563a..6b3a9af 100644 --- a/sys/powerpc/powerpc/elf32_machdep.c +++ b/sys/powerpc/powerpc/elf32_machdep.c @@ -108,6 +108,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c index 4324266..d871e54 100644 --- a/sys/powerpc/powerpc/elf64_machdep.c +++ b/sys/powerpc/powerpc/elf64_machdep.c @@ -84,6 +84,7 @@ struct sysentvec elf64_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); diff --git a/sys/security/audit/audit_worker.c b/sys/security/audit/audit_worker.c index caad5ac..f526cd4 100644 --- a/sys/security/audit/audit_worker.c +++ b/sys/security/audit/audit_worker.c @@ -71,6 +71,8 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> +#include <machine/stdarg.h> + /* * Worker thread that will schedule disk I/O, etc. */ @@ -98,6 +100,26 @@ static struct sx audit_worker_lock; #define AUDIT_WORKER_LOCK() sx_xlock(&audit_worker_lock) #define AUDIT_WORKER_UNLOCK() sx_xunlock(&audit_worker_lock) +static void +audit_worker_sync_vp(struct vnode *vp, struct mount *mp, const char *fmt, ...) +{ + struct mount *mp1; + int error; + va_list va; + + va_start(va, fmt); + error = vn_start_write(vp, &mp1, 0); + if (error == 0) { + VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); + (void)VOP_FSYNC(vp, MNT_WAIT, curthread); + VOP_UNLOCK(vp, 0); + vn_finished_write(mp1); + } + vfs_unbusy(mp); + vpanic(fmt, va); + va_end(va); +} + /* * Write an audit record to a file, performed as the last stage after both * preselection and BSM conversion. Both space management and write failures @@ -114,6 +136,7 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data, static struct timeval last_fail; static int cur_lowspace_trigger; struct statfs *mnt_stat; + struct mount *mp; int error; static int cur_fail; long temp; @@ -123,15 +146,25 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data, if (vp == NULL) return; - mnt_stat = &vp->v_mount->mnt_stat; + mp = vp->v_mount; + if (mp == NULL) { + error = EINVAL; + goto fail; + } + error = vfs_busy(mp, 0); + if (error != 0) { + mp = NULL; + goto fail; + } + mnt_stat = &mp->mnt_stat; /* * First, gather statistics on the audit log file and file system so * that we know how we're doing on space. Consider failure of these * operations to indicate a future inability to write to the file. */ - error = VFS_STATFS(vp->v_mount, mnt_stat); - if (error) + error = VFS_STATFS(mp, mnt_stat); + if (error != 0) goto fail; /* @@ -246,13 +279,12 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data, */ if (audit_in_failure) { if (audit_q_len == 0 && audit_pre_q_len == 0) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); - panic("Audit store overflow; record queue drained."); + audit_worker_sync_vp(vp, mp, + "Audit store overflow; record queue drained."); } } + vfs_unbusy(mp); return; fail_enospc: @@ -262,10 +294,8 @@ fail_enospc: * space, or ENOSPC returned by the vnode write call. */ if (audit_fail_stop) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); - panic("Audit log space exhausted and fail-stop set."); + audit_worker_sync_vp(vp, mp, + "Audit log space exhausted and fail-stop set."); } (void)audit_send_trigger(AUDIT_TRIGGER_NO_SPACE); audit_suspended = 1; @@ -277,12 +307,12 @@ fail: * lost, which may require an immediate system halt. */ if (audit_panic_on_write_fail) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); - panic("audit_worker: write error %d\n", error); + audit_worker_sync_vp(vp, mp, + "audit_worker: write error %d\n", error); } else if (ppsratecheck(&last_fail, &cur_fail, 1)) printf("audit_worker: write error %d\n", error); + if (mp != NULL) + vfs_unbusy(mp); } /* diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index 415f43d..fcac25a 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -521,14 +521,14 @@ nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, /* * XXX: - * (dmat->dt_alignment < dmat->dt_maxsize) is just a quick hack; the + * (dmat->dt_alignment <= dmat->dt_maxsize) is just a quick hack; the * exact alignment guarantees of malloc need to be nailed down, and * the code below should be rewritten to take that into account. * * In the meantime, we'll warn the user if malloc gets it wrong. */ if (dmat->dt_maxsize <= PAGE_SIZE && - dmat->dt_alignment < dmat->dt_maxsize) + dmat->dt_alignment <= dmat->dt_maxsize) *vaddr = malloc(dmat->dt_maxsize, M_DEVBUF, mflags); else { /* diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c index 0dab76d..6ddbd98 100644 --- a/sys/sparc64/sparc64/elf_machdep.c +++ b/sys/sparc64/sparc64/elf_machdep.c @@ -88,6 +88,7 @@ static struct sysentvec elf64_freebsd_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf64_Brandinfo freebsd_brand_info = { diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index dd6f31c..e49e449 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -383,7 +383,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) kmdp = preload_search_by_type("elf kernel"); if (kmdp != NULL) { boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); - kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), + 0); end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, int); diff --git a/sys/sys/conf.h b/sys/sys/conf.h index d72b58b..06c38c1 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -297,9 +297,9 @@ void setconf(void); #define dev2unit(d) ((d)->si_drv0) -typedef void (*cdevpriv_dtr_t)(void *data); +typedef void d_priv_dtor_t(void *data); int devfs_get_cdevpriv(void **datap); -int devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t dtr); +int devfs_set_cdevpriv(void *priv, d_priv_dtor_t *dtr); void devfs_clear_cdevpriv(void); void devfs_fpdrop(struct file *fp); /* XXX This is not public KPI */ diff --git a/sys/sys/elf32.h b/sys/sys/elf32.h index 62bf7be..03a546c 100644 --- a/sys/sys/elf32.h +++ b/sys/sys/elf32.h @@ -70,6 +70,18 @@ typedef struct { } Elf32_Ehdr; /* + * Shared object information, found in SHT_MIPS_LIBLIST. + */ + +typedef struct { + Elf32_Word l_name; /* The name of a shared object. */ + Elf32_Word l_time_stamp; /* 32-bit timestamp. */ + Elf32_Word l_checksum; /* Checksum of visible symbols, sizes. */ + Elf32_Word l_version; /* Interface version string index. */ + Elf32_Word l_flags; /* Flags (LL_*). */ +} Elf32_Lib; + +/* * Section header. */ diff --git a/sys/sys/elf64.h b/sys/sys/elf64.h index 4ec7d34..f069619 100644 --- a/sys/sys/elf64.h +++ b/sys/sys/elf64.h @@ -79,6 +79,18 @@ typedef struct { } Elf64_Ehdr; /* + * Shared object information, found in SHT_MIPS_LIBLIST. + */ + +typedef struct { + Elf64_Word l_name; /* The name of a shared object. */ + Elf64_Word l_time_stamp; /* 64-bit timestamp. */ + Elf64_Word l_checksum; /* Checksum of visible symbols, sizes. */ + Elf64_Word l_version; /* Interface version string index. */ + Elf64_Word l_flags; /* Flags (LL_*). */ +} Elf64_Lib; + +/* * Section header. */ diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 1947d11..d6ca101 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -50,6 +50,61 @@ typedef struct { } Elf_Note; /* + * Option kinds. + */ +#define ODK_NULL 0 /* undefined */ +#define ODK_REGINFO 1 /* register usage info */ +#define ODK_EXCEPTIONS 2 /* exception processing info */ +#define ODK_PAD 3 /* section padding */ +#define ODK_HWPATCH 4 /* hardware patch applied */ +#define ODK_FILL 5 /* fill value used by the linker */ +#define ODK_TAGS 6 /* reserved space for tools */ +#define ODK_HWAND 7 /* hardware AND patch applied */ +#define ODK_HWOR 8 /* hardware OR patch applied */ +#define ODK_GP_GROUP 9 /* GP group for text/data sections */ +#define ODK_IDENT 10 /* ID information */ +#define ODK_PAGESIZE 11 /* page size information */ + +/* + * ODK_EXCEPTIONS info field masks. + */ +#define OEX_FPU_MIN 0x0000001f /* min FPU exception required */ +#define OEX_FPU_MAX 0x00001f00 /* max FPU exception allowed */ +#define OEX_PAGE0 0x00010000 /* page zero must be mapped */ +#define OEX_SMM 0x00020000 /* run in sequential memory mode */ +#define OEX_PRECISEFP 0x00040000 /* run in precise FP exception mode */ +#define OEX_DISMISS 0x00080000 /* dismiss invalid address traps */ + +/* + * ODK_PAD info field masks. + */ +#define OPAD_PREFIX 0x0001 +#define OPAD_POSTFIX 0x0002 +#define OPAD_SYMBOL 0x0004 + +/* + * ODK_HWPATCH info field masks. + */ +#define OHW_R4KEOP 0x00000001 /* patch for R4000 branch at end-of-page bug */ +#define OHW_R8KPFETCH 0x00000002 /* R8000 prefetch bug may occur */ +#define OHW_R5KEOP 0x00000004 /* patch for R5000 branch at end-of-page bug */ +#define OHW_R5KCVTL 0x00000008 /* R5000 cvt.[ds].l bug: clean == 1 */ +#define OHW_R10KLDL 0x00000010UL /* need patch for R10000 misaligned load */ + +/* + * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks. + */ +#define OHWA0_R4KEOP_CHECKED 0x00000001 /* object checked for R4000 end-of-page bug */ +#define OHWA0_R4KEOP_CLEAN 0x00000002 /* object verified clean for R4000 end-of-page bug */ +#define OHWO0_FIXADE 0x00000001 /* object requires call to fixade */ + +/* + * ODK_IDENT/ODK_GP_GROUP info field masks. + */ +#define OGP_GROUP 0x0000ffff /* GP group number */ +#define OGP_SELF 0x00010000 /* GP group is self-contained */ + +/* * The header for GNU-style hash sections. */ @@ -121,6 +176,7 @@ typedef struct { #define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ #define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ +#define ELFOSABI_GNU ELFOSABI_LINUX /* e_ident */ #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ @@ -249,6 +305,60 @@ typedef struct { #define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ #define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ +/** + * e_flags + */ +#define EF_ARM_RELEXEC 0x1 +#define EF_ARM_HASENTRY 0x2 +#define EF_ARM_SYMSARESORTED 0x4 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_LE8 0x00400000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_EABIMASK 0xFF000000 +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 +#define EF_ARM_INTERWORK 0x00000004 +#define EF_ARM_APCS_26 0x00000008 +#define EF_ARM_APCS_FLOAT 0x00000010 +#define EF_ARM_PIC 0x00000020 +#define EF_ARM_ALIGN8 0x00000040 +#define EF_ARM_NEW_ABI 0x00000080 +#define EF_ARM_OLD_ABI 0x00000100 +#define EF_ARM_SOFT_FLOAT 0x00000200 +#define EF_ARM_VFP_FLOAT 0x00000400 +#define EF_ARM_MAVERICK_FLOAT 0x00000800 + +#define EF_MIPS_NOREORDER 0x00000001 +#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ +#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */ +#define EF_MIPS_UCODE 0x00000010 +#define EF_MIPS_ABI2 0x00000020 /* N32 */ +#define EF_MIPS_OPTIONS_FIRST 0x00000080 +#define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */ +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */ +#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */ +#define EF_MIPS_ARCH 0xF0000000 /* Architecture field */ + +#define EF_PPC_EMB 0x80000000 +#define EF_PPC_RELOCATABLE 0x00010000 +#define EF_PPC_RELOCATABLE_LIB 0x00008000 + +#define EF_SPARC_EXT_MASK 0x00ffff00 +#define EF_SPARC_32PLUS 0x00000100 +#define EF_SPARC_SUN_US1 0x00000200 +#define EF_SPARC_HAL_R1 0x00000200 +#define EF_SPARC_SUN_US3 0x00000800 + +#define EF_SPARCV9_MM 0x00000003 +#define EF_SPARCV9_TSO 0x00000000 +#define EF_SPARCV9_PSO 0x00000001 +#define EF_SPARCV9_RMO 0x00000002 + /* Special section indexes. */ #define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ #define SHN_LORESERVE 0xff00 /* First of reserved range. */ @@ -286,6 +396,7 @@ typedef struct { #define SHT_LOSUNW 0x6ffffff4 #define SHT_SUNW_dof 0x6ffffff4 #define SHT_SUNW_cap 0x6ffffff5 +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 #define SHT_SUNW_SIGNATURE 0x6ffffff6 #define SHT_GNU_HASH 0x6ffffff6 #define SHT_GNU_LIBLIST 0x6ffffff7 @@ -305,6 +416,7 @@ typedef struct { #define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ #define SHT_LOPROC 0x70000000 /* reserved range for processor */ #define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ + #define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ #define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map. */ @@ -312,9 +424,39 @@ typedef struct { attributes. */ #define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ #define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_LIBLIST 0x70000000 +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 +#define SHT_MIPS_GPTAB 0x70000003 +#define SHT_MIPS_UCODE 0x70000004 +#define SHT_MIPS_DEBUG 0x70000005 #define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c #define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d #define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 +#define SHT_MIPS_ABIFLAGS 0x7000002a + +#define SHT_SPARC_GOTDATA 0x70000000 + +#define SHTORDERED #define SHT_HIPROC 0x7fffffff /* specific section header types */ #define SHT_LOUSER 0x80000000 /* reserved range for application */ #define SHT_HIUSER 0xffffffff /* specific indexes */ @@ -440,11 +582,15 @@ typedef struct { * Dyn.d_un.d_val field of the Elf*_Dyn structure. */ #define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list */ #define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ #define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ #define DT_MOVEENT 0x6ffffdfa /* move table entry size */ #define DT_MOVESZ 0x6ffffdfb /* move table size */ #define DT_FEATURE 0x6ffffdfc /* feature holder */ +#define DT_FEATURE_1 DT_FEATURE #define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ /* the following DT_* entry. */ /* See DF_P1_* definitions */ @@ -461,6 +607,8 @@ typedef struct { */ #define DT_ADDRRNGLO 0x6ffffe00 #define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_GNU_CONFLICT 0x6ffffef8 /* address of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* address of library list */ #define DT_CONFIG 0x6ffffefa /* configuration information */ #define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ #define DT_AUDIT 0x6ffffefc /* object auditing */ @@ -479,7 +627,67 @@ typedef struct { #define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ #define DT_LOPROC 0x70000000 /* First processor-specific type. */ + +#define DT_ARM_SYMTABSZ 0x70000001 +#define DT_ARM_PREEMPTMAP 0x70000002 + +#define DT_SPARC_REGISTER 0x70000001 #define DT_DEPRECATED_SPARC_REGISTER 0x7000001 + +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_LOCAL_GOTNO 0x7000000a +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 +#define DT_MIPS_DELTA_CLASS 0x70000017 +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 +#define DT_MIPS_DELTA_INSTANCE 0x70000019 +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001A +#define DT_MIPS_DELTA_RELOC 0x7000001B +#define DT_MIPS_DELTA_RELOC_NO 0x7000001C +#define DT_MIPS_DELTA_SYM 0x7000001D +#define DT_MIPS_DELTA_SYM_NO 0x7000001E +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 +#define DT_MIPS_CXX_FLAGS 0x70000022 +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 +#define DT_MIPS_INTERFACE 0x7000002A +#define DT_MIPS_DYNSTR_ALIGN 0x7000002B +#define DT_MIPS_INTERFACE_SIZE 0x7000002C +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002D +#define DT_MIPS_PERF_SUFFIX 0x7000002E +#define DT_MIPS_COMPACT_SIZE 0x7000002F +#define DT_MIPS_GP_VALUE 0x70000030 +#define DT_MIPS_AUX_DYNAMIC 0x70000031 +#define DT_MIPS_PLTGOT 0x70000032 +#define DT_MIPS_RLD_OBJ_UPDATE 0x70000033 +#define DT_MIPS_RWPLT 0x70000034 + +#define DT_PPC_GOT 0x70000000 +#define DT_PPC_TLSOPT 0x70000001 + +#define DT_PPC64_GLINK 0x70000000 +#define DT_PPC64_OPD 0x70000001 +#define DT_PPC64_OPDSZ 0x70000002 +#define DT_PPC64_TLSOPT 0x70000003 + #define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ #define DT_USED 0x7ffffffe /* ignored - same as needed */ #define DT_FILTER 0x7fffffff /* shared library filter name */ @@ -510,6 +718,15 @@ typedef struct { #define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ #define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ +/* Values for l_flags. */ +#define LL_NONE 0x0 /* no flags */ +#define LL_EXACT_MATCH 0x1 /* require an exact match */ +#define LL_IGNORE_INT_VER 0x2 /* ignore version incompatibilities */ +#define LL_REQUIRE_MINOR 0x4 +#define LL_EXPORTS 0x8 +#define LL_DELAY_LOAD 0x10 +#define LL_DELTA 0x20 + /* Values for n_type. Used in core files. */ #define NT_PRSTATUS 1 /* Process status. */ #define NT_FPREGSET 2 /* Floating point registers. */ diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index a93d552..8436ba3 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -131,6 +131,7 @@ struct sysentvec { void *sv_shared_page_obj; void (*sv_schedtail)(struct thread *); void (*sv_thread_detach)(struct thread *); + int (*sv_trap)(struct thread *); }; #define SV_ILP32 0x000100 diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 291d0dd..d605c23 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -94,6 +94,9 @@ vm_map_t pipe_map; const void *zero_region; CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0); +/* NB: Used by kernel debuggers. */ +const u_long vm_maxuser_address = VM_MAXUSER_ADDRESS; + SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, SYSCTL_NULL_ULONG_PTR, VM_MIN_KERNEL_ADDRESS, "Min kernel address"); diff --git a/sys/x86/include/metadata.h b/sys/x86/include/metadata.h new file mode 100644 index 0000000..e13eba0 --- /dev/null +++ b/sys/x86/include/metadata.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org> + * 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$ + */ + +#ifndef _MACHINE_METADATA_H_ +#define _MACHINE_METADATA_H_ + +#define MODINFOMD_SMAP 0x1001 +#define MODINFOMD_SMAP_XATTR 0x1002 +#define MODINFOMD_DTBP 0x1003 +#define MODINFOMD_EFI_MAP 0x1004 +#define MODINFOMD_EFI_FB 0x1005 +#define MODINFOMD_MODULEP 0x1006 + +struct efi_map_header { + uint64_t memory_size; + uint64_t descriptor_size; + uint32_t descriptor_version; +}; + +struct efi_fb { + uint64_t fb_addr; + uint64_t fb_size; + uint32_t fb_height; + uint32_t fb_width; + uint32_t fb_stride; + uint32_t fb_mask_red; + uint32_t fb_mask_green; + uint32_t fb_mask_blue; + uint32_t fb_mask_reserved; +}; + +#endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c index 38c9f1e..bb63397 100644 --- a/sys/x86/x86/busdma_bounce.c +++ b/sys/x86/x86/busdma_bounce.c @@ -402,14 +402,14 @@ bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* * XXX: - * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact + * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact * alignment guarantees of malloc need to be nailed down, and the * code below should be rewritten to take that into account. * * In the meantime, we'll warn the user if malloc gets it wrong. */ if ((dmat->common.maxsize <= PAGE_SIZE) && - (dmat->common.alignment < dmat->common.maxsize) && + (dmat->common.alignment <= dmat->common.maxsize) && dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) && attr == VM_MEMATTR_DEFAULT) { *vaddr = malloc(dmat->common.maxsize, M_DEVBUF, mflags); |