From 466bcd3bf3e6f555e202cc0271a68224d44ad7b7 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 28 Jan 2016 00:51:17 +0000 Subject: [PATCH 001/236] filemon: Use process_exit EVENTHANDLER to capture process exit. This fixes some cases where a process could exit without being untracked by filemon. Reported by: mjg MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon_wrapper.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 9beb573966bc..fcf459d7d394 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -29,6 +29,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include "opt_compat.h" @@ -52,12 +53,13 @@ __FBSDID("$FreeBSD$"); #define sys_symlink symlink #define sys_unlink unlink #define sys_vfork vfork -#define sys_sys_exit sys_exit #ifdef FILEMON_HAS_LINKAT #define sys_linkat linkat #endif #endif /* __FreeBSD_version */ +static eventhandler_tag filemon_exit_tag; + static void filemon_output(struct filemon *filemon, char *msg, size_t len) { @@ -485,7 +487,7 @@ filemon_wrapper_freebsd32_stat(struct thread *td, #endif static void -filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap) +filemon_event_process_exit(void *arg __unused, struct proc *p) { size_t len; struct filemon *filemon; @@ -494,14 +496,14 @@ filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap) /* Get timestamp before locking. */ getmicrotime(&now); - if ((filemon = filemon_pid_check(curproc)) != NULL) { + if ((filemon = filemon_pid_check(p)) != NULL) { len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), - "X %d %d\n", curproc->p_pid, uap->rval); + "X %d %d %d\n", p->p_pid, p->p_xexit, p->p_xsig); filemon_output(filemon, filemon->msgbufr, len); /* Check if the monitored process is about to exit. */ - if (filemon->pid == curproc->p_pid) { + if (filemon->pid == p->p_pid) { len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# Stop %ju.%06ju\n# Bye bye\n", @@ -514,8 +516,6 @@ filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap) /* Unlock the found filemon structure. */ filemon_filemon_unlock(filemon); } - - sys_sys_exit(td, uap); } static int @@ -578,7 +578,6 @@ filemon_wrapper_install(void) #endif sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; - sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit; sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve; sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; @@ -597,7 +596,6 @@ filemon_wrapper_install(void) sv_table = ia32_freebsd_sysvec.sv_table; sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; - sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit; sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve; sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; @@ -612,6 +610,9 @@ filemon_wrapper_install(void) sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat; #endif #endif /* COMPAT_ARCH32 */ + + filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit, + filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST); } static void @@ -624,7 +625,6 @@ filemon_wrapper_deinstall(void) #endif sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir; - sv_table[SYS_exit].sy_call = (sy_call_t *)sys_sys_exit; sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve; sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[SYS_open].sy_call = (sy_call_t *)sys_open; @@ -643,7 +643,6 @@ filemon_wrapper_deinstall(void) sv_table = ia32_freebsd_sysvec.sv_table; sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir; - sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *)sys_sys_exit; sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve; sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open; @@ -658,4 +657,6 @@ filemon_wrapper_deinstall(void) sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat; #endif #endif /* COMPAT_ARCH32 */ + + EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag); } From f0449fbcaad82b04afc03e3dfa798c4c4ec0ddc1 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 28 Jan 2016 01:17:55 +0000 Subject: [PATCH 002/236] filemon: Trace fork via process_fork event. This avoids needing ugly hooks and needing both a vfork and fork handler. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon_wrapper.c | 61 +++++++------------------------ 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index fcf459d7d394..ea44175c8bcc 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -45,20 +45,19 @@ __FBSDID("$FreeBSD$"); 9-CURRENT September 10th-16th. */ #define sys_chdir chdir #define sys_execve execve -#define sys_fork fork #define sys_link link #define sys_open open #define sys_rename rename #define sys_stat stat #define sys_symlink symlink #define sys_unlink unlink -#define sys_vfork vfork #ifdef FILEMON_HAS_LINKAT #define sys_linkat linkat #endif #endif /* __FreeBSD_version */ static eventhandler_tag filemon_exit_tag; +static eventhandler_tag filemon_fork_tag; static void filemon_output(struct filemon *filemon, char *msg, size_t len) @@ -195,29 +194,6 @@ filemon_wrapper_freebsd32_execve(struct thread *td, } #endif -static int -filemon_wrapper_fork(struct thread *td, struct fork_args *uap) -{ - int ret; - size_t len; - struct filemon *filemon; - - if ((ret = sys_fork(td, uap)) == 0) { - if ((filemon = filemon_pid_check(curproc)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "F %d %ld\n", - curproc->p_pid, (long)curthread->td_retval[0]); - - filemon_output(filemon, filemon->msgbufr, len); - - /* Unlock the found filemon structure. */ - filemon_filemon_unlock(filemon); - } - } - - return (ret); -} - static int filemon_wrapper_open(struct thread *td, struct open_args *uap) { @@ -545,27 +521,23 @@ filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap) return (ret); } -static int -filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap) +static void +filemon_event_process_fork(void *arg __unused, struct proc *p1, + struct proc *p2, int flags) { - int ret; size_t len; struct filemon *filemon; - if ((ret = sys_vfork(td, uap)) == 0) { - if ((filemon = filemon_pid_check(curproc)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "F %d %ld\n", - curproc->p_pid, (long)curthread->td_retval[0]); + if ((filemon = filemon_pid_check(p1)) != NULL) { + len = snprintf(filemon->msgbufr, + sizeof(filemon->msgbufr), "F %d %d\n", + p1->p_pid, p2->p_pid); - filemon_output(filemon, filemon->msgbufr, len); + filemon_output(filemon, filemon->msgbufr, len); - /* Unlock the found filemon structure. */ - filemon_filemon_unlock(filemon); - } + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); } - - return (ret); } static void @@ -579,13 +551,11 @@ filemon_wrapper_install(void) sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve; - sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat; sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; - sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork; sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link; sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink; #ifdef FILEMON_HAS_LINKAT @@ -597,13 +567,11 @@ filemon_wrapper_install(void) sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve; - sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat; sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; - sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork; sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link; sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink; #ifdef FILEMON_HAS_LINKAT @@ -613,6 +581,8 @@ filemon_wrapper_install(void) filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit, filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST); + filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork, + filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST); } static void @@ -626,13 +596,11 @@ filemon_wrapper_deinstall(void) sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir; sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve; - sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[SYS_open].sy_call = (sy_call_t *)sys_open; sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename; sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat; sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink; - sv_table[SYS_vfork].sy_call = (sy_call_t *)sys_vfork; sv_table[SYS_link].sy_call = (sy_call_t *)sys_link; sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink; #ifdef FILEMON_HAS_LINKAT @@ -644,13 +612,11 @@ filemon_wrapper_deinstall(void) sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir; sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve; - sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open; sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename; sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat; sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink; - sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *)sys_vfork; sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link; sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink; #ifdef FILEMON_HAS_LINKAT @@ -659,4 +625,5 @@ filemon_wrapper_deinstall(void) #endif /* COMPAT_ARCH32 */ EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag); + EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag); } From 3b41a901ce519f40747475e3af8077ccc2cb4be1 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 28 Jan 2016 01:19:19 +0000 Subject: [PATCH 003/236] Follow-up r294967: Mark flags unused. X-MFC-With: r294967 MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index ea44175c8bcc..33dcc1304486 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -523,7 +523,7 @@ filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap) static void filemon_event_process_fork(void *arg __unused, struct proc *p1, - struct proc *p2, int flags) + struct proc *p2, int flags __unused) { size_t len; struct filemon *filemon; From db5922dc0a22b647ac1359df508e6dba335bbde4 Mon Sep 17 00:00:00 2001 From: ngie Date: Thu, 28 Jan 2016 03:24:06 +0000 Subject: [PATCH 004/236] Add pidfile support to ggated(8) The tests will manipulate the system daemon today, which can cause undesired service interruption when the tests are run. This change allows the geom_gate tests to be run with an arbitrary ggated(8) daemon / geom_gate(4) device pairing. Other changes: - Sort #includes - Use a more common idiom for parsing options with getopt(3) Differential Revision: https://reviews.freebsd.org/D4836 MFC after: 2 weeks Reviewed by: bjk (manpages), pjd (maintainer timeout) Sponsored by: EMC / Isilon Storage Division --- sbin/ggate/ggated/Makefile | 2 +- sbin/ggate/ggated/ggated.8 | 14 ++++++++- sbin/ggate/ggated/ggated.c | 61 ++++++++++++++++++++++++-------------- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/sbin/ggate/ggated/Makefile b/sbin/ggate/ggated/Makefile index af5c9bdf796a..83516c675261 100644 --- a/sbin/ggate/ggated/Makefile +++ b/sbin/ggate/ggated/Makefile @@ -6,7 +6,7 @@ PROG= ggated MAN= ggated.8 SRCS= ggated.c ggate.c -LIBADD= pthread +LIBADD= pthread util CFLAGS+= -I${.CURDIR}/../shared diff --git a/sbin/ggate/ggated/ggated.8 b/sbin/ggate/ggated/ggated.8 index dd6109aa61ef..f73e8a618eb1 100644 --- a/sbin/ggate/ggated/ggated.8 +++ b/sbin/ggate/ggated/ggated.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 14, 2015 +.Dd January 27, 2016 .Dt GGATED 8 .Os .Sh NAME @@ -37,6 +37,7 @@ .Op Fl v .Op Fl a Ar address .Op Fl p Ar port +.Op Fl F Ar pidfile .Op Fl R Ar rcvbuf .Op Fl S Ar sndbuf .Op Ar "exports file" @@ -67,6 +68,10 @@ Port on which .Nm listens for connections. Default is 3080. +.It Fl F Ar pidfile +PID file that +.Nm +uses. .It Fl R Ar rcvbuf Size of receive buffer to use. Default is 131072 (128kB). @@ -86,6 +91,13 @@ The format of an exports file is as follows: 1.2.3.0/24 RW /tmp/test.img hostname WO /tmp/image .Ed +.Sh FILES +.Bl -tag -width ".Pa /var/run/ggated.pid" -compact +.It Pa /var/run/ggated.pid +The default location of the +.Nm +PID file. +.El .Sh EXIT STATUS Exit status is 0 on success, or 1 if the command fails. To get details about the failure, diff --git a/sbin/ggate/ggated/ggated.c b/sbin/ggate/ggated/ggated.c index a340f01b1b5f..e234cb57b290 100644 --- a/sbin/ggate/ggated/ggated.c +++ b/sbin/ggate/ggated/ggated.c @@ -26,32 +26,34 @@ * $FreeBSD$ */ -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include -#include #include +#include +#include #include #include -#include -#include +#include #include #include -#include -#include #include #include #include -#include +#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include "ggate.h" @@ -110,8 +112,8 @@ static void usage(void) { - fprintf(stderr, "usage: %s [-nv] [-a address] [-p port] [-R rcvbuf] " - "[-S sndbuf] [exports file]\n", getprogname()); + fprintf(stderr, "usage: %s [-nv] [-a address] [-F pidfile] [-p port] " + "[-R rcvbuf] [-S sndbuf] [exports file]\n", getprogname()); exit(EXIT_FAILURE); } @@ -946,20 +948,18 @@ huphandler(int sig __unused) int main(int argc, char *argv[]) { + const char *ggated_pidfile = _PATH_VARRUN "/ggated.pid"; + struct pidfh *pfh; struct sockaddr_in serv; struct sockaddr from; socklen_t fromlen; - int sfd, tmpsfd; + pid_t otherpid; + int ch, sfd, tmpsfd; unsigned port; bindaddr = htonl(INADDR_ANY); port = G_GATE_PORT; - for (;;) { - int ch; - - ch = getopt(argc, argv, "a:hnp:R:S:v"); - if (ch == -1) - break; + while ((ch = getopt(argc, argv, "a:hnp:F:R:S:v")) != -1) { switch (ch) { case 'a': bindaddr = g_gate_str2ip(optarg); @@ -968,6 +968,9 @@ main(int argc, char *argv[]) "Invalid IP/host name to bind to."); } break; + case 'F': + ggated_pidfile = optarg; + break; case 'n': nagle = 0; break; @@ -1004,12 +1007,23 @@ main(int argc, char *argv[]) exports_file = argv[0]; exports_get(); + pfh = pidfile_open(ggated_pidfile, 0600, &otherpid); + if (pfh == NULL) { + if (errno == EEXIST) { + errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", + (intmax_t)otherpid); + } + err(EXIT_FAILURE, "Cannot open/create pidfile"); + } + if (!g_gate_verbose) { /* Run in daemon mode. */ if (daemon(0, 0) == -1) g_gate_xlog("Cannot daemonize: %s", strerror(errno)); } + pidfile_write(pfh); + signal(SIGCHLD, SIG_IGN); sfd = socket(AF_INET, SOCK_STREAM, 0); @@ -1046,5 +1060,6 @@ main(int argc, char *argv[]) close(tmpsfd); } close(sfd); + pidfile_remove(pfh); exit(EXIT_SUCCESS); } From d54bf9a884664360a49f9470547ec8310a002a9b Mon Sep 17 00:00:00 2001 From: wma Date: Thu, 28 Jan 2016 12:00:17 +0000 Subject: [PATCH 005/236] Fix mutex releasing in ARM64 cpu_switch The code should be comparing pointers, not any data gathered from a blocked_lock. Spotted by: cognet Approved by: zbb, cognet (mentor) Differential revision: https://reviews.freebsd.org/D5100 --- sys/arm64/arm64/swtch.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S index bc2e52103416..1f20b3d63c9c 100644 --- a/sys/arm64/arm64/swtch.S +++ b/sys/arm64/arm64/swtch.S @@ -166,9 +166,8 @@ ENTRY(cpu_switch) */ str x2, [x0, #TD_LOCK] #if defined(SCHED_ULE) && defined(SMP) - /* Read the value in blocked_lock */ - ldr x0, =_C_LABEL(blocked_lock) - ldr x2, [x0] + /* Spin if TD_LOCK points to a blocked_lock */ + ldr x2, =_C_LABEL(blocked_lock) 1: ldar x3, [x1, #TD_LOCK] cmp x3, x2 From 0fe7e27aea132d450078f8b9c4af064bcadd6c48 Mon Sep 17 00:00:00 2001 From: trasz Date: Thu, 28 Jan 2016 12:21:23 +0000 Subject: [PATCH 006/236] Remove ffs_mountroot() prototype; seems to be long gone. MFC after: 1 month Sponsored by: The FreeBSD Foundation --- sys/ufs/ffs/ffs_extern.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index c29e5d5dc12a..b4ec348f3329 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -77,7 +77,6 @@ void ffs_fserr(struct fs *, ino_t, char *); int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t); void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t); -int ffs_mountroot(void); void ffs_oldfscompat_write(struct fs *, struct ufsmount *); int ffs_own_mount(const struct mount *mp); int ffs_reallocblks(struct vop_reallocblks_args *); From fd752ed774f32a9029b1719067ee8463f9d53859 Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 12:43:58 +0000 Subject: [PATCH 007/236] SMP support for ARMv6/v7 HW watchpoints Use per-CPU structure to store HW watchpoints registers state for each CPU present in the system. Those registers will be restored upon wake up from the STOP state if requested by the debug_monitor code. The method is similar to the one introduced to AMD64. We store all possible 16 registers for HW watchpoints (maximum allowed by the architecture). HW breakpoints are not maintained since they are used for single stepping only. Pointed out by: kib Reviewed by: wma No strong objections from: kib Submitted by: Zbigniew Bodek Obtained from: Semihalf Sponsored by: Juniper Networks Inc. Differential Revision: https://reviews.freebsd.org/D4338 --- sys/arm/arm/debug_monitor.c | 159 ++++++++++++++++++++++++++++---- sys/arm/arm/mp_machdep.c | 7 ++ sys/arm/include/debug_monitor.h | 6 ++ sys/arm/include/pcpu.h | 7 +- sys/arm/include/reg.h | 4 +- 5 files changed, 165 insertions(+), 18 deletions(-) diff --git a/sys/arm/arm/debug_monitor.c b/sys/arm/arm/debug_monitor.c index 7eba5959f8e3..e216e347597c 100644 --- a/sys/arm/arm/debug_monitor.c +++ b/sys/arm/arm/debug_monitor.c @@ -35,14 +35,17 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include #include #include #include +#include #include #include @@ -80,7 +83,7 @@ static boolean_t dbg_ossr; /* OS Save and Restore implemented */ static uint32_t dbg_watchpoint_num; static uint32_t dbg_breakpoint_num; -static int dbg_ref_count_mme[MAXCPU]; /* Times monitor mode was enabled */ +static int dbg_ref_count_mme; /* Times monitor mode was enabled */ /* ID_DFR0 - Debug Feature Register 0 */ #define ID_DFR0_CP_DEBUG_M_SHIFT 0 @@ -542,11 +545,9 @@ dbg_enable_monitor(void) { uint32_t dbg_dscr; - /* Already enabled? Just increment reference counter and return */ - if (dbg_monitor_is_enabled()) { - dbg_ref_count_mme[PCPU_GET(cpuid)]++; + /* Already enabled? Just return */ + if (dbg_monitor_is_enabled()) return (0); - } dbg_dscr = cp14_dbgdscrint_get(); @@ -565,10 +566,8 @@ dbg_enable_monitor(void) isb(); /* Verify that Monitor mode is set */ - if (dbg_monitor_is_enabled()) { - dbg_ref_count_mme[PCPU_GET(cpuid)]++; + if (dbg_monitor_is_enabled()) return (0); - } return (ENXIO); } @@ -581,9 +580,6 @@ dbg_disable_monitor(void) if (!dbg_monitor_is_enabled()) return (0); - if (--dbg_ref_count_mme[PCPU_GET(cpuid)] > 0) - return (0); - dbg_dscr = cp14_dbgdscrint_get(); switch (dbg_model) { case ID_DFR0_CP_DEBUG_M_V6: @@ -607,11 +603,13 @@ dbg_disable_monitor(void) static int dbg_setup_xpoint(struct dbg_wb_conf *conf) { + struct pcpu *pcpu; + struct dbreg *d; const char *typestr; uint32_t cr_size, cr_priv, cr_access; uint32_t reg_ctrl, reg_addr, ctrl, addr; boolean_t is_bkpt; - u_int cpuid; + u_int cpuid, cpu; u_int i; int err; @@ -705,20 +703,52 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf) dbg_wb_write_reg(reg_addr, i, addr); dbg_wb_write_reg(reg_ctrl, i, ctrl); - return (dbg_enable_monitor()); + err = dbg_enable_monitor(); + if (err != 0) + return (err); + + /* Increment monitor enable counter */ + dbg_ref_count_mme++; + + /* + * Save watchpoint settings for all CPUs. + * We don't need to do the same with breakpoints since HW breakpoints + * are only used to perform single stepping. + */ + if (!is_bkpt) { + CPU_FOREACH(cpu) { + pcpu = pcpu_find(cpu); + /* Fill out the settings for watchpoint */ + d = (struct dbreg *)pcpu->pc_dbreg; + d->dbg_wvr[i] = addr; + d->dbg_wcr[i] = ctrl; + /* Skip update command for the current CPU */ + if (cpu != cpuid) + pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; + } + } + /* Ensure all data is written before waking other CPUs */ + atomic_thread_fence_rel(); + + return (0); } static int dbg_remove_xpoint(struct dbg_wb_conf *conf) { + struct pcpu *pcpu; + struct dbreg *d; uint32_t reg_ctrl, reg_addr, addr; - u_int cpuid; + boolean_t is_bkpt; + u_int cpuid, cpu; u_int i; int err; if (!dbg_capable) return (ENXIO); + is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT); + cpuid = PCPU_GET(cpuid); if (!dbg_ready[cpuid]) { err = dbg_reset_state(); @@ -729,7 +759,7 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf) addr = conf->address; - if (conf->type == DBG_TYPE_BREAKPOINT) { + if (is_bkpt) { i = conf->slot; reg_ctrl = DBG_REG_BASE_BCR; reg_addr = DBG_REG_BASE_BVR; @@ -746,7 +776,40 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf) dbg_wb_write_reg(reg_ctrl, i, 0); dbg_wb_write_reg(reg_addr, i, 0); - return (dbg_disable_monitor()); + /* Decrement monitor enable counter */ + dbg_ref_count_mme--; + if (dbg_ref_count_mme < 0) + dbg_ref_count_mme = 0; + + atomic_thread_fence_rel(); + + if (dbg_ref_count_mme == 0) { + err = dbg_disable_monitor(); + if (err != 0) + return (err); + } + + /* + * Save watchpoint settings for all CPUs. + * We don't need to do the same with breakpoints since HW breakpoints + * are only used to perform single stepping. + */ + if (!is_bkpt) { + CPU_FOREACH(cpu) { + pcpu = pcpu_find(cpu); + /* Fill out the settings for watchpoint */ + d = (struct dbreg *)pcpu->pc_dbreg; + d->dbg_wvr[i] = 0; + d->dbg_wcr[i] = 0; + /* Skip update command for the current CPU */ + if (cpu != cpuid) + pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; + } + /* Ensure all data is written before waking other CPUs */ + atomic_thread_fence_rel(); + } + + return (0); } static __inline uint32_t @@ -941,3 +1004,67 @@ dbg_monitor_init(void) db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n", PCPU_GET(cpuid)); } + +CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg)); + +void +dbg_resume_dbreg(void) +{ + struct dbreg *d; + u_int cpuid; + u_int i; + int err; + + /* + * This flag is set on the primary CPU + * and its meaning is valid for other CPUs too. + */ + if (!dbg_capable) + return; + + atomic_thread_fence_acq(); + + switch (PCPU_GET(dbreg_cmd)) { + case PC_DBREG_CMD_LOAD: + d = (struct dbreg *)PCPU_PTR(dbreg); + cpuid = PCPU_GET(cpuid); + + /* Reset Debug Architecture State if not done earlier */ + if (!dbg_ready[cpuid]) { + err = dbg_reset_state(); + if (err != 0) { + /* + * Something is very wrong. + * WPs/BPs will not work correctly in this CPU. + */ + panic("%s: Failed to reset Debug Architecture " + "state on CPU%d", __func__, cpuid); + } + dbg_ready[cpuid] = TRUE; + } + + /* Restore watchpoints */ + for (i = 0; i < dbg_watchpoint_num; i++) { + dbg_wb_write_reg(DBG_REG_BASE_WVR, i, d->dbg_wvr[i]); + dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]); + } + + if ((dbg_ref_count_mme > 0) && !dbg_monitor_is_enabled()) { + err = dbg_enable_monitor(); + if (err != 0) { + panic("%s: Failed to enable Debug Monitor " + "on CPU%d", __func__, cpuid); + } + } + if ((dbg_ref_count_mme == 0) && dbg_monitor_is_enabled()) { + err = dbg_disable_monitor(); + if (err != 0) { + panic("%s: Failed to disable Debug Monitor " + "on CPU%d", __func__, cpuid); + } + } + + PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE); + break; + } +} diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 60bb59895a44..463a00ac3b96 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -303,6 +304,9 @@ ipi_stop(void *dummy __unused) CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); +#ifdef DDB + dbg_resume_dbreg(); +#endif CTR0(KTR_SMP, "IPI_STOP (restart)"); } @@ -405,6 +409,9 @@ ipi_handler(void *arg) CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); +#ifdef DDB + dbg_resume_dbreg(); +#endif CTR0(KTR_SMP, "IPI_STOP (restart)"); break; case IPI_PREEMPT: diff --git a/sys/arm/include/debug_monitor.h b/sys/arm/include/debug_monitor.h index 0cc8156ba447..776d344f972e 100644 --- a/sys/arm/include/debug_monitor.h +++ b/sys/arm/include/debug_monitor.h @@ -48,6 +48,7 @@ void dbg_monitor_init(void); void dbg_show_watchpoint(void); int dbg_setup_watchpoint(db_expr_t, db_expr_t, enum dbg_access_t); int dbg_remove_watchpoint(db_expr_t, db_expr_t); +void dbg_resume_dbreg(void); #else /* __ARM_ARCH >= 6 */ static __inline void dbg_show_watchpoint(void) @@ -68,6 +69,11 @@ static __inline void dbg_monitor_init(void) { } + +static __inline void +dbg_resume_dbreg(void) +{ +} #endif /* __ARM_ARCH < 6 */ #else /* DDB */ diff --git a/sys/arm/include/pcpu.h b/sys/arm/include/pcpu.h index 4261a5a2a2d1..b4814fc2503c 100644 --- a/sys/arm/include/pcpu.h +++ b/sys/arm/include/pcpu.h @@ -49,7 +49,9 @@ struct vmspace; struct pmap *pc_curpmap; \ vm_offset_t pc_qmap_addr; \ void *pc_qmap_pte; \ - char __pad[133] + unsigned int pc_dbreg[32]; \ + int pc_dbreg_cmd; \ + char __pad[1] #else #define PCPU_MD_FIELDS \ vm_offset_t qmap_addr; \ @@ -59,6 +61,9 @@ struct vmspace; #ifdef _KERNEL +#define PC_DBREG_CMD_NONE 0 +#define PC_DBREG_CMD_LOAD 1 + struct pcb; struct pcpu; diff --git a/sys/arm/include/reg.h b/sys/arm/include/reg.h index 2f8c2ede7d21..d4cc4575627b 100644 --- a/sys/arm/include/reg.h +++ b/sys/arm/include/reg.h @@ -19,7 +19,9 @@ struct fpreg { }; struct dbreg { - unsigned int dr[8]; /* debug registers */ +#define ARM_WR_MAX 16 /* Maximum number of watchpoint registers */ + unsigned int dbg_wcr[ARM_WR_MAX]; /* Watchpoint Control Registers */ + unsigned int dbg_wvr[ARM_WR_MAX]; /* Watchpoint Value Registers */ }; #ifdef _KERNEL From a0d10caff7d70d415567d9fa0d26a1edb67ddb90 Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 28 Jan 2016 14:11:59 +0000 Subject: [PATCH 008/236] EHCI: Make core reset and port speed reading more generic. Use driver settable callbacks for handling of: - core post reset - reading actual port speed Typically, OTG enabled EHCI cores wants setting of USBMODE register, but this register is not defined in EHCI specification and different cores can have it on different offset. Also, for cores with TT extension, actual port speed must be determinable. But again, EHCI specification not covers this so this patch provides function for two most common variant of speed bits layout. Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D5088 --- sys/arm/freescale/vybrid/vf_ehci.c | 18 +++++++- sys/arm/xilinx/zy7_ehci.c | 17 +++++++- sys/dev/usb/controller/ehci.c | 64 +++++++++++++++++----------- sys/dev/usb/controller/ehci.h | 9 ++-- sys/dev/usb/controller/ehci_ixp4xx.c | 30 +++++++++---- sys/dev/usb/controller/ehci_mv.c | 18 ++++++-- sys/dev/usb/controller/ehcireg.h | 26 ++++++++++- sys/mips/atheros/ar71xx_ehci.c | 21 ++++++++- sys/powerpc/ps3/ehci_ps3.c | 13 +++++- 9 files changed, 170 insertions(+), 46 deletions(-) diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c index 122513f33c9c..0a7dc941fef3 100644 --- a/sys/arm/freescale/vybrid/vf_ehci.c +++ b/sys/arm/freescale/vybrid/vf_ehci.c @@ -169,6 +169,18 @@ static devclass_t ehci_devclass; DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0); MODULE_DEPEND(ehci, usb, 1, 1, 1); +static void +vybrid_ehci_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Force HOST mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode &= ~EHCI_UM_CM; + usbmode |= EHCI_UM_CM_HOST; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + /* * Public methods */ @@ -343,8 +355,10 @@ vybrid_ehci_attach(device_t dev) reg |= 0x3; bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg); - /* Set flags */ - sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM; + /* Set flags and callbacks*/ + sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; + sc->sc_vendor_post_reset = vybrid_ehci_post_reset; + sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; err = ehci_init(sc); if (!err) { diff --git a/sys/arm/xilinx/zy7_ehci.c b/sys/arm/xilinx/zy7_ehci.c index f74a02f3b27c..f03c131adb4b 100644 --- a/sys/arm/xilinx/zy7_ehci.c +++ b/sys/arm/xilinx/zy7_ehci.c @@ -138,6 +138,18 @@ __FBSDID("$FreeBSD$"); #define EHCI_REG_OFFSET ZY7_USB_CAPLENGTH_HCIVERSION #define EHCI_REG_SIZE 0x100 +static void +zy7_ehci_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Force HOST mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode &= ~EHCI_UM_CM; + usbmode |= EHCI_UM_CM_HOST; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + static int zy7_phy_config(device_t dev, bus_space_tag_t io_tag, bus_space_handle_t bsh) { @@ -275,8 +287,9 @@ zy7_ehci_attach(device_t dev) } /* Customization. */ - sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_TT | - EHCI_SCFLG_NORESTERM; + sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; + sc->sc_vendor_post_reset = zy7_ehci_post_reset; + sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; /* Modify FIFO burst threshold from 2 to 8. */ bus_space_write_4(sc->sc_io_tag, bsh, diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c index 0f9372585d1c..eb4ccb9b5ca2 100644 --- a/sys/dev/usb/controller/ehci.c +++ b/sys/dev/usb/controller/ehci.c @@ -189,24 +189,8 @@ ehci_reset(ehci_softc_t *sc) usb_pause_mtx(NULL, hz / 128); hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; if (!hcr) { - if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) { - /* - * Force USBMODE as requested. Controllers - * may have multiple operating modes. - */ - uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE); - if (sc->sc_flags & EHCI_SCFLG_SETMODE) { - usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST; - device_printf(sc->sc_bus.bdev, - "set host controller mode\n"); - } - if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) { - usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE; - device_printf(sc->sc_bus.bdev, - "set big-endian mode\n"); - } - EOWRITE4(sc, EHCI_USBMODE, usbmode); - } + if (sc->sc_vendor_post_reset != NULL) + sc->sc_vendor_post_reset(sc); return (0); } } @@ -3066,6 +3050,36 @@ struct usb_hub_descriptor ehci_hubd = .bDescriptorType = UDESC_HUB, }; +uint16_t +ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index) +{ + uint32_t v; + + v = EOREAD4(sc, EHCI_PORTSC(index)); + v = (v >> EHCI_PORTSC_PSPD_SHIFT) & EHCI_PORTSC_PSPD_MASK; + + if (v == EHCI_PORT_SPEED_HIGH) + return (UPS_HIGH_SPEED); + if (v == EHCI_PORT_SPEED_LOW) + return (UPS_LOW_SPEED); + return (0); +} + +uint16_t +ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index) +{ + uint32_t v; + + v = EOREAD4(sc, EHCI_HOSTC(index)); + v = (v >> EHCI_HOSTC_PSPD_SHIFT) & EHCI_HOSTC_PSPD_MASK; + + if (v == EHCI_PORT_SPEED_HIGH) + return (UPS_HIGH_SPEED); + if (v == EHCI_PORT_SPEED_LOW) + return (UPS_LOW_SPEED); + return (0); +} + static void ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed) { @@ -3330,13 +3344,15 @@ ehci_roothub_exec(struct usb_device *udev, } v = EOREAD4(sc, EHCI_PORTSC(index)); DPRINTFN(9, "port status=0x%04x\n", v); - if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) { - if ((v & 0xc000000) == 0x8000000) + if (sc->sc_flags & EHCI_SCFLG_TT) { + if (sc->sc_vendor_get_port_speed != NULL) { + i = sc->sc_vendor_get_port_speed(sc, index); + } else { + device_printf(sc->sc_bus.bdev, + "EHCI_SCFLG_TT quirk is set but " + "sc_vendor_get_hub_speed() is NULL\n"); i = UPS_HIGH_SPEED; - else if ((v & 0xc000000) == 0x4000000) - i = UPS_LOW_SPEED; - else - i = 0; + } } else { i = UPS_HIGH_SPEED; } diff --git a/sys/dev/usb/controller/ehci.h b/sys/dev/usb/controller/ehci.h index 808ff9f51bf9..0d1e19a39e52 100644 --- a/sys/dev/usb/controller/ehci.h +++ b/sys/dev/usb/controller/ehci.h @@ -337,11 +337,8 @@ typedef struct ehci_softc { uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT]; uint16_t sc_id_vendor; /* vendor ID for root hub */ uint16_t sc_flags; /* chip specific flags */ -#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */ -#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */ #define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */ #define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */ -#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */ #define EHCI_SCFLG_TT 0x0020 /* transaction translator present */ #define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */ #define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */ @@ -358,6 +355,10 @@ typedef struct ehci_softc { char sc_vendor[16]; /* vendor string for root hub */ + void (*sc_vendor_post_reset)(struct ehci_softc *sc); + uint16_t (*sc_vendor_get_port_speed)(struct ehci_softc *sc, + uint16_t index); + } ehci_softc_t; #define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a)) @@ -446,5 +447,7 @@ usb_error_t ehci_reset(ehci_softc_t *sc); usb_error_t ehci_init(ehci_softc_t *sc); void ehci_detach(struct ehci_softc *sc); void ehci_interrupt(ehci_softc_t *sc); +uint16_t ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index); +uint16_t ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index); #endif /* _EHCI_H_ */ diff --git a/sys/dev/usb/controller/ehci_ixp4xx.c b/sys/dev/usb/controller/ehci_ixp4xx.c index 301032ed0260..05efbb51c129 100644 --- a/sys/dev/usb/controller/ehci_ixp4xx.c +++ b/sys/dev/usb/controller/ehci_ixp4xx.c @@ -86,6 +86,19 @@ static void ehci_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, uin static uint32_t ehci_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t); static void ehci_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, uint32_t); +static void +ehci_ixp_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Force HOST mode, select big-endian mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode &= ~EHCI_UM_CM; + usbmode |= EHCI_UM_CM_HOST; + usbmode |= EHCI_UM_ES_BE; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + static int ehci_ixp_probe(device_t self) { @@ -173,20 +186,21 @@ ehci_ixp_attach(device_t self) } /* - * Arrange to force Host mode, select big-endian byte alignment, - * and arrange to not terminate reset operations (the adapter - * will ignore it if we do but might as well save a reg write). - * Also, the controller has an embedded Transaction Translator - * which means port speed must be read from the Port Status - * register following a port enable. + * Select big-endian byte alignment and arrange to not terminate + * reset operations (the adapter will ignore it if we do but might + * as well save a reg write). Also, the controller has an embedded + * Transaction Translator which means port speed must be read from + * the Port Status register following a port enable. */ sc->sc_flags |= EHCI_SCFLG_TT - | EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEDESC - | EHCI_SCFLG_BIGEMMIO | EHCI_SCFLG_NORESTERM ; + /* Setup callbacks. */ + sc->sc_vendor_post_reset = ehci_ixp_post_reset; + sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; + err = ehci_init(sc); if (!err) { err = device_probe_and_attach(sc->sc_bus.bdev); diff --git a/sys/dev/usb/controller/ehci_mv.c b/sys/dev/usb/controller/ehci_mv.c index f06a83056f7e..cd7d549aaf46 100644 --- a/sys/dev/usb/controller/ehci_mv.c +++ b/sys/dev/usb/controller/ehci_mv.c @@ -105,6 +105,18 @@ static struct ofw_compat_data compat_data[] = { {NULL, false} }; +static void +mv_ehci_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Force HOST mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode &= ~EHCI_UM_CM; + usbmode |= EHCI_UM_CM_HOST; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + static int mv_ehci_probe(device_t self) { @@ -226,13 +238,13 @@ mv_ehci_attach(device_t self) * Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for * details. */ - sc->sc_flags |= EHCI_SCFLG_SETMODE; + sc->sc_vendor_post_reset = mv_ehci_post_reset; if (bootverbose) device_printf(self, "5.24 GL USB-2 workaround enabled\n"); /* XXX all MV chips need it? */ - sc->sc_flags |= EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_NORESTERM; - + sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; + sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; err = ehci_init(sc); if (!err) { err = device_probe_and_attach(sc->sc_bus.bdev); diff --git a/sys/dev/usb/controller/ehcireg.h b/sys/dev/usb/controller/ehcireg.h index 1f5fc5c06cad..1bfda909cdd0 100644 --- a/sys/dev/usb/controller/ehcireg.h +++ b/sys/dev/usb/controller/ehcireg.h @@ -157,7 +157,17 @@ #define EHCI_PS_CS 0x00000001 /* RO connect status */ #define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) -#define EHCI_USBMODE 0x68 /* RW USB Device mode register */ +#define EHCI_PORT_RESET_COMPLETE 2 /* ms */ + +/* + * Registers not covered by EHCI specification + * + * + * EHCI_USBMODE register offset is different for cores with LPM support, + * bits are equal + */ +#define EHCI_USBMODE_NOLPM 0x68 /* RW USB Device mode reg (no LPM) */ +#define EHCI_USBMODE_LPM 0xA8 /* RW USB Device mode reg (LPM) */ #define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */ #define EHCI_UM_CM_IDLE 0x0 /* Idle */ #define EHCI_UM_CM_HOST 0x3 /* Host Controller */ @@ -166,6 +176,18 @@ #define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */ #define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */ -#define EHCI_PORT_RESET_COMPLETE 2 /* ms */ +/* + * Actual port speed bits depends on EHCI_HOSTC(n) registers presence, + * speed encoding is equal + */ +#define EHCI_HOSTC(n) (0x80+(4*(n))) /* RO, RW Host mode control reg */ +#define EHCI_HOSTC_PSPD_SHIFT 25 +#define EHCI_HOSTC_PSPD_MASK 0x3 +#define EHCI_PORTSC_PSPD_SHIFT 26 +#define EHCI_PORTSC_PSPD_MASK 0x3 + +#define EHCI_PORT_SPEED_FULL 0 +#define EHCI_PORT_SPEED_LOW 1 +#define EHCI_PORT_SPEED_HIGH 2 #endif /* _EHCIREG_H_ */ diff --git a/sys/mips/atheros/ar71xx_ehci.c b/sys/mips/atheros/ar71xx_ehci.c index 5b7b3e25b9dc..07e06b979a0b 100644 --- a/sys/mips/atheros/ar71xx_ehci.c +++ b/sys/mips/atheros/ar71xx_ehci.c @@ -61,6 +61,10 @@ __FBSDID("$FreeBSD$"); #define EHCI_HC_DEVSTR "AR71XX Integrated USB 2.0 controller" +#define EHCI_USBMODE 0x68 /* USB Device mode register */ +#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */ +#define EHCI_UM_CM_HOST 0x3 /* Host Controller */ + struct ar71xx_ehci_softc { ehci_softc_t base; /* storage for EHCI code */ }; @@ -71,6 +75,18 @@ static device_detach_t ar71xx_ehci_detach; bs_r_1_proto(reversed); bs_w_1_proto(reversed); +static void +ar71xx_ehci_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Force HOST mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode &= ~EHCI_UM_CM; + usbmode |= EHCI_UM_CM_HOST; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + static int ar71xx_ehci_probe(device_t self) { @@ -161,7 +177,8 @@ ar71xx_ehci_attach(device_t self) * which means port speed must be read from the Port Status * register following a port enable. */ - sc->sc_flags = EHCI_SCFLG_SETMODE; + sc->sc_flags = 0; + sc->sc_vendor_post_reset = ar71xx_ehci_post_reset; switch (ar71xx_soc) { case AR71XX_SOC_AR7241: @@ -178,6 +195,8 @@ ar71xx_ehci_attach(device_t self) case AR71XX_SOC_QCA9556: case AR71XX_SOC_QCA9558: sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; + sc->sc_vendor_get_port_speed = + ehci_get_port_speed_portsc; break; default: /* fallthrough */ diff --git a/sys/powerpc/ps3/ehci_ps3.c b/sys/powerpc/ps3/ehci_ps3.c index 2d57943a422c..63c31a5de063 100644 --- a/sys/powerpc/ps3/ehci_ps3.c +++ b/sys/powerpc/ps3/ehci_ps3.c @@ -69,6 +69,17 @@ struct ps3_ehci_softc { struct bus_space tag; }; +static void +ehci_ps3_post_reset(struct ehci_softc *ehci_softc) +{ + uint32_t usbmode; + + /* Select big-endian mode */ + usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); + usbmode |= EHCI_UM_ES_BE; + EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); +} + static int ehci_ps3_probe(device_t dev) { @@ -135,7 +146,7 @@ ehci_ps3_attach(device_t dev) goto error; } - sc->sc_flags |= EHCI_SCFLG_BIGEMMIO; + sc->sc_vendor_post_reset = ehci_ps3_post_reset; err = ehci_init(sc); if (err) { device_printf(dev, "USB init failed err=%d\n", err); From 2b71e630bdb9de13cdbe9ee805740855e32a1143 Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 15:30:58 +0000 Subject: [PATCH 009/236] Fix finding appropriate BGX node in DTB and move it to a separate function Search for BGX node in DTS in two ways: 1. Try to find it uder root node first 2. If not found under root, find the top level PCI bridge node and search all nodes below it until appropriate BGX node is found. Move search code to another function to make the code more clear. Remove unused variable by the way. Reviewed by: wma Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5066 --- sys/dev/vnic/thunder_bgx.c | 2 +- sys/dev/vnic/thunder_bgx_fdt.c | 150 ++++++++++++++++++++++++++++++--- sys/dev/vnic/thunder_bgx_var.h | 2 + 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/sys/dev/vnic/thunder_bgx.c b/sys/dev/vnic/thunder_bgx.c index 32d97c871cf6..349475459961 100644 --- a/sys/dev/vnic/thunder_bgx.c +++ b/sys/dev/vnic/thunder_bgx.c @@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$"); #define THUNDER_BGX_DEVSTR "ThunderX BGX Ethernet I/O Interface" -static MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory"); +MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory"); #define BGX_NODE_ID_MASK 0x1 #define BGX_NODE_ID_SHIFT 24 diff --git a/sys/dev/vnic/thunder_bgx_fdt.c b/sys/dev/vnic/thunder_bgx_fdt.c index 1560262c8cc0..23f5e4137575 100644 --- a/sys/dev/vnic/thunder_bgx_fdt.c +++ b/sys/dev/vnic/thunder_bgx_fdt.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include "thunder_bgx.h" @@ -61,6 +62,11 @@ __FBSDID("$FreeBSD$"); #define CONN_TYPE_MAXLEN 16 #define CONN_TYPE_OFFSET 2 +#define BGX_NODE_NAME "bgx" +#define BGX_MAXID 9 + +#define FDT_NAME_MAXLEN 31 + int bgx_fdt_init_phy(struct bgx *); static void @@ -119,28 +125,152 @@ bgx_fdt_phy_mode_match(struct bgx *bgx, char *qlm_mode, size_t size) return (FALSE); } +static phandle_t +bgx_fdt_traverse_nodes(phandle_t start, char *name, size_t len) +{ + phandle_t node, ret; + size_t buf_size; + char *node_name; + int err; + + buf_size = sizeof(*node_name) * FDT_NAME_MAXLEN; + if (len > buf_size) { + /* + * This is an erroneous situation since the string + * to compare cannot be longer than FDT_NAME_MAXLEN. + */ + return (0); + } + + node_name = malloc(buf_size, M_BGX, M_WAITOK); + for (node = OF_child(start); node != 0; node = OF_peer(node)) { + /* Clean-up the buffer */ + memset(node_name, 0, buf_size); + /* Recurse to children */ + if (OF_child(node) != 0) { + ret = bgx_fdt_traverse_nodes(node, name, len); + if (ret != 0) { + free(node_name, M_BGX); + return (ret); + } + } + err = OF_getprop(node, "name", node_name, FDT_NAME_MAXLEN); + if ((err > 0) && (strncmp(node_name, name, len) == 0)) { + free(node_name, M_BGX); + return (node); + } + } + free(node_name, M_BGX); + + return (0); +} + +/* + * Similar functionality to pci_find_pcie_root_port() + * but this one works for ThunderX. + */ +static device_t +bgx_find_root_pcib(device_t dev) +{ + devclass_t pci_class; + device_t pcib, bus; + + pci_class = devclass_find("pci"); + KASSERT(device_get_devclass(device_get_parent(dev)) == pci_class, + ("%s: non-pci device %s", __func__, device_get_nameunit(dev))); + + /* Walk the bridge hierarchy until we find a non-PCI device */ + for (;;) { + bus = device_get_parent(dev); + KASSERT(bus != NULL, ("%s: null parent of %s", __func__, + device_get_nameunit(dev))); + + if (device_get_devclass(bus) != pci_class) + return (NULL); + + pcib = device_get_parent(bus); + KASSERT(pcib != NULL, ("%s: null bridge of %s", __func__, + device_get_nameunit(bus))); + + /* + * If the parent of this PCIB is not PCI + * then we found our root PCIB. + */ + if (device_get_devclass(device_get_parent(pcib)) != pci_class) + return (pcib); + + dev = pcib; + } +} + +static __inline phandle_t +bgx_fdt_find_node(struct bgx *bgx) +{ + device_t root_pcib; + phandle_t node; + char *bgx_sel; + size_t len; + + KASSERT(bgx->bgx_id <= BGX_MAXID, + ("Invalid BGX ID: %d, max: %d", bgx->bgx_id, BGX_MAXID)); + + len = sizeof(BGX_NODE_NAME) + 1; /* ++<\0> */ + /* Allocate memory for BGX node name + "/" character */ + bgx_sel = malloc(sizeof(*bgx_sel) * (len + 1), M_BGX, + M_ZERO | M_WAITOK); + + /* Prepare node's name */ + snprintf(bgx_sel, len + 1, "/"BGX_NODE_NAME"%d", bgx->bgx_id); + /* First try the root node */ + node = OF_finddevice(bgx_sel); + if ((int)node > 0) { + /* Found relevant node */ + goto out; + } + /* + * Clean-up and try to find BGX in DT + * starting from the parent PCI bridge node. + */ + memset(bgx_sel, 0, sizeof(*bgx_sel) * (len + 1)); + snprintf(bgx_sel, len, BGX_NODE_NAME"%d", bgx->bgx_id); + + /* Find PCI bridge that we are connected to */ + + root_pcib = bgx_find_root_pcib(bgx->dev); + if (root_pcib == NULL) { + device_printf(bgx->dev, "Unable to find BGX root bridge\n"); + node = 0; + goto out; + } + + node = ofw_bus_get_node(root_pcib); + if (node == 0) { + device_printf(bgx->dev, "No parent FDT node for BGX\n"); + goto out; + } + + node = bgx_fdt_traverse_nodes(node, bgx_sel, len); +out: + free(bgx_sel, M_BGX); + return (node); +} + int bgx_fdt_init_phy(struct bgx *bgx) { phandle_t node, child; phandle_t phy, mdio; uint8_t lmac; - char bgx_sel[6]; char qlm_mode[CONN_TYPE_MAXLEN]; - const char *mac; - (void)mac; - - lmac = 0; - /* Get BGX node from DT */ - snprintf(bgx_sel, 6, "/bgx%d", bgx->bgx_id); - node = OF_finddevice(bgx_sel); - if (node == 0 || node == -1) { + node = bgx_fdt_find_node(bgx); + if (node == 0) { device_printf(bgx->dev, - "Could not find %s node in FDT\n", bgx_sel); + "Could not find bgx%d node in FDT\n", bgx->bgx_id); return (ENXIO); } + lmac = 0; for (child = OF_child(node); child > 0; child = OF_peer(child)) { if (OF_getprop(child, "qlm-mode", qlm_mode, sizeof(qlm_mode)) <= 0) { diff --git a/sys/dev/vnic/thunder_bgx_var.h b/sys/dev/vnic/thunder_bgx_var.h index bfb1ef0ccbb5..42f32d918210 100644 --- a/sys/dev/vnic/thunder_bgx_var.h +++ b/sys/dev/vnic/thunder_bgx_var.h @@ -30,6 +30,8 @@ #ifndef __THUNDER_BGX_VAR_H__ #define __THUNDER_BGX_VAR_H__ +MALLOC_DECLARE(M_BGX); + struct lmac { struct bgx *bgx; int dmac; From a4a7f925b592154694c3994b89ac838eb07592cf Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 15:34:13 +0000 Subject: [PATCH 010/236] Divide ThunderX PCIe driver to general and FDT part - Separate FDT and general PCIe driver parts - Drop some irrelevant printfs that cannot be displayed in FDT attach - Move ranges parsing to FDT portion of PCIe code Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5067 --- sys/arm64/cavium/thunder_pcie.c | 173 +------------------ sys/arm64/cavium/thunder_pcie_common.c | 2 + sys/arm64/cavium/thunder_pcie_common.h | 12 ++ sys/arm64/cavium/thunder_pcie_fdt.c | 219 +++++++++++++++++++++++++ sys/conf/files.arm64 | 3 +- 5 files changed, 238 insertions(+), 171 deletions(-) create mode 100644 sys/arm64/cavium/thunder_pcie_fdt.c diff --git a/sys/arm64/cavium/thunder_pcie.c b/sys/arm64/cavium/thunder_pcie.c index 9785739a858f..5de33980a03c 100644 --- a/sys/arm64/cavium/thunder_pcie.c +++ b/sys/arm64/cavium/thunder_pcie.c @@ -43,9 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include #include #include #include @@ -82,23 +79,6 @@ __FBSDID("$FreeBSD$"); #define THUNDER_ECAM6_CFG_BASE 0x94a000000000UL #define THUNDER_ECAM7_CFG_BASE 0x94b000000000UL -#define OFW_CELL_TO_UINT64(cell) \ - (((uint64_t)(*(cell)) << 32) | (uint64_t)(*((cell) + 1))) - -#define SPACE_CODE_SHIFT 24 -#define SPACE_CODE_MASK 0x3 -#define SPACE_CODE_IO_SPACE 0x1 -#define PROPS_CELL_SIZE 1 -#define PCI_ADDR_CELL_SIZE 2 - -struct thunder_pcie_softc { - struct pcie_range ranges[RANGES_TUPLES_MAX]; - struct rman mem_rman; - struct resource *res; - int ecam; - device_t dev; -}; - /* * ThunderX supports up to 4 ethernet interfaces, so it's good * value to use as default for numbers of VFs, since each eth @@ -111,11 +91,8 @@ SYSCTL_INT(_hw, OID_AUTO, thunder_pcie_max_vfs, CTLFLAG_RWTUN, /* Forward prototypes */ static struct resource *thunder_pcie_alloc_resource(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); -static int thunder_pcie_attach(device_t); static int thunder_pcie_identify_pcib(device_t); static int thunder_pcie_maxslots(device_t); -static int parse_pci_mem_ranges(struct thunder_pcie_softc *); -static int thunder_pcie_probe(device_t); static uint32_t thunder_pcie_read_config(device_t, u_int, u_int, u_int, u_int, int); static int thunder_pcie_read_ivar(device_t, device_t, int, uintptr_t *); @@ -125,23 +102,7 @@ static void thunder_pcie_write_config(device_t, u_int, u_int, u_int, u_int, uint32_t, int); static int thunder_pcie_write_ivar(device_t, device_t, int, uintptr_t); -static int -thunder_pcie_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (ofw_bus_is_compatible(dev, "cavium,thunder-pcie") || - ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-ecam")) { - device_set_desc(dev, "Cavium Integrated PCI/PCI-E Controller"); - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -static int +int thunder_pcie_attach(device_t dev) { int rid; @@ -167,13 +128,6 @@ thunder_pcie_attach(device_t dev) sc->mem_rman.rm_type = RMAN_ARRAY; sc->mem_rman.rm_descr = "PCIe Memory"; - /* Retrieve 'ranges' property from FDT */ - if (bootverbose) - device_printf(dev, "parsing FDT for ECAM%d:\n", - sc->ecam); - if (parse_pci_mem_ranges(sc)) - return (ENXIO); - /* Initialize rman and allocate memory regions */ error = rman_init(&sc->mem_rman); if (error) { @@ -199,115 +153,6 @@ thunder_pcie_attach(device_t dev) return (bus_generic_attach(dev)); } -static int -parse_pci_mem_ranges(struct thunder_pcie_softc *sc) -{ - phandle_t node; - pcell_t pci_addr_cells, parent_addr_cells, size_cells; - pcell_t attributes; - pcell_t *ranges_buf, *cell_ptr; - int cells_count, tuples_count; - int tuple; - int rv; - - node = ofw_bus_get_node(sc->dev); - - /* Find address cells if present */ - if (OF_getencprop(node, "#address-cells", &pci_addr_cells, - sizeof(pci_addr_cells)) < sizeof(pci_addr_cells)) - pci_addr_cells = 2; - - /* Find size cells if present */ - if (OF_getencprop(node, "#size-cells", &size_cells, - sizeof(size_cells)) < sizeof(size_cells)) - size_cells = 1; - - /* Find parent address cells if present */ - if (OF_getencprop(OF_parent(node), "#address-cells", - &parent_addr_cells, sizeof(parent_addr_cells)) < sizeof(parent_addr_cells)) - parent_addr_cells = 2; - - /* Check if FDT format matches driver requirements */ - if ((parent_addr_cells != 2) || (pci_addr_cells != 3) || - (size_cells != 2)) { - device_printf(sc->dev, - "Unexpected number of address or size cells in FDT " - " %d:%d:%d\n", - parent_addr_cells, pci_addr_cells, size_cells); - return (ENXIO); - } - - cells_count = OF_getencprop_alloc(node, "ranges", - sizeof(pcell_t), (void **)&ranges_buf); - if (cells_count == -1) { - device_printf(sc->dev, "Error parsing FDT 'ranges' property\n"); - return (ENXIO); - } - - tuples_count = cells_count / - (pci_addr_cells + parent_addr_cells + size_cells); - if (tuples_count > RANGES_TUPLES_MAX) { - device_printf(sc->dev, - "Unexpected number of 'ranges' tuples in FDT\n"); - rv = ENXIO; - goto out; - } - - cell_ptr = ranges_buf; - - for (tuple = 0; tuple < tuples_count; tuple++) { - /* - * TUPLE FORMAT: - * attributes - 32-bit attributes field - * PCI address - bus address combined of two cells in - * a following format: - * - * PA address - physical address combined of two cells in - * a following format: - * - * size - range size combined of two cells in - * a following format: - * - */ - attributes = *cell_ptr; - attributes = (attributes >> SPACE_CODE_SHIFT) & SPACE_CODE_MASK; - if (attributes == SPACE_CODE_IO_SPACE) { - /* Internal PCIe does not support IO space, ignore. */ - sc->ranges[tuple].phys_base = 0; - sc->ranges[tuple].size = 0; - cell_ptr += - (pci_addr_cells + parent_addr_cells + size_cells); - continue; - } - cell_ptr += PROPS_CELL_SIZE; - sc->ranges[tuple].pci_base = OFW_CELL_TO_UINT64(cell_ptr); - cell_ptr += PCI_ADDR_CELL_SIZE; - sc->ranges[tuple].phys_base = OFW_CELL_TO_UINT64(cell_ptr); - cell_ptr += parent_addr_cells; - sc->ranges[tuple].size = OFW_CELL_TO_UINT64(cell_ptr); - cell_ptr += size_cells; - - if (bootverbose) { - device_printf(sc->dev, - "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n", - sc->ranges[tuple].pci_base, - sc->ranges[tuple].phys_base, - sc->ranges[tuple].size); - } - - } - for (; tuple < RANGES_TUPLES_MAX; tuple++) { - /* zero-fill remaining tuples to mark empty elements in array */ - sc->ranges[tuple].phys_base = 0; - sc->ranges[tuple].size = 0; - } - - rv = 0; -out: - free(ranges_buf, M_OFWPROP); - return (rv); -} - static uint32_t thunder_pcie_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int bytes) @@ -558,8 +403,6 @@ thunder_pcie_identify_pcib(device_t dev) } static device_method_t thunder_pcie_methods[] = { - DEVMETHOD(device_probe, thunder_pcie_probe), - DEVMETHOD(device_attach, thunder_pcie_attach), DEVMETHOD(pcib_maxslots, thunder_pcie_maxslots), DEVMETHOD(pcib_read_config, thunder_pcie_read_config), DEVMETHOD(pcib_write_config, thunder_pcie_write_config), @@ -581,15 +424,5 @@ static device_method_t thunder_pcie_methods[] = { DEVMETHOD_END }; -static driver_t thunder_pcie_driver = { - "pcib", - thunder_pcie_methods, - sizeof(struct thunder_pcie_softc), -}; - -static devclass_t thunder_pcie_devclass; - -DRIVER_MODULE(thunder_pcib, simplebus, thunder_pcie_driver, -thunder_pcie_devclass, 0, 0); -DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_driver, -thunder_pcie_devclass, 0, 0); +DEFINE_CLASS_0(pcib, thunder_pcie_driver, thunder_pcie_methods, + sizeof(struct thunder_pcie_softc)); diff --git a/sys/arm64/cavium/thunder_pcie_common.c b/sys/arm64/cavium/thunder_pcie_common.c index e1b7fb2c0d95..aca1c725af59 100644 --- a/sys/arm64/cavium/thunder_pcie_common.c +++ b/sys/arm64/cavium/thunder_pcie_common.c @@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + #include #include #include diff --git a/sys/arm64/cavium/thunder_pcie_common.h b/sys/arm64/cavium/thunder_pcie_common.h index 731675b9b0b4..180cbda97f9b 100644 --- a/sys/arm64/cavium/thunder_pcie_common.h +++ b/sys/arm64/cavium/thunder_pcie_common.h @@ -32,6 +32,8 @@ #define RANGES_TUPLES_MAX 6 #define RANGES_TUPLES_INVALID (RANGES_TUPLES_MAX + 1) +DECLARE_CLASS(thunder_pcie_driver); + struct pcie_range { uint64_t pci_base; uint64_t phys_base; @@ -39,6 +41,14 @@ struct pcie_range { uint64_t flags; }; +struct thunder_pcie_softc { + struct pcie_range ranges[RANGES_TUPLES_MAX]; + struct rman mem_rman; + struct resource *res; + int ecam; + device_t dev; +}; + uint32_t range_addr_is_pci(struct pcie_range *, uint64_t, uint64_t); uint32_t range_addr_is_phys(struct pcie_range *, uint64_t, uint64_t); uint64_t range_addr_pci_to_phys(struct pcie_range *, uint64_t); @@ -48,4 +58,6 @@ int thunder_common_map_msi(device_t, device_t, int, uint64_t *, uint32_t *); int thunder_common_release_msi(device_t, device_t, int, int *); int thunder_common_release_msix(device_t, device_t, int); +int thunder_pcie_attach(device_t); + #endif /* _CAVIUM_THUNDER_PCIE_COMMON_H_ */ diff --git a/sys/arm64/cavium/thunder_pcie_fdt.c b/sys/arm64/cavium/thunder_pcie_fdt.c new file mode 100644 index 000000000000..79eb4edf13a4 --- /dev/null +++ b/sys/arm64/cavium/thunder_pcie_fdt.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2016 Cavium Inc. + * All rights reserved. + * + * Developed by Semihalf. + * + * 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. + */ +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "thunder_pcie_common.h" + +#define OFW_CELL_TO_UINT64(cell) \ + (((uint64_t)(*(cell)) << 32) | (uint64_t)(*((cell) + 1))) + +#define SPACE_CODE_SHIFT 24 +#define SPACE_CODE_MASK 0x3 +#define SPACE_CODE_IO_SPACE 0x1 +#define PROPS_CELL_SIZE 1 +#define PCI_ADDR_CELL_SIZE 2 + +static int thunder_pcie_fdt_probe(device_t); +static int thunder_pcie_fdt_attach(device_t); + +static device_method_t thunder_pcie_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, thunder_pcie_fdt_probe), + DEVMETHOD(device_attach, thunder_pcie_fdt_attach), + /* End */ + DEVMETHOD_END +}; + +DEFINE_CLASS_1(pcib, thunder_pcie_fdt_driver, thunder_pcie_fdt_methods, + sizeof(struct thunder_pcie_softc), thunder_pcie_driver); + +static devclass_t thunder_pcie_fdt_devclass; + +DRIVER_MODULE(thunder_pcib, simplebus, thunder_pcie_fdt_driver, + thunder_pcie_fdt_devclass, 0, 0); +DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_fdt_driver, + thunder_pcie_fdt_devclass, 0, 0); + +static int thunder_pcie_fdt_ranges(device_t); + +static int +thunder_pcie_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_is_compatible(dev, "cavium,thunder-pcie") || + ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-ecam")) { + device_set_desc(dev, "Cavium Integrated PCI/PCI-E Controller"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +thunder_pcie_fdt_attach(device_t dev) +{ + + /* Retrieve 'ranges' property from FDT */ + if (thunder_pcie_fdt_ranges(dev) != 0) + return (ENXIO); + + return (thunder_pcie_attach(dev)); +} + +static int +thunder_pcie_fdt_ranges(device_t dev) +{ + struct thunder_pcie_softc *sc; + phandle_t node; + pcell_t pci_addr_cells, parent_addr_cells, size_cells; + pcell_t attributes; + pcell_t *ranges_buf, *cell_ptr; + int cells_count, tuples_count; + int tuple; + int rv; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + + /* Find address cells if present */ + if (OF_getencprop(node, "#address-cells", &pci_addr_cells, + sizeof(pci_addr_cells)) < sizeof(pci_addr_cells)) + pci_addr_cells = 2; + + /* Find size cells if present */ + if (OF_getencprop(node, "#size-cells", &size_cells, + sizeof(size_cells)) < sizeof(size_cells)) + size_cells = 1; + + /* Find parent address cells if present */ + if (OF_getencprop(OF_parent(node), "#address-cells", + &parent_addr_cells, sizeof(parent_addr_cells)) < sizeof(parent_addr_cells)) + parent_addr_cells = 2; + + /* Check if FDT format matches driver requirements */ + if ((parent_addr_cells != 2) || (pci_addr_cells != 3) || + (size_cells != 2)) { + device_printf(dev, + "Unexpected number of address or size cells in FDT " + " %d:%d:%d\n", + parent_addr_cells, pci_addr_cells, size_cells); + return (ENXIO); + } + + cells_count = OF_getencprop_alloc(node, "ranges", + sizeof(pcell_t), (void **)&ranges_buf); + if (cells_count == -1) { + device_printf(dev, "Error parsing FDT 'ranges' property\n"); + return (ENXIO); + } + + tuples_count = cells_count / + (pci_addr_cells + parent_addr_cells + size_cells); + if (tuples_count > RANGES_TUPLES_MAX) { + device_printf(dev, + "Unexpected number of 'ranges' tuples in FDT\n"); + rv = ENXIO; + goto out; + } + + cell_ptr = ranges_buf; + + for (tuple = 0; tuple < tuples_count; tuple++) { + /* + * TUPLE FORMAT: + * attributes - 32-bit attributes field + * PCI address - bus address combined of two cells in + * a following format: + * + * PA address - physical address combined of two cells in + * a following format: + * + * size - range size combined of two cells in + * a following format: + * + */ + attributes = *cell_ptr; + attributes = (attributes >> SPACE_CODE_SHIFT) & SPACE_CODE_MASK; + if (attributes == SPACE_CODE_IO_SPACE) { + /* Internal PCIe does not support IO space, ignore. */ + sc->ranges[tuple].phys_base = 0; + sc->ranges[tuple].size = 0; + cell_ptr += + (pci_addr_cells + parent_addr_cells + size_cells); + continue; + } + cell_ptr += PROPS_CELL_SIZE; + sc->ranges[tuple].pci_base = OFW_CELL_TO_UINT64(cell_ptr); + cell_ptr += PCI_ADDR_CELL_SIZE; + sc->ranges[tuple].phys_base = OFW_CELL_TO_UINT64(cell_ptr); + cell_ptr += parent_addr_cells; + sc->ranges[tuple].size = OFW_CELL_TO_UINT64(cell_ptr); + cell_ptr += size_cells; + + if (bootverbose) { + device_printf(dev, + "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n", + sc->ranges[tuple].pci_base, + sc->ranges[tuple].phys_base, + sc->ranges[tuple].size); + } + + } + for (; tuple < RANGES_TUPLES_MAX; tuple++) { + /* zero-fill remaining tuples to mark empty elements in array */ + sc->ranges[tuple].phys_base = 0; + sc->ranges[tuple].size = 0; + } + + rv = 0; +out: + free(ranges_buf, M_OFWPROP); + return (rv); +} diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 6168d704ed18..118f064aa5f2 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -51,7 +51,8 @@ arm64/arm64/uma_machdep.c standard arm64/arm64/unwind.c optional ddb | kdtrace_hooks | stack arm64/arm64/vfp.c standard arm64/arm64/vm_machdep.c standard -arm64/cavium/thunder_pcie.c optional soc_cavm_thunderx pci fdt +arm64/cavium/thunder_pcie.c optional soc_cavm_thunderx pci +arm64/cavium/thunder_pcie_fdt.c optional soc_cavm_thunderx pci fdt arm64/cavium/thunder_pcie_pem.c optional soc_cavm_thunderx pci arm64/cavium/thunder_pcie_common.c optional soc_cavm_thunderx pci arm64/cloudabi64/cloudabi64_sysvec.c optional compat_cloudabi64 From 0f04b1d51e13d3825e8e209609a2d691453625f9 Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 15:38:02 +0000 Subject: [PATCH 011/236] Correct alloc_ and release_resource methods in thunder_pcie driver - Avoid using BUS_ macros as bus_generic_ functions should be used instead. - Fix mistaken device_t pointers in thunder_pcie_alloc_resource. Should use dev->parent method and allocate resource for child device Reviewed by: wma Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5068 --- sys/arm64/cavium/thunder_pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm64/cavium/thunder_pcie.c b/sys/arm64/cavium/thunder_pcie.c index 5de33980a03c..b04763949e46 100644 --- a/sys/arm64/cavium/thunder_pcie.c +++ b/sys/arm64/cavium/thunder_pcie.c @@ -268,7 +268,7 @@ thunder_pcie_release_resource(device_t dev, device_t child, int type, int rid, { if (type != SYS_RES_MEMORY) - return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, + return (bus_generic_release_resource(dev, child, type, rid, res)); return (rman_release_resource(res)); @@ -291,7 +291,7 @@ thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, rm = &sc->mem_rman; break; default: - return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); }; From 096bc4d6c4a620f1253b7ca74b9dc02cf3baf51d Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 15:40:56 +0000 Subject: [PATCH 012/236] Add FDT bus capabilities to ThunderX PCI driver New ThunderX firmware incorporates modified DTB that presents different device hierarchy. In the new device tree, MDIO devices are below two additional buses that oddly hang on PCI bridge. Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5069 --- sys/arm64/cavium/thunder_pcie.c | 9 +- sys/arm64/cavium/thunder_pcie_common.c | 3 + sys/arm64/cavium/thunder_pcie_common.h | 7 + sys/arm64/cavium/thunder_pcie_fdt.c | 181 +++++++++++++++++++++++-- 4 files changed, 185 insertions(+), 15 deletions(-) diff --git a/sys/arm64/cavium/thunder_pcie.c b/sys/arm64/cavium/thunder_pcie.c index b04763949e46..ca2fd6f7ea68 100644 --- a/sys/arm64/cavium/thunder_pcie.c +++ b/sys/arm64/cavium/thunder_pcie.c @@ -28,6 +28,7 @@ */ /* PCIe root complex driver for Cavium Thunder SOC */ +#include "opt_platform.h" #include __FBSDID("$FreeBSD$"); @@ -89,15 +90,11 @@ SYSCTL_INT(_hw, OID_AUTO, thunder_pcie_max_vfs, CTLFLAG_RWTUN, &thunder_pcie_max_vfs, 0, "Max VFs supported by ThunderX internal PCIe"); /* Forward prototypes */ -static struct resource *thunder_pcie_alloc_resource(device_t, - device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); static int thunder_pcie_identify_pcib(device_t); static int thunder_pcie_maxslots(device_t); static uint32_t thunder_pcie_read_config(device_t, u_int, u_int, u_int, u_int, int); static int thunder_pcie_read_ivar(device_t, device_t, int, uintptr_t *); -static int thunder_pcie_release_resource(device_t, device_t, int, int, - struct resource *); static void thunder_pcie_write_config(device_t, u_int, u_int, u_int, u_int, uint32_t, int); static int thunder_pcie_write_ivar(device_t, device_t, int, uintptr_t); @@ -262,7 +259,7 @@ thunder_pcie_write_ivar(device_t dev, device_t child, int index, return (ENOENT); } -static int +int thunder_pcie_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { @@ -274,7 +271,7 @@ thunder_pcie_release_resource(device_t dev, device_t child, int type, int rid, return (rman_release_resource(res)); } -static struct resource * +struct resource * thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { diff --git a/sys/arm64/cavium/thunder_pcie_common.c b/sys/arm64/cavium/thunder_pcie_common.c index aca1c725af59..58239f1eed9f 100644 --- a/sys/arm64/cavium/thunder_pcie_common.c +++ b/sys/arm64/cavium/thunder_pcie_common.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -44,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include "thunder_pcie_common.h" +MALLOC_DEFINE(M_THUNDER_PCIE, "Thunder PCIe driver", "Thunder PCIe driver memory"); + uint32_t range_addr_is_pci(struct pcie_range *ranges, uint64_t addr, uint64_t size) { diff --git a/sys/arm64/cavium/thunder_pcie_common.h b/sys/arm64/cavium/thunder_pcie_common.h index 180cbda97f9b..548a43518c68 100644 --- a/sys/arm64/cavium/thunder_pcie_common.h +++ b/sys/arm64/cavium/thunder_pcie_common.h @@ -34,6 +34,8 @@ DECLARE_CLASS(thunder_pcie_driver); +MALLOC_DECLARE(M_THUNDER_PCIE); + struct pcie_range { uint64_t pci_base; uint64_t phys_base; @@ -58,6 +60,11 @@ int thunder_common_map_msi(device_t, device_t, int, uint64_t *, uint32_t *); int thunder_common_release_msi(device_t, device_t, int, int *); int thunder_common_release_msix(device_t, device_t, int); +struct resource *thunder_pcie_alloc_resource(device_t, + device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); +int thunder_pcie_release_resource(device_t, device_t, int, int, + struct resource *); + int thunder_pcie_attach(device_t); #endif /* _CAVIUM_THUNDER_PCIE_COMMON_H_ */ diff --git a/sys/arm64/cavium/thunder_pcie_fdt.c b/sys/arm64/cavium/thunder_pcie_fdt.c index 79eb4edf13a4..bde453741802 100644 --- a/sys/arm64/cavium/thunder_pcie_fdt.c +++ b/sys/arm64/cavium/thunder_pcie_fdt.c @@ -60,10 +60,32 @@ __FBSDID("$FreeBSD$"); static int thunder_pcie_fdt_probe(device_t); static int thunder_pcie_fdt_attach(device_t); +static struct resource * thunder_pcie_ofw_bus_alloc_res(device_t, device_t, + int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); +static int thunder_pcie_ofw_bus_rel_res(device_t, device_t, int, int, + struct resource *); + +static const struct ofw_bus_devinfo *thunder_pcie_ofw_get_devinfo(device_t, + device_t); + static device_method_t thunder_pcie_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, thunder_pcie_fdt_probe), DEVMETHOD(device_attach, thunder_pcie_fdt_attach), + + /* Bus interface */ + DEVMETHOD(bus_alloc_resource, thunder_pcie_ofw_bus_alloc_res), + DEVMETHOD(bus_release_resource, thunder_pcie_ofw_bus_rel_res), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, thunder_pcie_ofw_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + /* End */ DEVMETHOD_END }; @@ -79,6 +101,7 @@ DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_fdt_driver, thunder_pcie_fdt_devclass, 0, 0); static int thunder_pcie_fdt_ranges(device_t); +static int thunder_pcie_ofw_bus_attach(device_t); static int thunder_pcie_fdt_probe(device_t dev) @@ -99,14 +122,32 @@ thunder_pcie_fdt_probe(device_t dev) static int thunder_pcie_fdt_attach(device_t dev) { + int err; /* Retrieve 'ranges' property from FDT */ if (thunder_pcie_fdt_ranges(dev) != 0) return (ENXIO); + err = thunder_pcie_ofw_bus_attach(dev); + if (err != 0) + return (err); + return (thunder_pcie_attach(dev)); } +static __inline void +get_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells) +{ + + *addr_cells = 2; + /* Find address cells if present */ + OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells)); + + *size_cells = 2; + /* Find size cells if present */ + OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells)); +} + static int thunder_pcie_fdt_ranges(device_t dev) { @@ -122,15 +163,7 @@ thunder_pcie_fdt_ranges(device_t dev) sc = device_get_softc(dev); node = ofw_bus_get_node(dev); - /* Find address cells if present */ - if (OF_getencprop(node, "#address-cells", &pci_addr_cells, - sizeof(pci_addr_cells)) < sizeof(pci_addr_cells)) - pci_addr_cells = 2; - - /* Find size cells if present */ - if (OF_getencprop(node, "#size-cells", &size_cells, - sizeof(size_cells)) < sizeof(size_cells)) - size_cells = 1; + get_addr_size_cells(node, &pci_addr_cells, &size_cells); /* Find parent address cells if present */ if (OF_getencprop(OF_parent(node), "#address-cells", @@ -217,3 +250,133 @@ thunder_pcie_fdt_ranges(device_t dev) free(ranges_buf, M_OFWPROP); return (rv); } + +/* OFW bus interface */ +struct thunder_pcie_ofw_devinfo { + struct ofw_bus_devinfo di_dinfo; + struct resource_list di_rl; +}; + +static const struct ofw_bus_devinfo * +thunder_pcie_ofw_get_devinfo(device_t bus __unused, device_t child) +{ + struct thunder_pcie_ofw_devinfo *di; + + di = device_get_ivars(child); + return (&di->di_dinfo); +} + +static struct resource * +thunder_pcie_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct thunder_pcie_softc *sc; + struct thunder_pcie_ofw_devinfo *di; + struct resource_list_entry *rle; + int i; + + /* For PCIe devices that do not have FDT nodes, use PCIB method */ + if (ofw_bus_get_node(child) == 0) { + return (thunder_pcie_alloc_resource(bus, child, type, rid, + start, end, count, flags)); + } + + sc = device_get_softc(bus); + + if ((start == 0UL) && (end == ~0UL)) { + if ((di = device_get_ivars(child)) == NULL) + return (NULL); + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + /* Find defaults for this rid */ + rle = resource_list_find(&di->di_rl, type, *rid); + if (rle == NULL) + return (NULL); + + start = rle->start; + end = rle->end; + count = rle->count; + } + + if (type == SYS_RES_MEMORY) { + /* Remap through ranges property */ + for (i = 0; i < RANGES_TUPLES_MAX; i++) { + if (start >= sc->ranges[i].phys_base && end < + sc->ranges[i].pci_base + sc->ranges[i].size) { + start -= sc->ranges[i].phys_base; + start += sc->ranges[i].pci_base; + end -= sc->ranges[i].phys_base; + end += sc->ranges[i].pci_base; + break; + } + } + + if (i == RANGES_TUPLES_MAX) { + device_printf(bus, "Could not map resource " + "%#lx-%#lx\n", start, end); + return (NULL); + } + } + + return (bus_generic_alloc_resource(bus, child, type, rid, start, end, + count, flags)); +} + +static int +thunder_pcie_ofw_bus_rel_res(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + /* For PCIe devices that do not have FDT nodes, use PCIB method */ + if (ofw_bus_get_node(child) == 0) { + return (thunder_pcie_release_resource(bus, + child, type, rid, res)); + } + + return (bus_generic_release_resource(bus, child, type, rid, res)); +} + +/* Helper functions */ + +static int +thunder_pcie_ofw_bus_attach(device_t dev) +{ + struct thunder_pcie_ofw_devinfo *di; + device_t child; + phandle_t parent, node; + pcell_t addr_cells, size_cells; + + parent = ofw_bus_get_node(dev); + if (parent > 0) { + get_addr_size_cells(parent, &addr_cells, &size_cells); + /* Iterate through all bus subordinates */ + for (node = OF_child(parent); node > 0; node = OF_peer(node)) { + /* Allocate and populate devinfo. */ + di = malloc(sizeof(*di), M_THUNDER_PCIE, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) { + free(di, M_THUNDER_PCIE); + continue; + } + + /* Initialize and populate resource list. */ + resource_list_init(&di->di_rl); + ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells, + &di->di_rl); + ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); + + /* Add newbus device for this FDT node */ + child = device_add_child(dev, NULL, -1); + if (child == NULL) { + resource_list_free(&di->di_rl); + ofw_bus_gen_destroy_devinfo(&di->di_dinfo); + free(di, M_THUNDER_PCIE); + continue; + } + + device_set_ivars(child, di); + } + } + + return (0); +} From af2b2e40e5332d8ce6df87884ad766152b295bf2 Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 15:44:14 +0000 Subject: [PATCH 013/236] Support new MDIO hierarchy in ThunderX DTB Some firmware revisions provide different DTB tree that include odd MDIO placement in the tree. This commit adds support for 2 new buses: - MRML bridge (PCIB subordinate) - MDIO nexus (MRML subordinate) This allows for the correct MDIO attachment with both - new and old firmware. Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5070 --- sys/conf/files.arm64 | 1 + sys/dev/vnic/mrml_bridge.c | 280 ++++++++++++++++++++++++++++++++ sys/dev/vnic/thunder_mdio_fdt.c | 204 ++++++++++++++++++++++- sys/dev/vnic/thunder_mdio_var.h | 1 + 4 files changed, 481 insertions(+), 5 deletions(-) create mode 100644 sys/dev/vnic/mrml_bridge.c diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 118f064aa5f2..3d5fc4679a79 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -71,6 +71,7 @@ dev/psci/psci_arm64.S optional psci dev/uart/uart_cpu_fdt.c optional uart fdt dev/uart/uart_dev_pl011.c optional uart pl011 dev/usb/controller/dwc_otg_hisi.c optional dwcotg soc_hisi_hi6220 +dev/vnic/mrml_bridge.c optional vnic fdt dev/vnic/nic_main.c optional vnic pci dev/vnic/nicvf_main.c optional vnic pci pci_iov dev/vnic/nicvf_queues.c optional vnic pci pci_iov diff --git a/sys/dev/vnic/mrml_bridge.c b/sys/dev/vnic/mrml_bridge.c new file mode 100644 index 000000000000..edc15717c4ae --- /dev/null +++ b/sys/dev/vnic/mrml_bridge.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2016 Cavium Inc. + * All rights reserved. + * + * Developed by Semihalf. + * + * 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. + */ +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static MALLOC_DEFINE(M_MRMLB, "MRML bridge", "Cavium MRML bridge"); + +static device_probe_t mrmlb_fdt_probe; +static device_attach_t mrmlb_fdt_attach; + +static struct resource * mrmlb_ofw_bus_alloc_res(device_t, device_t, int, int *, + rman_res_t, rman_res_t, rman_res_t, u_int); + +static const struct ofw_bus_devinfo * mrmlb_ofw_get_devinfo(device_t, device_t); + +static device_method_t mrmlbus_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, mrmlb_fdt_probe), + DEVMETHOD(device_attach, mrmlb_fdt_attach), + + /* Bus interface */ + DEVMETHOD(bus_alloc_resource, mrmlb_ofw_bus_alloc_res), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, mrmlb_ofw_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(mrmlbus, mrmlbus_fdt_driver, mrmlbus_fdt_methods, + sizeof(struct simplebus_softc)); + +static devclass_t mrmlbus_fdt_devclass; + +EARLY_DRIVER_MODULE(mrmlbus, pcib, mrmlbus_fdt_driver, mrmlbus_fdt_devclass, 0, 0, + BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); + +static int mrmlb_ofw_fill_ranges(phandle_t, struct simplebus_softc *); +static int mrmlb_ofw_bus_attach(device_t); + +static int +mrmlb_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "cavium,thunder-8890-mrml-bridge")) + return (ENXIO); + + device_set_desc(dev, "Cavium ThunderX MRML bridge"); + return (BUS_PROBE_SPECIFIC); +} + +static int +mrmlb_fdt_attach(device_t dev) +{ + int err; + + err = mrmlb_ofw_bus_attach(dev); + if (err != 0) + return (err); + + return (bus_generic_attach(dev)); +} + +/* OFW bus interface */ +struct mrmlb_ofw_devinfo { + struct ofw_bus_devinfo di_dinfo; + struct resource_list di_rl; +}; + +static const struct ofw_bus_devinfo * +mrmlb_ofw_get_devinfo(device_t bus __unused, device_t child) +{ + struct mrmlb_ofw_devinfo *di; + + di = device_get_ivars(child); + return (&di->di_dinfo); +} + +static struct resource * +mrmlb_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct simplebus_softc *sc; + struct mrmlb_ofw_devinfo *di; + struct resource_list_entry *rle; + int i; + + if ((start == 0UL) && (end == ~0UL)) { + if ((di = device_get_ivars(child)) == NULL) + return (NULL); + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + /* Find defaults for this rid */ + rle = resource_list_find(&di->di_rl, type, *rid); + if (rle == NULL) + return (NULL); + + start = rle->start; + end = rle->end; + count = rle->count; + } + + sc = device_get_softc(bus); + + if (type == SYS_RES_MEMORY) { + /* Remap through ranges property */ + for (i = 0; i < sc->nranges; i++) { + if (start >= sc->ranges[i].bus && end < + sc->ranges[i].bus + sc->ranges[i].size) { + start -= sc->ranges[i].bus; + start += sc->ranges[i].host; + end -= sc->ranges[i].bus; + end += sc->ranges[i].host; + break; + } + } + + if (i == sc->nranges && sc->nranges != 0) { + device_printf(bus, "Could not map resource " + "%#lx-%#lx\n", start, end); + return (NULL); + } + } + + return (bus_generic_alloc_resource(bus, child, type, rid, start, end, + count, flags)); +} + +/* Helper functions */ + +static int +mrmlb_ofw_fill_ranges(phandle_t node, struct simplebus_softc *sc) +{ + int host_address_cells; + cell_t *base_ranges; + ssize_t nbase_ranges; + int err; + int i, j, k; + + err = OF_searchencprop(OF_parent(node), "#address-cells", + &host_address_cells, sizeof(host_address_cells)); + if (err <= 0) + return (-1); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges < 0) + return (-1); + sc->nranges = nbase_ranges / sizeof(cell_t) / + (sc->acells + host_address_cells + sc->scells); + if (sc->nranges == 0) + return (0); + + sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), + M_MRMLB, M_WAITOK); + base_ranges = malloc(nbase_ranges, M_MRMLB, M_WAITOK); + OF_getencprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < sc->nranges; i++) { + sc->ranges[i].bus = 0; + for (k = 0; k < sc->acells; k++) { + sc->ranges[i].bus <<= 32; + sc->ranges[i].bus |= base_ranges[j++]; + } + sc->ranges[i].host = 0; + for (k = 0; k < host_address_cells; k++) { + sc->ranges[i].host <<= 32; + sc->ranges[i].host |= base_ranges[j++]; + } + sc->ranges[i].size = 0; + for (k = 0; k < sc->scells; k++) { + sc->ranges[i].size <<= 32; + sc->ranges[i].size |= base_ranges[j++]; + } + } + + free(base_ranges, M_MRMLB); + return (sc->nranges); +} + +static int +mrmlb_ofw_bus_attach(device_t dev) +{ + struct simplebus_softc *sc; + struct mrmlb_ofw_devinfo *di; + device_t child; + phandle_t parent, node; + + parent = ofw_bus_get_node(dev); + simplebus_init(dev, parent); + + sc = device_get_softc(dev); + + if (mrmlb_ofw_fill_ranges(parent, sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + /* Iterate through all bus subordinates */ + for (node = OF_child(parent); node > 0; node = OF_peer(node)) { + /* Allocate and populate devinfo. */ + di = malloc(sizeof(*di), M_MRMLB, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) { + free(di, M_MRMLB); + continue; + } + + /* Initialize and populate resource list. */ + resource_list_init(&di->di_rl); + ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, + &di->di_rl); + ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); + + /* Add newbus device for this FDT node */ + child = device_add_child(dev, NULL, -1); + if (child == NULL) { + resource_list_free(&di->di_rl); + ofw_bus_gen_destroy_devinfo(&di->di_dinfo); + free(di, M_MRMLB); + continue; + } + + device_set_ivars(child, di); + } + + return (0); +} diff --git a/sys/dev/vnic/thunder_mdio_fdt.c b/sys/dev/vnic/thunder_mdio_fdt.c index b24be1dc3ee6..cc9415050388 100644 --- a/sys/dev/vnic/thunder_mdio_fdt.c +++ b/sys/dev/vnic/thunder_mdio_fdt.c @@ -38,6 +38,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include +#include #include "thunder_mdio_var.h" @@ -60,17 +64,26 @@ static devclass_t thunder_mdio_fdt_devclass; EARLY_DRIVER_MODULE(thunder_mdio, ofwbus, thunder_mdio_fdt_driver, thunder_mdio_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(thunder_mdio, mdionexus, thunder_mdio_fdt_driver, + thunder_mdio_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); + +static struct ofw_compat_data mdio_compat_data[] = { + {"cavium,octeon-3860-mdio", true}, + {"cavium,thunder-8890-mdio", true}, + {NULL, false} +}; static int thunder_mdio_fdt_probe(device_t dev) { - if (ofw_bus_is_compatible(dev, "cavium,octeon-3860-mdio")) { - device_set_desc(dev, THUNDER_MDIO_DEVSTR); - return (BUS_PROBE_DEFAULT); - } + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + if (!ofw_bus_search_compatible(dev, mdio_compat_data)->ocd_data) + return (ENXIO); - return (ENXIO); + device_set_desc(dev, THUNDER_MDIO_DEVSTR); + return (BUS_PROBE_DEFAULT); } static int @@ -93,3 +106,184 @@ thunder_mdio_fdt_attach(device_t dev) return (0); } + +struct mdionexus_softc { + struct simplebus_softc simplebus_sc; +}; + +static device_probe_t mdionexus_fdt_probe; +static device_attach_t mdionexus_fdt_attach; + +static const struct ofw_bus_devinfo * mdionexus_ofw_get_devinfo(device_t, + device_t); + +static device_method_t mdionexus_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, mdionexus_fdt_probe), + DEVMETHOD(device_attach, mdionexus_fdt_attach), + + /* Bus interface */ + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, mdionexus_ofw_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(mdionexus, mdionexus_fdt_driver, mdionexus_fdt_methods, + sizeof(struct mdionexus_softc)); + +static devclass_t mdionexus_fdt_devclass; + +EARLY_DRIVER_MODULE(mdionexus, mrmlbus, mdionexus_fdt_driver, + mdionexus_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); + +static int mdionexus_ofw_fill_ranges(phandle_t, struct simplebus_softc *); +static int mdionexus_ofw_bus_attach(device_t); + +static int +mdionexus_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "cavium,thunder-8890-mdio-nexus")) + return (ENXIO); + + device_set_desc(dev, "Cavium ThunderX MDIO nexus"); + return (BUS_PROBE_SPECIFIC); +} + +static int +mdionexus_fdt_attach(device_t dev) +{ + int err; + + err = mdionexus_ofw_bus_attach(dev); + if (err != 0) + return (err); + + return (bus_generic_attach(dev)); +} + +/* OFW bus interface */ +struct mdionexus_ofw_devinfo { + struct ofw_bus_devinfo di_dinfo; + struct resource_list di_rl; +}; + +static const struct ofw_bus_devinfo * +mdionexus_ofw_get_devinfo(device_t bus __unused, device_t child) +{ + struct mdionexus_ofw_devinfo *di; + + di = device_get_ivars(child); + return (&di->di_dinfo); +} + +/* Helper functions */ + +static int +mdionexus_ofw_fill_ranges(phandle_t node, struct simplebus_softc *sc) +{ + int host_address_cells; + cell_t *base_ranges; + ssize_t nbase_ranges; + int err; + int i, j, k; + + err = OF_searchencprop(OF_parent(node), "#address-cells", + &host_address_cells, sizeof(host_address_cells)); + if (err <= 0) + return (-1); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges < 0) + return (-1); + sc->nranges = nbase_ranges / sizeof(cell_t) / + (sc->acells + host_address_cells + sc->scells); + if (sc->nranges == 0) + return (0); + + sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), + M_THUNDER_MDIO, M_WAITOK); + base_ranges = malloc(nbase_ranges, M_THUNDER_MDIO, M_WAITOK); + OF_getencprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < sc->nranges; i++) { + sc->ranges[i].bus = 0; + for (k = 0; k < sc->acells; k++) { + sc->ranges[i].bus <<= 32; + sc->ranges[i].bus |= base_ranges[j++]; + } + sc->ranges[i].host = 0; + for (k = 0; k < host_address_cells; k++) { + sc->ranges[i].host <<= 32; + sc->ranges[i].host |= base_ranges[j++]; + } + sc->ranges[i].size = 0; + for (k = 0; k < sc->scells; k++) { + sc->ranges[i].size <<= 32; + sc->ranges[i].size |= base_ranges[j++]; + } + } + + free(base_ranges, M_THUNDER_MDIO); + return (sc->nranges); +} + +static int +mdionexus_ofw_bus_attach(device_t dev) +{ + struct simplebus_softc *sc; + struct mdionexus_ofw_devinfo *di; + device_t child; + phandle_t parent, node; + + parent = ofw_bus_get_node(dev); + simplebus_init(dev, parent); + + sc = (struct simplebus_softc *)device_get_softc(dev); + + if (mdionexus_ofw_fill_ranges(parent, sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + /* Iterate through all bus subordinates */ + for (node = OF_child(parent); node > 0; node = OF_peer(node)) { + /* Allocate and populate devinfo. */ + di = malloc(sizeof(*di), M_THUNDER_MDIO, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) { + free(di, M_THUNDER_MDIO); + continue; + } + + /* Initialize and populate resource list. */ + resource_list_init(&di->di_rl); + ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, + &di->di_rl); + ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); + + /* Add newbus device for this FDT node */ + child = device_add_child(dev, NULL, -1); + if (child == NULL) { + resource_list_free(&di->di_rl); + ofw_bus_gen_destroy_devinfo(&di->di_dinfo); + free(di, M_THUNDER_MDIO); + continue; + } + + device_set_ivars(child, di); + } + + return (0); +} diff --git a/sys/dev/vnic/thunder_mdio_var.h b/sys/dev/vnic/thunder_mdio_var.h index 01c4ca7f637c..73fedcc77811 100644 --- a/sys/dev/vnic/thunder_mdio_var.h +++ b/sys/dev/vnic/thunder_mdio_var.h @@ -34,6 +34,7 @@ #define __THUNDER_MDIO_VAR_H__ #define THUNDER_MDIO_DEVSTR "Cavium ThunderX SMI/MDIO driver" +MALLOC_DECLARE(M_THUNDER_MDIO); DECLARE_CLASS(thunder_mdio_driver); enum thunder_mdio_mode { From 845cb3f3dcb5412e840fba96d7572b9aa181d76d Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 Jan 2016 16:05:46 +0000 Subject: [PATCH 014/236] Always look in the TCP pool. This fixes issues with a restarting peer when the listening 1-to-1 style socket is closed. MFC after: 3 days --- sys/netinet/sctp_input.c | 3 +++ sys/netinet/sctp_pcb.c | 17 ++--------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 9edfcf67808a..87be2d4b1a82 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5688,6 +5688,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } +printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif @@ -5719,6 +5720,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } +printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif @@ -5831,6 +5833,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } +printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index d4a9dff0bb22..a3efcab0a575 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -2256,7 +2256,6 @@ sctp_findassociation_addr(struct mbuf *m, int offset, struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) { - int find_tcp_pool; struct sctp_tcb *stcb; struct sctp_inpcb *inp; @@ -2268,25 +2267,13 @@ sctp_findassociation_addr(struct mbuf *m, int offset, return (stcb); } } - find_tcp_pool = 0; - /* - * 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. */ - find_tcp_pool = 1; - } if (inp_p) { stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp, - find_tcp_pool, vrf_id); + 1, vrf_id); inp = *inp_p; } else { stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp, - find_tcp_pool, vrf_id); + 1, vrf_id); } SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp); if (stcb == NULL && inp) { From 482bbdb4222e936ab0ab18b5b14a366b4339aca4 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 28 Jan 2016 16:51:56 +0000 Subject: [PATCH 015/236] Use m_getjcl() instead of manually selecting zone. Reviewed by: arybchik --- sys/dev/sfxge/sfxge.h | 2 +- sys/dev/sfxge/sfxge_rx.c | 30 ++++++------------------------ 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h index 9ff84c03a0b7..8c1d63657b7e 100644 --- a/sys/dev/sfxge/sfxge.h +++ b/sys/dev/sfxge/sfxge.h @@ -273,7 +273,7 @@ struct sfxge_softc { size_t rx_prefix_size; size_t rx_buffer_size; size_t rx_buffer_align; - uma_zone_t rx_buffer_zone; + int rx_cluster_size; unsigned int evq_max; unsigned int evq_count; diff --git a/sys/dev/sfxge/sfxge_rx.c b/sys/dev/sfxge/sfxge_rx.c index 3782c3496674..5ee946872867 100644 --- a/sys/dev/sfxge/sfxge_rx.c +++ b/sys/dev/sfxge/sfxge_rx.c @@ -205,25 +205,6 @@ sfxge_rx_schedule_refill(struct sfxge_rxq *rxq, boolean_t retrying) sfxge_rx_post_refill, rxq); } -static struct mbuf *sfxge_rx_alloc_mbuf(struct sfxge_softc *sc) -{ - struct mb_args args; - struct mbuf *m; - - /* Allocate mbuf structure */ - args.flags = M_PKTHDR; - args.type = MT_DATA; - m = (struct mbuf *)uma_zalloc_arg(zone_mbuf, &args, M_NOWAIT); - - /* Allocate (and attach) packet buffer */ - if (m != NULL && !uma_zalloc_arg(sc->rx_buffer_zone, m, M_NOWAIT)) { - uma_zfree(zone_mbuf, m); - m = NULL; - } - - return (m); -} - #define SFXGE_REFILL_BATCH 64 static void @@ -273,7 +254,8 @@ sfxge_rx_qfill(struct sfxge_rxq *rxq, unsigned int target, boolean_t retrying) KASSERT(rx_desc->mbuf == NULL, ("rx_desc->mbuf != NULL")); rx_desc->flags = EFX_DISCARD; - m = rx_desc->mbuf = sfxge_rx_alloc_mbuf(sc); + m = rx_desc->mbuf = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, + sc->rx_cluster_size); if (m == NULL) break; @@ -1125,13 +1107,13 @@ sfxge_rx_start(struct sfxge_softc *sc) /* Select zone for packet buffers */ if (reserved <= MCLBYTES) - sc->rx_buffer_zone = zone_clust; + sc->rx_cluster_size = MCLBYTES; else if (reserved <= MJUMPAGESIZE) - sc->rx_buffer_zone = zone_jumbop; + sc->rx_cluster_size = MJUMPAGESIZE; else if (reserved <= MJUM9BYTES) - sc->rx_buffer_zone = zone_jumbo9; + sc->rx_cluster_size = MJUM9BYTES; else - sc->rx_buffer_zone = zone_jumbo16; + sc->rx_cluster_size = MJUM16BYTES; /* * Set up the scale table. Enable all hash types and hash insertion. From 792baee6b7e046d5fba07463a8c505674df55600 Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 28 Jan 2016 16:58:49 +0000 Subject: [PATCH 016/236] Fix VNIC enumeration after r294993 and r294990 ofw_bus_get_node() must be tested against negative values since missing parent bus method will result in calling the default method which simply returns (-1): sys/dev/ofw/ofw_bus_if.m This was lost in the review process. Obtained from: Semihalf Sponsored by: Cavium --- sys/arm64/cavium/thunder_pcie_fdt.c | 4 ++-- sys/dev/vnic/thunder_bgx_fdt.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/arm64/cavium/thunder_pcie_fdt.c b/sys/arm64/cavium/thunder_pcie_fdt.c index bde453741802..f1624f615484 100644 --- a/sys/arm64/cavium/thunder_pcie_fdt.c +++ b/sys/arm64/cavium/thunder_pcie_fdt.c @@ -276,7 +276,7 @@ thunder_pcie_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid, int i; /* For PCIe devices that do not have FDT nodes, use PCIB method */ - if (ofw_bus_get_node(child) == 0) { + if ((int)ofw_bus_get_node(child) <= 0) { return (thunder_pcie_alloc_resource(bus, child, type, rid, start, end, count, flags)); } @@ -329,7 +329,7 @@ thunder_pcie_ofw_bus_rel_res(device_t bus, device_t child, int type, int rid, { /* For PCIe devices that do not have FDT nodes, use PCIB method */ - if (ofw_bus_get_node(child) == 0) { + if ((int)ofw_bus_get_node(child) <= 0) { return (thunder_pcie_release_resource(bus, child, type, rid, res)); } diff --git a/sys/dev/vnic/thunder_bgx_fdt.c b/sys/dev/vnic/thunder_bgx_fdt.c index 23f5e4137575..ec6e68f64850 100644 --- a/sys/dev/vnic/thunder_bgx_fdt.c +++ b/sys/dev/vnic/thunder_bgx_fdt.c @@ -244,7 +244,7 @@ bgx_fdt_find_node(struct bgx *bgx) } node = ofw_bus_get_node(root_pcib); - if (node == 0) { + if ((int)node <= 0) { device_printf(bgx->dev, "No parent FDT node for BGX\n"); goto out; } From 71cece53f20ad0348c8e6a83b032a4bcfa42cdcf Mon Sep 17 00:00:00 2001 From: jkim Date: Thu, 28 Jan 2016 18:41:59 +0000 Subject: [PATCH 017/236] Import OpenSSL 1.0.2f. --- ACKNOWLEDGMENTS | 32 +------- CHANGES | 48 ++++++++++++ Configure | 33 ++++---- FREEBSD-upgrade | 4 +- INSTALL | 8 +- LICENSE | 2 +- Makefile | 40 +++++----- Makefile.org | 38 +++++----- NEWS | 5 ++ README | 13 ++-- apps/engine.c | 2 +- apps/ocsp.c | 2 +- apps/pkcs12.c | 42 ++++------- apps/pkeyutl.c | 38 +++++++--- apps/s_client.c | 2 +- apps/s_server.c | 2 +- apps/speed.c | 2 +- apps/x509.c | 7 +- crypto/aes/aes.h | 2 +- crypto/aes/aes_cbc.c | 2 +- crypto/aes/aes_cfb.c | 2 +- crypto/aes/aes_core.c | 2 +- crypto/aes/aes_ctr.c | 2 +- crypto/aes/aes_ecb.c | 2 +- crypto/aes/aes_ige.c | 2 +- crypto/aes/aes_locl.h | 2 +- crypto/aes/aes_misc.c | 2 +- crypto/aes/aes_ofb.c | 2 +- crypto/aes/aes_x86core.c | 2 +- crypto/aes/asm/aesni-mb-x86_64.pl | 2 +- crypto/aes/asm/aesni-sha1-x86_64.pl | 2 +- crypto/aes/asm/aesni-sha256-x86_64.pl | 2 +- crypto/bio/bio.h | 8 +- crypto/bio/bss_bio.c | 2 +- crypto/bio/bss_conn.c | 31 +++++--- crypto/bio/bss_dgram.c | 2 - crypto/bn/asm/rsaz-x86_64.pl | 2 +- crypto/bn/asm/x86_64-mont.pl | 2 +- crypto/bn/asm/x86_64-mont5.pl | 2 +- crypto/bn/bn_exp.c | 41 +++++++--- crypto/bn/exptest.c | 82 +++++++++++++++++--- crypto/camellia/camellia.c | 4 +- crypto/camellia/camellia.h | 2 +- crypto/camellia/cmll_cbc.c | 2 +- crypto/camellia/cmll_cfb.c | 2 +- crypto/camellia/cmll_ctr.c | 2 +- crypto/camellia/cmll_ecb.c | 2 +- crypto/camellia/cmll_locl.h | 2 +- crypto/camellia/cmll_misc.c | 2 +- crypto/camellia/cmll_ofb.c | 2 +- crypto/camellia/cmll_utl.c | 2 +- crypto/des/des_old.c | 2 +- crypto/des/des_old.h | 2 +- crypto/des/des_old2.c | 2 +- crypto/dh/dh.h | 1 + crypto/dh/dh_check.c | 35 ++++++--- crypto/dh/dhtest.c | 87 +++++++++++++++++++++- crypto/dsa/dsa_ossl.c | 8 +- crypto/dso/dso.h | 2 +- crypto/dso/dso_dl.c | 2 +- crypto/dso/dso_dlfcn.c | 2 +- crypto/dso/dso_lib.c | 2 +- crypto/ec/asm/ecp_nistz256-x86_64.pl | 2 +- crypto/ec/ec2_smpl.c | 1 + crypto/ec/ec_key.c | 2 + crypto/ec/ecp_nistz256_table.c | 2 +- crypto/ec/ectest.c | 2 +- crypto/engine/eng_all.c | 2 +- crypto/evp/e_camellia.c | 2 +- crypto/evp/e_old.c | 2 +- crypto/evp/e_seed.c | 2 +- crypto/mem_clr.c | 2 +- crypto/modes/asm/aesni-gcm-x86_64.pl | 2 +- crypto/modes/asm/ghash-x86_64.pl | 2 +- crypto/o_dir.c | 2 +- crypto/o_dir.h | 2 +- crypto/o_dir_test.c | 2 +- crypto/o_str.c | 2 +- crypto/o_str.h | 2 +- crypto/o_time.c | 2 +- crypto/o_time.h | 2 +- crypto/opensslv.h | 6 +- crypto/rc4/rc4_utl.c | 2 +- crypto/rsa/rsa_chk.c | 2 +- crypto/rsa/rsa_sign.c | 4 +- crypto/seed/seed_cbc.c | 2 +- crypto/seed/seed_cfb.c | 2 +- crypto/seed/seed_ecb.c | 2 +- crypto/seed/seed_ofb.c | 2 +- crypto/sha/asm/sha1-mb-x86_64.pl | 2 +- crypto/sha/asm/sha1-x86_64.pl | 2 +- crypto/sha/asm/sha256-mb-x86_64.pl | 2 +- crypto/sha/asm/sha512-x86_64.pl | 2 +- crypto/sha/sha1test.c | 2 +- crypto/store/store.h | 2 +- crypto/store/str_lib.c | 2 +- crypto/store/str_locl.h | 2 +- crypto/store/str_mem.c | 2 +- crypto/store/str_meth.c | 2 +- crypto/ts/ts_rsp_verify.c | 3 +- crypto/ui/ui.h | 2 +- crypto/ui/ui_compat.c | 2 +- crypto/ui/ui_compat.h | 2 +- crypto/ui/ui_lib.c | 2 +- crypto/ui/ui_locl.h | 2 +- crypto/ui/ui_openssl.c | 2 +- crypto/ui/ui_util.c | 2 +- crypto/x509/x509_vfy.c | 39 ++++++---- crypto/x509/x509_vfy.h | 2 +- crypto/x509/x509_vpm.c | 4 +- crypto/x509v3/v3_pci.c | 2 +- crypto/x509v3/v3_pcia.c | 2 +- crypto/x509v3/v3_utl.c | 3 +- crypto/x509v3/v3nametest.c | 10 +++ doc/apps/s_time.pod | 4 +- doc/crypto/BIO_s_connect.pod | 4 +- doc/ssl/SSL_CTX_set1_verify_cert_store.pod | 8 +- doc/ssl/SSL_CTX_set_tlsext_status_cb.pod | 73 ++++++++++++++++++ doc/ssl/SSL_CTX_set_tmp_dh_callback.pod | 29 ++------ engines/e_chil.c | 2 +- ssl/d1_both.c | 70 +++++++++++------ ssl/kssl.c | 2 +- ssl/kssl.h | 2 +- ssl/kssl_lcl.h | 2 +- ssl/s2_srvr.c | 20 ++++- ssl/s3_clnt.c | 63 +++++++++------- ssl/s3_lib.c | 34 +++++---- ssl/s3_srvr.c | 25 +++---- ssl/ssl.h | 6 +- ssl/ssl_err.c | 2 + ssl/ssl_lib.c | 5 +- ssl/ssl_sess.c | 3 - ssl/t1_enc.c | 2 +- ssl/t1_lib.c | 22 +++--- util/domd | 4 +- util/pl/VC-32.pl | 8 +- util/pod2mantest | 58 +++++++++++++++ 137 files changed, 847 insertions(+), 446 deletions(-) create mode 100644 doc/ssl/SSL_CTX_set_tlsext_status_cb.pod create mode 100755 util/pod2mantest diff --git a/ACKNOWLEDGMENTS b/ACKNOWLEDGMENTS index 59c6f01f97f6..d21dccbb79cf 100644 --- a/ACKNOWLEDGMENTS +++ b/ACKNOWLEDGMENTS @@ -1,30 +1,2 @@ -The OpenSSL project depends on volunteer efforts and financial support from -the end user community. That support comes in the form of donations and paid -sponsorships, software support contracts, paid consulting services -and commissioned software development. - -Since all these activities support the continued development and improvement -of OpenSSL we consider all these clients and customers as sponsors of the -OpenSSL project. - -We would like to identify and thank the following such sponsors for their past -or current significant support of the OpenSSL project: - -Major support: - - Qualys http://www.qualys.com/ - -Very significant support: - - OpenGear: http://www.opengear.com/ - -Significant support: - - PSW Group: http://www.psw.net/ - Acano Ltd. http://acano.com/ - -Please note that we ask permission to identify sponsors and that some sponsors -we consider eligible for inclusion here have requested to remain anonymous. - -Additional sponsorship or financial support is always welcome: for more -information please contact the OpenSSL Software Foundation. +Please https://www.openssl.org/community/thanks.html for the current +acknowledgements. diff --git a/CHANGES b/CHANGES index 5e9225b57cd9..18693f70efe9 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,54 @@ OpenSSL CHANGES _______________ + Changes between 1.0.2e and 1.0.2f [28 Jan 2016] + + *) DH small subgroups + + Historically OpenSSL only ever generated DH parameters based on "safe" + primes. More recently (in version 1.0.2) support was provided for + generating X9.42 style parameter files such as those required for RFC 5114 + support. The primes used in such files may not be "safe". Where an + application is using DH configured with parameters based on primes that are + not "safe" then an attacker could use this fact to find a peer's private + DH exponent. This attack requires that the attacker complete multiple + handshakes in which the peer uses the same private DH exponent. For example + this could be used to discover a TLS server's private DH exponent if it's + reusing the private DH exponent or it's using a static DH ciphersuite. + + OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in + TLS. It is not on by default. If the option is not set then the server + reuses the same private DH exponent for the life of the server process and + would be vulnerable to this attack. It is believed that many popular + applications do set this option and would therefore not be at risk. + + The fix for this issue adds an additional check where a "q" parameter is + available (as is the case in X9.42 based parameters). This detects the + only known attack, and is the only possible defense for static DH + ciphersuites. This could have some performance impact. + + Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by + default and cannot be disabled. This could have some performance impact. + + This issue was reported to OpenSSL by Antonio Sanso (Adobe). + (CVE-2016-0701) + [Matt Caswell] + + *) SSLv2 doesn't block disabled ciphers + + A malicious client can negotiate SSLv2 ciphers that have been disabled on + the server and complete SSLv2 handshakes even if all SSLv2 ciphers have + been disabled, provided that the SSLv2 protocol was not also disabled via + SSL_OP_NO_SSLv2. + + This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram + and Sebastian Schinzel. + (CVE-2015-3197) + [Viktor Dukhovni] + + *) Reject DH handshakes with parameters shorter than 1024 bits. + [Kurt Roeckx] + Changes between 1.0.2d and 1.0.2e [3 Dec 2015] *) BN_mod_exp may produce incorrect results on x86_64 diff --git a/Configure b/Configure index ac86cd6cf6a2..4a715dc43732 100755 --- a/Configure +++ b/Configure @@ -124,6 +124,9 @@ my $clang_disabled_warnings = "-Wno-unused-parameter -Wno-missing-field-initiali # -Wextended-offsetof my $clang_devteam_warn = "-Wno-unused-parameter -Wno-missing-field-initializers -Wno-language-extension-token -Wno-extended-offsetof -Qunused-arguments"; +# Warn that "make depend" should be run? +my $warn_make_depend = 0; + my $strict_warnings = 0; my $x86_gcc_des="DES_PTR DES_RISC1 DES_UNROLL"; @@ -1513,7 +1516,7 @@ if ($target =~ /\-icc$/) # Intel C compiler # linker only when --prefix is not /usr. if ($target =~ /^BSD\-/) { - $shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|); + $shared_ldflag.=" -Wl,-rpath,\$\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|); } if ($sys_id ne "") @@ -2028,14 +2031,8 @@ EOF &dofile("apps/CA.pl",'/usr/local/bin/perl','^#!/', '#!%s'); } if ($depflags ne $default_depflags && !$make_depend) { - print < (note that your message will be recorded in the request tracker publicly readable - via http://www.openssl.org/support/rt.html and will be forwarded to a - public mailing list). Include the output of "make report" in your message. - Please check out the request tracker. Maybe the bug was already - reported or has already been fixed. + at https://www.openssl.org/community/index.html#bugs and will be + forwarded to a public mailing list). Include the output of "make + report" in your message. Please check out the request tracker. Maybe + the bug was already reported or has already been fixed. [If you encounter assembler error messages, try the "no-asm" configuration option as an immediate fix.] diff --git a/LICENSE b/LICENSE index e47d101f1025..fb03713dd111 100644 --- a/LICENSE +++ b/LICENSE @@ -12,7 +12,7 @@ --------------- /* ==================================================================== - * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/Makefile b/Makefile index e2bbb475c7df..ee04c02cc1ca 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ## Makefile for OpenSSL ## -VERSION=1.0.2e +VERSION=1.0.2f MAJOR=1 MINOR=0.2 SHLIB_VERSION_NUMBER=1.0.0 @@ -182,8 +182,7 @@ SHARED_LDFLAGS= GENERAL= Makefile BASENAME= openssl NAME= $(BASENAME)-$(VERSION) -TARFILE= $(NAME).tar -WTARFILE= $(NAME)-win.tar +TARFILE= ../$(NAME).tar EXHEADER= e_os2.h HEADER= e_os.h @@ -501,38 +500,35 @@ TABLE: Configure # would occur. Therefore the list of files is temporarily stored into a file # and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal # tar does not support the --files-from option. -TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list \ - --owner openssl:0 --group openssl:0 \ - --transform 's|^|openssl-$(VERSION)/|' \ +TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from $(TARFILE).list \ + --owner 0 --group 0 \ + --transform 's|^|$(NAME)/|' \ -cvf - -../$(TARFILE).list: +$(TARFILE).list: find * \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \ \! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \ - \! -name '*test' \! -name '.#*' \! -name '*~' \ - | sort > ../$(TARFILE).list + \( \! -name '*test' -o -name bctest -o -name pod2mantest \) \ + \! -name '.#*' \! -name '*~' \! -type l \ + | sort > $(TARFILE).list -tar: ../$(TARFILE).list +tar: $(TARFILE).list find . -type d -print | xargs chmod 755 find . -type f -print | xargs chmod a+r find . -type f -perm -0100 -print | xargs chmod a+x - $(TAR_COMMAND) | gzip --best >../$(TARFILE).gz - rm -f ../$(TARFILE).list - ls -l ../$(TARFILE).gz + $(TAR_COMMAND) | gzip --best > $(TARFILE).gz + rm -f $(TARFILE).list + ls -l $(TARFILE).gz -tar-snap: ../$(TARFILE).list - $(TAR_COMMAND) > ../$(TARFILE) - rm -f ../$(TARFILE).list - ls -l ../$(TARFILE) +tar-snap: $(TARFILE).list + $(TAR_COMMAND) > $(TARFILE) + rm -f $(TARFILE).list + ls -l $(TARFILE) dist: $(PERL) Configure dist - @$(MAKE) dist_pem_h @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar - -dist_pem_h: - (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean) + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar install: all install_docs install_sw diff --git a/Makefile.org b/Makefile.org index 0333644415a2..76fdbdf6ac5c 100644 --- a/Makefile.org +++ b/Makefile.org @@ -180,8 +180,7 @@ SHARED_LDFLAGS= GENERAL= Makefile BASENAME= openssl NAME= $(BASENAME)-$(VERSION) -TARFILE= $(NAME).tar -WTARFILE= $(NAME)-win.tar +TARFILE= ../$(NAME).tar EXHEADER= e_os2.h HEADER= e_os.h @@ -499,38 +498,35 @@ TABLE: Configure # would occur. Therefore the list of files is temporarily stored into a file # and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal # tar does not support the --files-from option. -TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list \ - --owner openssl:0 --group openssl:0 \ - --transform 's|^|openssl-$(VERSION)/|' \ +TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from $(TARFILE).list \ + --owner 0 --group 0 \ + --transform 's|^|$(NAME)/|' \ -cvf - -../$(TARFILE).list: +$(TARFILE).list: find * \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \ \! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \ - \! -name '*test' \! -name '.#*' \! -name '*~' \ - | sort > ../$(TARFILE).list + \( \! -name '*test' -o -name bctest -o -name pod2mantest \) \ + \! -name '.#*' \! -name '*~' \! -type l \ + | sort > $(TARFILE).list -tar: ../$(TARFILE).list +tar: $(TARFILE).list find . -type d -print | xargs chmod 755 find . -type f -print | xargs chmod a+r find . -type f -perm -0100 -print | xargs chmod a+x - $(TAR_COMMAND) | gzip --best >../$(TARFILE).gz - rm -f ../$(TARFILE).list - ls -l ../$(TARFILE).gz + $(TAR_COMMAND) | gzip --best > $(TARFILE).gz + rm -f $(TARFILE).list + ls -l $(TARFILE).gz -tar-snap: ../$(TARFILE).list - $(TAR_COMMAND) > ../$(TARFILE) - rm -f ../$(TARFILE).list - ls -l ../$(TARFILE) +tar-snap: $(TARFILE).list + $(TAR_COMMAND) > $(TARFILE) + rm -f $(TARFILE).list + ls -l $(TARFILE) dist: $(PERL) Configure dist - @$(MAKE) dist_pem_h @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar - -dist_pem_h: - (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean) + @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar install: all install_docs install_sw diff --git a/NEWS b/NEWS index e1c78f834f08..06c77025e999 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,11 @@ This file gives a brief overview of the major changes between each OpenSSL release. For more details please read the CHANGES file. + Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016] + + o DH small subgroups (CVE-2016-0701) + o SSLv2 doesn't block disabled ciphers (CVE-2015-3197) + Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015] o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193) diff --git a/README b/README index 49c4c9f147c3..1e9869daee00 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ - OpenSSL 1.0.2e 3 Dec 2015 + OpenSSL 1.0.2f 28 Jan 2016 Copyright (c) 1998-2015 The OpenSSL Project Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson @@ -90,11 +90,12 @@ In order to avoid spam, this is a moderated mailing list, and it might take a day for the ticket to show up. (We also scan posts to make sure - that security disclosures aren't publically posted by mistake.) Mail to - this address is recorded in the public RT (request tracker) database (see - https://www.openssl.org/support/rt.html for details) and also forwarded - the public openssl-dev mailing list. Confidential mail may be sent to - openssl-security@openssl.org (PGP key available from the key servers). + that security disclosures aren't publically posted by mistake.) Mail + to this address is recorded in the public RT (request tracker) database + (see https://www.openssl.org/community/index.html#bugs for details) and + also forwarded the public openssl-dev mailing list. Confidential mail + may be sent to openssl-security@openssl.org (PGP key available from the + key servers). Please do NOT use this for general assistance or support queries. Just because something doesn't work the way you expect does not mean it diff --git a/apps/engine.c b/apps/engine.c index 460ec60cb14c..f54631b50d81 100644 --- a/apps/engine.c +++ b/apps/engine.c @@ -1,4 +1,4 @@ -/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ +/* apps/engine.c */ /* * Written by Richard Levitte for the OpenSSL project * 2000. diff --git a/apps/ocsp.c b/apps/ocsp.c index 6ed255d4b563..5da51df5148c 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -1041,7 +1041,7 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, bs = OCSP_BASICRESP_new(); thisupd = X509_gmtime_adj(NULL, 0); if (ndays != -1) - nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24); + nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL); /* Examine each certificate id in the request */ for (i = 0; i < id_count; i++) { diff --git a/apps/pkcs12.c b/apps/pkcs12.c index e41b445a50b0..cbb75b7d5fe4 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -79,7 +79,8 @@ const EVP_CIPHER *enc; # define CLCERTS 0x8 # define CACERTS 0x10 -int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); +static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) **chain); int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, char *pempass); int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, @@ -594,7 +595,7 @@ int MAIN(int argc, char **argv) vret = get_cert_chain(ucert, store, &chain2); X509_STORE_free(store); - if (!vret) { + if (vret == X509_V_OK) { /* Exclude verified certificate */ for (i = 1; i < sk_X509_num(chain2); i++) sk_X509_push(certs, sk_X509_value(chain2, i)); @@ -602,7 +603,7 @@ int MAIN(int argc, char **argv) X509_free(sk_X509_value(chain2, 0)); sk_X509_free(chain2); } else { - if (vret >= 0) + if (vret != X509_V_ERR_UNSPECIFIED) BIO_printf(bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); else @@ -906,36 +907,25 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, /* Given a single certificate return a verified chain or NULL if error */ -/* Hope this is OK .... */ - -int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) +static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) **chain) { X509_STORE_CTX store_ctx; - STACK_OF(X509) *chn; + STACK_OF(X509) *chn = NULL; int i = 0; - /* - * FIXME: Should really check the return status of X509_STORE_CTX_init - * for an error, but how that fits into the return value of this function - * is less obvious. - */ - X509_STORE_CTX_init(&store_ctx, store, cert, NULL); - if (X509_verify_cert(&store_ctx) <= 0) { - i = X509_STORE_CTX_get_error(&store_ctx); - if (i == 0) - /* - * avoid returning 0 if X509_verify_cert() did not set an - * appropriate error value in the context - */ - i = -1; - chn = NULL; - goto err; - } else + if (!X509_STORE_CTX_init(&store_ctx, store, cert, NULL)) { + *chain = NULL; + return X509_V_ERR_UNSPECIFIED; + } + + if (X509_verify_cert(&store_ctx) > 0) chn = X509_STORE_CTX_get1_chain(&store_ctx); - err: + else if ((i = X509_STORE_CTX_get_error(&store_ctx)) == 0) + i = X509_V_ERR_UNSPECIFIED; + X509_STORE_CTX_cleanup(&store_ctx); *chain = chn; - return i; } diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c index aaa90740ad4d..c8d513b44ac4 100644 --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -74,10 +74,11 @@ static void usage(void); static EVP_PKEY_CTX *init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, ENGINE *e); + char *passargin, int pkey_op, ENGINE *e, + int impl); static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, - const char *file); + const char *file, ENGINE* e); static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, unsigned char *out, size_t *poutlen, @@ -97,6 +98,7 @@ int MAIN(int argc, char **argv) EVP_PKEY_CTX *ctx = NULL; char *passargin = NULL; int keysize = -1; + int engine_impl = 0; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; size_t buf_outlen; @@ -137,7 +139,7 @@ int MAIN(int argc, char **argv) else { ctx = init_ctx(&keysize, *(++argv), keyform, key_type, - passargin, pkey_op, e); + passargin, pkey_op, e, engine_impl); if (!ctx) { BIO_puts(bio_err, "Error initializing context\n"); ERR_print_errors(bio_err); @@ -147,7 +149,7 @@ int MAIN(int argc, char **argv) } else if (!strcmp(*argv, "-peerkey")) { if (--argc < 1) badarg = 1; - else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) + else if (!setup_peer(bio_err, ctx, peerform, *(++argv), e)) badarg = 1; } else if (!strcmp(*argv, "-passin")) { if (--argc < 1) @@ -171,6 +173,8 @@ int MAIN(int argc, char **argv) badarg = 1; else e = setup_engine(bio_err, *(++argv), 0); + } else if (!strcmp(*argv, "-engine_impl")) { + engine_impl = 1; } #endif else if (!strcmp(*argv, "-pubin")) @@ -368,7 +372,8 @@ static void usage() BIO_printf(bio_err, "-hexdump hex dump output\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); + "-engine e use engine e, maybe a hardware device, for loading keys.\n"); + BIO_printf(bio_err, "-engine_impl also use engine given by -engine for crypto operations\n"); #endif BIO_printf(bio_err, "-passin arg pass phrase source\n"); @@ -376,10 +381,12 @@ static void usage() static EVP_PKEY_CTX *init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, ENGINE *e) + char *passargin, int pkey_op, ENGINE *e, + int engine_impl) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; + ENGINE *impl = NULL; char *passin = NULL; int rv = -1; X509 *x; @@ -418,9 +425,14 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, if (!pkey) goto end; - - ctx = EVP_PKEY_CTX_new(pkey, e); - + +#ifndef OPENSSL_NO_ENGINE + if (engine_impl) + impl = e; +#endif + + ctx = EVP_PKEY_CTX_new(pkey, impl); + EVP_PKEY_free(pkey); if (!ctx) @@ -467,16 +479,20 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, } static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, - const char *file) + const char *file, ENGINE* e) { EVP_PKEY *peer = NULL; + ENGINE* engine = NULL; int ret; if (!ctx) { BIO_puts(err, "-peerkey command before -inkey\n"); return 0; } - peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key"); + if (peerform == FORMAT_ENGINE) + engine = e; + + peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key"); if (!peer) { BIO_printf(bio_err, "Error reading peer key %s\n", file); diff --git a/apps/s_client.c b/apps/s_client.c index f80711fd5e58..caf76d35dc5a 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -308,7 +308,7 @@ static void sc_usage(void) " -connect host:port - who to connect to (default is %s:%s)\n", SSL_HOST_NAME, PORT_STR); BIO_printf(bio_err, - " -verify_host host - check peer certificate matches \"host\"\n"); + " -verify_hostname host - check peer certificate matches \"host\"\n"); BIO_printf(bio_err, " -verify_email email - check peer certificate matches \"email\"\n"); BIO_printf(bio_err, diff --git a/apps/s_server.c b/apps/s_server.c index f19532b75fab..65cbaaf6eb9b 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -498,7 +498,7 @@ static void sv_usage(void) BIO_printf(bio_err, " -accept arg - port to accept on (default is %d)\n", PORT); BIO_printf(bio_err, - " -verify_host host - check peer certificate matches \"host\"\n"); + " -verify_hostname host - check peer certificate matches \"host\"\n"); BIO_printf(bio_err, " -verify_email email - check peer certificate matches \"email\"\n"); BIO_printf(bio_err, diff --git a/apps/speed.c b/apps/speed.c index 3697b71ec18b..95adcc19cc15 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -1,4 +1,4 @@ -/* apps/speed.c -*- mode:C; c-file-style: "eay" -*- */ +/* apps/speed.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * diff --git a/apps/x509.c b/apps/x509.c index 864a60dda2e7..7c215bced001 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -1226,12 +1226,7 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) goto err; - /* Lets just make it 12:00am GMT, Jan 1 1970 */ - /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ - /* 28 days to be certified */ - - if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) == - NULL) + if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) goto err; if (!X509_set_pubkey(x, pkey)) diff --git a/crypto/aes/aes.h b/crypto/aes/aes.h index 87bf60f6f2bf..faa66c49148f 100644 --- a/crypto/aes/aes.h +++ b/crypto/aes/aes.h @@ -1,4 +1,4 @@ -/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes.h */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_cbc.c b/crypto/aes/aes_cbc.c index e39231f17cb8..805d0e260a6f 100644 --- a/crypto/aes/aes_cbc.c +++ b/crypto/aes/aes_cbc.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_cbc.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_cbc.c */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_cfb.c b/crypto/aes/aes_cfb.c index 1c79ce2dbaa1..1225000963ea 100644 --- a/crypto/aes/aes_cfb.c +++ b/crypto/aes/aes_cfb.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_cfb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_cfb.c */ /* ==================================================================== * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_core.c b/crypto/aes/aes_core.c index 2ddb0860d78a..7019b5d7aa3a 100644 --- a/crypto/aes/aes_core.c +++ b/crypto/aes/aes_core.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_core.c */ /** * rijndael-alg-fst.c * diff --git a/crypto/aes/aes_ctr.c b/crypto/aes/aes_ctr.c index 3ee382299881..9e760c4b12ad 100644 --- a/crypto/aes/aes_ctr.c +++ b/crypto/aes/aes_ctr.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_ctr.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_ctr.c */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_ecb.c b/crypto/aes/aes_ecb.c index 2e0d20ca224e..52151a5c70f4 100644 --- a/crypto/aes/aes_ecb.c +++ b/crypto/aes/aes_ecb.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_ecb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_ecb.c */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c index cf31c9bba44a..8f2b7706472a 100644 --- a/crypto/aes/aes_ige.c +++ b/crypto/aes/aes_ige.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_ige.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_locl.h b/crypto/aes/aes_locl.h index fabfd02ac095..7acd74ec1603 100644 --- a/crypto/aes/aes_locl.h +++ b/crypto/aes/aes_locl.h @@ -1,4 +1,4 @@ -/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes.h */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_misc.c b/crypto/aes/aes_misc.c index ab948ad85eb4..fafad4d6f57a 100644 --- a/crypto/aes/aes_misc.c +++ b/crypto/aes/aes_misc.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_misc.c */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_ofb.c b/crypto/aes/aes_ofb.c index e6153f99ba70..64a08caaec6d 100644 --- a/crypto/aes/aes_ofb.c +++ b/crypto/aes/aes_ofb.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_ofb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_ofb.c */ /* ==================================================================== * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/aes/aes_x86core.c b/crypto/aes/aes_x86core.c index c869ed719852..b5dd6976772a 100644 --- a/crypto/aes/aes_x86core.c +++ b/crypto/aes/aes_x86core.c @@ -1,4 +1,4 @@ -/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/aes/aes_core.c */ /** * rijndael-alg-fst.c * diff --git a/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/aes/asm/aesni-mb-x86_64.pl index 5a100fa8983b..d7ad7882c4ee 100755 --- a/crypto/aes/asm/aesni-mb-x86_64.pl +++ b/crypto/aes/asm/aesni-mb-x86_64.pl @@ -63,7 +63,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl index c803cdebc112..8c84260856e1 100755 --- a/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -94,7 +94,7 @@ $avx=1 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && $avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && `ml64 2>&1` =~ /Version ([0-9]+)\./ && $1>=10); -$avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0); +$avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0); $shaext=1; ### set to zero if compiling for 1.0.1 diff --git a/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl index bfe29268c781..72f44ecf6253 100755 --- a/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -59,7 +59,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=12); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index f78796b069f5..6e2293bc66da 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -479,11 +479,11 @@ struct bio_dgram_sctp_prinfo { # define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0) # define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1) # define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2) -# define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0) +# define BIO_get_conn_int_port(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,0,NULL) # define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) -/* BIO_s_accept_socket() */ +/* BIO_s_accept() */ # define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name) # define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0) /* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ @@ -496,6 +496,7 @@ struct bio_dgram_sctp_prinfo { # define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) # define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) +/* BIO_s_accept() and BIO_s_connect() */ # define BIO_do_connect(b) BIO_do_handshake(b) # define BIO_do_accept(b) BIO_do_handshake(b) # define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) @@ -515,12 +516,15 @@ struct bio_dgram_sctp_prinfo { # define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url)) # define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL) +/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */ # define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) # define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c) +/* BIO_s_file() */ # define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp) # define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp) +/* BIO_s_fd() and BIO_s_file() */ # define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) # define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c index d629a37a5a1d..4d8727f8f890 100644 --- a/crypto/bio/bss_bio.c +++ b/crypto/bio/bss_bio.c @@ -1,4 +1,4 @@ -/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ +/* crypto/bio/bss_bio.c */ /* ==================================================================== * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index 42d0afffbc6c..7d15ad29dcd7 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -419,7 +419,7 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; int *ip; - const char **pptr; + const char **pptr = NULL; long ret = 1; BIO_CONNECT *data; @@ -442,19 +442,28 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_GET_CONNECT: if (ptr != NULL) { pptr = (const char **)ptr; - if (num == 0) { - *pptr = data->param_hostname; + } - } else if (num == 1) { - *pptr = data->param_port; - } else if (num == 2) { - *pptr = (char *)&(data->ip[0]); - } else if (num == 3) { - *((int *)ptr) = data->port; + if (b->init) { + if (pptr != NULL) { + ret = 1; + if (num == 0) { + *pptr = data->param_hostname; + } else if (num == 1) { + *pptr = data->param_port; + } else if (num == 2) { + *pptr = (char *)&(data->ip[0]); + } else { + ret = 0; + } } - if ((!b->init) || (ptr == NULL)) + if (num == 3) { + ret = data->port; + } + } else { + if (pptr != NULL) *pptr = "not initialized"; - ret = 1; + ret = 0; } break; case BIO_C_SET_CONNECT: diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 7fcd831da06b..bdd7bf88ea0e 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -519,10 +519,8 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_RESET: num = 0; - case BIO_C_FILE_SEEK: ret = 0; break; - case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret = 0; break; diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl index 12b571c282dc..091cdc2069da 100755 --- a/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/bn/asm/rsaz-x86_64.pl @@ -113,7 +113,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $addx = ($1>=12); } -if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 $addx = ($ver>=3.03); } diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl index 725833d022e2..e82e451388c7 100755 --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -68,7 +68,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $addx = ($1>=12); } -if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 $addx = ($ver>=3.03); } diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index 64e668f140c2..292409c4ffb8 100755 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -53,7 +53,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $addx = ($1>=12); } -if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 $addx = ($ver>=3.03); } diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 50cf3231b07b..6d30d1e0fff5 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -282,9 +282,14 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, } bits = BN_num_bits(p); - if (bits == 0) { - ret = BN_one(r); + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(r); + } else { + ret = BN_one(r); + } return ret; } @@ -418,7 +423,13 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, } bits = BN_num_bits(p); if (bits == 0) { - ret = BN_one(rr); + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(rr); + } else { + ret = BN_one(rr); + } return ret; } @@ -639,7 +650,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, * precomputation memory layout to limit data-dependency to a minimum to * protect secret exponents (cf. the hyper-threading timing attacks pointed * out by Colin Percival, - * http://www.daemong-consideredperthreading-considered-harmful/) + * http://www.daemonology.net/hyperthreading-considered-harmful/) */ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, @@ -671,7 +682,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, bits = BN_num_bits(p); if (bits == 0) { - ret = BN_one(rr); + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(rr); + } else { + ret = BN_one(rr); + } return ret; } @@ -1182,8 +1199,9 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, if (BN_is_one(m)) { ret = 1; BN_zero(rr); - } else + } else { ret = BN_one(rr); + } return ret; } if (a == 0) { @@ -1297,9 +1315,14 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, } bits = BN_num_bits(p); - - if (bits == 0) { - ret = BN_one(r); + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(r); + } else { + ret = BN_one(r); + } return ret; } diff --git a/crypto/bn/exptest.c b/crypto/bn/exptest.c index 8b3a4bae4328..ac611c2e2614 100644 --- a/crypto/bn/exptest.c +++ b/crypto/bn/exptest.c @@ -72,6 +72,25 @@ static const char rnd_seed[] = "string to make the random number generator think it has entropy"; +/* + * Test that r == 0 in test_exp_mod_zero(). Returns one on success, + * returns zero and prints debug output otherwise. + */ +static int a_is_zero_mod_one(const char *method, const BIGNUM *r, + const BIGNUM *a) { + if (!BN_is_zero(r)) { + fprintf(stderr, "%s failed:\n", method); + fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n"); + fprintf(stderr, "a = "); + BN_print_fp(stderr, a); + fprintf(stderr, "\nr = "); + BN_print_fp(stderr, r); + fprintf(stderr, "\n"); + return 0; + } + return 1; +} + /* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ @@ -79,8 +98,9 @@ static int test_exp_mod_zero() { BIGNUM a, p, m; BIGNUM r; + BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); - int ret = 1; + int ret = 1, failed = 0; BN_init(&m); BN_one(&m); @@ -92,21 +112,65 @@ static int test_exp_mod_zero() BN_zero(&p); BN_init(&r); - BN_mod_exp(&r, &a, &p, &m, ctx); - BN_CTX_free(ctx); - if (BN_is_zero(&r)) - ret = 0; - else { - printf("1**0 mod 1 = "); - BN_print_fp(stdout, &r); - printf(", should be 0\n"); + if (!BN_rand(&a, 1024, 0, 0)) + goto err; + + if (!BN_mod_exp(&r, &a, &p, &m, ctx)) + goto err; + + if (!a_is_zero_mod_one("BN_mod_exp", &r, &a)) + failed = 1; + + if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx)) + goto err; + + if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a)) + failed = 1; + + if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx)) + goto err; + + if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a)) + failed = 1; + + if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL)) + goto err; + + if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a)) + failed = 1; + + if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) { + goto err; } + if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a)) + failed = 1; + + /* + * A different codepath exists for single word multiplication + * in non-constant-time only. + */ + if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL)) + goto err; + + if (!BN_is_zero(&r)) { + fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); + fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); + fprintf(stderr, "r = "); + BN_print_fp(stderr, &r); + fprintf(stderr, "\n"); + return 0; + } + + ret = failed; + + err: BN_free(&r); BN_free(&a); BN_free(&p); BN_free(&m); + BN_CTX_free(ctx); return ret; } diff --git a/crypto/camellia/camellia.c b/crypto/camellia/camellia.c index b4a6766c623c..719fa61cf627 100644 --- a/crypto/camellia/camellia.c +++ b/crypto/camellia/camellia.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia.c */ /* ==================================================================== * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . * ALL RIGHTS RESERVED. @@ -67,7 +67,7 @@ /* * Algorithm Specification - * http://info.isl.llia/specicrypt/eng/camellia/specifications.html + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ /* diff --git a/crypto/camellia/camellia.h b/crypto/camellia/camellia.h index 9be7c0fd9996..45e8d25b1dd5 100644 --- a/crypto/camellia/camellia.h +++ b/crypto/camellia/camellia.h @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia.h */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_cbc.c b/crypto/camellia/cmll_cbc.c index a4907ca05f78..4017e00d9272 100644 --- a/crypto/camellia/cmll_cbc.c +++ b/crypto/camellia/cmll_cbc.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_cbc.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_cfb.c b/crypto/camellia/cmll_cfb.c index 59b85225c35e..78f2ae4566b1 100644 --- a/crypto/camellia/cmll_cfb.c +++ b/crypto/camellia/cmll_cfb.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_cfb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_cfb.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_ctr.c b/crypto/camellia/cmll_ctr.c index b8f523d44648..95e26621b7d8 100644 --- a/crypto/camellia/cmll_ctr.c +++ b/crypto/camellia/cmll_ctr.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_ctr.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_ctr.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_ecb.c b/crypto/camellia/cmll_ecb.c index 16f1af86ac38..b030791b275c 100644 --- a/crypto/camellia/cmll_ecb.c +++ b/crypto/camellia/cmll_ecb.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_ecb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_ecb.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_locl.h b/crypto/camellia/cmll_locl.h index 4e4707b6213e..2bd79b8c4eb3 100644 --- a/crypto/camellia/cmll_locl.h +++ b/crypto/camellia/cmll_locl.h @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_locl.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_locl.h */ /* ==================================================================== * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . * ALL RIGHTS RESERVED. diff --git a/crypto/camellia/cmll_misc.c b/crypto/camellia/cmll_misc.c index cbd250227bec..694d2fac8f1f 100644 --- a/crypto/camellia/cmll_misc.c +++ b/crypto/camellia/cmll_misc.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_misc.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_misc.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_ofb.c b/crypto/camellia/cmll_ofb.c index 46c3ae2af737..85eb8921568f 100644 --- a/crypto/camellia/cmll_ofb.c +++ b/crypto/camellia/cmll_ofb.c @@ -1,4 +1,4 @@ -/* crypto/camellia/camellia_ofb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/camellia_ofb.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/camellia/cmll_utl.c b/crypto/camellia/cmll_utl.c index d19ee19317ce..d5eb6b4d68b1 100644 --- a/crypto/camellia/cmll_utl.c +++ b/crypto/camellia/cmll_utl.c @@ -1,4 +1,4 @@ -/* crypto/camellia/cmll_utl.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/camellia/cmll_utl.c */ /* ==================================================================== * Copyright (c) 2011 The OpenSSL Project. All rights reserved. * diff --git a/crypto/des/des_old.c b/crypto/des/des_old.c index 54b0968e663b..c5c5a00f00c1 100644 --- a/crypto/des/des_old.c +++ b/crypto/des/des_old.c @@ -1,4 +1,4 @@ -/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/des/des_old.c */ /*- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING diff --git a/crypto/des/des_old.h b/crypto/des/des_old.h index f1e1e2cb09cf..ee7607a2415f 100644 --- a/crypto/des/des_old.h +++ b/crypto/des/des_old.h @@ -1,4 +1,4 @@ -/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/des/des_old.h */ /*- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING diff --git a/crypto/des/des_old2.c b/crypto/des/des_old2.c index f7d28a671355..247ff8dcf85f 100644 --- a/crypto/des/des_old2.c +++ b/crypto/des/des_old2.c @@ -1,4 +1,4 @@ -/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/des/des_old.c */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING The diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h index b17767328183..5498a9dc1060 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h @@ -174,6 +174,7 @@ struct dh_st { /* DH_check_pub_key error codes */ # define DH_CHECK_PUBKEY_TOO_SMALL 0x01 # define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +# define DH_CHECK_PUBKEY_INVALID 0x03 /* * primes p where (p-1)/2 is prime too are called "safe"; we define this for diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 347467c6a433..5adedc0d264e 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -151,23 +151,38 @@ int DH_check(const DH *dh, int *ret) int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { int ok = 0; - BIGNUM *q = NULL; + BIGNUM *tmp = NULL; + BN_CTX *ctx = NULL; *ret = 0; - q = BN_new(); - if (q == NULL) + ctx = BN_CTX_new(); + if (ctx == NULL) goto err; - BN_set_word(q, 1); - if (BN_cmp(pub_key, q) <= 0) + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + BN_set_word(tmp, 1); + if (BN_cmp(pub_key, tmp) <= 0) *ret |= DH_CHECK_PUBKEY_TOO_SMALL; - BN_copy(q, dh->p); - BN_sub_word(q, 1); - if (BN_cmp(pub_key, q) >= 0) + BN_copy(tmp, dh->p); + BN_sub_word(tmp, 1); + if (BN_cmp(pub_key, tmp) >= 0) *ret |= DH_CHECK_PUBKEY_TOO_LARGE; + if (dh->q != NULL) { + /* Check pub_key^q == 1 mod p */ + if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) + goto err; + if (!BN_is_one(tmp)) + *ret |= DH_CHECK_PUBKEY_INVALID; + } + ok = 1; err: - if (q != NULL) - BN_free(q); + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } return (ok); } diff --git a/crypto/dh/dhtest.c b/crypto/dh/dhtest.c index 6fe8ff4c0c49..c5d3d87ea549 100644 --- a/crypto/dh/dhtest.c +++ b/crypto/dh/dhtest.c @@ -471,6 +471,31 @@ static const unsigned char dhtest_2048_256_Z[] = { 0xC2, 0x6C, 0x5D, 0x7C }; +static const unsigned char dhtest_rfc5114_2048_224_bad_y[] = { + 0x45, 0x32, 0x5F, 0x51, 0x07, 0xE5, 0xDF, 0x1C, 0xD6, 0x02, 0x82, 0xB3, + 0x32, 0x8F, 0xA4, 0x0F, 0x87, 0xB8, 0x41, 0xFE, 0xB9, 0x35, 0xDE, 0xAD, + 0xC6, 0x26, 0x85, 0xB4, 0xFF, 0x94, 0x8C, 0x12, 0x4C, 0xBF, 0x5B, 0x20, + 0xC4, 0x46, 0xA3, 0x26, 0xEB, 0xA4, 0x25, 0xB7, 0x68, 0x8E, 0xCC, 0x67, + 0xBA, 0xEA, 0x58, 0xD0, 0xF2, 0xE9, 0xD2, 0x24, 0x72, 0x60, 0xDA, 0x88, + 0x18, 0x9C, 0xE0, 0x31, 0x6A, 0xAD, 0x50, 0x6D, 0x94, 0x35, 0x8B, 0x83, + 0x4A, 0x6E, 0xFA, 0x48, 0x73, 0x0F, 0x83, 0x87, 0xFF, 0x6B, 0x66, 0x1F, + 0xA8, 0x82, 0xC6, 0x01, 0xE5, 0x80, 0xB5, 0xB0, 0x52, 0xD0, 0xE9, 0xD8, + 0x72, 0xF9, 0x7D, 0x5B, 0x8B, 0xA5, 0x4C, 0xA5, 0x25, 0x95, 0x74, 0xE2, + 0x7A, 0x61, 0x4E, 0xA7, 0x8F, 0x12, 0xE2, 0xD2, 0x9D, 0x8C, 0x02, 0x70, + 0x34, 0x44, 0x32, 0xC7, 0xB2, 0xF3, 0xB9, 0xFE, 0x17, 0x2B, 0xD6, 0x1F, + 0x8B, 0x7E, 0x4A, 0xFA, 0xA3, 0xB5, 0x3E, 0x7A, 0x81, 0x9A, 0x33, 0x66, + 0x62, 0xA4, 0x50, 0x18, 0x3E, 0xA2, 0x5F, 0x00, 0x07, 0xD8, 0x9B, 0x22, + 0xE4, 0xEC, 0x84, 0xD5, 0xEB, 0x5A, 0xF3, 0x2A, 0x31, 0x23, 0xD8, 0x44, + 0x22, 0x2A, 0x8B, 0x37, 0x44, 0xCC, 0xC6, 0x87, 0x4B, 0xBE, 0x50, 0x9D, + 0x4A, 0xC4, 0x8E, 0x45, 0xCF, 0x72, 0x4D, 0xC0, 0x89, 0xB3, 0x72, 0xED, + 0x33, 0x2C, 0xBC, 0x7F, 0x16, 0x39, 0x3B, 0xEB, 0xD2, 0xDD, 0xA8, 0x01, + 0x73, 0x84, 0x62, 0xB9, 0x29, 0xD2, 0xC9, 0x51, 0x32, 0x9E, 0x7A, 0x6A, + 0xCF, 0xC1, 0x0A, 0xDB, 0x0E, 0xE0, 0x62, 0x77, 0x6F, 0x59, 0x62, 0x72, + 0x5A, 0x69, 0xA6, 0x5B, 0x70, 0xCA, 0x65, 0xC4, 0x95, 0x6F, 0x9A, 0xC2, + 0xDF, 0x72, 0x6D, 0xB1, 0x1E, 0x54, 0x7B, 0x51, 0xB4, 0xEF, 0x7F, 0x89, + 0x93, 0x74, 0x89, 0x59 +}; + typedef struct { DH *(*get_param) (void); const unsigned char *xA; @@ -503,10 +528,15 @@ static const rfc5114_td rfctd[] = { static int run_rfc5114_tests(void) { int i; + DH *dhA = NULL; + DH *dhB = NULL; + unsigned char *Z1 = NULL; + unsigned char *Z2 = NULL; + const rfc5114_td *td = NULL; + BIGNUM *bady = NULL; + for (i = 0; i < (int)(sizeof(rfctd) / sizeof(rfc5114_td)); i++) { - DH *dhA, *dhB; - unsigned char *Z1 = NULL, *Z2 = NULL; - const rfc5114_td *td = rfctd + i; + td = rfctd + i; /* Set up DH structures setting key components */ dhA = td->get_param(); dhB = td->get_param(); @@ -549,14 +579,63 @@ static int run_rfc5114_tests(void) DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); - + dhA = NULL; + dhB = NULL; + Z1 = NULL; + Z2 = NULL; } + + /* Now i == OSSL_NELEM(rfctd) */ + /* RFC5114 uses unsafe primes, so now test an invalid y value */ + dhA = DH_get_2048_224(); + if (dhA == NULL) + goto bad_err; + Z1 = OPENSSL_malloc(DH_size(dhA)); + if (Z1 == NULL) + goto bad_err; + + bady = BN_bin2bn(dhtest_rfc5114_2048_224_bad_y, + sizeof(dhtest_rfc5114_2048_224_bad_y), NULL); + if (bady == NULL) + goto bad_err; + + if (!DH_generate_key(dhA)) + goto bad_err; + + if (DH_compute_key(Z1, bady, dhA) != -1) { + /* + * DH_compute_key should fail with -1. If we get here we unexpectedly + * allowed an invalid y value + */ + goto err; + } + /* We'll have a stale error on the queue from the above test so clear it */ + ERR_clear_error(); + + printf("RFC5114 parameter test %d OK\n", i + 1); + + BN_free(bady); + DH_free(dhA); + OPENSSL_free(Z1); + return 1; bad_err: + BN_free(bady); + DH_free(dhA); + DH_free(dhB); + OPENSSL_free(Z1); + OPENSSL_free(Z2); + fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1); ERR_print_errors_fp(stderr); return 0; err: + BN_free(bady); + DH_free(dhA); + DH_free(dhB); + OPENSSL_free(Z1); + OPENSSL_free(Z2); + fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1); return 0; } diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index f0ec8faa84cc..efc4f1b6aeba 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -187,9 +187,6 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) goto err; - ret = DSA_SIG_new(); - if (ret == NULL) - goto err; /* * Redo if r or s is zero as required by FIPS 186-3: this is very * unlikely. @@ -201,11 +198,14 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) } goto redo; } + ret = DSA_SIG_new(); + if (ret == NULL) + goto err; ret->r = r; ret->s = s; err: - if (!ret) { + if (ret == NULL) { DSAerr(DSA_F_DSA_DO_SIGN, reason); BN_free(r); BN_free(s); diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h index 7c4a1dc4a620..c9013f5cea8b 100644 --- a/crypto/dso/dso.h +++ b/crypto/dso/dso.h @@ -1,4 +1,4 @@ -/* dso.h -*- mode:C; c-file-style: "eay" -*- */ +/* dso.h */ /* * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project * 2000. diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index 0087ac54afe1..ceedf66e8856 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -1,4 +1,4 @@ -/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */ +/* dso_dl.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2000. diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index f629f0380d8c..78df723ffbae 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -1,4 +1,4 @@ -/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */ +/* dso_dlfcn.c */ /* * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project * 2000. diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 09b8eafccacc..3312450eae67 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -1,4 +1,4 @@ -/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */ +/* dso_lib.c */ /* * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project * 2000. diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl index 648c969be621..e6acfd59f0d4 100755 --- a/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -81,7 +81,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $addx = ($1>=12); } -if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 $avx = ($ver>=3.0) + ($ver>=3.01); $addx = ($ver>=3.03); diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index 077c7fc8dda5..5b27b91fcc94 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -746,6 +746,7 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, goto err; if (!BN_one(&point->Z)) goto err; + point->Z_is_one = 1; ret = 1; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index c784b6fd30a3..bc94ab5661ff 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -387,6 +387,8 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, tx = BN_CTX_get(ctx); ty = BN_CTX_get(ctx); + if (ty == NULL) + goto err; #ifndef OPENSSL_NO_EC2M tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); diff --git a/crypto/ec/ecp_nistz256_table.c b/crypto/ec/ecp_nistz256_table.c index 216d024e0120..2f0797db6b9b 100644 --- a/crypto/ec/ecp_nistz256_table.c +++ b/crypto/ec/ecp_nistz256_table.c @@ -17,7 +17,7 @@ __attribute((aligned(4096))) #elif defined(_MSC_VER) __declspec(align(4096)) #elif defined(__SUNPRO_C) -# pragma align 4096(ecp_nistz256_precomputed) +# pragma align 64(ecp_nistz256_precomputed) #endif static const BN_ULONG ecp_nistz256_precomputed[37][64 * sizeof(P256_POINT_AFFINE) / diff --git a/crypto/ec/ectest.c b/crypto/ec/ectest.c index fede530bc139..efab0b07b1d2 100644 --- a/crypto/ec/ectest.c +++ b/crypto/ec/ectest.c @@ -1591,7 +1591,7 @@ struct nistp_test_params { int degree; /* * Qx, Qy and D are taken from - * http://csrcdocut.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf * Otherwise, values are standard curve parameters from FIPS 180-3 */ const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d; diff --git a/crypto/engine/eng_all.c b/crypto/engine/eng_all.c index 195a3a95542a..48ad0d26b41e 100644 --- a/crypto/engine/eng_all.c +++ b/crypto/engine/eng_all.c @@ -1,4 +1,4 @@ -/* crypto/engine/eng_all.c -*- mode: C; c-file-style: "eay" -*- */ +/* crypto/engine/eng_all.c */ /* * Written by Richard Levitte for the OpenSSL project * 2000. diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c index f9c84013675d..f273f9c9475a 100644 --- a/crypto/evp/e_camellia.c +++ b/crypto/evp/e_camellia.c @@ -1,4 +1,4 @@ -/* crypto/evp/e_camellia.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/evp/e_camellia.c */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * diff --git a/crypto/evp/e_old.c b/crypto/evp/e_old.c index c93f5a548163..a23d143b7fae 100644 --- a/crypto/evp/e_old.c +++ b/crypto/evp/e_old.c @@ -1,4 +1,4 @@ -/* crypto/evp/e_old.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/evp/e_old.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2004. diff --git a/crypto/evp/e_seed.c b/crypto/evp/e_seed.c index c948a8f3914f..7249d1b1eecb 100644 --- a/crypto/evp/e_seed.c +++ b/crypto/evp/e_seed.c @@ -1,4 +1,4 @@ -/* crypto/evp/e_seed.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/evp/e_seed.c */ /* ==================================================================== * Copyright (c) 2007 The OpenSSL Project. All rights reserved. * diff --git a/crypto/mem_clr.c b/crypto/mem_clr.c index 1a06636d0ce8..ab85344eef38 100644 --- a/crypto/mem_clr.c +++ b/crypto/mem_clr.c @@ -1,4 +1,4 @@ -/* crypto/mem_clr.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/mem_clr.c */ /* * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project * 2002. diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl index 4be25571ea28..bd6bf72fe487 100755 --- a/crypto/modes/asm/aesni-gcm-x86_64.pl +++ b/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -56,7 +56,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl index 0bcb6d4e028b..4ff2d39aa7b2 100755 --- a/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/modes/asm/ghash-x86_64.pl @@ -105,7 +105,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/o_dir.c b/crypto/o_dir.c index 26242444c885..f9dbed871127 100644 --- a/crypto/o_dir.c +++ b/crypto/o_dir.c @@ -1,4 +1,4 @@ -/* crypto/o_dir.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_dir.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2004. diff --git a/crypto/o_dir.h b/crypto/o_dir.h index d55431194ef2..bf45a14d02ec 100644 --- a/crypto/o_dir.h +++ b/crypto/o_dir.h @@ -1,4 +1,4 @@ -/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_dir.h */ /* * Copied from Richard Levitte's (richard@levitte.org) LP library. All * symbol names have been changed, with permission from the author. diff --git a/crypto/o_dir_test.c b/crypto/o_dir_test.c index 7cdbbbc403e7..60436b72ce37 100644 --- a/crypto/o_dir_test.c +++ b/crypto/o_dir_test.c @@ -1,4 +1,4 @@ -/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_dir.h */ /* * Copied from Richard Levitte's (richard@levitte.org) LP library. All * symbol names have been changed, with permission from the author. diff --git a/crypto/o_str.c b/crypto/o_str.c index 4e2d096704f0..7e61cde85a27 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -1,4 +1,4 @@ -/* crypto/o_str.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_str.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/o_str.h b/crypto/o_str.h index 5313528ed926..fa512eb39784 100644 --- a/crypto/o_str.h +++ b/crypto/o_str.h @@ -1,4 +1,4 @@ -/* crypto/o_str.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_str.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/o_time.c b/crypto/o_time.c index 58413fe97d09..635dae184d2f 100644 --- a/crypto/o_time.c +++ b/crypto/o_time.c @@ -1,4 +1,4 @@ -/* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_time.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/o_time.h b/crypto/o_time.h index a83a3d247d41..f192c6dccf37 100644 --- a/crypto/o_time.h +++ b/crypto/o_time.h @@ -1,4 +1,4 @@ -/* crypto/o_time.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/o_time.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/opensslv.h b/crypto/opensslv.h index abcef15b17d9..03b8c4843784 100644 --- a/crypto/opensslv.h +++ b/crypto/opensslv.h @@ -30,11 +30,11 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x1000205fL +# define OPENSSL_VERSION_NUMBER 0x1000206fL # ifdef OPENSSL_FIPS -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2e-fips 3 Dec 2015" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2f-fips 28 Jan 2016" # else -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2e 3 Dec 2015" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2f 28 Jan 2016" # endif # define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/rc4/rc4_utl.c b/crypto/rc4/rc4_utl.c index 7c6a15f1c71f..cbd4a24e4b4d 100644 --- a/crypto/rc4/rc4_utl.c +++ b/crypto/rc4/rc4_utl.c @@ -1,4 +1,4 @@ -/* crypto/rc4/rc4_utl.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/rc4/rc4_utl.c */ /* ==================================================================== * Copyright (c) 2011 The OpenSSL Project. All rights reserved. * diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c index f4383860b58b..607faa00171e 100644 --- a/crypto/rsa/rsa_chk.c +++ b/crypto/rsa/rsa_chk.c @@ -1,4 +1,4 @@ -/* crypto/rsa/rsa_chk.c -*- Mode: C; c-file-style: "eay" -*- */ +/* crypto/rsa/rsa_chk.c */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 82ca8324dfbc..ed63a1d8b0e3 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -84,7 +84,7 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len, return 0; } #endif - if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) { + if (rsa->meth->rsa_sign) { return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); } /* Special case: SSL signature, just check the length */ @@ -293,7 +293,7 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, RSA *rsa) { - if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) { + if (rsa->meth->rsa_verify) { return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa); } diff --git a/crypto/seed/seed_cbc.c b/crypto/seed/seed_cbc.c index 33e6887740e9..ee1115b4c113 100644 --- a/crypto/seed/seed_cbc.c +++ b/crypto/seed/seed_cbc.c @@ -1,4 +1,4 @@ -/* crypto/seed/seed_cbc.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/seed/seed_cbc.c */ /* ==================================================================== * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. * diff --git a/crypto/seed/seed_cfb.c b/crypto/seed/seed_cfb.c index 3437d7b4e111..b6a5648b35fd 100644 --- a/crypto/seed/seed_cfb.c +++ b/crypto/seed/seed_cfb.c @@ -1,4 +1,4 @@ -/* crypto/seed/seed_cfb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/seed/seed_cfb.c */ /* ==================================================================== * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. * diff --git a/crypto/seed/seed_ecb.c b/crypto/seed/seed_ecb.c index 937a31b42a87..9363d5508044 100644 --- a/crypto/seed/seed_ecb.c +++ b/crypto/seed/seed_ecb.c @@ -1,4 +1,4 @@ -/* crypto/seed/seed_ecb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/seed/seed_ecb.c */ /* ==================================================================== * Copyright (c) 2007 The OpenSSL Project. All rights reserved. * diff --git a/crypto/seed/seed_ofb.c b/crypto/seed/seed_ofb.c index 6974302ce80f..48b71224c52c 100644 --- a/crypto/seed/seed_ofb.c +++ b/crypto/seed/seed_ofb.c @@ -1,4 +1,4 @@ -/* crypto/seed/seed_ofb.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/seed/seed_ofb.c */ /* ==================================================================== * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. * diff --git a/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/sha/asm/sha1-mb-x86_64.pl index f856bb888b0e..a8d8708d4b75 100755 --- a/crypto/sha/asm/sha1-mb-x86_64.pl +++ b/crypto/sha/asm/sha1-mb-x86_64.pl @@ -58,7 +58,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl index 9a6acc347d33..5f375fc6886b 100755 --- a/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/sha/asm/sha1-x86_64.pl @@ -107,7 +107,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([2-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([2-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/sha/asm/sha256-mb-x86_64.pl index 3d37ae31ad3e..9770286b9596 100755 --- a/crypto/sha/asm/sha256-mb-x86_64.pl +++ b/crypto/sha/asm/sha256-mb-x86_64.pl @@ -59,7 +59,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl index 58665667f149..78e445f3fe4a 100755 --- a/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/sha/asm/sha512-x86_64.pl @@ -124,7 +124,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && $avx = ($1>=10) + ($1>=11); } -if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } diff --git a/crypto/sha/sha1test.c b/crypto/sha/sha1test.c index 0052a95c7dd4..551a348df37f 100644 --- a/crypto/sha/sha1test.c +++ b/crypto/sha/sha1test.c @@ -157,8 +157,8 @@ int main(int argc, char *argv[]) if (err) printf("ERROR: %d\n", err); # endif - EXIT(err); EVP_MD_CTX_cleanup(&c); + EXIT(err); return (0); } diff --git a/crypto/store/store.h b/crypto/store/store.h index 834334104907..ce3709d9f00b 100644 --- a/crypto/store/store.h +++ b/crypto/store/store.h @@ -1,4 +1,4 @@ -/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/store/store.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/store/str_lib.c b/crypto/store/str_lib.c index 227b797b5949..e3d5da938868 100644 --- a/crypto/store/str_lib.c +++ b/crypto/store/str_lib.c @@ -1,4 +1,4 @@ -/* crypto/store/str_lib.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/store/str_lib.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/store/str_locl.h b/crypto/store/str_locl.h index ac55784df0aa..c0b40f0db674 100644 --- a/crypto/store/str_locl.h +++ b/crypto/store/str_locl.h @@ -1,4 +1,4 @@ -/* crypto/store/str_locl.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/store/str_locl.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/store/str_mem.c b/crypto/store/str_mem.c index 8edd0eb41b12..6eee5bba2922 100644 --- a/crypto/store/str_mem.c +++ b/crypto/store/str_mem.c @@ -1,4 +1,4 @@ -/* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/store/str_mem.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/store/str_meth.c b/crypto/store/str_meth.c index d83a6de0fc47..c83fbc565aac 100644 --- a/crypto/store/str_meth.c +++ b/crypto/store/str_meth.c @@ -1,4 +1,4 @@ -/* crypto/store/str_meth.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/store/str_meth.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2003. diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index da8991173ced..29aa5a497e89 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -255,7 +255,8 @@ static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, /* chain is an out argument. */ *chain = NULL; - X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted); + if (!X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted)) + return 0; X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN); i = X509_verify_cert(&cert_ctx); if (i <= 0) { diff --git a/crypto/ui/ui.h b/crypto/ui/ui.h index b917edab3a7a..0dc16330b870 100644 --- a/crypto/ui/ui.h +++ b/crypto/ui/ui.h @@ -1,4 +1,4 @@ -/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/ui/ui_compat.c b/crypto/ui/ui_compat.c index 0ca5284f91c0..e79d54eea682 100644 --- a/crypto/ui/ui_compat.c +++ b/crypto/ui/ui_compat.c @@ -1,4 +1,4 @@ -/* crypto/ui/ui_compat.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui_compat.c */ /* ==================================================================== * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/ui/ui_compat.h b/crypto/ui/ui_compat.h index 42fb9ff6500f..bf541542c041 100644 --- a/crypto/ui/ui_compat.h +++ b/crypto/ui/ui_compat.h @@ -1,4 +1,4 @@ -/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c index 5ddd7317e52b..2f580352ce8f 100644 --- a/crypto/ui/ui_lib.c +++ b/crypto/ui/ui_lib.c @@ -1,4 +1,4 @@ -/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui_lib.c */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/ui/ui_locl.h b/crypto/ui/ui_locl.h index 0d919cd7b1cc..bebc13abfc52 100644 --- a/crypto/ui/ui_locl.h +++ b/crypto/ui/ui_locl.h @@ -1,4 +1,4 @@ -/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui.h */ /* * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project * 2001. diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c index 5d66276418fc..9ab259b8f605 100644 --- a/crypto/ui/ui_openssl.c +++ b/crypto/ui/ui_openssl.c @@ -1,4 +1,4 @@ -/* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui_openssl.c */ /* * Written by Richard Levitte (richard@levitte.org) and others for the * OpenSSL project 2001. diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c index f65f80d71de6..0f290115d0f8 100644 --- a/crypto/ui/ui_util.c +++ b/crypto/ui/ui_util.c @@ -1,4 +1,4 @@ -/* crypto/ui/ui_util.c -*- mode:C; c-file-style: "eay" -*- */ +/* crypto/ui/ui_util.c */ /* ==================================================================== * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved. * diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index ab94948f0135..0429767032fd 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -2283,9 +2283,10 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->current_reasons = 0; ctx->tree = NULL; ctx->parent = NULL; + /* Zero ex_data to make sure we're cleanup-safe */ + memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); ctx->param = X509_VERIFY_PARAM_new(); - if (!ctx->param) { X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); return 0; @@ -2294,7 +2295,6 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, /* * Inherit callbacks and flags from X509_STORE if not set use defaults. */ - if (store) ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); else @@ -2302,6 +2302,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, if (store) { ctx->verify_cb = store->verify_cb; + /* Seems to always be 0 in OpenSSL, else must be idempotent */ ctx->cleanup = store->cleanup; } else ctx->cleanup = 0; @@ -2312,7 +2313,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, if (ret == 0) { X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } if (store && store->check_issued) @@ -2367,19 +2368,18 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->check_policy = check_policy; + if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, + &ctx->ex_data)) + return 1; + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + + err: /* - * This memset() can't make any sense anyway, so it's removed. As - * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a - * corresponding "new" here and remove this bogus initialisation. + * On error clean up allocated storage, if the store context was not + * allocated with X509_STORE_CTX_new() this is our last chance to do so. */ - /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */ - if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, - &(ctx->ex_data))) { - OPENSSL_free(ctx); - X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - return 1; + X509_STORE_CTX_cleanup(ctx); + return 0; } /* @@ -2395,8 +2395,17 @@ void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) { - if (ctx->cleanup) + /* + * We need to be idempotent because, unfortunately, free() also calls + * cleanup(), so the natural call sequence new(), init(), cleanup(), free() + * calls cleanup() for the same object twice! Thus we must zero the + * pointers below after they're freed! + */ + /* Seems to always be 0 in OpenSSL, do this at most once. */ + if (ctx->cleanup != NULL) { ctx->cleanup(ctx); + ctx->cleanup = NULL; + } if (ctx->param != NULL) { if (ctx->parent == NULL) X509_VERIFY_PARAM_free(ctx->param); diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index bd8613c62ba4..2663e1c0a362 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -313,7 +313,7 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) # define X509_V_OK 0 -/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */ +# define X509_V_ERR_UNSPECIFIED 1 # define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 # define X509_V_ERR_UNABLE_TO_GET_CRL 3 diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 592a8a5f6a5c..1ac15a881a10 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -94,11 +94,11 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, * Refuse names with embedded NUL bytes, except perhaps as final byte. * XXX: Do we need to push an error onto the error stack? */ - if (namelen == 0) + if (namelen == 0 || name == NULL) namelen = name ? strlen(name) : 0; else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen)) return 0; - if (name && name[namelen - 1] == '\0') + if (namelen > 0 && name[namelen - 1] == '\0') --namelen; if (mode == SET_HOST && id->hosts) { diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509v3/v3_pci.c index 48ac0959cb10..34cad53cb5f0 100644 --- a/crypto/x509v3/v3_pci.c +++ b/crypto/x509v3/v3_pci.c @@ -1,4 +1,4 @@ -/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */ +/* v3_pci.c */ /* * Contributed to the OpenSSL Project 2004 by Richard Levitte * (richard@levitte.org) diff --git a/crypto/x509v3/v3_pcia.c b/crypto/x509v3/v3_pcia.c index 43fd362aeda0..e53c82e8dc79 100644 --- a/crypto/x509v3/v3_pcia.c +++ b/crypto/x509v3/v3_pcia.c @@ -1,4 +1,4 @@ -/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */ +/* v3_pcia.c */ /* * Contributed to the OpenSSL Project 2004 by Richard Levitte * (richard@levitte.org) diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c index 4d1ecc58bf94..43b9cb9c5861 100644 --- a/crypto/x509v3/v3_utl.c +++ b/crypto/x509v3/v3_utl.c @@ -841,7 +841,8 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len, state = LABEL_START; ++dots; } else if (p[i] == '-') { - if ((state & LABEL_HYPHEN) != 0) + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) return NULL; state |= LABEL_HYPHEN; } else diff --git a/crypto/x509v3/v3nametest.c b/crypto/x509v3/v3nametest.c index 7b5c1c8e5127..ac5c9ff432d9 100644 --- a/crypto/x509v3/v3nametest.c +++ b/crypto/x509v3/v3nametest.c @@ -6,12 +6,16 @@ static const char *const names[] = { "a", "b", ".", "*", "@", ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..", + "-example.com", "example-.com", "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com", "*@example.com", "test@*.example.com", "example.com", "www.example.com", "test.www.example.com", "*.example.com", "*.www.example.com", "test.*.example.com", "www.*.com", ".www.example.com", "*www.example.com", "example.net", "xn--rger-koa.example.com", + "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com", + "*.good--example.com", "www.good--example.com", + "*.xn--bar.com", "xn--foo.xn--bar.com", "a.example.com", "b.example.com", "postmaster@example.com", "Postmaster@example.com", "postmaster@EXAMPLE.COM", @@ -27,6 +31,9 @@ static const char *const exceptions[] = { "set CN: host: [*.www.example.com] matches [.www.example.com]", "set CN: host: [*www.example.com] matches [www.example.com]", "set CN: host: [test.www.example.com] matches [.www.example.com]", + "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set CN: host: [*.good--example.com] matches [www.good--example.com]", "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]", "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]", "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]", @@ -43,6 +50,9 @@ static const char *const exceptions[] = { "set dnsName: host: [*.www.example.com] matches [.www.example.com]", "set dnsName: host: [*www.example.com] matches [www.example.com]", "set dnsName: host: [test.www.example.com] matches [.www.example.com]", + "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set dnsName: host: [*.good--example.com] matches [www.good--example.com]", "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]", "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]", "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]", diff --git a/doc/apps/s_time.pod b/doc/apps/s_time.pod index 5a38aa2e0394..9082d876feeb 100644 --- a/doc/apps/s_time.pod +++ b/doc/apps/s_time.pod @@ -26,7 +26,7 @@ B B =head1 DESCRIPTION -The B command implements a generic SSL/TLS client which connects to a +The B command implements a generic SSL/TLS client which connects to a remote host using SSL/TLS. It can request a page from the server and includes the time to transfer the payload data in its timing measurements. It measures the number of connections within a given timeframe, the amount of data @@ -127,7 +127,7 @@ and the link speed determine how many connections B can establish. =head1 NOTES -B can be used to measure the performance of an SSL connection. +B can be used to measure the performance of an SSL connection. To connect to an SSL HTTP server and get the default page the command openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3] diff --git a/doc/crypto/BIO_s_connect.pod b/doc/crypto/BIO_s_connect.pod index 18ece4c91f66..345a468a5d74 100644 --- a/doc/crypto/BIO_s_connect.pod +++ b/doc/crypto/BIO_s_connect.pod @@ -21,8 +21,8 @@ BIO_set_nbio, BIO_do_connect - connect BIO long BIO_set_conn_int_port(BIO *b, char *port); char *BIO_get_conn_hostname(BIO *b); char *BIO_get_conn_port(BIO *b); - char *BIO_get_conn_ip(BIO *b, dummy); - long BIO_get_conn_int_port(BIO *b, int port); + char *BIO_get_conn_ip(BIO *b); + long BIO_get_conn_int_port(BIO *b); long BIO_set_nbio(BIO *b, long n); diff --git a/doc/ssl/SSL_CTX_set1_verify_cert_store.pod b/doc/ssl/SSL_CTX_set1_verify_cert_store.pod index 493cca481940..3e3a4fa90c0e 100644 --- a/doc/ssl/SSL_CTX_set1_verify_cert_store.pod +++ b/doc/ssl/SSL_CTX_set1_verify_cert_store.pod @@ -17,10 +17,10 @@ verification or chain store int SSL_CTX_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st); int SSL_CTX_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st); - int SSL_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *st); - int SSL_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *st); - int SSL_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st); - int SSL_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st); + int SSL_set0_verify_cert_store(SSL *ctx, X509_STORE *st); + int SSL_set1_verify_cert_store(SSL *ctx, X509_STORE *st); + int SSL_set0_chain_cert_store(SSL *ctx, X509_STORE *st); + int SSL_set1_chain_cert_store(SSL *ctx, X509_STORE *st); =head1 DESCRIPTION diff --git a/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod b/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod new file mode 100644 index 000000000000..b8147baecf98 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod @@ -0,0 +1,73 @@ +=pod + +=head1 NAME + +SSL_CTX_set_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg, +SSL_set_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp, +SSL_set_tlsext_status_ocsp_resp - OCSP Certificate Status Request functions + +=head1 SYNOPSIS + + #include + + long SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx, + int (*callback)(SSL *, void *)); + long SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg); + + long SSL_set_tlsext_status_type(SSL *s, int type); + + long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp); + long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len); + +=head1 DESCRIPTION + +A client application may request that a server send back an OCSP status response +(also known as OCSP stapling). To do so the client should call the +SSL_set_tlsext_status_type() function prior to the start of the handshake. +Currently the only supported type is B. This value +should be passed in the B argument. The client should additionally provide +a callback function to decide what to do with the returned OCSP response by +calling SSL_CTX_set_tlsext_status_cb(). The callback function should determine +whether the returned OCSP response is acceptable or not. The callback will be +passed as an argument the value previously set via a call to +SSL_CTX_set_tlsext_status_arg(). Note that the callback will not be called in +the event of a handshake where session resumption occurs (because there are no +Certificates exchanged in such a handshake). + +The response returned by the server can be obtained via a call to +SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to point +to the OCSP response data and the return value will be the length of that data. +Typically a callback would obtain an OCSP_RESPONSE object from this data via a +call to the d2i_OCSP_RESPONSE() function. If the server has not provided any +response data then B<*resp> will be NULL and the return value from +SSL_get_tlsext_status_ocsp_resp() will be -1. + +A server application must also call the SSL_CTX_set_tlsext_status_cb() function +if it wants to be able to provide clients with OCSP Certificate Status +responses. Typically the server callback would obtain the server certificate +that is being sent back to the client via a call to SSL_get_certificate(); +obtain the OCSP response to be sent back; and then set that response data by +calling SSL_set_tlsext_status_ocsp_resp(). A pointer to the response data should +be provided in the B argument, and the length of that data should be in +the B argument. + +=head1 RETURN VALUES + +The callback when used on the client side should return a negative value on +error; 0 if the response is not acceptable (in which case the handshake will +fail) or a positive value if it is acceptable. + +The callback when used on the server side should return with either +SSL_TLSEXT_ERR_OK (meaning that the OCSP response that has been set should be +returned), SSL_TLSEXT_ERR_NOACK (meaning that an OCSP response should not be +returned) or SSL_TLSEXT_ERR_ALERT_FATAL (meaning that a fatal error has +occurred). + +SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(), +SSL_set_tlsext_status_type() and SSL_set_tlsext_status_ocsp_resp() return 0 on +error or 1 on success. + +SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data +or -1 if there is no OCSP response data. + +=cut diff --git a/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod index b754c16a86e6..234fbc845002 100644 --- a/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod +++ b/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod @@ -48,25 +48,8 @@ even if he gets hold of the normal (certified) key, as this key was only used for signing. In order to perform a DH key exchange the server must use a DH group -(DH parameters) and generate a DH key. -The server will always generate a new DH key during the negotiation -if either the DH parameters are supplied via callback or the -SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set (or both). -It will immediately create a DH key if DH parameters are supplied via -SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set. -In this case, -it may happen that a key is generated on initialization without later -being needed, while on the other hand the computer time during the -negotiation is being saved. - -If "strong" primes were used to generate the DH parameters, it is not strictly -necessary to generate a new key for each handshake but it does improve forward -secrecy. If it is not assured that "strong" primes were used, -SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup -attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the -computer time needed during negotiation, but it is not very large, so -application authors/users should consider always enabling this option. -The option is required to implement perfect forward secrecy (PFS). +(DH parameters) and generate a DH key. The server will always generate +a new DH key during the negotiation. As generating DH parameters is extremely time consuming, an application should not generate the parameters on the fly but supply the parameters. @@ -93,10 +76,9 @@ can supply the DH parameters via a callback function. Previous versions of the callback used B and B parameters to control parameter generation for export and non-export cipher suites. Modern servers that do not support export ciphersuites -are advised to either use SSL_CTX_set_tmp_dh() in combination with -SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore -B and B and simply supply at least 2048-bit -parameters in the callback. +are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use +the callback but ignore B and B and simply +supply at least 2048-bit parameters in the callback. =head1 EXAMPLES @@ -128,7 +110,6 @@ partly left out.) if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) { /* Error. */ } - SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); ... =head1 RETURN VALUES diff --git a/engines/e_chil.c b/engines/e_chil.c index 72d14fe383a4..5dfab5134527 100644 --- a/engines/e_chil.c +++ b/engines/e_chil.c @@ -1,4 +1,4 @@ -/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */ +/* crypto/engine/e_chil.c */ /* * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for diff --git a/ssl/d1_both.c b/ssl/d1_both.c index c2c8d57e9d9c..d1fc716d5c5c 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -295,8 +295,44 @@ int dtls1_do_write(SSL *s, int type) blocksize = 0; frag_off = 0; + s->rwstate = SSL_NOTHING; + /* s->init_num shouldn't ever be < 0...but just in case */ while (s->init_num > 0) { + if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) { + /* We must be writing a fragment other than the first one */ + + if (frag_off > 0) { + /* This is the first attempt at writing out this fragment */ + + if (s->init_off <= DTLS1_HM_HEADER_LENGTH) { + /* + * Each fragment that was already sent must at least have + * contained the message header plus one other byte. + * Therefore |init_off| must have progressed by at least + * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went + * wrong. + */ + return -1; + } + + /* + * Adjust |init_off| and |init_num| to allow room for a new + * message header for this fragment. + */ + s->init_off -= DTLS1_HM_HEADER_LENGTH; + s->init_num += DTLS1_HM_HEADER_LENGTH; + } else { + /* + * We must have been called again after a retry so use the + * fragment offset from our last attempt. We do not need + * to adjust |init_off| and |init_num| as above, because + * that should already have been done before the retry. + */ + frag_off = s->d1->w_msg_hdr.frag_off; + } + } + used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH + mac_size + blocksize; if (s->d1->mtu > used_len) @@ -309,8 +345,10 @@ int dtls1_do_write(SSL *s, int type) * grr.. we could get an error if MTU picked was wrong */ ret = BIO_flush(SSL_get_wbio(s)); - if (ret <= 0) + if (ret <= 0) { + s->rwstate = SSL_WRITING; return ret; + } used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize; if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) { curr_mtu = s->d1->mtu - used_len; @@ -336,25 +374,6 @@ int dtls1_do_write(SSL *s, int type) * XDTLS: this function is too long. split out the CCS part */ if (type == SSL3_RT_HANDSHAKE) { - if (s->init_off != 0) { - OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH); - s->init_off -= DTLS1_HM_HEADER_LENGTH; - s->init_num += DTLS1_HM_HEADER_LENGTH; - - /* - * We just checked that s->init_num > 0 so this cast should - * be safe - */ - if (((unsigned int)s->init_num) > curr_mtu) - len = curr_mtu; - else - len = s->init_num; - } - - /* Shouldn't ever happen */ - if (len > INT_MAX) - len = INT_MAX; - if (len < DTLS1_HM_HEADER_LENGTH) { /* * len is so small that we really can't do anything sensible @@ -442,7 +461,16 @@ int dtls1_do_write(SSL *s, int type) } s->init_off += ret; s->init_num -= ret; - frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); + ret -= DTLS1_HM_HEADER_LENGTH; + frag_off += ret; + + /* + * We save the fragment offset for the next fragment so we have it + * available in case of an IO retry. We don't know the length of the + * next fragment yet so just set that to 0 for now. It will be + * updated again later. + */ + dtls1_fix_message_header(s, frag_off, 0); } } return (0); diff --git a/ssl/kssl.c b/ssl/kssl.c index cf585679dccc..f2839bdcd7f5 100644 --- a/ssl/kssl.c +++ b/ssl/kssl.c @@ -1,4 +1,4 @@ -/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ +/* ssl/kssl.c */ /* * Written by Vern Staats for the OpenSSL project * 2000. diff --git a/ssl/kssl.h b/ssl/kssl.h index 9a5767280150..ae8a51f472da 100644 --- a/ssl/kssl.h +++ b/ssl/kssl.h @@ -1,4 +1,4 @@ -/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */ +/* ssl/kssl.h */ /* * Written by Vern Staats for the OpenSSL project * 2000. project 2000. diff --git a/ssl/kssl_lcl.h b/ssl/kssl_lcl.h index 46dcef22d16c..8e6a6d69e949 100644 --- a/ssl/kssl_lcl.h +++ b/ssl/kssl_lcl.h @@ -1,4 +1,4 @@ -/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */ +/* ssl/kssl.h */ /* * Written by Vern Staats for the OpenSSL project * 2000. project 2000. diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c index 4289272b73d3..07e9df82820a 100644 --- a/ssl/s2_srvr.c +++ b/ssl/s2_srvr.c @@ -402,7 +402,7 @@ static int get_client_master_key(SSL *s) } cp = ssl2_get_cipher_by_char(p); - if (cp == NULL) { + if (cp == NULL || sk_SSL_CIPHER_find(s->session->ciphers, cp) < 0) { ssl2_return_error(s, SSL2_PE_NO_CIPHER); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH); return (-1); @@ -598,6 +598,11 @@ static int get_client_hello(SSL *s) s->s2->tmp.cipher_spec_length = i; n2s(p, i); s->s2->tmp.session_id_length = i; + if ((i < 0) || (i > SSL_MAX_SSL_SESSION_ID_LENGTH)) { + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + return -1; + } n2s(p, i); s->s2->challenge_length = i; if ((i < SSL2_MIN_CHALLENGE_LENGTH) || @@ -687,8 +692,12 @@ static int get_client_hello(SSL *s) prio = cs; allow = cl; } + + /* Generate list of SSLv2 ciphers shared between client and server */ for (z = 0; z < sk_SSL_CIPHER_num(prio); z++) { - if (sk_SSL_CIPHER_find(allow, sk_SSL_CIPHER_value(prio, z)) < 0) { + const SSL_CIPHER *cp = sk_SSL_CIPHER_value(prio, z); + if ((cp->algorithm_ssl & SSL_SSLV2) == 0 || + sk_SSL_CIPHER_find(allow, cp) < 0) { (void)sk_SSL_CIPHER_delete(prio, z); z--; } @@ -697,6 +706,13 @@ static int get_client_hello(SSL *s) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers = prio; } + + /* Make sure we have at least one cipher in common */ + if (sk_SSL_CIPHER_num(s->session->ciphers) == 0) { + ssl2_return_error(s, SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_NO_CIPHER_MATCH); + return -1; + } /* * s->session->ciphers should now have a list of ciphers that are on * both the client and server. This list is ordered by the order the diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index bc5254c81160..04cc9f54a92d 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -2350,37 +2350,44 @@ int ssl3_get_cert_status(SSL *s) n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_STATUS_A, SSL3_ST_CR_CERT_STATUS_B, - SSL3_MT_CERTIFICATE_STATUS, 16384, &ok); + -1, 16384, &ok); if (!ok) return ((int)n); - if (n < 4) { - /* need at least status type + length */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH); - goto f_err; + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) { + /* + * The CertificateStatus message is optional even if + * tlsext_status_expected is set + */ + s->s3->tmp.reuse_message = 1; + } else { + if (n < 4) { + /* need at least status type + length */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + p = (unsigned char *)s->init_msg; + if (*p++ != TLSEXT_STATUSTYPE_ocsp) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE); + goto f_err; + } + n2l3(p, resplen); + if (resplen + 4 != n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + s->tlsext_ocsp_resp = BUF_memdup(p, resplen); + if (s->tlsext_ocsp_resp == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE); + goto f_err; + } + s->tlsext_ocsp_resplen = resplen; } - p = (unsigned char *)s->init_msg; - if (*p++ != TLSEXT_STATUSTYPE_ocsp) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE); - goto f_err; - } - n2l3(p, resplen); - if (resplen + 4 != n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - if (s->tlsext_ocsp_resp) - OPENSSL_free(s->tlsext_ocsp_resp); - s->tlsext_ocsp_resp = BUF_memdup(p, resplen); - if (!s->tlsext_ocsp_resp) { - al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE); - goto f_err; - } - s->tlsext_ocsp_resplen = resplen; if (s->ctx->tlsext_status_cb) { int ret; ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); @@ -3603,7 +3610,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) DH_free(dh_srvr); } - if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) + if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024) || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); goto f_err; diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 64793d6af34f..f846cb5b7b01 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3206,13 +3206,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); return (ret); } - if (!(s->options & SSL_OP_SINGLE_DH_USE)) { - if (!DH_generate_key(dh)) { - DH_free(dh); - SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); - return (ret); - } - } if (s->cert->dh_tmp != NULL) DH_free(s->cert->dh_tmp); s->cert->dh_tmp = dh; @@ -3263,6 +3256,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) #ifndef OPENSSL_NO_TLSEXT case SSL_CTRL_SET_TLSEXT_HOSTNAME: if (larg == TLSEXT_NAMETYPE_host_name) { + size_t len; + if (s->tlsext_hostname != NULL) OPENSSL_free(s->tlsext_hostname); s->tlsext_hostname = NULL; @@ -3270,7 +3265,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) ret = 1; if (parg == NULL) break; - if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name) { + len = strlen((char *)parg); + if (len == 0 || len > TLSEXT_MAXLEN_host_name) { SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME); return 0; } @@ -3710,13 +3706,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB); return 0; } - if (!(ctx->options & SSL_OP_SINGLE_DH_USE)) { - if (!DH_generate_key(new)) { - SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB); - DH_free(new); - return 0; - } - } if (cert->dh_tmp != NULL) DH_free(cert->dh_tmp); cert->dh_tmp = new; @@ -4337,6 +4326,21 @@ int ssl3_shutdown(SSL *s) } #endif } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { + if (SSL_in_init(s)) { + /* + * We can't shutdown properly if we are in the middle of a + * handshake. Doing so is problematic because the peer may send a + * CCS before it acts on our close_notify. However we should not + * continue to process received handshake messages or CCS once our + * close_notify has been sent. Therefore any close_notify from + * the peer will be unreadable because we have not moved to the next + * cipher state. Its best just to avoid this can-of-worms. Return + * an error if we are wanting to wait for a close_notify from the + * peer and we are in init. + */ + SSLerr(SSL_F_SSL3_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT); + return -1; + } /* * If we are waiting for a close from our peer, we are closed */ diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index ee83105b75bf..ab28702ee972 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -1,4 +1,4 @@ -/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */ +/* ssl/s3_srvr.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1004,6 +1004,12 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } + if ((j < 0) || (j > SSL_MAX_SSL_SESSION_ID_LENGTH)) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + s->hit = 0; /* * Versions before 0.9.7 always allow clients to resume sessions in @@ -1681,20 +1687,9 @@ int ssl3_send_server_key_exchange(SSL *s) } s->s3->tmp.dh = dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) { - if (!DH_generate_key(dh)) { - SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - } else { - dh->pub_key = BN_dup(dhp->pub_key); - dh->priv_key = BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) { - SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } + if (!DH_generate_key(dh)) { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); + goto err; } r[0] = dh->p; r[1] = dh->g; diff --git a/ssl/ssl.h b/ssl/ssl.h index afec1f5bf29f..ae8c92575e03 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -625,7 +625,7 @@ struct ssl_session_st { # define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L /* If set, always create a new key when using tmp_ecdh parameters */ # define SSL_OP_SINGLE_ECDH_USE 0x00080000L -/* If set, always create a new key when using tmp_dh parameters */ +/* Does nothing: retained for compatibility */ # define SSL_OP_SINGLE_DH_USE 0x00100000L /* Does nothing: retained for compatibiity */ # define SSL_OP_EPHEMERAL_RSA 0x0 @@ -2092,7 +2092,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_CTX_set1_sigalgs_list(ctx, s) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) # define SSL_set1_sigalgs(ctx, slist, slistlen) \ - SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,clistlen,(int *)slist) + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)slist) # define SSL_set1_sigalgs_list(ctx, s) \ SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) # define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \ @@ -2713,6 +2713,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL3_SETUP_KEY_BLOCK 157 # define SSL_F_SSL3_SETUP_READ_BUFFER 156 # define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 +# define SSL_F_SSL3_SHUTDOWN 396 # define SSL_F_SSL3_WRITE_BYTES 158 # define SSL_F_SSL3_WRITE_PENDING 159 # define SSL_F_SSL_ADD_CERT_CHAIN 318 @@ -3056,6 +3057,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_SERVERHELLO_TLSEXT 275 # define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 # define SSL_R_SHORT_READ 219 +# define SSL_R_SHUTDOWN_WHILE_IN_INIT 407 # define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360 # define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 # define SSL_R_SRP_A_CALC 361 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 6d1366f2a59d..dd3b2afd1ea6 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -206,6 +206,7 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "ssl3_setup_key_block"}, {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "ssl3_setup_read_buffer"}, {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "ssl3_setup_write_buffer"}, + {ERR_FUNC(SSL_F_SSL3_SHUTDOWN), "ssl3_shutdown"}, {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "ssl3_write_bytes"}, {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "ssl3_write_pending"}, {ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "ssl_add_cert_chain"}, @@ -647,6 +648,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED), "session id context uninitialized"}, {ERR_REASON(SSL_R_SHORT_READ), "short read"}, + {ERR_REASON(SSL_R_SHUTDOWN_WHILE_IN_INIT), "shutdown while in init"}, {ERR_REASON(SSL_R_SIGNATURE_ALGORITHMS_ERROR), "signature algorithms error"}, {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE), diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index f2071db93702..2744be8ad8ce 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1060,10 +1060,7 @@ int SSL_shutdown(SSL *s) return -1; } - if ((s != NULL) && !SSL_in_init(s)) - return (s->method->ssl_shutdown(s)); - else - return (1); + return s->method->ssl_shutdown(s); } int SSL_renegotiate(SSL *s) diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 68390d310809..b18299834384 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -573,9 +573,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, int r; #endif - if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH) - goto err; - if (session_id + len > limit) { fatal = 1; goto err; diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index f46544b4d713..514fcb3e4e74 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -1155,7 +1155,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, so = s->s3->server_opaque_prf_input; /* * must be same as col (see - * draft-resc-00.txts-opaque-prf-input-00.txt, section 3.1) + * draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1) */ sol = s->s3->client_opaque_prf_input_len; } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 3176d1e3baba..d9ba99d73584 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -3157,22 +3157,20 @@ int ssl_check_serverhello_tlsext(SSL *s) } # endif + OPENSSL_free(s->tlsext_ocsp_resp); + s->tlsext_ocsp_resp = NULL; + s->tlsext_ocsp_resplen = -1; /* * If we've requested certificate status and we wont get one tell the * callback */ if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected) - && s->ctx && s->ctx->tlsext_status_cb) { + && !(s->hit) && s->ctx && s->ctx->tlsext_status_cb) { int r; /* - * Set resp to NULL, resplen to -1 so callback knows there is no - * response. + * Call callback with resp == NULL and resplen == -1 so callback + * knows there is no response */ - if (s->tlsext_ocsp_resp) { - OPENSSL_free(s->tlsext_ocsp_resp); - s->tlsext_ocsp_resp = NULL; - } - s->tlsext_ocsp_resplen = -1; r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); if (r == 0) { al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; @@ -3583,7 +3581,7 @@ static int tls12_get_pkey_idx(unsigned char sig_alg) static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, int *psignhash_nid, const unsigned char *data) { - int sign_nid = 0, hash_nid = 0; + int sign_nid = NID_undef, hash_nid = NID_undef; if (!phash_nid && !psign_nid && !psignhash_nid) return; if (phash_nid || psignhash_nid) { @@ -3599,9 +3597,9 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, *psign_nid = sign_nid; } if (psignhash_nid) { - if (sign_nid && hash_nid) - OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid); - else + if (sign_nid == NID_undef || hash_nid == NID_undef + || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, + sign_nid) <= 0) *psignhash_nid = NID_undef; } } diff --git a/util/domd b/util/domd index 6a628c7f96c2..95bb1b06e257 100755 --- a/util/domd +++ b/util/domd @@ -14,8 +14,8 @@ if [ "$MAKEDEPEND" = "" ]; then MAKEDEPEND=makedepend; fi cp Makefile Makefile.save # fake the presence of Kerberos touch $TOP/krb5.h -if ${MAKEDEPEND} --version 2>&1 | grep -q "clang" || - echo $MAKEDEPEND | grep -q "gcc"; then +if ${MAKEDEPEND} --version 2>&1 | grep "clang" > /dev/null || + echo $MAKEDEPEND | grep "gcc" > /dev/null; then args="" while [ $# -gt 0 ]; do if [ "$1" != "--" ]; then args="$args $1"; fi diff --git a/util/pl/VC-32.pl b/util/pl/VC-32.pl index 284fe0381ed9..0f5547f056c2 100644 --- a/util/pl/VC-32.pl +++ b/util/pl/VC-32.pl @@ -361,9 +361,13 @@ sub do_link_rule $ret.="$target: $files $dep_libs"; if ($standalone == 1) { - $ret.=" \$(OBJ_D)${o}applink.obj\n"; + $ret.=" \$(OBJ_D)${o}applink.obj" if $shlib; + $ret.="\n"; $ret.=" \$(LINK) \$(LFLAGS) $efile$target @<<\n\t"; - $ret.= "\$(EX_LIBS) \$(OBJ_D)${o}applink.obj " if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild); + if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild) { + $ret.= "\$(EX_LIBS) "; + $ret.= "\$(OBJ_D)${o}applink.obj " if $shlib; + } $ret.="$files $libs\n<<\n"; } elsif ($standalone == 2) diff --git a/util/pod2mantest b/util/pod2mantest new file mode 100755 index 000000000000..384e683df4cc --- /dev/null +++ b/util/pod2mantest @@ -0,0 +1,58 @@ +#!/bin/sh + +# This script is used by test/Makefile to check whether a sane 'pod2man' +# is installed. +# ('make install' should not try to run 'pod2man' if it does not exist or if +# it is a broken 'pod2man' version that is known to cause trouble. if we find +# the system 'pod2man' to be broken, we use our own copy instead) +# +# In any case, output an appropriate command line for running (or not +# running) pod2man. + + +IFS=: +if test "$OSTYPE" = "msdosdjgpp"; then IFS=";"; fi + +try_without_dir=true +# First we try "pod2man", then "$dir/pod2man" for each item in $PATH. +for dir in dummy${IFS}$PATH; do + if [ "$try_without_dir" = true ]; then + # first iteration + pod2man=pod2man + try_without_dir=false + else + # second and later iterations + pod2man="$dir/pod2man" + if [ ! -f "$pod2man" ]; then # '-x' is not available on Ultrix + pod2man='' + fi + fi + + if [ ! "$pod2man" = '' ]; then + failure=none + + if "$pod2man" --section=1 --center=OpenSSL --release=dev pod2mantest.pod | fgrep OpenSSL >/dev/null; then + : + else + failure=BasicTest + fi + + if [ "$failure" = none ]; then + if "$pod2man" --section=1 --center=OpenSSL --release=dev pod2mantest.pod | grep '^MARKER - ' >/dev/null; then + failure=MultilineTest + fi + fi + + + if [ "$failure" = none ]; then + echo "$pod2man" + exit 0 + fi + + echo "$pod2man does not work properly ('$failure' failed). Looking for another pod2man ..." >&2 + fi +done + +echo "No working pod2man found. Consider installing a new version." >&2 +echo "As a workaround, we'll use a bundled old copy of pod2man.pl." >&2 +echo "$1 ../../util/pod2man.pl" From d04bd9e9248a5b28fa75fdc94acf9ecb1c4cf4a4 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 28 Jan 2016 18:57:47 +0000 Subject: [PATCH 018/236] Fix -include .depend hack from r294370 for headers not in .PATH. This hack will be removed in a few weeks. It is here to fix incremental builds of SSH between r291941 and r294370. Reported by: jmallett MFC after: 1 day Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.dep.mk | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk index 948f31008a71..0300e77d7e5f 100644 --- a/share/mk/bsd.dep.mk +++ b/share/mk/bsd.dep.mk @@ -206,12 +206,13 @@ depend: beforedepend ${DEPENDFILE} afterdepend _CFLAGS_INCLUDES= ${CFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g} _CXXFLAGS_INCLUDES= ${CXXFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g} # XXX: Temporary hack to workaround .depend files not tracking -include -.if !empty(_CFLAGS_INCLUDES) -${OBJS} ${POBJS} ${SOBJS}: ${_CFLAGS_INCLUDES:M*.h} -.endif -.if !empty(_CXXFLAGS_INCLUDES) -${OBJS} ${POBJS} ${SOBJS}: ${_CXXFLAGS_INCLUDES:M*.h} +_hdrincludes=${_CFLAGS_INCLUDES:M*.h} ${_CXXFLAGS_INCLUDES:M*.h} +.for _hdr in ${_hdrincludes:O:u} +.if exists(${_hdr}) +${OBJS} ${POBJS} ${SOBJS}: ${_hdr} .endif +.endfor +.undef _hdrincludes # Different types of sources are compiled with slightly different flags. # Split up the sources, and filter out headers and non-applicable flags. From f8f3d276732e67c4809fe64ee9822d10356a156a Mon Sep 17 00:00:00 2001 From: vangyzen Date: Thu, 28 Jan 2016 20:24:15 +0000 Subject: [PATCH 019/236] kqueue EVFILT_PROC: avoid collision between NOTE_CHILD and NOTE_EXIT NOTE_CHILD and NOTE_EXIT return something in kevent.data: the parent pid (ppid) for NOTE_CHILD and the exit status for NOTE_EXIT. Do not let the two events be combined, since one would overwrite the other's data. PR: 180385 Submitted by: David A. Bright Reviewed by: jhb MFC after: 1 month Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D4900 --- sys/kern/kern_event.c | 61 +++++++++++--- sys/sys/event.h | 1 + tests/sys/kqueue/common.h | 1 + tests/sys/kqueue/main.c | 75 +++++++++++++---- tests/sys/kqueue/proc.c | 168 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 25 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index d41ac96a70af..805b6b541612 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -373,11 +373,21 @@ filt_procattach(struct knote *kn) kn->kn_flags |= EV_CLEAR; /* automatically set */ /* - * internal flag indicating registration done by kernel + * Internal flag indicating registration done by kernel for the + * purposes of getting a NOTE_CHILD notification. */ - if (kn->kn_flags & EV_FLAG1) { + if (kn->kn_flags & EV_FLAG2) { + kn->kn_flags &= ~EV_FLAG2; kn->kn_data = kn->kn_sdata; /* ppid */ kn->kn_fflags = NOTE_CHILD; + kn->kn_sfflags &= ~NOTE_EXIT; + immediate = 1; /* Force immediate activation of child note. */ + } + /* + * Internal flag indicating registration done by kernel (for other than + * NOTE_CHILD). + */ + if (kn->kn_flags & EV_FLAG1) { kn->kn_flags &= ~EV_FLAG1; } @@ -385,9 +395,10 @@ filt_procattach(struct knote *kn) knlist_add(&p->p_klist, kn, 1); /* - * Immediately activate any exit notes if the target process is a - * zombie. This is necessary to handle the case where the target - * process, e.g. a child, dies before the kevent is registered. + * Immediately activate any child notes or, in the case of a zombie + * target process, exit notes. The latter is necessary to handle the + * case where the target process, e.g. a child, dies before the kevent + * is registered. */ if (immediate && filt_proc(kn, NOTE_EXIT)) KNOTE_ACTIVATE(kn, 0); @@ -495,7 +506,7 @@ knote_fork(struct knlist *list, int pid) /* * The NOTE_TRACK case. In addition to the activation - * of the event, we need to register new event to + * of the event, we need to register new events to * track the child. Drop the locks in preparation for * the call to kqueue_register(). */ @@ -504,8 +515,27 @@ knote_fork(struct knlist *list, int pid) list->kl_unlock(list->kl_lockarg); /* - * Activate existing knote and register a knote with + * Activate existing knote and register tracking knotes with * new process. + * + * First register a knote to get just the child notice. This + * must be a separate note from a potential NOTE_EXIT + * notification since both NOTE_CHILD and NOTE_EXIT are defined + * to use the data field (in conflicting ways). + */ + kev.ident = pid; + kev.filter = kn->kn_filter; + kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_ONESHOT | EV_FLAG2; + kev.fflags = kn->kn_sfflags; + kev.data = kn->kn_id; /* parent */ + kev.udata = kn->kn_kevent.udata;/* preserve udata */ + error = kqueue_register(kq, &kev, NULL, 0); + if (error) + kn->kn_fflags |= NOTE_TRACKERR; + + /* + * Then register another knote to track other potential events + * from the new process. */ kev.ident = pid; kev.filter = kn->kn_filter; @@ -1129,7 +1159,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa if (fp->f_type == DTYPE_KQUEUE) { /* - * if we add some inteligence about what we are doing, + * If we add some intelligence about what we are doing, * we should be able to support events on ourselves. * We need to know when we are doing this to prevent * getting both the knlist lock and the kq lock since @@ -1161,7 +1191,18 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa kqueue_expand(kq, fops, kev->ident, waitok); KQ_LOCK(kq); - if (kq->kq_knhashmask != 0) { + + /* + * If possible, find an existing knote to use for this kevent. + */ + if (kev->filter == EVFILT_PROC && + (kev->flags & (EV_FLAG1 | EV_FLAG2)) != 0) { + /* This is an internal creation of a process tracking + * note. Don't attempt to coalesce this with an + * existing note. + */ + ; + } else if (kq->kq_knhashmask != 0) { struct klist *list; list = &kq->kq_knhash[ @@ -1173,7 +1214,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa } } - /* knote is in the process of changing, wait for it to stablize. */ + /* knote is in the process of changing, wait for it to stabilize. */ if (kn != NULL && (kn->kn_status & KN_INFLUX) == KN_INFLUX) { KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal); if (filedesc_unlock) { diff --git a/sys/sys/event.h b/sys/sys/event.h index 0f132318c827..35aad99899e3 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -80,6 +80,7 @@ struct kevent { #define EV_SYSFLAGS 0xF000 /* reserved by system */ #define EV_DROP 0x1000 /* note should be dropped */ #define EV_FLAG1 0x2000 /* filter-specific flag */ +#define EV_FLAG2 0x4000 /* filter-specific flag */ /* returned values */ #define EV_EOF 0x8000 /* EOF detected */ diff --git a/tests/sys/kqueue/common.h b/tests/sys/kqueue/common.h index aada7786ad0c..89a402986021 100644 --- a/tests/sys/kqueue/common.h +++ b/tests/sys/kqueue/common.h @@ -46,6 +46,7 @@ int vnode_fd; extern const char * kevent_to_str(struct kevent *); struct kevent * kevent_get(int); +struct kevent * kevent_get_timeout(int, int); void kevent_cmp(struct kevent *, struct kevent *); diff --git a/tests/sys/kqueue/main.c b/tests/sys/kqueue/main.c index f76c4e23be12..553478a514f5 100644 --- a/tests/sys/kqueue/main.c +++ b/tests/sys/kqueue/main.c @@ -69,6 +69,28 @@ kevent_get(int kqfd) return (kev); } +/* Retrieve a single kevent, specifying a maximum time to wait for it. */ +struct kevent * +kevent_get_timeout(int kqfd, int seconds) +{ + int nfds; + struct kevent *kev; + struct timespec timeout = {seconds, 0}; + + if ((kev = calloc(1, sizeof(*kev))) == NULL) + err(1, "out of memory"); + + nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout); + if (nfds < 0) { + err(1, "kevent(2)"); + } else if (nfds == 0) { + free(kev); + kev = NULL; + } + + return (kev); +} + char * kevent_fflags_dump(struct kevent *kev) { @@ -82,25 +104,39 @@ kevent_fflags_dump(struct kevent *kev) abort(); /* Not every filter has meaningful fflags */ - if (kev->filter != EVFILT_VNODE) { - snprintf(buf, 1024, "fflags = %d", kev->fflags); - return (buf); - } - - snprintf(buf, 1024, "fflags = %d (", kev->fflags); - KEVFFL_DUMP(NOTE_DELETE); - KEVFFL_DUMP(NOTE_WRITE); - KEVFFL_DUMP(NOTE_EXTEND); + if (kev->filter == EVFILT_PROC) { + snprintf(buf, 1024, "fflags = %x (", kev->fflags); + KEVFFL_DUMP(NOTE_EXIT); + KEVFFL_DUMP(NOTE_FORK); + KEVFFL_DUMP(NOTE_EXEC); + KEVFFL_DUMP(NOTE_CHILD); + KEVFFL_DUMP(NOTE_TRACKERR); + KEVFFL_DUMP(NOTE_TRACK); + buf[strlen(buf) - 1] = ')'; + } else if (kev->filter == EVFILT_PROCDESC) { + snprintf(buf, 1024, "fflags = %x (", kev->fflags); + KEVFFL_DUMP(NOTE_EXIT); + KEVFFL_DUMP(NOTE_FORK); + KEVFFL_DUMP(NOTE_EXEC); + buf[strlen(buf) - 1] = ')'; + } else if (kev->filter == EVFILT_VNODE) { + snprintf(buf, 1024, "fflags = %x (", kev->fflags); + KEVFFL_DUMP(NOTE_DELETE); + KEVFFL_DUMP(NOTE_WRITE); + KEVFFL_DUMP(NOTE_EXTEND); #if HAVE_NOTE_TRUNCATE - KEVFFL_DUMP(NOTE_TRUNCATE); + KEVFFL_DUMP(NOTE_TRUNCATE); #endif - KEVFFL_DUMP(NOTE_ATTRIB); - KEVFFL_DUMP(NOTE_LINK); - KEVFFL_DUMP(NOTE_RENAME); + KEVFFL_DUMP(NOTE_ATTRIB); + KEVFFL_DUMP(NOTE_LINK); + KEVFFL_DUMP(NOTE_RENAME); #if HAVE_NOTE_REVOKE - KEVFFL_DUMP(NOTE_REVOKE); + KEVFFL_DUMP(NOTE_REVOKE); #endif - buf[strlen(buf) - 1] = ')'; + buf[strlen(buf) - 1] = ')'; + } else { + snprintf(buf, 1024, "fflags = %x", kev->fflags); + } return (buf); } @@ -260,6 +296,15 @@ main(int argc, char **argv) argc--; } + /* + * Some tests fork. If output is fully buffered, + * the children inherit some buffered data and flush + * it when they exit, causing some data to be printed twice. + * Use line buffering to avoid this problem. + */ + setlinebuf(stdout); + setlinebuf(stderr); + test_kqueue(); test_kqueue_close(); diff --git a/tests/sys/kqueue/proc.c b/tests/sys/kqueue/proc.c index 6288ee6d91b4..79b8d35f4f25 100644 --- a/tests/sys/kqueue/proc.c +++ b/tests/sys/kqueue/proc.c @@ -74,6 +74,172 @@ add_and_delete(void) } +static void +proc_track(int sleep_time) +{ + char test_id[64]; + struct kevent kev; + pid_t pid; + int pipe_fd[2]; + ssize_t result; + + snprintf(test_id, sizeof(test_id), + "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time); + test_begin(test_id); + test_no_kevents(); + + if (pipe(pipe_fd)) { + err(1, "pipe (parent) failed! (%s() at %s:%d)", + __func__, __FILE__, __LINE__); + } + + /* Create a child to track. */ + pid = fork(); + if (pid == 0) { /* Child */ + pid_t grandchild = -1; + + /* + * Give the parent a chance to start tracking us. + */ + result = read(pipe_fd[1], test_id, 1); + if (result != 1) { + err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)", + result, __func__, __FILE__, __LINE__); + } + + /* + * Spawn a grandchild that will immediately exit. If the kernel has bug + * 180385, the parent will see a kevent with both NOTE_CHILD and + * NOTE_EXIT. If that bug is fixed, it will see two separate kevents + * for those notes. Note that this triggers the conditions for + * detecting the bug quite reliably on a 1 CPU system (or if the test + * process is restricted to a single CPU), but may not trigger it on a + * multi-CPU system. + */ + grandchild = fork(); + if (grandchild == 0) { /* Grandchild */ + if (sleep_time) sleep(sleep_time); + exit(1); + } else if (grandchild == -1) { /* Error */ + err(1, "fork (grandchild) failed! (%s() at %s:%d)", + __func__, __FILE__, __LINE__); + } else { /* Child (Grandchild Parent) */ + printf(" -- grandchild created (pid %d)\n", (int) grandchild); + } + if (sleep_time) sleep(sleep_time); + exit(0); + } else if (pid == -1) { /* Error */ + err(1, "fork (child) failed! (%s() at %s:%d)", + __func__, __FILE__, __LINE__); + } + + printf(" -- child created (pid %d)\n", (int) pid); + + kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE, + NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK, + 0, NULL); + + printf(" -- tracking child (pid %d)\n", (int) pid); + + /* Now that we're tracking the child, tell it to proceed. */ + result = write(pipe_fd[0], test_id, 1); + if (result != 1) { + err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)", + result, __func__, __FILE__, __LINE__); + } + + /* + * Several events should be received: + * - NOTE_FORK (from child) + * - NOTE_CHILD (from grandchild) + * - NOTE_EXIT (from grandchild) + * - NOTE_EXIT (from child) + * + * The NOTE_FORK and NOTE_EXIT from the child could be combined into a + * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must + * not be combined. + * + * The loop continues until no events are received within a 5 second + * period, at which point it is assumed that no more will be coming. The + * loop is deliberately designed to attempt to get events even after all + * the expected ones are received in case some spurious events are + * generated as well as the expected ones. + */ + { + int child_exit = 0; + int child_fork = 0; + int gchild_exit = 0; + int gchild_note = 0; + pid_t gchild_pid = -1; + int done = 0; + + while (!done) + { + int handled = 0; + struct kevent *kevp; + + kevp = kevent_get_timeout(kqfd, 5); + if (kevp == NULL) { + done = 1; + } else { + printf(" -- Received kevent: %s\n", kevent_to_str(kevp)); + + if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) { + errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp)); + } + + if (kevp->fflags & NOTE_CHILD) { + if (kevp->data == pid) { + if (!gchild_note) { + ++gchild_note; + gchild_pid = kevp->ident; + ++handled; + } else { + errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp)); + } + } + } + + if (kevp->fflags & NOTE_EXIT) { + if ((kevp->ident == pid) && (!child_exit)) { + ++child_exit; + ++handled; + } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) { + ++gchild_exit; + ++handled; + } else { + errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp)); + } + } + + if (kevp->fflags & NOTE_FORK) { + if ((kevp->ident == pid) && (!child_fork)) { + ++child_fork; + ++handled; + } else { + errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp)); + } + } + + if (!handled) { + errx(1, "Spurious kevent: %s", kevent_to_str(kevp)); + } + + free(kevp); + } + } + + /* Make sure all expected events were received. */ + if (child_exit && child_fork && gchild_exit && gchild_note) { + printf(" -- Received all expected events.\n"); + } else { + errx(1, "Did not receive all expected events."); + } + } + + success(); +} + #ifdef TODO static void event_trigger(void) @@ -236,6 +402,8 @@ test_evfilt_proc() signal(SIGUSR1, sig_handler); add_and_delete(); + proc_track(0); /* Run without sleeping before children exit. */ + proc_track(1); /* Sleep a bit in the children before exiting. */ #if TODO event_trigger(); From ecd8f7784da1ca216b83d3e323e547735dda7218 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 28 Jan 2016 21:45:25 +0000 Subject: [PATCH 020/236] filemon: Use process_exec EVENTHANDLER to capture sys_execve. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon_wrapper.c | 76 ++++++++++--------------------- sys/modules/filemon/Makefile | 2 +- 2 files changed, 25 insertions(+), 53 deletions(-) diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 33dcc1304486..9e157037ba16 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -29,8 +29,10 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include +#include #include "opt_compat.h" @@ -44,7 +46,6 @@ __FBSDID("$FreeBSD$"); (2011-09-10) so this code is broken for 9-CURRENT September 10th-16th. */ #define sys_chdir chdir -#define sys_execve execve #define sys_link link #define sys_open open #define sys_rename rename @@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$"); #endif #endif /* __FreeBSD_version */ +static eventhandler_tag filemon_exec_tag; static eventhandler_tag filemon_exit_tag; static eventhandler_tag filemon_fork_tag; @@ -137,62 +139,33 @@ filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap) return (ret); } -static int -filemon_wrapper_execve(struct thread *td, struct execve_args *uap) +static void +filemon_event_process_exec(void *arg __unused, struct proc *p, + struct image_params *imgp) { - char fname[MAXPATHLEN]; - int ret; - size_t done; - size_t len; struct filemon *filemon; - - copyinstr(uap->fname, fname, sizeof(fname), &done); - - if ((ret = sys_execve(td, uap)) == 0) { - if ((filemon = filemon_pid_check(curproc)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "E %d %s\n", - curproc->p_pid, fname); - - filemon_output(filemon, filemon->msgbufr, len); - - /* Unlock the found filemon structure. */ - filemon_filemon_unlock(filemon); - } - } - - return (ret); -} - -#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32) -static int -filemon_wrapper_freebsd32_execve(struct thread *td, - struct freebsd32_execve_args *uap) -{ - char fname[MAXPATHLEN]; - int ret; - size_t done; + char *fullpath, *freepath; size_t len; - struct filemon *filemon; - copyinstr(uap->fname, fname, sizeof(fname), &done); + if ((filemon = filemon_pid_check(p)) != NULL) { + fullpath = ""; + freepath = NULL; - if ((ret = freebsd32_execve(td, uap)) == 0) { - if ((filemon = filemon_pid_check(curproc)) != NULL) { - len = snprintf(filemon->msgbufr, - sizeof(filemon->msgbufr), "E %d %s\n", - curproc->p_pid, fname); + vn_fullpath(FIRST_THREAD_IN_PROC(p), imgp->vp, &fullpath, + &freepath); - filemon_output(filemon, filemon->msgbufr, len); + len = snprintf(filemon->msgbufr, + sizeof(filemon->msgbufr), "E %d %s\n", + p->p_pid, fullpath); - /* Unlock the found filemon structure. */ - filemon_filemon_unlock(filemon); - } + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + + free(freepath, M_TEMP); } - - return (ret); } -#endif static int filemon_wrapper_open(struct thread *td, struct open_args *uap) @@ -550,7 +523,6 @@ filemon_wrapper_install(void) #endif sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; - sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve; sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; @@ -566,7 +538,6 @@ filemon_wrapper_install(void) sv_table = ia32_freebsd_sysvec.sv_table; sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; - sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; @@ -579,6 +550,8 @@ filemon_wrapper_install(void) #endif #endif /* COMPAT_ARCH32 */ + filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec, + filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST); filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit, filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST); filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork, @@ -595,7 +568,6 @@ filemon_wrapper_deinstall(void) #endif sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir; - sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve; sv_table[SYS_open].sy_call = (sy_call_t *)sys_open; sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename; @@ -611,7 +583,6 @@ filemon_wrapper_deinstall(void) sv_table = ia32_freebsd_sysvec.sv_table; sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir; - sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve; sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open; sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat; sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename; @@ -624,6 +595,7 @@ filemon_wrapper_deinstall(void) #endif #endif /* COMPAT_ARCH32 */ + EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag); EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag); EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag); } diff --git a/sys/modules/filemon/Makefile b/sys/modules/filemon/Makefile index 80cc0a095abf..b97b2e2fbbd3 100644 --- a/sys/modules/filemon/Makefile +++ b/sys/modules/filemon/Makefile @@ -4,6 +4,6 @@ KMOD= filemon SRCS= ${KMOD}.c -SRCS+= opt_compat.h +SRCS+= opt_compat.h vnode_if.h .include From e1471224904e2479f5729771b945be48862c4ed5 Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 28 Jan 2016 23:12:12 +0000 Subject: [PATCH 021/236] Remove debug output which was committed by accident. Thanks to Oliver Pinter for reporting. MFC after: 3 days X-MFC with: r294995 --- sys/netinet/sctp_input.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 87be2d4b1a82..9edfcf67808a 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5688,7 +5688,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } -printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif @@ -5720,7 +5719,6 @@ printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(p if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } -printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif @@ -5833,7 +5831,6 @@ printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(p if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } -printf("Changing remote encaps port from %u to %u.\n", ntohs(net->port), ntohs(port)); net->port = port; } #endif From bab4c585f372eb9a2b1a18bc94709c64ab9724d4 Mon Sep 17 00:00:00 2001 From: jimharris Date: Thu, 28 Jan 2016 23:15:14 +0000 Subject: [PATCH 022/236] nvd: add hw.nvd.delete_max tunable The NVMe specification does not define a maximum or optimal delete size, so technically max delete size is min(full size of namespace, 2^32 - 1 LBAs). A single delete operation for a multi-TB NVMe namespace though may take much longer to complete than the nvme(4) I/O timeout period. So choose a sensible default here that is still suitably large to minimize the number of overall delete operations. This also fixes possible uint32_t overflow on initial TRIM operation for zpool create operations for NVMe namespaces with >4G LBAs. MFC after: 3 days Sponsored by: Intel --- share/man/man4/nvd.4 | 13 +++++++++++-- sys/dev/nvd/nvd.c | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/share/man/man4/nvd.4 b/share/man/man4/nvd.4 index f5210bf4a146..f7786790cd3f 100644 --- a/share/man/man4/nvd.4 +++ b/share/man/man4/nvd.4 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2012-2014 Intel Corporation +.\" Copyright (c) 2012-2016 Intel Corporation .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -33,7 +33,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 18, 2014 +.Dd January 28, 2016 .Dt NVD 4 .Os .Sh NAME @@ -74,6 +74,15 @@ Note that device nodes from the driver are not .Xr GEOM 4 disks and cannot be partitioned. +.Sh CONFIGURATION +The +.Nm +driver defines a system-wide maximum delete size for NVMe devices. The +default is 1GB. To select a different value, set the following tunable in +.Xr loader.conf 5 : +.Bd -literal -offset indent +hw.nvd.delete_max= +.Ed .Sh SEE ALSO .Xr GEOM 4 , .Xr nvme 4 , diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c index 24ee07583034..e062f57973d4 100644 --- a/sys/dev/nvd/nvd.c +++ b/sys/dev/nvd/nvd.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012-2013 Intel Corporation + * Copyright (C) 2012-2016 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -88,6 +89,19 @@ struct nvd_controller { static TAILQ_HEAD(, nvd_controller) ctrlr_head; static TAILQ_HEAD(disk_list, nvd_disk) disk_head; +static SYSCTL_NODE(_hw, OID_AUTO, nvd, CTLFLAG_RD, 0, "nvd driver parameters"); +/* + * The NVMe specification does not define a maximum or optimal delete size, so + * technically max delete size is min(full size of the namespace, 2^32 - 1 + * LBAs). A single delete for a multi-TB NVMe namespace though may take much + * longer to complete than the nvme(4) I/O timeout period. So choose a sensible + * default here that is still suitably large to minimize the number of overall + * delete operations. + */ +static uint64_t nvd_delete_max = (1024 * 1024 * 1024); /* 1GB */ +SYSCTL_UQUAD(_hw_nvd, OID_AUTO, delete_max, CTLFLAG_RDTUN, &nvd_delete_max, 0, + "nvd maximum BIO_DELETE size in bytes"); + static int nvd_modevent(module_t mod, int type, void *arg) { int error = 0; @@ -295,6 +309,8 @@ 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); + if (disk->d_delmaxsize > nvd_delete_max) + disk->d_delmaxsize = nvd_delete_max; disk->d_stripesize = nvme_ns_get_optimal_sector_size(ns); if (TAILQ_EMPTY(&disk_head)) From ac9c98889cf83d797f36d430ae2eec8b5a5c9c20 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Fri, 29 Jan 2016 00:44:28 +0000 Subject: [PATCH 023/236] filemon_open: Don't record a process to trace here. Only ioctl(FILEMON_SET_PID) should be setting the process-to-be-traced. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c index 0ec83465dbed..4f24bbbb6c19 100644 --- a/sys/dev/filemon/filemon.c +++ b/sys/dev/filemon/filemon.c @@ -221,10 +221,9 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, filemon = malloc(sizeof(struct filemon), M_FILEMON, M_WAITOK | M_ZERO); sx_init(&filemon->lock, "filemon"); + filemon->pid = -1; } - filemon->pid = curproc->p_pid; - devfs_set_cdevpriv(filemon, filemon_dtr); /* Get exclusive write access. */ From 885522c5df9f3ec6b8d0bbddf1ec3ed04937a89b Mon Sep 17 00:00:00 2001 From: bdrewery Date: Fri, 29 Jan 2016 00:44:32 +0000 Subject: [PATCH 024/236] filemon: Track the process pointer rather than a pid. The process is not held since the process_exit hook is called after the exithold. There is no need to hold the process since the hook will always see it exiting via the process_exit event. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/dev/filemon/filemon.c | 7 +++---- sys/dev/filemon/filemon_wrapper.c | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c index 4f24bbbb6c19..352f68241ede 100644 --- a/sys/dev/filemon/filemon.c +++ b/sys/dev/filemon/filemon.c @@ -89,7 +89,7 @@ struct filemon { TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */ struct sx lock; /* Lock mutex for this filemon. */ struct file *fp; /* Output file pointer. */ - pid_t pid; /* The process ID being monitored. */ + struct proc *p; /* The process being monitored. */ char fname1[MAXPATHLEN]; /* Temporary filename buffer. */ char fname2[MAXPATHLEN]; /* Temporary filename buffer. */ char msgbufr[1024]; /* Output message buffer. */ @@ -137,7 +137,7 @@ filemon_dtr(void *data) fp = filemon->fp; filemon->fp = NULL; - filemon->pid = -1; + filemon->p = NULL; /* Add to the free list. */ TAILQ_INSERT_TAIL(&filemons_free, filemon, link); @@ -188,7 +188,7 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT, &p); if (error == 0) { - filemon->pid = p->p_pid; + filemon->p = p; PROC_UNLOCK(p); } break; @@ -221,7 +221,6 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, filemon = malloc(sizeof(struct filemon), M_FILEMON, M_WAITOK | M_ZERO); sx_init(&filemon->lock, "filemon"); - filemon->pid = -1; } devfs_set_cdevpriv(filemon, filemon_dtr); diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 9e157037ba16..1b9877a68592 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -98,7 +98,7 @@ filemon_pid_check(struct proc *p) sx_slock(&proctree_lock); while (p != initproc) { TAILQ_FOREACH(filemon, &filemons_inuse, link) { - if (p->p_pid == filemon->pid) { + if (p == filemon->p) { sx_sunlock(&proctree_lock); filemon_filemon_lock(filemon); filemon_unlock_read(); @@ -452,14 +452,14 @@ filemon_event_process_exit(void *arg __unused, struct proc *p) filemon_output(filemon, filemon->msgbufr, len); /* Check if the monitored process is about to exit. */ - if (filemon->pid == p->p_pid) { + if (filemon->p == p) { len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# Stop %ju.%06ju\n# Bye bye\n", (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec); filemon_output(filemon, filemon->msgbufr, len); - filemon->pid = -1; + filemon->p = NULL; } /* Unlock the found filemon structure. */ From 05bb4186fe7470ffedb6642d1c9b9748dce7f1ef Mon Sep 17 00:00:00 2001 From: brooks Date: Fri, 29 Jan 2016 00:59:48 +0000 Subject: [PATCH 025/236] Declare bt_devenum() to match the definition. Obtained from: CheriBSD (1c1dad87ef9983a4ca0c7d6eb0792d489436bcd1) MFC after: 1 week Sponsored by: DARPA, AFRL --- lib/libbluetooth/bluetooth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libbluetooth/bluetooth.h b/lib/libbluetooth/bluetooth.h index 0435b4e2f232..85059972cbb1 100644 --- a/lib/libbluetooth/bluetooth.h +++ b/lib/libbluetooth/bluetooth.h @@ -178,7 +178,7 @@ int bt_devfilter_evt_tst(struct bt_devfilter const *filter, uint8_t event); int bt_devinquiry(char const *devname, time_t length, int num_rsp, struct bt_devinquiry **ii); int bt_devinfo (struct bt_devinfo *di); -int bt_devenum (bt_devenum_cb_t *cb, void *arg); +int bt_devenum (bt_devenum_cb_t cb, void *arg); /* * bdaddr utility functions (from NetBSD) From ab39a5f58e74fa282b886054f459016b36d74cc2 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Fri, 29 Jan 2016 01:00:12 +0000 Subject: [PATCH 026/236] Document the purpose and non-purpose of filemon(4). MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- share/man/man4/filemon.4 | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4 index a1522c8df6ca..2a3ddddea8ea 100644 --- a/share/man/man4/filemon.4 +++ b/share/man/man4/filemon.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 14, 2013 +.Dd January 28, 2016 .Dt FILEMON 4 .Os .Sh NAME @@ -49,6 +49,18 @@ responds to two .Xr ioctl 2 calls. .Pp +.Nm +is not intended to be a security auditing tool. +Many syscalls are not tracked and binaries of foreign ABI will not be fully +audited. +It is intended for auditing of processes for the purpose of determining its +dependencies in an efficient and easily parsable format. +An example of this is +.Xr make 1 +which uses this module with +.Sy .MAKE.MODE=meta +to handle incremental builds more smartly. +.Pp System calls are denoted using the following single letters: .Pp .Bl -tag -width indent -compact @@ -173,3 +185,7 @@ A .Nm device appeared in .Fx 9.1 . +.Sh BUGS +Loading +.Nm +may reduce system performance for the noted syscalls. From 078a106cb8ad7232701906c62a918ee510fb0303 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Fri, 29 Jan 2016 01:09:04 +0000 Subject: [PATCH 027/236] Note the double fork behavior with filemon. X-MFC-With: r295029 MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- share/man/man4/filemon.4 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4 index 2a3ddddea8ea..c0b4a51c5b4a 100644 --- a/share/man/man4/filemon.4 +++ b/share/man/man4/filemon.4 @@ -189,3 +189,8 @@ device appeared in Loading .Nm may reduce system performance for the noted syscalls. +.Pp +Only children of the set process are logged. +Processes can escape being traced by double forking. +This is not seen as a problem as the intended use is build monitoring, which +does not make sense to have daemons for. From 694bb1bf14f15dfce8a60d007edab8fc551bb080 Mon Sep 17 00:00:00 2001 From: brooks Date: Fri, 29 Jan 2016 01:22:12 +0000 Subject: [PATCH 028/236] Use intptr_t note ptrdiff_t when storing flags in the bottom bits of pointers. Obtained from: CheriBSD (e3a69027cc5a384431156d61c90d4304387a9b9d) Sponsored by: DARPA, AFRL --- lib/libc/db/hash/hash.h | 10 +++++----- lib/libc/db/hash/hash_buf.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h index cd11a3ae98eb..663ecdd10f8f 100644 --- a/lib/libc/db/hash/hash.h +++ b/lib/libc/db/hash/hash.h @@ -138,11 +138,11 @@ typedef struct htab { /* Memory resident data structure */ #define ALL_SET ((u_int32_t)0xFFFFFFFF) #define ALL_CLEAR 0 -#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) -#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) -#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) -#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) -#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) +#define PTROF(X) ((BUFHEAD *)((intptr_t)(X)&~0x3)) +#define ISMOD(X) ((u_int32_t)(intptr_t)(X)&0x1) +#define DOMOD(X) ((X) = (char *)((intptr_t)(X)|0x1)) +#define ISDISK(X) ((u_int32_t)(intptr_t)(X)&0x2) +#define DODISK(X) ((X) = (char *)((intptr_t)(X)|0x2)) #define BITS_PER_MAP 32 diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c index 4445fc52b043..e79e7b3efcfa 100644 --- a/lib/libc/db/hash/hash_buf.c +++ b/lib/libc/db/hash/hash_buf.c @@ -138,7 +138,7 @@ __get_buf(HTAB *hashp, u_int32_t addr, return (NULL); if (!prev_bp) segp[segment_ndx] = - (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); + (BUFHEAD *)((intptr_t)bp | is_disk_mask); } else { BUF_REMOVE(bp); MRU_INSERT(bp); From 46cf14d7bf24ebbb83d9692b2acabdb324575f1b Mon Sep 17 00:00:00 2001 From: marius Date: Fri, 29 Jan 2016 01:54:32 +0000 Subject: [PATCH 029/236] Use '^[>+][^+]' instead of '^[>+]' with grep(1) when filtering the diff(1) output between two files in "new_only"-mode. Otherwise, with the default of using unified format a remnant of the header in the output is the result. This is especially irritating when the two files differ but the second one is empty, amounting to the vestige of the header being the only readout. Reported by: Stefan Haemmerl MFC after: 3 days --- etc/periodic/security/security.functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/periodic/security/security.functions b/etc/periodic/security/security.functions index bc2bcba16877..c2c757a3789d 100644 --- a/etc/periodic/security/security.functions +++ b/etc/periodic/security/security.functions @@ -51,7 +51,7 @@ check_diff() { rc=0 if [ "$1" = "new_only" ]; then shift - filter="grep '^[>+]'" + filter="grep '^[>+][^+]'" else filter="cat" fi From eec4d6c02731c54b0bb31053c7517dae8498e8aa Mon Sep 17 00:00:00 2001 From: mmel Date: Fri, 29 Jan 2016 10:31:54 +0000 Subject: [PATCH 030/236] ARM: remove old pmap-v6 code. The new pmap-v6 is mature enough, and dual implementation is showstopper for major cleanup. This patch only removes old code from tree. Cleanups will follow asap. --- sys/arm/arm/genassym.c | 6 +- sys/arm/arm/locore-v6.S | 22 +- sys/arm/arm/machdep.c | 12 +- sys/arm/arm/mem.c | 3 +- sys/arm/arm/mp_machdep.c | 9 +- sys/arm/arm/pmap-v6.c | 5452 ------------------------------------- sys/arm/arm/swtch.S | 6 +- sys/arm/arm/trap-v6.c | 9 - sys/arm/conf/std.armv6 | 2 - sys/arm/include/machdep.h | 4 +- sys/arm/include/pmap.h | 8 +- sys/arm/include/pte.h | 8 +- sys/arm/include/sf_buf.h | 6 +- sys/arm/include/vm.h | 8 +- sys/conf/files.arm | 3 +- sys/conf/options.arm | 1 - 16 files changed, 44 insertions(+), 5515 deletions(-) delete mode 100644 sys/arm/arm/pmap-v6.c diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index 659c47153fd6..a5d2f6b9645f 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -61,16 +61,16 @@ __FBSDID("$FreeBSD$"); ASSYM(KERNBASE, KERNBASE); ASSYM(PCB_NOALIGNFLT, PCB_NOALIGNFLT); -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 ASSYM(CPU_ASID_KERNEL,CPU_ASID_KERNEL); #endif ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 ASSYM(PCB_DACR, offsetof(struct pcb, pcb_dacr)); #endif ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir)); -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec)); ASSYM(PCB_PL1VEC, offsetof(struct pcb, pcb_pl1vec)); #endif diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index b66b60183c61..eda60146dd5b 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -30,6 +30,7 @@ #include "assym.s" #include +#include #include #include #include @@ -39,11 +40,6 @@ __FBSDID("$FreeBSD$"); -#ifndef ARM_NEW_PMAP -#define PTE1_OFFSET L1_S_OFFSET -#define PTE1_SHIFT L1_S_SHIFT -#define PTE1_SIZE L1_S_SIZE -#endif #if __ARM_ARCH >= 7 #if defined(__ARM_ARCH_7VE__) || defined(__clang__) @@ -287,7 +283,6 @@ ASENTRY_NP(init_mmu) mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) mcr CP15_DACR(r0) -#ifdef ARM_NEW_PMAP /* * Set TEX remap registers * - All is set to uncacheable memory @@ -296,7 +291,6 @@ ASENTRY_NP(init_mmu) mcr CP15_PRRR(r0) mov r0, #0 mcr CP15_NMRR(r0) -#endif mcr CP15_TLBIALL /* Flush TLB */ DSB ISB @@ -305,9 +299,7 @@ ASENTRY_NP(init_mmu) mrc CP15_SCTLR(r0) orr r0, r0, #CPU_CONTROL_MMU_ENABLE orr r0, r0, #CPU_CONTROL_V6_EXTPAGE -#ifdef ARM_NEW_PMAP orr r0, r0, #CPU_CONTROL_TR_ENABLE -#endif orr r0, r0, #CPU_CONTROL_AF_ENABLE mcr CP15_SCTLR(r0) DSB @@ -398,23 +390,11 @@ END(reinit_mmu) * Addresses must be 1MiB aligned */ build_device_pagetables: -#if defined(ARM_NEW_PMAP) ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 -#elif defined(SMP) - ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED) -#else - ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)) -#endif b 1f build_pagetables: /* Set the required page attributed */ -#if defined(ARM_NEW_PMAP) ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 -#elif defined(SMP) - ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED) -#else - ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) -#endif 1: orr r1, r4 diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index d2811a6dc071..52413b89109e 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -199,7 +199,7 @@ static char *loader_envp; vm_paddr_t pmap_pa; -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 vm_offset_t systempage; vm_offset_t irqstack; vm_offset_t undstack; @@ -456,7 +456,7 @@ cpu_startup(void *dummy) pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack + USPACE_SVC_STACK_TOP; pmap_set_pcb_pagedir(pmap_kernel(), pcb); -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 vector_page_setprot(VM_PROT_READ); pmap_postinit(); #endif @@ -1283,7 +1283,7 @@ arm_predict_branch(void *cookie, u_int insn, register_t pc, register_t *new_pc, } } -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 void set_stackptrs(int cpu) { @@ -1447,7 +1447,7 @@ print_kenv(void) debugf(" %x %s\n", (uint32_t)cp, cp); } -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 void * initarm(struct arm_boot_params *abp) { @@ -1717,7 +1717,7 @@ initarm(struct arm_boot_params *abp) return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - sizeof(struct pcb))); } -#else /* !ARM_NEW_PMAP */ +#else /* __ARM_ARCH < 6 */ void * initarm(struct arm_boot_params *abp) { @@ -1905,7 +1905,7 @@ initarm(struct arm_boot_params *abp) } -#endif /* !ARM_NEW_PMAP */ +#endif /* __ARM_ARCH < 6 */ #endif /* FDT */ uint32_t (*arm_cpu_fill_vdso_timehands)(struct vdso_timehands *, diff --git a/sys/arm/arm/mem.c b/sys/arm/arm/mem.c index 2e4128b55196..1218ea474209 100644 --- a/sys/arm/arm/mem.c +++ b/sys/arm/arm/mem.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -113,7 +114,7 @@ memrw(struct cdev *dev, struct uio *uio, int flags) return (EINVAL); sx_xlock(&tmppt_lock); pmap_kenter((vm_offset_t)_tmppt, v); -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 pmap_tlb_flush(kernel_pmap, (vm_offset_t)_tmppt); #endif o = (int)uio->uio_offset & PAGE_MASK; diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 463a00ac3b96..36618669ac61 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -155,7 +156,7 @@ init_secondary(int cpu) #ifndef ARM_INTRNG int start = 0, end = 0; #endif -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 uint32_t actlr_mask, actlr_set; pmap_set_tex(); @@ -167,11 +168,11 @@ init_secondary(int cpu) set_stackptrs(cpu); enable_interrupts(PSR_A); -#else /* ARM_NEW_PMAP */ +#else /* __ARM_ARCH >= 6 */ cpu_setup(); setttb(pmap_pa); cpu_tlb_flushID(); -#endif /* ARM_NEW_PMAP */ +#endif /* __ARM_ARCH >= 6 */ pc = &__pcpu[cpu]; /* @@ -183,7 +184,7 @@ init_secondary(int cpu) pcpu_init(pc, cpu, sizeof(struct pcpu)); dpcpu_init(dpcpu[cpu - 1], cpu); -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 /* Provide stack pointers for other processor modes. */ set_stackptrs(cpu); #endif diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c deleted file mode 100644 index 5d7021189ed7..000000000000 --- a/sys/arm/arm/pmap-v6.c +++ /dev/null @@ -1,5452 +0,0 @@ -/* From: $NetBSD: pmap.c,v 1.148 2004/04/03 04:35:48 bsh Exp $ */ -/*- - * Copyright 2011 Semihalf - * Copyright 2004 Olivier Houchard. - * Copyright 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Steve C. Woodford for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * From: FreeBSD: src/sys/arm/arm/pmap.c,v 1.113 2009/07/24 13:50:29 - */ - -/*- - * Copyright (c) 2002-2003 Wasabi Systems, Inc. - * Copyright (c) 2001 Richard Earnshaw - * Copyright (c) 2001-2002 Christopher Gilbert - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum. - * - * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/*- - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * This code is derived from software written for Brini by Mark Brinicombe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Mark Brinicombe. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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 - * - * RiscBSD kernel project - * - * pmap.c - * - * Machine dependant vm stuff - * - * Created : 20/09/94 - */ - -/* - * Special compilation symbols - * PMAP_DEBUG - Build in pmap_debug_level code - * - * Note that pmap_mapdev() and pmap_unmapdev() are implemented in arm/devmap.c -*/ -/* Include header files */ - -#include "opt_vm.h" -#include "opt_pmap.h" - -#include -__FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef DEBUG -extern int last_fault_code; -#endif - -#ifdef PMAP_DEBUG -#define PDEBUG(_lev_,_stat_) \ - if (pmap_debug_level >= (_lev_)) \ - ((_stat_)) -#define dprintf printf - -int pmap_debug_level = 0; -#define PMAP_INLINE -#else /* PMAP_DEBUG */ -#define PDEBUG(_lev_,_stat_) /* Nothing */ -#define dprintf(x, arg...) -#define PMAP_INLINE __inline -#endif /* PMAP_DEBUG */ - -#ifdef PV_STATS -#define PV_STAT(x) do { x ; } while (0) -#else -#define PV_STAT(x) do { } while (0) -#endif - -#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) - -#ifdef ARM_L2_PIPT -#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size)) -#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size)) -#else -#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((va), (size)) -#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((va), (size)) -#endif - -extern struct pv_addr systempage; - -/* - * Internal function prototypes - */ - -static PMAP_INLINE -struct pv_entry *pmap_find_pv(struct md_page *, pmap_t, vm_offset_t); -static void pmap_free_pv_chunk(struct pv_chunk *pc); -static void pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv); -static pv_entry_t pmap_get_pv_entry(pmap_t pmap, boolean_t try); -static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap); -static boolean_t pmap_pv_insert_section(pmap_t, vm_offset_t, - vm_paddr_t); -static struct pv_entry *pmap_remove_pv(struct vm_page *, pmap_t, vm_offset_t); -static int pmap_pvh_wired_mappings(struct md_page *, int); - -static int pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t, - vm_prot_t, u_int); -static vm_paddr_t pmap_extract_locked(pmap_t pmap, vm_offset_t va); -static void pmap_alloc_l1(pmap_t); -static void pmap_free_l1(pmap_t); - -static void pmap_map_section(pmap_t, vm_offset_t, vm_offset_t, - vm_prot_t, boolean_t); -static void pmap_promote_section(pmap_t, vm_offset_t); -static boolean_t pmap_demote_section(pmap_t, vm_offset_t); -static boolean_t pmap_enter_section(pmap_t, vm_offset_t, vm_page_t, - vm_prot_t); -static void pmap_remove_section(pmap_t, vm_offset_t); - -static int pmap_clearbit(struct vm_page *, u_int); - -static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vm_offset_t); -static struct l2_bucket *pmap_alloc_l2_bucket(pmap_t, vm_offset_t); -static void pmap_free_l2_bucket(pmap_t, struct l2_bucket *, u_int); -static vm_offset_t kernel_pt_lookup(vm_paddr_t); - -static MALLOC_DEFINE(M_VMPMAP, "pmap", "PMAP L1"); - -vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ -vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ -vm_offset_t pmap_curmaxkvaddr; -vm_paddr_t kernel_l1pa; - -vm_offset_t kernel_vm_end = 0; - -vm_offset_t vm_max_kernel_address; - -struct pmap kernel_pmap_store; - -/* - * Resources for quickly copying and zeroing pages using virtual address space - * and page table entries that are pre-allocated per-CPU by pmap_init(). - */ -struct czpages { - struct mtx lock; - pt_entry_t *srcptep; - pt_entry_t *dstptep; - vm_offset_t srcva; - vm_offset_t dstva; -}; -static struct czpages cpu_czpages[MAXCPU]; - -static void pmap_init_l1(struct l1_ttable *, pd_entry_t *); -/* - * These routines are called when the CPU type is identified to set up - * the PTE prototypes, cache modes, etc. - * - * The variables are always here, just in case LKMs need to reference - * them (though, they shouldn't). - */ -static void pmap_set_prot(pt_entry_t *pte, vm_prot_t prot, uint8_t user); -pt_entry_t pte_l1_s_cache_mode; -pt_entry_t pte_l1_s_cache_mode_pt; - -pt_entry_t pte_l2_l_cache_mode; -pt_entry_t pte_l2_l_cache_mode_pt; - -pt_entry_t pte_l2_s_cache_mode; -pt_entry_t pte_l2_s_cache_mode_pt; - -struct msgbuf *msgbufp = 0; - -/* - * Crashdump maps. - */ -static caddr_t crashdumpmap; - -extern void bcopy_page(vm_offset_t, vm_offset_t); -extern void bzero_page(vm_offset_t); - -char *_tmppt; - -/* - * Metadata for L1 translation tables. - */ -struct l1_ttable { - /* Entry on the L1 Table list */ - SLIST_ENTRY(l1_ttable) l1_link; - - /* Entry on the L1 Least Recently Used list */ - TAILQ_ENTRY(l1_ttable) l1_lru; - - /* Track how many domains are allocated from this L1 */ - volatile u_int l1_domain_use_count; - - /* - * A free-list of domain numbers for this L1. - * We avoid using ffs() and a bitmap to track domains since ffs() - * is slow on ARM. - */ - u_int8_t l1_domain_first; - u_int8_t l1_domain_free[PMAP_DOMAINS]; - - /* Physical address of this L1 page table */ - vm_paddr_t l1_physaddr; - - /* KVA of this L1 page table */ - pd_entry_t *l1_kva; -}; - -/* - * Convert a virtual address into its L1 table index. That is, the - * index used to locate the L2 descriptor table pointer in an L1 table. - * This is basically used to index l1->l1_kva[]. - * - * Each L2 descriptor table represents 1MB of VA space. - */ -#define L1_IDX(va) (((vm_offset_t)(va)) >> L1_S_SHIFT) - -/* - * L1 Page Tables are tracked using a Least Recently Used list. - * - New L1s are allocated from the HEAD. - * - Freed L1s are added to the TAIl. - * - Recently accessed L1s (where an 'access' is some change to one of - * the userland pmaps which owns this L1) are moved to the TAIL. - */ -static TAILQ_HEAD(, l1_ttable) l1_lru_list; -/* - * A list of all L1 tables - */ -static SLIST_HEAD(, l1_ttable) l1_list; -static struct mtx l1_lru_lock; - -/* - * The l2_dtable tracks L2_BUCKET_SIZE worth of L1 slots. - * - * This is normally 16MB worth L2 page descriptors for any given pmap. - * Reference counts are maintained for L2 descriptors so they can be - * freed when empty. - */ -struct l2_dtable { - /* The number of L2 page descriptors allocated to this l2_dtable */ - u_int l2_occupancy; - - /* List of L2 page descriptors */ - struct l2_bucket { - pt_entry_t *l2b_kva; /* KVA of L2 Descriptor Table */ - vm_paddr_t l2b_phys; /* Physical address of same */ - u_short l2b_l1idx; /* This L2 table's L1 index */ - u_short l2b_occupancy; /* How many active descriptors */ - } l2_bucket[L2_BUCKET_SIZE]; -}; - -/* pmap_kenter_internal flags */ -#define KENTER_CACHE 0x1 -#define KENTER_DEVICE 0x2 -#define KENTER_USER 0x4 - -/* - * Given an L1 table index, calculate the corresponding l2_dtable index - * and bucket index within the l2_dtable. - */ -#define L2_IDX(l1idx) (((l1idx) >> L2_BUCKET_LOG2) & \ - (L2_SIZE - 1)) -#define L2_BUCKET(l1idx) ((l1idx) & (L2_BUCKET_SIZE - 1)) - -/* - * Given a virtual address, this macro returns the - * virtual address required to drop into the next L2 bucket. - */ -#define L2_NEXT_BUCKET(va) (((va) & L1_S_FRAME) + L1_S_SIZE) - -/* - * We try to map the page tables write-through, if possible. However, not - * all CPUs have a write-through cache mode, so on those we have to sync - * the cache when we frob page tables. - * - * We try to evaluate this at compile time, if possible. However, it's - * not always possible to do that, hence this run-time var. - */ -int pmap_needs_pte_sync; - -/* - * Macro to determine if a mapping might be resident in the - * instruction cache and/or TLB - */ -#define PTE_BEEN_EXECD(pte) (L2_S_EXECUTABLE(pte) && L2_S_REFERENCED(pte)) - -/* - * Macro to determine if a mapping might be resident in the - * data cache and/or TLB - */ -#define PTE_BEEN_REFD(pte) (L2_S_REFERENCED(pte)) - -#ifndef PMAP_SHPGPERPROC -#define PMAP_SHPGPERPROC 200 -#endif - -#define pmap_is_current(pm) ((pm) == pmap_kernel() || \ - curproc->p_vmspace->vm_map.pmap == (pm)) - -/* - * Data for the pv entry allocation mechanism - */ -static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks); -static int pv_entry_count, pv_entry_max, pv_entry_high_water; -static struct md_page *pv_table; -static int shpgperproc = PMAP_SHPGPERPROC; - -struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */ -int pv_maxchunks; /* How many chunks we have KVA for */ -vm_offset_t pv_vafree; /* Freelist stored in the PTE */ - -static __inline struct pv_chunk * -pv_to_chunk(pv_entry_t pv) -{ - - return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK)); -} - -#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap) - -CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE); -CTASSERT(_NPCM == 8); -CTASSERT(_NPCPV == 252); - -#define PC_FREE0_6 0xfffffffful /* Free values for index 0 through 6 */ -#define PC_FREE7 0x0ffffffful /* Free values for index 7 */ - -static const uint32_t pc_freemask[_NPCM] = { - PC_FREE0_6, PC_FREE0_6, PC_FREE0_6, - PC_FREE0_6, PC_FREE0_6, PC_FREE0_6, - PC_FREE0_6, PC_FREE7 -}; - -static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); - -/* Superpages utilization enabled = 1 / disabled = 0 */ -static int sp_enabled = 1; -SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &sp_enabled, 0, - "Are large page mappings enabled?"); - -SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0, - "Current number of pv entries"); - -#ifdef PV_STATS -static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail; - -SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0, - "Current number of pv entry chunks"); -SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0, - "Current number of pv entry chunks allocated"); -SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0, - "Current number of pv entry chunks frees"); -SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0, - "Number of times tried to get a chunk page but failed."); - -static long pv_entry_frees, pv_entry_allocs; -static int pv_entry_spare; - -SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0, - "Current number of pv entry frees"); -SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0, - "Current number of pv entry allocs"); -SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0, - "Current number of spare pv entries"); -#endif - -uma_zone_t l2zone; -static uma_zone_t l2table_zone; -static vm_offset_t pmap_kernel_l2dtable_kva; -static vm_offset_t pmap_kernel_l2ptp_kva; -static vm_paddr_t pmap_kernel_l2ptp_phys; -static struct rwlock pvh_global_lock; - -int l1_mem_types[] = { - ARM_L1S_STRONG_ORD, - ARM_L1S_DEVICE_NOSHARE, - ARM_L1S_DEVICE_SHARE, - ARM_L1S_NRML_NOCACHE, - ARM_L1S_NRML_IWT_OWT, - ARM_L1S_NRML_IWB_OWB, - ARM_L1S_NRML_IWBA_OWBA -}; - -int l2l_mem_types[] = { - ARM_L2L_STRONG_ORD, - ARM_L2L_DEVICE_NOSHARE, - ARM_L2L_DEVICE_SHARE, - ARM_L2L_NRML_NOCACHE, - ARM_L2L_NRML_IWT_OWT, - ARM_L2L_NRML_IWB_OWB, - ARM_L2L_NRML_IWBA_OWBA -}; - -int l2s_mem_types[] = { - ARM_L2S_STRONG_ORD, - ARM_L2S_DEVICE_NOSHARE, - ARM_L2S_DEVICE_SHARE, - ARM_L2S_NRML_NOCACHE, - ARM_L2S_NRML_IWT_OWT, - ARM_L2S_NRML_IWB_OWB, - ARM_L2S_NRML_IWBA_OWBA -}; - -/* - * This list exists for the benefit of pmap_map_chunk(). It keeps track - * of the kernel L2 tables during bootstrap, so that pmap_map_chunk() can - * find them as necessary. - * - * Note that the data on this list MUST remain valid after initarm() returns, - * as pmap_bootstrap() uses it to contruct L2 table metadata. - */ -SLIST_HEAD(, pv_addr) kernel_pt_list = SLIST_HEAD_INITIALIZER(kernel_pt_list); - -static void -pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt) -{ - int i; - - l1->l1_kva = l1pt; - l1->l1_domain_use_count = 0; - l1->l1_domain_first = 0; - - for (i = 0; i < PMAP_DOMAINS; i++) - l1->l1_domain_free[i] = i + 1; - - /* - * Copy the kernel's L1 entries to each new L1. - */ - if (l1pt != pmap_kernel()->pm_l1->l1_kva) - memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE); - - if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0) - panic("pmap_init_l1: can't get PA of L1 at %p", l1pt); - SLIST_INSERT_HEAD(&l1_list, l1, l1_link); - TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru); -} - -static vm_offset_t -kernel_pt_lookup(vm_paddr_t pa) -{ - struct pv_addr *pv; - - SLIST_FOREACH(pv, &kernel_pt_list, pv_list) { - if (pv->pv_pa == pa) - return (pv->pv_va); - } - return (0); -} - -void -pmap_pte_init_mmu_v6(void) -{ - - if (PTE_PAGETABLE >= 3) - pmap_needs_pte_sync = 1; - pte_l1_s_cache_mode = l1_mem_types[PTE_CACHE]; - pte_l2_l_cache_mode = l2l_mem_types[PTE_CACHE]; - pte_l2_s_cache_mode = l2s_mem_types[PTE_CACHE]; - - pte_l1_s_cache_mode_pt = l1_mem_types[PTE_PAGETABLE]; - pte_l2_l_cache_mode_pt = l2l_mem_types[PTE_PAGETABLE]; - pte_l2_s_cache_mode_pt = l2s_mem_types[PTE_PAGETABLE]; - -} - -/* - * Allocate an L1 translation table for the specified pmap. - * This is called at pmap creation time. - */ -static void -pmap_alloc_l1(pmap_t pmap) -{ - struct l1_ttable *l1; - u_int8_t domain; - - /* - * Remove the L1 at the head of the LRU list - */ - mtx_lock(&l1_lru_lock); - l1 = TAILQ_FIRST(&l1_lru_list); - TAILQ_REMOVE(&l1_lru_list, l1, l1_lru); - - /* - * Pick the first available domain number, and update - * the link to the next number. - */ - domain = l1->l1_domain_first; - l1->l1_domain_first = l1->l1_domain_free[domain]; - - /* - * If there are still free domain numbers in this L1, - * put it back on the TAIL of the LRU list. - */ - if (++l1->l1_domain_use_count < PMAP_DOMAINS) - TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru); - - mtx_unlock(&l1_lru_lock); - - /* - * Fix up the relevant bits in the pmap structure - */ - pmap->pm_l1 = l1; - pmap->pm_domain = domain + 1; -} - -/* - * Free an L1 translation table. - * This is called at pmap destruction time. - */ -static void -pmap_free_l1(pmap_t pmap) -{ - struct l1_ttable *l1 = pmap->pm_l1; - - mtx_lock(&l1_lru_lock); - - /* - * If this L1 is currently on the LRU list, remove it. - */ - if (l1->l1_domain_use_count < PMAP_DOMAINS) - TAILQ_REMOVE(&l1_lru_list, l1, l1_lru); - - /* - * Free up the domain number which was allocated to the pmap - */ - l1->l1_domain_free[pmap->pm_domain - 1] = l1->l1_domain_first; - l1->l1_domain_first = pmap->pm_domain - 1; - l1->l1_domain_use_count--; - - /* - * The L1 now must have at least 1 free domain, so add - * it back to the LRU list. If the use count is zero, - * put it at the head of the list, otherwise it goes - * to the tail. - */ - if (l1->l1_domain_use_count == 0) { - TAILQ_INSERT_HEAD(&l1_lru_list, l1, l1_lru); - } else - TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru); - - mtx_unlock(&l1_lru_lock); -} - -/* - * Returns a pointer to the L2 bucket associated with the specified pmap - * and VA, or NULL if no L2 bucket exists for the address. - */ -static PMAP_INLINE struct l2_bucket * -pmap_get_l2_bucket(pmap_t pmap, vm_offset_t va) -{ - struct l2_dtable *l2; - struct l2_bucket *l2b; - u_short l1idx; - - l1idx = L1_IDX(va); - - if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL || - (l2b = &l2->l2_bucket[L2_BUCKET(l1idx)])->l2b_kva == NULL) - return (NULL); - - return (l2b); -} - -/* - * Returns a pointer to the L2 bucket associated with the specified pmap - * and VA. - * - * If no L2 bucket exists, perform the necessary allocations to put an L2 - * bucket/page table in place. - * - * Note that if a new L2 bucket/page was allocated, the caller *must* - * increment the bucket occupancy counter appropriately *before* - * releasing the pmap's lock to ensure no other thread or cpu deallocates - * the bucket/page in the meantime. - */ -static struct l2_bucket * -pmap_alloc_l2_bucket(pmap_t pmap, vm_offset_t va) -{ - struct l2_dtable *l2; - struct l2_bucket *l2b; - u_short l1idx; - - l1idx = L1_IDX(va); - - PMAP_ASSERT_LOCKED(pmap); - rw_assert(&pvh_global_lock, RA_WLOCKED); - if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) { - /* - * No mapping at this address, as there is - * no entry in the L1 table. - * Need to allocate a new l2_dtable. - */ - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); - if ((l2 = uma_zalloc(l2table_zone, M_NOWAIT)) == NULL) { - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - return (NULL); - } - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - if (pmap->pm_l2[L2_IDX(l1idx)] != NULL) { - /* - * Someone already allocated the l2_dtable while - * we were doing the same. - */ - uma_zfree(l2table_zone, l2); - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - } else { - bzero(l2, sizeof(*l2)); - /* - * Link it into the parent pmap - */ - pmap->pm_l2[L2_IDX(l1idx)] = l2; - } - } - - l2b = &l2->l2_bucket[L2_BUCKET(l1idx)]; - - /* - * Fetch pointer to the L2 page table associated with the address. - */ - if (l2b->l2b_kva == NULL) { - pt_entry_t *ptep; - - /* - * No L2 page table has been allocated. Chances are, this - * is because we just allocated the l2_dtable, above. - */ - l2->l2_occupancy++; - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); - ptep = uma_zalloc(l2zone, M_NOWAIT); - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - if (l2b->l2b_kva != 0) { - /* We lost the race. */ - l2->l2_occupancy--; - uma_zfree(l2zone, ptep); - return (l2b); - } - l2b->l2b_phys = vtophys(ptep); - if (ptep == NULL) { - /* - * Oops, no more L2 page tables available at this - * time. We may need to deallocate the l2_dtable - * if we allocated a new one above. - */ - l2->l2_occupancy--; - if (l2->l2_occupancy == 0) { - pmap->pm_l2[L2_IDX(l1idx)] = NULL; - uma_zfree(l2table_zone, l2); - } - return (NULL); - } - - l2b->l2b_kva = ptep; - l2b->l2b_l1idx = l1idx; - } - - return (l2b); -} - -static PMAP_INLINE void -pmap_free_l2_ptp(pt_entry_t *l2) -{ - uma_zfree(l2zone, l2); -} -/* - * One or more mappings in the specified L2 descriptor table have just been - * invalidated. - * - * Garbage collect the metadata and descriptor table itself if necessary. - * - * The pmap lock must be acquired when this is called (not necessary - * for the kernel pmap). - */ -static void -pmap_free_l2_bucket(pmap_t pmap, struct l2_bucket *l2b, u_int count) -{ - struct l2_dtable *l2; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep; - u_short l1idx; - - - /* - * Update the bucket's reference count according to how many - * PTEs the caller has just invalidated. - */ - l2b->l2b_occupancy -= count; - - /* - * Note: - * - * Level 2 page tables allocated to the kernel pmap are never freed - * as that would require checking all Level 1 page tables and - * removing any references to the Level 2 page table. See also the - * comment elsewhere about never freeing bootstrap L2 descriptors. - * - * We make do with just invalidating the mapping in the L2 table. - * - * This isn't really a big deal in practice and, in fact, leads - * to a performance win over time as we don't need to continually - * alloc/free. - */ - if (l2b->l2b_occupancy > 0 || pmap == pmap_kernel()) - return; - - /* - * There are no more valid mappings in this level 2 page table. - * Go ahead and NULL-out the pointer in the bucket, then - * free the page table. - */ - l1idx = l2b->l2b_l1idx; - ptep = l2b->l2b_kva; - l2b->l2b_kva = NULL; - - pl1pd = &pmap->pm_l1->l1_kva[l1idx]; - - /* - * If the L1 slot matches the pmap's domain - * number, then invalidate it. - */ - l1pd = *pl1pd & (L1_TYPE_MASK | L1_C_DOM_MASK); - if (l1pd == (L1_C_DOM(pmap->pm_domain) | L1_TYPE_C)) { - *pl1pd = 0; - PTE_SYNC(pl1pd); - cpu_tlb_flushD_SE((vm_offset_t)ptep); - cpu_cpwait(); - } - - /* - * Release the L2 descriptor table back to the pool cache. - */ - pmap_free_l2_ptp(ptep); - - /* - * Update the reference count in the associated l2_dtable - */ - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - if (--l2->l2_occupancy > 0) - return; - - /* - * There are no more valid mappings in any of the Level 1 - * slots managed by this l2_dtable. Go ahead and NULL-out - * the pointer in the parent pmap and free the l2_dtable. - */ - pmap->pm_l2[L2_IDX(l1idx)] = NULL; - uma_zfree(l2table_zone, l2); -} - -/* - * Pool cache constructors for L2 descriptor tables, metadata and pmap - * structures. - */ -static int -pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags) -{ - struct l2_bucket *l2b; - pt_entry_t *ptep, pte; - vm_offset_t va = (vm_offset_t)mem & ~PAGE_MASK; - - /* - * The mappings for these page tables were initially made using - * pmap_kenter() by the pool subsystem. Therefore, the cache- - * mode will not be right for page table mappings. To avoid - * polluting the pmap_kenter() code with a special case for - * page tables, we simply fix up the cache-mode here if it's not - * correct. - */ - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - pte = *ptep; - - cpu_idcache_wbinv_range(va, PAGE_SIZE); - pmap_l2cache_wbinv_range(va, pte & L2_S_FRAME, PAGE_SIZE); - if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) { - /* - * Page tables must have the cache-mode set to - * Write-Thru. - */ - *ptep = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt; - PTE_SYNC(ptep); - cpu_tlb_flushD_SE(va); - cpu_cpwait(); - } - - memset(mem, 0, L2_TABLE_SIZE_REAL); - return (0); -} - -/* - * Modify pte bits for all ptes corresponding to the given physical address. - * We use `maskbits' rather than `clearbits' because we're always passing - * constants and the latter would require an extra inversion at run-time. - */ -static int -pmap_clearbit(struct vm_page *m, u_int maskbits) -{ - struct l2_bucket *l2b; - struct pv_entry *pv, *pve, *next_pv; - struct md_page *pvh; - pd_entry_t *pl1pd; - pt_entry_t *ptep, npte, opte; - pmap_t pmap; - vm_offset_t va; - u_int oflags; - int count = 0; - - rw_wlock(&pvh_global_lock); - if ((m->flags & PG_FICTITIOUS) != 0) - goto small_mappings; - - pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); - TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) { - va = pv->pv_va; - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO, - ("pmap_clearbit: valid section mapping expected")); - if ((maskbits & PVF_WRITE) && (pv->pv_flags & PVF_WRITE)) - (void)pmap_demote_section(pmap, va); - else if ((maskbits & PVF_REF) && L1_S_REFERENCED(*pl1pd)) { - if (pmap_demote_section(pmap, va)) { - if ((pv->pv_flags & PVF_WIRED) == 0) { - /* - * Remove the mapping to a single page - * so that a subsequent access may - * repromote. Since the underlying - * l2_bucket is fully populated, this - * removal never frees an entire - * l2_bucket. - */ - va += (VM_PAGE_TO_PHYS(m) & - L1_S_OFFSET); - l2b = pmap_get_l2_bucket(pmap, va); - KASSERT(l2b != NULL, - ("pmap_clearbit: no l2 bucket for " - "va 0x%#x, pmap 0x%p", va, pmap)); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - *ptep = 0; - PTE_SYNC(ptep); - pmap_free_l2_bucket(pmap, l2b, 1); - pve = pmap_remove_pv(m, pmap, va); - KASSERT(pve != NULL, ("pmap_clearbit: " - "no PV entry for managed mapping")); - pmap_free_pv_entry(pmap, pve); - - } - } - } else if ((maskbits & PVF_MOD) && L1_S_WRITABLE(*pl1pd)) { - if (pmap_demote_section(pmap, va)) { - if ((pv->pv_flags & PVF_WIRED) == 0) { - /* - * Write protect the mapping to a - * single page so that a subsequent - * write access may repromote. - */ - va += (VM_PAGE_TO_PHYS(m) & - L1_S_OFFSET); - l2b = pmap_get_l2_bucket(pmap, va); - KASSERT(l2b != NULL, - ("pmap_clearbit: no l2 bucket for " - "va 0x%#x, pmap 0x%p", va, pmap)); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - if ((*ptep & L2_S_PROTO) != 0) { - pve = pmap_find_pv(&m->md, - pmap, va); - KASSERT(pve != NULL, - ("pmap_clearbit: no PV " - "entry for managed mapping")); - pve->pv_flags &= ~PVF_WRITE; - *ptep |= L2_APX; - PTE_SYNC(ptep); - } - } - } - } - PMAP_UNLOCK(pmap); - } - -small_mappings: - if (TAILQ_EMPTY(&m->md.pv_list)) { - rw_wunlock(&pvh_global_lock); - return (0); - } - - /* - * Loop over all current mappings setting/clearing as appropos - */ - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { - va = pv->pv_va; - pmap = PV_PMAP(pv); - oflags = pv->pv_flags; - pv->pv_flags &= ~maskbits; - - PMAP_LOCK(pmap); - - l2b = pmap_get_l2_bucket(pmap, va); - KASSERT(l2b != NULL, ("pmap_clearbit: no l2 bucket for " - "va 0x%#x, pmap 0x%p", va, pmap)); - - ptep = &l2b->l2b_kva[l2pte_index(va)]; - npte = opte = *ptep; - - if (maskbits & (PVF_WRITE | PVF_MOD)) { - /* make the pte read only */ - npte |= L2_APX; - } - - if (maskbits & PVF_REF) { - /* - * Clear referenced flag in PTE so that we - * will take a flag fault the next time the mapping - * is referenced. - */ - npte &= ~L2_S_REF; - } - - CTR4(KTR_PMAP,"clearbit: pmap:%p bits:%x pte:%x->%x", - pmap, maskbits, opte, npte); - if (npte != opte) { - count++; - *ptep = npte; - PTE_SYNC(ptep); - /* Flush the TLB entry if a current pmap. */ - if (PTE_BEEN_EXECD(opte)) - cpu_tlb_flushID_SE(pv->pv_va); - else if (PTE_BEEN_REFD(opte)) - cpu_tlb_flushD_SE(pv->pv_va); - cpu_cpwait(); - } - - PMAP_UNLOCK(pmap); - - } - - if (maskbits & PVF_WRITE) - vm_page_aflag_clear(m, PGA_WRITEABLE); - rw_wunlock(&pvh_global_lock); - return (count); -} - -/* - * main pv_entry manipulation functions: - * pmap_enter_pv: enter a mapping onto a vm_page list - * pmap_remove_pv: remove a mappiing from a vm_page list - * - * NOTE: pmap_enter_pv expects to lock the pvh itself - * pmap_remove_pv expects the caller to lock the pvh before calling - */ - -/* - * pmap_enter_pv: enter a mapping onto a vm_page's PV list - * - * => caller should hold the proper lock on pvh_global_lock - * => caller should have pmap locked - * => we will (someday) gain the lock on the vm_page's PV list - * => caller should adjust ptp's wire_count before calling - * => caller should not adjust pmap's wire_count - */ -static void -pmap_enter_pv(struct vm_page *m, struct pv_entry *pve, pmap_t pmap, - vm_offset_t va, u_int flags) -{ - - rw_assert(&pvh_global_lock, RA_WLOCKED); - - PMAP_ASSERT_LOCKED(pmap); - pve->pv_va = va; - pve->pv_flags = flags; - - TAILQ_INSERT_HEAD(&m->md.pv_list, pve, pv_list); - if (pve->pv_flags & PVF_WIRED) - ++pmap->pm_stats.wired_count; -} - -/* - * - * pmap_find_pv: Find a pv entry - * - * => caller should hold lock on vm_page - */ -static PMAP_INLINE struct pv_entry * -pmap_find_pv(struct md_page *md, pmap_t pmap, vm_offset_t va) -{ - struct pv_entry *pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - TAILQ_FOREACH(pv, &md->pv_list, pv_list) - if (pmap == PV_PMAP(pv) && va == pv->pv_va) - break; - - return (pv); -} - -/* - * vector_page_setprot: - * - * Manipulate the protection of the vector page. - */ -void -vector_page_setprot(int prot) -{ - struct l2_bucket *l2b; - pt_entry_t *ptep; - - l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page); - - ptep = &l2b->l2b_kva[l2pte_index(vector_page)]; - /* - * Set referenced flag. - * Vectors' page is always desired - * to be allowed to reside in TLB. - */ - *ptep |= L2_S_REF; - - pmap_set_prot(ptep, prot|VM_PROT_EXECUTE, 0); - PTE_SYNC(ptep); - cpu_tlb_flushID_SE(vector_page); - cpu_cpwait(); -} - -static void -pmap_set_prot(pt_entry_t *ptep, vm_prot_t prot, uint8_t user) -{ - - *ptep &= ~(L2_S_PROT_MASK | L2_XN); - - if (!(prot & VM_PROT_EXECUTE)) - *ptep |= L2_XN; - - /* Set defaults first - kernel read access */ - *ptep |= L2_APX; - *ptep |= L2_S_PROT_R; - /* Now tune APs as desired */ - if (user) - *ptep |= L2_S_PROT_U; - - if (prot & VM_PROT_WRITE) - *ptep &= ~(L2_APX); -} - -/* - * pmap_remove_pv: try to remove a mapping from a pv_list - * - * => caller should hold proper lock on pmap_main_lock - * => pmap should be locked - * => caller should hold lock on vm_page [so that attrs can be adjusted] - * => caller should adjust ptp's wire_count and free PTP if needed - * => caller should NOT adjust pmap's wire_count - * => we return the removed pve - */ -static struct pv_entry * -pmap_remove_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va) -{ - struct pv_entry *pve; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); - - pve = pmap_find_pv(&m->md, pmap, va); /* find corresponding pve */ - if (pve != NULL) { - TAILQ_REMOVE(&m->md.pv_list, pve, pv_list); - if (pve->pv_flags & PVF_WIRED) - --pmap->pm_stats.wired_count; - } - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - - return(pve); /* return removed pve */ -} - -/* - * - * pmap_modify_pv: Update pv flags - * - * => caller should hold lock on vm_page [so that attrs can be adjusted] - * => caller should NOT adjust pmap's wire_count - * => we return the old flags - * - * Modify a physical-virtual mapping in the pv table - */ -static u_int -pmap_modify_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va, - u_int clr_mask, u_int set_mask) -{ - struct pv_entry *npv; - u_int flags, oflags; - - PMAP_ASSERT_LOCKED(pmap); - rw_assert(&pvh_global_lock, RA_WLOCKED); - if ((npv = pmap_find_pv(&m->md, pmap, va)) == NULL) - return (0); - - /* - * There is at least one VA mapping this page. - */ - oflags = npv->pv_flags; - npv->pv_flags = flags = (oflags & ~clr_mask) | set_mask; - - if ((flags ^ oflags) & PVF_WIRED) { - if (flags & PVF_WIRED) - ++pmap->pm_stats.wired_count; - else - --pmap->pm_stats.wired_count; - } - - return (oflags); -} - -/* Function to set the debug level of the pmap code */ -#ifdef PMAP_DEBUG -void -pmap_debug(int level) -{ - pmap_debug_level = level; - dprintf("pmap_debug: level=%d\n", pmap_debug_level); -} -#endif /* PMAP_DEBUG */ - -void -pmap_pinit0(struct pmap *pmap) -{ - PDEBUG(1, printf("pmap_pinit0: pmap = %08x\n", (u_int32_t) pmap)); - - bcopy(kernel_pmap, pmap, sizeof(*pmap)); - bzero(&pmap->pm_mtx, sizeof(pmap->pm_mtx)); - PMAP_LOCK_INIT(pmap); - TAILQ_INIT(&pmap->pm_pvchunk); -} - -/* - * Initialize a vm_page's machine-dependent fields. - */ -void -pmap_page_init(vm_page_t m) -{ - - TAILQ_INIT(&m->md.pv_list); - m->md.pv_memattr = VM_MEMATTR_DEFAULT; -} - -static vm_offset_t -pmap_ptelist_alloc(vm_offset_t *head) -{ - pt_entry_t *pte; - vm_offset_t va; - - va = *head; - if (va == 0) - return (va); /* Out of memory */ - pte = vtopte(va); - *head = *pte; - if ((*head & L2_TYPE_MASK) != L2_TYPE_INV) - panic("%s: va is not L2_TYPE_INV!", __func__); - *pte = 0; - return (va); -} - -static void -pmap_ptelist_free(vm_offset_t *head, vm_offset_t va) -{ - pt_entry_t *pte; - - if ((va & L2_TYPE_MASK) != L2_TYPE_INV) - panic("%s: freeing va that is not L2_TYPE INV!", __func__); - pte = vtopte(va); - *pte = *head; /* virtual! L2_TYPE is L2_TYPE_INV though */ - *head = va; -} - -static void -pmap_ptelist_init(vm_offset_t *head, void *base, int npages) -{ - int i; - vm_offset_t va; - - *head = 0; - for (i = npages - 1; i >= 0; i--) { - va = (vm_offset_t)base + i * PAGE_SIZE; - pmap_ptelist_free(head, va); - } -} - -/* - * Initialize the pmap module. - * Called by vm_init, to initialize any structures that the pmap - * system needs to map virtual memory. - */ -void -pmap_init(void) -{ - vm_size_t s; - int i, pv_npg; - - l2zone = uma_zcreate("L2 Table", L2_TABLE_SIZE_REAL, pmap_l2ptp_ctor, - NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE); - l2table_zone = uma_zcreate("L2 Table", sizeof(struct l2_dtable), NULL, - NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE); - - /* - * Are large page mappings supported and enabled? - */ - TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled); - if (sp_enabled) { - KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, - ("pmap_init: can't assign to pagesizes[1]")); - pagesizes[1] = NBPDR; - } - - /* - * Calculate the size of the pv head table for superpages. - * Handle the possibility that "vm_phys_segs[...].end" is zero. - */ - pv_npg = trunc_1mpage(vm_phys_segs[vm_phys_nsegs - 1].end - - PAGE_SIZE) / NBPDR + 1; - - /* - * Allocate memory for the pv head table for superpages. - */ - s = (vm_size_t)(pv_npg * sizeof(struct md_page)); - s = round_page(s); - pv_table = (struct md_page *)kmem_malloc(kernel_arena, s, - M_WAITOK | M_ZERO); - for (i = 0; i < pv_npg; i++) - TAILQ_INIT(&pv_table[i].pv_list); - - /* - * Initialize the address space for the pv chunks. - */ - - TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc); - pv_entry_max = shpgperproc * maxproc + vm_cnt.v_page_count; - TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max); - pv_entry_max = roundup(pv_entry_max, _NPCPV); - pv_entry_high_water = 9 * (pv_entry_max / 10); - - pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc); - pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks); - - if (pv_chunkbase == NULL) - panic("pmap_init: not enough kvm for pv chunks"); - - pmap_ptelist_init(&pv_vafree, pv_chunkbase, pv_maxchunks); - - /* - * Now it is safe to enable pv_table recording. - */ - PDEBUG(1, printf("pmap_init: done!\n")); -} - -SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0, - "Max number of PV entries"); -SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0, - "Page share factor per proc"); - -static SYSCTL_NODE(_vm_pmap, OID_AUTO, section, CTLFLAG_RD, 0, - "1MB page mapping counters"); - -static u_long pmap_section_demotions; -SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, demotions, CTLFLAG_RD, - &pmap_section_demotions, 0, "1MB page demotions"); - -static u_long pmap_section_mappings; -SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, mappings, CTLFLAG_RD, - &pmap_section_mappings, 0, "1MB page mappings"); - -static u_long pmap_section_p_failures; -SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, p_failures, CTLFLAG_RD, - &pmap_section_p_failures, 0, "1MB page promotion failures"); - -static u_long pmap_section_promotions; -SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, promotions, CTLFLAG_RD, - &pmap_section_promotions, 0, "1MB page promotions"); - -int -pmap_fault_fixup(pmap_t pmap, vm_offset_t va, vm_prot_t ftype, int user) -{ - struct l2_dtable *l2; - struct l2_bucket *l2b; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep, pte; - vm_paddr_t pa; - u_int l1idx; - int rv = 0; - - l1idx = L1_IDX(va); - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - /* - * Check and possibly fix-up L1 section mapping - * only when superpage mappings are enabled to speed up. - */ - if (sp_enabled) { - pl1pd = &pmap->pm_l1->l1_kva[l1idx]; - l1pd = *pl1pd; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - /* Catch an access to the vectors section */ - if (l1idx == L1_IDX(vector_page)) - goto out; - /* - * Stay away from the kernel mappings. - * None of them should fault from L1 entry. - */ - if (pmap == pmap_kernel()) - goto out; - /* - * Catch a forbidden userland access - */ - if (user && !(l1pd & L1_S_PROT_U)) - goto out; - /* - * Superpage is always either mapped read only - * or it is modified and permitted to be written - * by default. Therefore, process only reference - * flag fault and demote page in case of write fault. - */ - if ((ftype & VM_PROT_WRITE) && !L1_S_WRITABLE(l1pd) && - L1_S_REFERENCED(l1pd)) { - (void)pmap_demote_section(pmap, va); - goto out; - } else if (!L1_S_REFERENCED(l1pd)) { - /* Mark the page "referenced" */ - *pl1pd = l1pd | L1_S_REF; - PTE_SYNC(pl1pd); - goto l1_section_out; - } else - goto out; - } - } - /* - * If there is no l2_dtable for this address, then the process - * has no business accessing it. - * - * Note: This will catch userland processes trying to access - * kernel addresses. - */ - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - if (l2 == NULL) - goto out; - - /* - * Likewise if there is no L2 descriptor table - */ - l2b = &l2->l2_bucket[L2_BUCKET(l1idx)]; - if (l2b->l2b_kva == NULL) - goto out; - - /* - * Check the PTE itself. - */ - ptep = &l2b->l2b_kva[l2pte_index(va)]; - pte = *ptep; - if (pte == 0) - goto out; - - /* - * Catch a userland access to the vector page mapped at 0x0 - */ - if (user && !(pte & L2_S_PROT_U)) - goto out; - if (va == vector_page) - goto out; - - pa = l2pte_pa(pte); - CTR5(KTR_PMAP, "pmap_fault_fix: pmap:%p va:%x pte:0x%x ftype:%x user:%x", - pmap, va, pte, ftype, user); - if ((ftype & VM_PROT_WRITE) && !(L2_S_WRITABLE(pte)) && - L2_S_REFERENCED(pte)) { - /* - * This looks like a good candidate for "page modified" - * emulation... - */ - struct pv_entry *pv; - struct vm_page *m; - - /* Extract the physical address of the page */ - if ((m = PHYS_TO_VM_PAGE(pa)) == NULL) { - goto out; - } - /* Get the current flags for this page. */ - - pv = pmap_find_pv(&m->md, pmap, va); - if (pv == NULL) { - goto out; - } - - /* - * Do the flags say this page is writable? If not then it - * is a genuine write fault. If yes then the write fault is - * our fault as we did not reflect the write access in the - * PTE. Now we know a write has occurred we can correct this - * and also set the modified bit - */ - if ((pv->pv_flags & PVF_WRITE) == 0) { - goto out; - } - - vm_page_dirty(m); - - /* Re-enable write permissions for the page */ - *ptep = (pte & ~L2_APX); - PTE_SYNC(ptep); - rv = 1; - CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep); - } else if (!L2_S_REFERENCED(pte)) { - /* - * This looks like a good candidate for "page referenced" - * emulation. - */ - struct pv_entry *pv; - struct vm_page *m; - - /* Extract the physical address of the page */ - if ((m = PHYS_TO_VM_PAGE(pa)) == NULL) - goto out; - /* Get the current flags for this page. */ - pv = pmap_find_pv(&m->md, pmap, va); - if (pv == NULL) - goto out; - - vm_page_aflag_set(m, PGA_REFERENCED); - - /* Mark the page "referenced" */ - *ptep = pte | L2_S_REF; - PTE_SYNC(ptep); - rv = 1; - CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep); - } - - /* - * We know there is a valid mapping here, so simply - * fix up the L1 if necessary. - */ - pl1pd = &pmap->pm_l1->l1_kva[l1idx]; - l1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO; - if (*pl1pd != l1pd) { - *pl1pd = l1pd; - PTE_SYNC(pl1pd); - rv = 1; - } - -#ifdef DEBUG - /* - * If 'rv == 0' at this point, it generally indicates that there is a - * stale TLB entry for the faulting address. This happens when two or - * more processes are sharing an L1. Since we don't flush the TLB on - * a context switch between such processes, we can take domain faults - * for mappings which exist at the same VA in both processes. EVEN IF - * WE'VE RECENTLY FIXED UP THE CORRESPONDING L1 in pmap_enter(), for - * example. - * - * This is extremely likely to happen if pmap_enter() updated the L1 - * entry for a recently entered mapping. In this case, the TLB is - * flushed for the new mapping, but there may still be TLB entries for - * other mappings belonging to other processes in the 1MB range - * covered by the L1 entry. - * - * Since 'rv == 0', we know that the L1 already contains the correct - * value, so the fault must be due to a stale TLB entry. - * - * Since we always need to flush the TLB anyway in the case where we - * fixed up the L1, or frobbed the L2 PTE, we effectively deal with - * stale TLB entries dynamically. - * - * However, the above condition can ONLY happen if the current L1 is - * being shared. If it happens when the L1 is unshared, it indicates - * that other parts of the pmap are not doing their job WRT managing - * the TLB. - */ - if (rv == 0 && pmap->pm_l1->l1_domain_use_count == 1) { - printf("fixup: pmap %p, va 0x%08x, ftype %d - nothing to do!\n", - pmap, va, ftype); - printf("fixup: l2 %p, l2b %p, ptep %p, pl1pd %p\n", - l2, l2b, ptep, pl1pd); - printf("fixup: pte 0x%x, l1pd 0x%x, last code 0x%x\n", - pte, l1pd, last_fault_code); -#ifdef DDB - Debugger(); -#endif - } -#endif - -l1_section_out: - cpu_tlb_flushID_SE(va); - cpu_cpwait(); - - rv = 1; - -out: - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); - return (rv); -} - -void -pmap_postinit(void) -{ - struct l2_bucket *l2b; - struct l1_ttable *l1; - pd_entry_t *pl1pt; - pt_entry_t *ptep, pte; - vm_offset_t va, eva; - u_int loop, needed; - - needed = (maxproc / PMAP_DOMAINS) + ((maxproc % PMAP_DOMAINS) ? 1 : 0); - needed -= 1; - l1 = malloc(sizeof(*l1) * needed, M_VMPMAP, M_WAITOK); - - for (loop = 0; loop < needed; loop++, l1++) { - /* Allocate a L1 page table */ - va = (vm_offset_t)contigmalloc(L1_TABLE_SIZE, M_VMPMAP, 0, 0x0, - 0xffffffff, L1_TABLE_SIZE, 0); - - if (va == 0) - panic("Cannot allocate L1 KVM"); - - eva = va + L1_TABLE_SIZE; - pl1pt = (pd_entry_t *)va; - - while (va < eva) { - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - pte = *ptep; - pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt; - *ptep = pte; - PTE_SYNC(ptep); - cpu_tlb_flushID_SE(va); - cpu_cpwait(); - va += PAGE_SIZE; - } - pmap_init_l1(l1, pl1pt); - } -#ifdef DEBUG - printf("pmap_postinit: Allocated %d static L1 descriptor tables\n", - needed); -#endif -} - -/* - * This is used to stuff certain critical values into the PCB where they - * can be accessed quickly from cpu_switch() et al. - */ -void -pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb) -{ - struct l2_bucket *l2b; - - pcb->pcb_pagedir = pmap->pm_l1->l1_physaddr; - pcb->pcb_dacr = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | - (DOMAIN_CLIENT << (pmap->pm_domain * 2)); - - if (vector_page < KERNBASE) { - pcb->pcb_pl1vec = &pmap->pm_l1->l1_kva[L1_IDX(vector_page)]; - l2b = pmap_get_l2_bucket(pmap, vector_page); - pcb->pcb_l1vec = l2b->l2b_phys | L1_C_PROTO | - L1_C_DOM(pmap->pm_domain) | L1_C_DOM(PMAP_DOMAIN_KERNEL); - } else - pcb->pcb_pl1vec = NULL; -} - -void -pmap_activate(struct thread *td) -{ - pmap_t pmap; - struct pcb *pcb; - - pmap = vmspace_pmap(td->td_proc->p_vmspace); - pcb = td->td_pcb; - - critical_enter(); - pmap_set_pcb_pagedir(pmap, pcb); - - if (td == curthread) { - u_int cur_dacr, cur_ttb; - - __asm __volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(cur_ttb)); - __asm __volatile("mrc p15, 0, %0, c3, c0, 0" : "=r"(cur_dacr)); - - cur_ttb &= ~(L1_TABLE_SIZE - 1); - - if (cur_ttb == (u_int)pcb->pcb_pagedir && - cur_dacr == pcb->pcb_dacr) { - /* - * No need to switch address spaces. - */ - critical_exit(); - return; - } - - - /* - * We MUST, I repeat, MUST fix up the L1 entry corresponding - * to 'vector_page' in the incoming L1 table before switching - * to it otherwise subsequent interrupts/exceptions (including - * domain faults!) will jump into hyperspace. - */ - if (pcb->pcb_pl1vec) { - *pcb->pcb_pl1vec = pcb->pcb_l1vec; - } - - cpu_domains(pcb->pcb_dacr); - cpu_setttb(pcb->pcb_pagedir); - } - critical_exit(); -} - -static int -pmap_set_pt_cache_mode(pd_entry_t *kl1, vm_offset_t va) -{ - pd_entry_t *pdep, pde; - pt_entry_t *ptep, pte; - vm_offset_t pa; - int rv = 0; - - /* - * Make sure the descriptor itself has the correct cache mode - */ - pdep = &kl1[L1_IDX(va)]; - pde = *pdep; - - if (l1pte_section_p(pde)) { - if ((pde & L1_S_CACHE_MASK) != pte_l1_s_cache_mode_pt) { - *pdep = (pde & ~L1_S_CACHE_MASK) | - pte_l1_s_cache_mode_pt; - PTE_SYNC(pdep); - rv = 1; - } - } else { - pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK); - ptep = (pt_entry_t *)kernel_pt_lookup(pa); - if (ptep == NULL) - panic("pmap_bootstrap: No L2 for L2 @ va %p\n", ptep); - - ptep = &ptep[l2pte_index(va)]; - pte = *ptep; - if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) { - *ptep = (pte & ~L2_S_CACHE_MASK) | - pte_l2_s_cache_mode_pt; - PTE_SYNC(ptep); - rv = 1; - } - } - - return (rv); -} - -static void -pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap, - pt_entry_t **ptep) -{ - vm_offset_t va = *availp; - struct l2_bucket *l2b; - - if (ptep) { - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - if (l2b == NULL) - panic("pmap_alloc_specials: no l2b for 0x%x", va); - - *ptep = &l2b->l2b_kva[l2pte_index(va)]; - } - - *vap = va; - *availp = va + (PAGE_SIZE * pages); -} - -/* - * Bootstrap the system enough to run with virtual memory. - * - * On the arm this is called after mapping has already been enabled - * and just syncs the pmap module with what has already been done. - * [We can't call it easily with mapping off since the kernel is not - * mapped with PA == VA, hence we would have to relocate every address - * from the linked base (virtual) address "KERNBASE" to the actual - * (physical) address starting relative to 0] - */ -#define PMAP_STATIC_L2_SIZE 16 - -void -pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt) -{ - static struct l1_ttable static_l1; - static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE]; - struct l1_ttable *l1 = &static_l1; - struct l2_dtable *l2; - struct l2_bucket *l2b; - struct czpages *czp; - pd_entry_t pde; - pd_entry_t *kernel_l1pt = (pd_entry_t *)l1pt->pv_va; - pt_entry_t *ptep; - vm_paddr_t pa; - vm_offset_t va; - vm_size_t size; - int i, l1idx, l2idx, l2next = 0; - - PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n", - firstaddr, vm_max_kernel_address)); - - virtual_avail = firstaddr; - kernel_pmap->pm_l1 = l1; - kernel_l1pa = l1pt->pv_pa; - - /* - * Scan the L1 translation table created by initarm() and create - * the required metadata for all valid mappings found in it. - */ - for (l1idx = 0; l1idx < (L1_TABLE_SIZE / sizeof(pd_entry_t)); l1idx++) { - pde = kernel_l1pt[l1idx]; - - /* - * We're only interested in Coarse mappings. - * pmap_extract() can deal with section mappings without - * recourse to checking L2 metadata. - */ - if ((pde & L1_TYPE_MASK) != L1_TYPE_C) - continue; - - /* - * Lookup the KVA of this L2 descriptor table - */ - pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK); - ptep = (pt_entry_t *)kernel_pt_lookup(pa); - - if (ptep == NULL) { - panic("pmap_bootstrap: No L2 for va 0x%x, pa 0x%lx", - (u_int)l1idx << L1_S_SHIFT, (long unsigned int)pa); - } - - /* - * Fetch the associated L2 metadata structure. - * Allocate a new one if necessary. - */ - if ((l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]) == NULL) { - if (l2next == PMAP_STATIC_L2_SIZE) - panic("pmap_bootstrap: out of static L2s"); - kernel_pmap->pm_l2[L2_IDX(l1idx)] = l2 = - &static_l2[l2next++]; - } - - /* - * One more L1 slot tracked... - */ - l2->l2_occupancy++; - - /* - * Fill in the details of the L2 descriptor in the - * appropriate bucket. - */ - l2b = &l2->l2_bucket[L2_BUCKET(l1idx)]; - l2b->l2b_kva = ptep; - l2b->l2b_phys = pa; - l2b->l2b_l1idx = l1idx; - - /* - * Establish an initial occupancy count for this descriptor - */ - for (l2idx = 0; - l2idx < (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t)); - l2idx++) { - if ((ptep[l2idx] & L2_TYPE_MASK) != L2_TYPE_INV) { - l2b->l2b_occupancy++; - } - } - - /* - * Make sure the descriptor itself has the correct cache mode. - * If not, fix it, but whine about the problem. Port-meisters - * should consider this a clue to fix up their initarm() - * function. :) - */ - if (pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)ptep)) { - printf("pmap_bootstrap: WARNING! wrong cache mode for " - "L2 pte @ %p\n", ptep); - } - } - - - /* - * Ensure the primary (kernel) L1 has the correct cache mode for - * a page table. Bitch if it is not correctly set. - */ - for (va = (vm_offset_t)kernel_l1pt; - va < ((vm_offset_t)kernel_l1pt + L1_TABLE_SIZE); va += PAGE_SIZE) { - if (pmap_set_pt_cache_mode(kernel_l1pt, va)) - printf("pmap_bootstrap: WARNING! wrong cache mode for " - "primary L1 @ 0x%x\n", va); - } - - cpu_dcache_wbinv_all(); - cpu_l2cache_wbinv_all(); - cpu_tlb_flushID(); - cpu_cpwait(); - - PMAP_LOCK_INIT(kernel_pmap); - CPU_FILL(&kernel_pmap->pm_active); - kernel_pmap->pm_domain = PMAP_DOMAIN_KERNEL; - TAILQ_INIT(&kernel_pmap->pm_pvchunk); - - /* - * Initialize the global pv list lock. - */ - rw_init(&pvh_global_lock, "pmap pv global"); - - /* - * Reserve some special page table entries/VA space for temporary - * mapping of pages that are being copied or zeroed. - */ - for (czp = cpu_czpages, i = 0; i < MAXCPU; ++i, ++czp) { - mtx_init(&czp->lock, "czpages", NULL, MTX_DEF); - pmap_alloc_specials(&virtual_avail, 1, &czp->srcva, &czp->srcptep); - pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->srcptep); - pmap_alloc_specials(&virtual_avail, 1, &czp->dstva, &czp->dstptep); - pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->dstptep); - } - - size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) / - L1_S_SIZE; - pmap_alloc_specials(&virtual_avail, - round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE, - &pmap_kernel_l2ptp_kva, NULL); - - size = (size + (L2_BUCKET_SIZE - 1)) / L2_BUCKET_SIZE; - pmap_alloc_specials(&virtual_avail, - round_page(size * sizeof(struct l2_dtable)) / PAGE_SIZE, - &pmap_kernel_l2dtable_kva, NULL); - - pmap_alloc_specials(&virtual_avail, - 1, (vm_offset_t*)&_tmppt, NULL); - pmap_alloc_specials(&virtual_avail, - MAXDUMPPGS, (vm_offset_t *)&crashdumpmap, NULL); - SLIST_INIT(&l1_list); - TAILQ_INIT(&l1_lru_list); - mtx_init(&l1_lru_lock, "l1 list lock", NULL, MTX_DEF); - pmap_init_l1(l1, kernel_l1pt); - cpu_dcache_wbinv_all(); - cpu_l2cache_wbinv_all(); - cpu_tlb_flushID(); - cpu_cpwait(); - - virtual_avail = round_page(virtual_avail); - virtual_end = vm_max_kernel_address; - kernel_vm_end = pmap_curmaxkvaddr; - - pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb); -} - - -/*************************************************** - * Pmap allocation/deallocation routines. - ***************************************************/ - -/* - * Release any resources held by the given physical map. - * Called when a pmap initialized by pmap_pinit is being released. - * Should only be called if the map contains no valid mappings. - */ -void -pmap_release(pmap_t pmap) -{ - struct pcb *pcb; - - cpu_tlb_flushID(); - cpu_cpwait(); - if (vector_page < KERNBASE) { - struct pcb *curpcb = PCPU_GET(curpcb); - pcb = thread0.td_pcb; - if (pmap_is_current(pmap)) { - /* - * Frob the L1 entry corresponding to the vector - * page so that it contains the kernel pmap's domain - * number. This will ensure pmap_remove() does not - * pull the current vector page out from under us. - */ - critical_enter(); - *pcb->pcb_pl1vec = pcb->pcb_l1vec; - cpu_domains(pcb->pcb_dacr); - cpu_setttb(pcb->pcb_pagedir); - critical_exit(); - } - pmap_remove(pmap, vector_page, vector_page + PAGE_SIZE); - /* - * Make sure cpu_switch(), et al, DTRT. This is safe to do - * since this process has no remaining mappings of its own. - */ - curpcb->pcb_pl1vec = pcb->pcb_pl1vec; - curpcb->pcb_l1vec = pcb->pcb_l1vec; - curpcb->pcb_dacr = pcb->pcb_dacr; - curpcb->pcb_pagedir = pcb->pcb_pagedir; - - } - pmap_free_l1(pmap); - - dprintf("pmap_release()\n"); -} - - - -/* - * Helper function for pmap_grow_l2_bucket() - */ -static __inline int -pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap) -{ - struct l2_bucket *l2b; - pt_entry_t *ptep; - vm_paddr_t pa; - struct vm_page *m; - - m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_WIRED); - if (m == NULL) - return (1); - pa = VM_PAGE_TO_PHYS(m); - - if (pap) - *pap = pa; - - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - - ptep = &l2b->l2b_kva[l2pte_index(va)]; - *ptep = L2_S_PROTO | pa | cache_mode | L2_S_REF; - pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE, 0); - PTE_SYNC(ptep); - cpu_tlb_flushD_SE(va); - cpu_cpwait(); - - return (0); -} - -/* - * This is the same as pmap_alloc_l2_bucket(), except that it is only - * used by pmap_growkernel(). - */ -static __inline struct l2_bucket * -pmap_grow_l2_bucket(pmap_t pmap, vm_offset_t va) -{ - struct l2_dtable *l2; - struct l2_bucket *l2b; - struct l1_ttable *l1; - pd_entry_t *pl1pd; - u_short l1idx; - vm_offset_t nva; - - l1idx = L1_IDX(va); - - if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) { - /* - * No mapping at this address, as there is - * no entry in the L1 table. - * Need to allocate a new l2_dtable. - */ - nva = pmap_kernel_l2dtable_kva; - if ((nva & PAGE_MASK) == 0) { - /* - * Need to allocate a backing page - */ - if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL)) - return (NULL); - } - - l2 = (struct l2_dtable *)nva; - nva += sizeof(struct l2_dtable); - - if ((nva & PAGE_MASK) < (pmap_kernel_l2dtable_kva & - PAGE_MASK)) { - /* - * The new l2_dtable straddles a page boundary. - * Map in another page to cover it. - */ - if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL)) - return (NULL); - } - - pmap_kernel_l2dtable_kva = nva; - - /* - * Link it into the parent pmap - */ - pmap->pm_l2[L2_IDX(l1idx)] = l2; - memset(l2, 0, sizeof(*l2)); - } - - l2b = &l2->l2_bucket[L2_BUCKET(l1idx)]; - - /* - * Fetch pointer to the L2 page table associated with the address. - */ - if (l2b->l2b_kva == NULL) { - pt_entry_t *ptep; - - /* - * No L2 page table has been allocated. Chances are, this - * is because we just allocated the l2_dtable, above. - */ - nva = pmap_kernel_l2ptp_kva; - ptep = (pt_entry_t *)nva; - if ((nva & PAGE_MASK) == 0) { - /* - * Need to allocate a backing page - */ - if (pmap_grow_map(nva, pte_l2_s_cache_mode_pt, - &pmap_kernel_l2ptp_phys)) - return (NULL); - } - memset(ptep, 0, L2_TABLE_SIZE_REAL); - l2->l2_occupancy++; - l2b->l2b_kva = ptep; - l2b->l2b_l1idx = l1idx; - l2b->l2b_phys = pmap_kernel_l2ptp_phys; - - pmap_kernel_l2ptp_kva += L2_TABLE_SIZE_REAL; - pmap_kernel_l2ptp_phys += L2_TABLE_SIZE_REAL; - } - - /* Distribute new L1 entry to all other L1s */ - SLIST_FOREACH(l1, &l1_list, l1_link) { - pl1pd = &l1->l1_kva[L1_IDX(va)]; - *pl1pd = l2b->l2b_phys | L1_C_DOM(PMAP_DOMAIN_KERNEL) | - L1_C_PROTO; - PTE_SYNC(pl1pd); - } - cpu_tlb_flushID_SE(va); - cpu_cpwait(); - - return (l2b); -} - - -/* - * grow the number of kernel page table entries, if needed - */ -void -pmap_growkernel(vm_offset_t addr) -{ - pmap_t kpmap = pmap_kernel(); - - if (addr <= pmap_curmaxkvaddr) - return; /* we are OK */ - - /* - * whoops! we need to add kernel PTPs - */ - - /* Map 1MB at a time */ - for (; pmap_curmaxkvaddr < addr; pmap_curmaxkvaddr += L1_S_SIZE) - pmap_grow_l2_bucket(kpmap, pmap_curmaxkvaddr); - - kernel_vm_end = pmap_curmaxkvaddr; -} - -/* - * Returns TRUE if the given page is mapped individually or as part of - * a 1MB section. Otherwise, returns FALSE. - */ -boolean_t -pmap_page_is_mapped(vm_page_t m) -{ - boolean_t rv; - - if ((m->oflags & VPO_UNMANAGED) != 0) - return (FALSE); - rw_wlock(&pvh_global_lock); - rv = !TAILQ_EMPTY(&m->md.pv_list) || - ((m->flags & PG_FICTITIOUS) == 0 && - !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list)); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * Remove all pages from specified address space - * this aids process exit speeds. Also, this code - * is special cased for current process only, but - * can have the more generic (and slightly slower) - * mode enabled. This is much faster than pmap_remove - * in the case of running down an entire address space. - */ -void -pmap_remove_pages(pmap_t pmap) -{ - struct pv_entry *pv; - struct l2_bucket *l2b = NULL; - struct pv_chunk *pc, *npc; - struct md_page *pvh; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep; - vm_page_t m, mt; - vm_offset_t va; - uint32_t inuse, bitmask; - int allfree, bit, field, idx; - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - - TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) { - allfree = 1; - for (field = 0; field < _NPCM; field++) { - inuse = ~pc->pc_map[field] & pc_freemask[field]; - while (inuse != 0) { - bit = ffs(inuse) - 1; - bitmask = 1ul << bit; - idx = field * sizeof(inuse) * NBBY + bit; - pv = &pc->pc_pventry[idx]; - va = pv->pv_va; - inuse &= ~bitmask; - if (pv->pv_flags & PVF_WIRED) { - /* Cannot remove wired pages now. */ - allfree = 0; - continue; - } - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - l1pd = *pl1pd; - l2b = pmap_get_l2_bucket(pmap, va); - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - pvh = pa_to_pvh(l1pd & L1_S_FRAME); - TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); - if (TAILQ_EMPTY(&pvh->pv_list)) { - m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME); - KASSERT((vm_offset_t)m >= KERNBASE, - ("Trying to access non-existent page " - "va %x l1pd %x", trunc_1mpage(va), l1pd)); - for (mt = m; mt < &m[L2_PTE_NUM_TOTAL]; mt++) { - if (TAILQ_EMPTY(&mt->md.pv_list)) - vm_page_aflag_clear(mt, PGA_WRITEABLE); - } - } - if (l2b != NULL) { - KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL, - ("pmap_remove_pages: l2_bucket occupancy error")); - pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL); - } - pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL; - *pl1pd = 0; - PTE_SYNC(pl1pd); - } else { - KASSERT(l2b != NULL, - ("No L2 bucket in pmap_remove_pages")); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep)); - KASSERT((vm_offset_t)m >= KERNBASE, - ("Trying to access non-existent page " - "va %x pte %x", va, *ptep)); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list) && - (m->flags & PG_FICTITIOUS) == 0) { - pvh = pa_to_pvh(l2pte_pa(*ptep)); - if (TAILQ_EMPTY(&pvh->pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - } - *ptep = 0; - PTE_SYNC(ptep); - pmap_free_l2_bucket(pmap, l2b, 1); - pmap->pm_stats.resident_count--; - } - - /* Mark free */ - PV_STAT(pv_entry_frees++); - PV_STAT(pv_entry_spare++); - pv_entry_count--; - pc->pc_map[field] |= bitmask; - } - } - if (allfree) { - TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); - pmap_free_pv_chunk(pc); - } - - } - - rw_wunlock(&pvh_global_lock); - cpu_tlb_flushID(); - cpu_cpwait(); - PMAP_UNLOCK(pmap); -} - -static void -pmap_init_qpages(void) -{ - struct pcpu *pc; - struct l2_bucket *l2b; - int i; - - CPU_FOREACH(i) { - pc = pcpu_find(i); - pc->pc_qmap_addr = kva_alloc(PAGE_SIZE); - if (pc->pc_qmap_addr == 0) - panic("pmap_init_qpages: unable to allocate KVA"); - - l2b = pmap_get_l2_bucket(pmap_kernel(), pc->pc_qmap_addr); - if (l2b == NULL) - l2b = pmap_grow_l2_bucket(pmap_kernel(), - pc->pc_qmap_addr); - if (l2b == NULL) - panic("pmap_alloc_specials: no l2b for 0x%x", - pc->pc_qmap_addr); - pc->pc_qmap_pte = &l2b->l2b_kva[l2pte_index(pc->pc_qmap_addr)]; - } -} - -SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL); - -/*************************************************** - * Low level mapping routines..... - ***************************************************/ - -#ifdef ARM_HAVE_SUPERSECTIONS -/* Map a super section into the KVA. */ - -void -pmap_kenter_supersection(vm_offset_t va, uint64_t pa, int flags) -{ - pd_entry_t pd = L1_S_PROTO | L1_S_SUPERSEC | (pa & L1_SUP_FRAME) | - (((pa >> 32) & 0xf) << 20) | L1_S_PROT(PTE_KERNEL, - VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) | - L1_S_DOM(PMAP_DOMAIN_KERNEL); - struct l1_ttable *l1; - vm_offset_t va0, va_end; - - KASSERT(((va | pa) & L1_SUP_OFFSET) == 0, - ("Not a valid super section mapping")); - if (flags & SECTION_CACHE) - pd |= pte_l1_s_cache_mode; - else if (flags & SECTION_PT) - pd |= pte_l1_s_cache_mode_pt; - - va0 = va & L1_SUP_FRAME; - va_end = va + L1_SUP_SIZE; - SLIST_FOREACH(l1, &l1_list, l1_link) { - va = va0; - for (; va < va_end; va += L1_S_SIZE) { - l1->l1_kva[L1_IDX(va)] = pd; - PTE_SYNC(&l1->l1_kva[L1_IDX(va)]); - } - } -} -#endif - -/* Map a section into the KVA. */ - -void -pmap_kenter_section(vm_offset_t va, vm_offset_t pa, int flags) -{ - pd_entry_t pd = L1_S_PROTO | pa | L1_S_PROT(PTE_KERNEL, - VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) | L1_S_REF | - L1_S_DOM(PMAP_DOMAIN_KERNEL); - struct l1_ttable *l1; - - KASSERT(((va | pa) & L1_S_OFFSET) == 0, - ("Not a valid section mapping")); - if (flags & SECTION_CACHE) - pd |= pte_l1_s_cache_mode; - else if (flags & SECTION_PT) - pd |= pte_l1_s_cache_mode_pt; - - SLIST_FOREACH(l1, &l1_list, l1_link) { - l1->l1_kva[L1_IDX(va)] = pd; - PTE_SYNC(&l1->l1_kva[L1_IDX(va)]); - } - cpu_tlb_flushID_SE(va); - cpu_cpwait(); -} - -/* - * Make a temporary mapping for a physical address. This is only intended - * to be used for panic dumps. - */ -void * -pmap_kenter_temporary(vm_paddr_t pa, int i) -{ - vm_offset_t va; - - va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE); - pmap_kenter(va, pa); - return ((void *)crashdumpmap); -} - -/* - * add a wired page to the kva - * note that in order for the mapping to take effect -- you - * should do a invltlb after doing the pmap_kenter... - */ -static PMAP_INLINE void -pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags) -{ - struct l2_bucket *l2b; - pt_entry_t *ptep; - pt_entry_t opte; - - PDEBUG(1, printf("pmap_kenter: va = %08x, pa = %08x\n", - (uint32_t) va, (uint32_t) pa)); - - - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - if (l2b == NULL) - l2b = pmap_grow_l2_bucket(pmap_kernel(), va); - KASSERT(l2b != NULL, ("No L2 Bucket")); - - ptep = &l2b->l2b_kva[l2pte_index(va)]; - opte = *ptep; - - if (flags & KENTER_CACHE) - *ptep = L2_S_PROTO | l2s_mem_types[PTE_CACHE] | pa | L2_S_REF; - else if (flags & KENTER_DEVICE) - *ptep = L2_S_PROTO | l2s_mem_types[PTE_DEVICE] | pa | L2_S_REF; - else - *ptep = L2_S_PROTO | l2s_mem_types[PTE_NOCACHE] | pa | L2_S_REF; - - if (flags & KENTER_CACHE) { - pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE, - flags & KENTER_USER); - } else { - pmap_set_prot(ptep, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, - 0); - } - - PTE_SYNC(ptep); - if (l2pte_valid(opte)) { - if (L2_S_EXECUTABLE(opte) || L2_S_EXECUTABLE(*ptep)) - cpu_tlb_flushID_SE(va); - else - cpu_tlb_flushD_SE(va); - } else { - if (opte == 0) - l2b->l2b_occupancy++; - } - cpu_cpwait(); - - PDEBUG(1, printf("pmap_kenter: pte = %08x, opte = %08x, npte = %08x\n", - (uint32_t) ptep, opte, *ptep)); -} - -void -pmap_kenter(vm_offset_t va, vm_paddr_t pa) -{ - pmap_kenter_internal(va, pa, KENTER_CACHE); -} - -void -pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa) -{ - - pmap_kenter_internal(va, pa, 0); -} - -void -pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa) -{ - vm_offset_t sva; - - KASSERT((size & PAGE_MASK) == 0, - ("%s: device mapping not page-sized", __func__)); - - sva = va; - while (size != 0) { - pmap_kenter_internal(va, pa, KENTER_DEVICE); - va += PAGE_SIZE; - pa += PAGE_SIZE; - size -= PAGE_SIZE; - } -} - -void -pmap_kremove_device(vm_offset_t va, vm_size_t size) -{ - vm_offset_t sva; - - KASSERT((size & PAGE_MASK) == 0, - ("%s: device mapping not page-sized", __func__)); - - sva = va; - while (size != 0) { - pmap_kremove(va); - va += PAGE_SIZE; - size -= PAGE_SIZE; - } -} - -void -pmap_kenter_user(vm_offset_t va, vm_paddr_t pa) -{ - - pmap_kenter_internal(va, pa, KENTER_CACHE|KENTER_USER); - /* - * Call pmap_fault_fixup now, to make sure we'll have no exception - * at the first use of the new address, or bad things will happen, - * as we use one of these addresses in the exception handlers. - */ - pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1); -} - -vm_paddr_t -pmap_kextract(vm_offset_t va) -{ - - if (kernel_vm_end == 0) - return (0); - return (pmap_extract_locked(kernel_pmap, va)); -} - -/* - * remove a page from the kernel pagetables - */ -void -pmap_kremove(vm_offset_t va) -{ - struct l2_bucket *l2b; - pt_entry_t *ptep, opte; - - l2b = pmap_get_l2_bucket(pmap_kernel(), va); - if (!l2b) - return; - KASSERT(l2b != NULL, ("No L2 Bucket")); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - opte = *ptep; - if (l2pte_valid(opte)) { - va = va & ~PAGE_MASK; - *ptep = 0; - PTE_SYNC(ptep); - if (L2_S_EXECUTABLE(opte)) - cpu_tlb_flushID_SE(va); - else - cpu_tlb_flushD_SE(va); - cpu_cpwait(); - } -} - - -/* - * Used to map a range of physical addresses into kernel - * virtual address space. - * - * The value passed in '*virt' is a suggested virtual address for - * the mapping. Architectures which can support a direct-mapped - * physical to virtual region can return the appropriate address - * within that region, leaving '*virt' unchanged. Other - * architectures should map the pages starting at '*virt' and - * update '*virt' with the first usable address after the mapped - * region. - */ -vm_offset_t -pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot) -{ - vm_offset_t sva = *virt; - vm_offset_t va = sva; - - PDEBUG(1, printf("pmap_map: virt = %08x, start = %08x, end = %08x, " - "prot = %d\n", (uint32_t) *virt, (uint32_t) start, (uint32_t) end, - prot)); - - while (start < end) { - pmap_kenter(va, start); - va += PAGE_SIZE; - start += PAGE_SIZE; - } - *virt = va; - return (sva); -} - -/* - * Add a list of wired pages to the kva - * this routine is only used for temporary - * kernel mappings that do not need to have - * page modification or references recorded. - * Note that old mappings are simply written - * over. The page *must* be wired. - */ -void -pmap_qenter(vm_offset_t va, vm_page_t *m, int count) -{ - int i; - - for (i = 0; i < count; i++) { - pmap_kenter_internal(va, VM_PAGE_TO_PHYS(m[i]), - KENTER_CACHE); - va += PAGE_SIZE; - } -} - - -/* - * this routine jerks page mappings from the - * kernel -- it is meant only for temporary mappings. - */ -void -pmap_qremove(vm_offset_t va, int count) -{ - int i; - - for (i = 0; i < count; i++) { - if (vtophys(va)) - pmap_kremove(va); - - va += PAGE_SIZE; - } -} - - -/* - * pmap_object_init_pt preloads the ptes for a given object - * into the specified pmap. This eliminates the blast of soft - * faults on process startup and immediately after an mmap. - */ -void -pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, - vm_pindex_t pindex, vm_size_t size) -{ - - VM_OBJECT_ASSERT_WLOCKED(object); - KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG, - ("pmap_object_init_pt: non-device object")); -} - - -/* - * pmap_is_prefaultable: - * - * Return whether or not the specified virtual address is elgible - * for prefault. - */ -boolean_t -pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr) -{ - pd_entry_t *pdep; - pt_entry_t *ptep; - - if (!pmap_get_pde_pte(pmap, addr, &pdep, &ptep)) - return (FALSE); - KASSERT((pdep != NULL && (l1pte_section_p(*pdep) || ptep != NULL)), - ("Valid mapping but no pte ?")); - if (*pdep != 0 && !l1pte_section_p(*pdep)) - if (*ptep == 0) - return (TRUE); - return (FALSE); -} - -/* - * Fetch pointers to the PDE/PTE for the given pmap/VA pair. - * Returns TRUE if the mapping exists, else FALSE. - * - * NOTE: This function is only used by a couple of arm-specific modules. - * It is not safe to take any pmap locks here, since we could be right - * in the middle of debugging the pmap anyway... - * - * It is possible for this routine to return FALSE even though a valid - * mapping does exist. This is because we don't lock, so the metadata - * state may be inconsistent. - * - * NOTE: We can return a NULL *ptp in the case where the L1 pde is - * a "section" mapping. - */ -boolean_t -pmap_get_pde_pte(pmap_t pmap, vm_offset_t va, pd_entry_t **pdp, - pt_entry_t **ptp) -{ - struct l2_dtable *l2; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep; - u_short l1idx; - - if (pmap->pm_l1 == NULL) - return (FALSE); - - l1idx = L1_IDX(va); - *pdp = pl1pd = &pmap->pm_l1->l1_kva[l1idx]; - l1pd = *pl1pd; - - if (l1pte_section_p(l1pd)) { - *ptp = NULL; - return (TRUE); - } - - if (pmap->pm_l2 == NULL) - return (FALSE); - - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - - if (l2 == NULL || - (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { - return (FALSE); - } - - *ptp = &ptep[l2pte_index(va)]; - return (TRUE); -} - -/* - * Routine: pmap_remove_all - * Function: - * Removes this physical page from - * all physical maps in which it resides. - * Reflects back modify bits to the pager. - * - * Notes: - * Original versions of this routine were very - * inefficient because they iteratively called - * pmap_remove (slow...) - */ -void -pmap_remove_all(vm_page_t m) -{ - struct md_page *pvh; - pv_entry_t pv; - pmap_t pmap; - pt_entry_t *ptep; - struct l2_bucket *l2b; - boolean_t flush = FALSE; - pmap_t curpmap; - u_int is_exec = 0; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_remove_all: page %p is not managed", m)); - rw_wlock(&pvh_global_lock); - if ((m->flags & PG_FICTITIOUS) != 0) - goto small_mappings; - pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); - while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pd_entry_t *pl1pd; - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)]; - KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO, - ("pmap_remove_all: valid section mapping expected")); - (void)pmap_demote_section(pmap, pv->pv_va); - PMAP_UNLOCK(pmap); - } -small_mappings: - curpmap = vmspace_pmap(curproc->p_vmspace); - while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { - pmap = PV_PMAP(pv); - if (flush == FALSE && (pmap == curpmap || - pmap == pmap_kernel())) - flush = TRUE; - - PMAP_LOCK(pmap); - l2b = pmap_get_l2_bucket(pmap, pv->pv_va); - KASSERT(l2b != NULL, ("No l2 bucket")); - ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)]; - is_exec |= PTE_BEEN_EXECD(*ptep); - *ptep = 0; - if (pmap_is_current(pmap)) - PTE_SYNC(ptep); - pmap_free_l2_bucket(pmap, l2b, 1); - pmap->pm_stats.resident_count--; - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (pv->pv_flags & PVF_WIRED) - pmap->pm_stats.wired_count--; - pmap_free_pv_entry(pmap, pv); - PMAP_UNLOCK(pmap); - } - - if (flush) { - if (is_exec) - cpu_tlb_flushID(); - else - cpu_tlb_flushD(); - cpu_cpwait(); - } - vm_page_aflag_clear(m, PGA_WRITEABLE); - rw_wunlock(&pvh_global_lock); -} - -int -pmap_change_attr(vm_offset_t sva, vm_size_t len, int mode) -{ - vm_offset_t base, offset, tmpva; - vm_size_t size; - struct l2_bucket *l2b; - pt_entry_t *ptep, pte; - vm_offset_t next_bucket; - - PMAP_LOCK(kernel_pmap); - - base = trunc_page(sva); - offset = sva & PAGE_MASK; - size = roundup(offset + len, PAGE_SIZE); - - for (tmpva = base; tmpva < base + size; ) { - next_bucket = L2_NEXT_BUCKET(tmpva); - if (next_bucket > base + size) - next_bucket = base + size; - - l2b = pmap_get_l2_bucket(kernel_pmap, tmpva); - if (l2b == NULL) { - tmpva = next_bucket; - continue; - } - - ptep = &l2b->l2b_kva[l2pte_index(tmpva)]; - - if (*ptep == 0) { - PMAP_UNLOCK(kernel_pmap); - return(EINVAL); - } - - pte = *ptep &~ L2_S_CACHE_MASK; - cpu_idcache_wbinv_range(tmpva, PAGE_SIZE); - pmap_l2cache_wbinv_range(tmpva, pte & L2_S_FRAME, PAGE_SIZE); - *ptep = pte; - cpu_tlb_flushID_SE(tmpva); - cpu_cpwait(); - - dprintf("%s: for va:%x ptep:%x pte:%x\n", - __func__, tmpva, (uint32_t)ptep, pte); - tmpva += PAGE_SIZE; - } - - PMAP_UNLOCK(kernel_pmap); - - return (0); -} - -/* - * Set the physical protection on the - * specified range of this map as requested. - */ -void -pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) -{ - struct l2_bucket *l2b; - struct md_page *pvh; - struct pv_entry *pve; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep, pte; - vm_offset_t next_bucket; - u_int is_exec, is_refd; - int flush; - - if ((prot & VM_PROT_READ) == 0) { - pmap_remove(pmap, sva, eva); - return; - } - - if (prot & VM_PROT_WRITE) { - /* - * If this is a read->write transition, just ignore it and let - * vm_fault() take care of it later. - */ - return; - } - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - - /* - * OK, at this point, we know we're doing write-protect operation. - * If the pmap is active, write-back the range. - */ - - flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1; - is_exec = is_refd = 0; - - while (sva < eva) { - next_bucket = L2_NEXT_BUCKET(sva); - /* - * Check for large page. - */ - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)]; - l1pd = *pl1pd; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - KASSERT(pmap != pmap_kernel(), - ("pmap_protect: trying to modify " - "kernel section protections")); - /* - * Are we protecting the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + L1_S_SIZE == next_bucket && - eva >= next_bucket) { - l1pd &= ~(L1_S_PROT_MASK | L1_S_XN); - if (!(prot & VM_PROT_EXECUTE)) - l1pd |= L1_S_XN; - /* - * At this point we are always setting - * write-protect bit. - */ - l1pd |= L1_S_APX; - /* All managed superpages are user pages. */ - l1pd |= L1_S_PROT_U; - *pl1pd = l1pd; - PTE_SYNC(pl1pd); - pvh = pa_to_pvh(l1pd & L1_S_FRAME); - pve = pmap_find_pv(pvh, pmap, - trunc_1mpage(sva)); - pve->pv_flags &= ~PVF_WRITE; - sva = next_bucket; - continue; - } else if (!pmap_demote_section(pmap, sva)) { - /* The large page mapping was destroyed. */ - sva = next_bucket; - continue; - } - } - if (next_bucket > eva) - next_bucket = eva; - l2b = pmap_get_l2_bucket(pmap, sva); - if (l2b == NULL) { - sva = next_bucket; - continue; - } - - ptep = &l2b->l2b_kva[l2pte_index(sva)]; - - while (sva < next_bucket) { - if ((pte = *ptep) != 0 && L2_S_WRITABLE(pte)) { - struct vm_page *m; - - m = PHYS_TO_VM_PAGE(l2pte_pa(pte)); - pmap_set_prot(ptep, prot, - !(pmap == pmap_kernel())); - PTE_SYNC(ptep); - - pmap_modify_pv(m, pmap, sva, PVF_WRITE, 0); - - if (flush >= 0) { - flush++; - is_exec |= PTE_BEEN_EXECD(pte); - is_refd |= PTE_BEEN_REFD(pte); - } else { - if (PTE_BEEN_EXECD(pte)) - cpu_tlb_flushID_SE(sva); - else if (PTE_BEEN_REFD(pte)) - cpu_tlb_flushD_SE(sva); - } - } - - sva += PAGE_SIZE; - ptep++; - } - } - - - if (flush) { - if (is_exec) - cpu_tlb_flushID(); - else - if (is_refd) - cpu_tlb_flushD(); - cpu_cpwait(); - } - rw_wunlock(&pvh_global_lock); - - PMAP_UNLOCK(pmap); -} - - -/* - * Insert the given physical page (p) at - * the specified virtual address (v) in the - * target physical map with the protection requested. - * - * If specified, the page will be wired down, meaning - * that the related pte can not be reclaimed. - * - * NB: This is the only routine which MAY NOT lazy-evaluate - * or lose information. That is, this routine must actually - * insert this page into the given map NOW. - */ - -int -pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, - u_int flags, int8_t psind __unused) -{ - struct l2_bucket *l2b; - int rv; - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - rv = pmap_enter_locked(pmap, va, m, prot, flags); - if (rv == KERN_SUCCESS) { - /* - * If both the l2b_occupancy and the reservation are fully - * populated, then attempt promotion. - */ - l2b = pmap_get_l2_bucket(pmap, va); - if (l2b != NULL && l2b->l2b_occupancy == L2_PTE_NUM_TOTAL && - sp_enabled && (m->flags & PG_FICTITIOUS) == 0 && - vm_reserv_level_iffullpop(m) == 0) - pmap_promote_section(pmap, va); - } - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * The pvh global and pmap locks must be held. - */ -static int -pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, - u_int flags) -{ - struct l2_bucket *l2b = NULL; - struct vm_page *om; - struct pv_entry *pve = NULL; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep, npte, opte; - u_int nflags; - u_int is_exec, is_refd; - vm_paddr_t pa; - u_char user; - - PMAP_ASSERT_LOCKED(pmap); - rw_assert(&pvh_global_lock, RA_WLOCKED); - if (va == vector_page) { - pa = systempage.pv_pa; - m = NULL; - } else { - if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m)) - VM_OBJECT_ASSERT_LOCKED(m->object); - pa = VM_PAGE_TO_PHYS(m); - } - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - if ((va < VM_MAXUSER_ADDRESS) && - (*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) { - (void)pmap_demote_section(pmap, va); - } - - user = 0; - /* - * Make sure userland mappings get the right permissions - */ - if (pmap != pmap_kernel() && va != vector_page) - user = 1; - - nflags = 0; - - if (prot & VM_PROT_WRITE) - nflags |= PVF_WRITE; - if ((flags & PMAP_ENTER_WIRED) != 0) - nflags |= PVF_WIRED; - - PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, " - "prot = %x, flags = %x\n", (uint32_t) pmap, va, (uint32_t) m, - prot, flags)); - - if (pmap == pmap_kernel()) { - l2b = pmap_get_l2_bucket(pmap, va); - if (l2b == NULL) - l2b = pmap_grow_l2_bucket(pmap, va); - } else { -do_l2b_alloc: - l2b = pmap_alloc_l2_bucket(pmap, va); - if (l2b == NULL) { - if ((flags & PMAP_ENTER_NOSLEEP) == 0) { - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); - VM_WAIT; - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - goto do_l2b_alloc; - } - return (KERN_RESOURCE_SHORTAGE); - } - } - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) - panic("pmap_enter: attempt to enter on 1MB page, va: %#x", va); - - ptep = &l2b->l2b_kva[l2pte_index(va)]; - - opte = *ptep; - npte = pa; - is_exec = is_refd = 0; - - if (opte) { - if (l2pte_pa(opte) == pa) { - /* - * We're changing the attrs of an existing mapping. - */ - if (m != NULL) - pmap_modify_pv(m, pmap, va, - PVF_WRITE | PVF_WIRED, nflags); - is_exec |= PTE_BEEN_EXECD(opte); - is_refd |= PTE_BEEN_REFD(opte); - goto validate; - } - if ((om = PHYS_TO_VM_PAGE(l2pte_pa(opte)))) { - /* - * Replacing an existing mapping with a new one. - * It is part of our managed memory so we - * must remove it from the PV list - */ - if ((pve = pmap_remove_pv(om, pmap, va))) { - is_exec |= PTE_BEEN_EXECD(opte); - is_refd |= PTE_BEEN_REFD(opte); - - if (m && ((m->oflags & VPO_UNMANAGED))) - pmap_free_pv_entry(pmap, pve); - } - } - - } else { - /* - * Keep the stats up to date - */ - l2b->l2b_occupancy++; - pmap->pm_stats.resident_count++; - } - - /* - * Enter on the PV list if part of our managed memory. - */ - if ((m && !(m->oflags & VPO_UNMANAGED))) { - if ((!pve) && (pve = pmap_get_pv_entry(pmap, FALSE)) == NULL) - panic("pmap_enter: no pv entries"); - - KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva, - ("pmap_enter: managed mapping within the clean submap")); - KASSERT(pve != NULL, ("No pv")); - pmap_enter_pv(m, pve, pmap, va, nflags); - } - -validate: - /* Make the new PTE valid */ - npte |= L2_S_PROTO; -#ifdef SMP - npte |= L2_SHARED; -#endif - /* Set defaults first - kernel read access */ - npte |= L2_APX; - npte |= L2_S_PROT_R; - /* Set "referenced" flag */ - npte |= L2_S_REF; - - /* Now tune APs as desired */ - if (user) - npte |= L2_S_PROT_U; - /* - * If this is not a vector_page - * then continue setting mapping parameters - */ - if (m != NULL) { - if ((m->oflags & VPO_UNMANAGED) == 0) { - if (prot & (VM_PROT_ALL)) { - vm_page_aflag_set(m, PGA_REFERENCED); - } else { - /* - * Need to do page referenced emulation. - */ - npte &= ~L2_S_REF; - } - } - - if (prot & VM_PROT_WRITE) { - if ((m->oflags & VPO_UNMANAGED) == 0) { - vm_page_aflag_set(m, PGA_WRITEABLE); - /* - * XXX: Skip modified bit emulation for now. - * The emulation reveals problems - * that result in random failures - * during memory allocation on some - * platforms. - * Therefore, the page is marked RW - * immediately. - */ - npte &= ~(L2_APX); - vm_page_dirty(m); - } else - npte &= ~(L2_APX); - } - if (!(prot & VM_PROT_EXECUTE)) - npte |= L2_XN; - - if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE) - npte |= pte_l2_s_cache_mode; - } - - CTR5(KTR_PMAP,"enter: pmap:%p va:%x prot:%x pte:%x->%x", - pmap, va, prot, opte, npte); - /* - * If this is just a wiring change, the two PTEs will be - * identical, so there's no need to update the page table. - */ - if (npte != opte) { - boolean_t is_cached = pmap_is_current(pmap); - - *ptep = npte; - PTE_SYNC(ptep); - if (is_cached) { - /* - * We only need to frob the cache/tlb if this pmap - * is current - */ - if (L1_IDX(va) != L1_IDX(vector_page) && - l2pte_valid(npte)) { - /* - * This mapping is likely to be accessed as - * soon as we return to userland. Fix up the - * L1 entry to avoid taking another - * page/domain fault. - */ - l1pd = l2b->l2b_phys | - L1_C_DOM(pmap->pm_domain) | L1_C_PROTO; - if (*pl1pd != l1pd) { - *pl1pd = l1pd; - PTE_SYNC(pl1pd); - } - } - } - - if (is_exec) - cpu_tlb_flushID_SE(va); - else if (is_refd) - cpu_tlb_flushD_SE(va); - cpu_cpwait(); - } - - if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap)) - cpu_icache_sync_range(va, PAGE_SIZE); - return (KERN_SUCCESS); -} - -/* - * Maps a sequence of resident pages belonging to the same object. - * The sequence begins with the given page m_start. This page is - * mapped at the given virtual address start. Each subsequent page is - * mapped at a virtual address that is offset from start by the same - * amount as the page is offset from m_start within the object. The - * last page in the sequence is the page with the largest offset from - * m_start that can be mapped at a virtual address less than the given - * virtual address end. Not every virtual page between start and end - * is mapped; only those for which a resident page exists with the - * corresponding offset from m_start are mapped. - */ -void -pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end, - vm_page_t m_start, vm_prot_t prot) -{ - vm_offset_t va; - vm_page_t m; - vm_pindex_t diff, psize; - - VM_OBJECT_ASSERT_LOCKED(m_start->object); - - psize = atop(end - start); - m = m_start; - prot &= VM_PROT_READ | VM_PROT_EXECUTE; - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { - va = start + ptoa(diff); - if ((va & L1_S_OFFSET) == 0 && L2_NEXT_BUCKET(va) <= end && - m->psind == 1 && sp_enabled && - pmap_enter_section(pmap, va, m, prot)) - m = &m[L1_S_SIZE / PAGE_SIZE - 1]; - else - pmap_enter_locked(pmap, va, m, prot, - PMAP_ENTER_NOSLEEP); - m = TAILQ_NEXT(m, listq); - } - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); -} - -/* - * this code makes some *MAJOR* assumptions: - * 1. Current pmap & pmap exists. - * 2. Not wired. - * 3. Read access. - * 4. No page table pages. - * but is *MUCH* faster than pmap_enter... - */ - -void -pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) -{ - - prot &= VM_PROT_READ | VM_PROT_EXECUTE; - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - pmap_enter_locked(pmap, va, m, prot, PMAP_ENTER_NOSLEEP); - PMAP_UNLOCK(pmap); - rw_wunlock(&pvh_global_lock); -} - -/* - * Clear the wired attribute from the mappings for the specified range of - * addresses in the given pmap. Every valid mapping within that range - * must have the wired attribute set. In contrast, invalid mappings - * cannot have the wired attribute set, so they are ignored. - * - * XXX Wired mappings of unmanaged pages cannot be counted by this pmap - * implementation. - */ -void -pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) -{ - struct l2_bucket *l2b; - struct md_page *pvh; - pd_entry_t l1pd; - pt_entry_t *ptep, pte; - pv_entry_t pv; - vm_offset_t next_bucket; - vm_paddr_t pa; - vm_page_t m; - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - while (sva < eva) { - next_bucket = L2_NEXT_BUCKET(sva); - l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)]; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - pa = l1pd & L1_S_FRAME; - m = PHYS_TO_VM_PAGE(pa); - KASSERT(m != NULL && (m->oflags & VPO_UNMANAGED) == 0, - ("pmap_unwire: unmanaged 1mpage %p", m)); - pvh = pa_to_pvh(pa); - pv = pmap_find_pv(pvh, pmap, trunc_1mpage(sva)); - if ((pv->pv_flags & PVF_WIRED) == 0) - panic("pmap_unwire: pv %p isn't wired", pv); - - /* - * Are we unwiring the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + L1_S_SIZE == next_bucket && - eva >= next_bucket) { - pv->pv_flags &= ~PVF_WIRED; - pmap->pm_stats.wired_count -= L2_PTE_NUM_TOTAL; - sva = next_bucket; - continue; - } else if (!pmap_demote_section(pmap, sva)) - panic("pmap_unwire: demotion failed"); - } - if (next_bucket > eva) - next_bucket = eva; - l2b = pmap_get_l2_bucket(pmap, sva); - if (l2b == NULL) { - sva = next_bucket; - continue; - } - for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket; - sva += PAGE_SIZE, ptep++) { - if ((pte = *ptep) == 0 || - (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL || - (m->oflags & VPO_UNMANAGED) != 0) - continue; - pv = pmap_find_pv(&m->md, pmap, sva); - if ((pv->pv_flags & PVF_WIRED) == 0) - panic("pmap_unwire: pv %p isn't wired", pv); - pv->pv_flags &= ~PVF_WIRED; - pmap->pm_stats.wired_count--; - } - } - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); -} - - -/* - * Copy the range specified by src_addr/len - * from the source map to the range dst_addr/len - * in the destination map. - * - * This routine is only advisory and need not do anything. - */ -void -pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, - vm_size_t len, vm_offset_t src_addr) -{ -} - - -/* - * Routine: pmap_extract - * Function: - * Extract the physical page address associated - * with the given map/virtual_address pair. - */ -vm_paddr_t -pmap_extract(pmap_t pmap, vm_offset_t va) -{ - vm_paddr_t pa; - - PMAP_LOCK(pmap); - pa = pmap_extract_locked(pmap, va); - PMAP_UNLOCK(pmap); - return (pa); -} - -static vm_paddr_t -pmap_extract_locked(pmap_t pmap, vm_offset_t va) -{ - struct l2_dtable *l2; - pd_entry_t l1pd; - pt_entry_t *ptep, pte; - vm_paddr_t pa; - u_int l1idx; - - if (kernel_vm_end != 0 && pmap != kernel_pmap) - PMAP_ASSERT_LOCKED(pmap); - l1idx = L1_IDX(va); - l1pd = pmap->pm_l1->l1_kva[l1idx]; - if (l1pte_section_p(l1pd)) { - /* XXX: what to do about the bits > 32 ? */ - if (l1pd & L1_S_SUPERSEC) - pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); - else - pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); - } else { - /* - * Note that we can't rely on the validity of the L1 - * descriptor as an indication that a mapping exists. - * We have to look it up in the L2 dtable. - */ - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - if (l2 == NULL || - (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) - return (0); - pte = ptep[l2pte_index(va)]; - if (pte == 0) - return (0); - if ((pte & L2_TYPE_MASK) == L2_TYPE_L) - pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET); - else - pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); - } - return (pa); -} - -/* - * Atomically extract and hold the physical page with the given - * pmap and virtual address pair if that mapping permits the given - * protection. - * - */ -vm_page_t -pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) -{ - struct l2_dtable *l2; - pd_entry_t l1pd; - pt_entry_t *ptep, pte; - vm_paddr_t pa, paddr; - vm_page_t m = NULL; - u_int l1idx; - l1idx = L1_IDX(va); - paddr = 0; - - PMAP_LOCK(pmap); -retry: - l1pd = pmap->pm_l1->l1_kva[l1idx]; - if (l1pte_section_p(l1pd)) { - /* XXX: what to do about the bits > 32 ? */ - if (l1pd & L1_S_SUPERSEC) - pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); - else - pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); - if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr)) - goto retry; - if (L1_S_WRITABLE(l1pd) || (prot & VM_PROT_WRITE) == 0) { - m = PHYS_TO_VM_PAGE(pa); - vm_page_hold(m); - } - } else { - /* - * Note that we can't rely on the validity of the L1 - * descriptor as an indication that a mapping exists. - * We have to look it up in the L2 dtable. - */ - l2 = pmap->pm_l2[L2_IDX(l1idx)]; - - if (l2 == NULL || - (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { - PMAP_UNLOCK(pmap); - return (NULL); - } - - ptep = &ptep[l2pte_index(va)]; - pte = *ptep; - - if (pte == 0) { - PMAP_UNLOCK(pmap); - return (NULL); - } else if ((prot & VM_PROT_WRITE) && (pte & L2_APX)) { - PMAP_UNLOCK(pmap); - return (NULL); - } else { - if ((pte & L2_TYPE_MASK) == L2_TYPE_L) - panic("extract and hold section mapping"); - else - pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); - if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr)) - goto retry; - m = PHYS_TO_VM_PAGE(pa); - vm_page_hold(m); - } - } - - PMAP_UNLOCK(pmap); - PA_UNLOCK_COND(paddr); - return (m); -} - -vm_paddr_t -pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) -{ - struct l2_dtable *l2; - pd_entry_t l1pd; - pt_entry_t *ptep, pte; - vm_paddr_t pa; - u_int l1idx; - - l1idx = L1_IDX(va); - l1pd = kernel_pmap->pm_l1->l1_kva[l1idx]; - if (l1pte_section_p(l1pd)) { - if (l1pd & L1_S_SUPERSEC) - pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); - else - pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); - pte = L2_S_PROTO | pa | - L2_S_PROT(PTE_KERNEL, VM_PROT_READ | VM_PROT_WRITE); - } else { - l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]; - if (l2 == NULL || - (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { - pte = 0; - pa = 0; - goto out; - } - pte = ptep[l2pte_index(va)]; - if (pte == 0) { - pa = 0; - goto out; - } - if ((pte & L2_TYPE_MASK) == L2_TYPE_L) - pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET); - else - pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); - } -out: - if (pte2p != NULL) - *pte2p = pte; - return (pa); -} - -/* - * Initialize a preallocated and zeroed pmap structure, - * such as one in a vmspace structure. - */ - -int -pmap_pinit(pmap_t pmap) -{ - PDEBUG(1, printf("pmap_pinit: pmap = %08x\n", (uint32_t) pmap)); - - pmap_alloc_l1(pmap); - bzero(pmap->pm_l2, sizeof(pmap->pm_l2)); - - CPU_ZERO(&pmap->pm_active); - - TAILQ_INIT(&pmap->pm_pvchunk); - bzero(&pmap->pm_stats, sizeof pmap->pm_stats); - pmap->pm_stats.resident_count = 1; - if (vector_page < KERNBASE) { - pmap_enter(pmap, vector_page, - PHYS_TO_VM_PAGE(systempage.pv_pa), VM_PROT_READ, - PMAP_ENTER_WIRED, 0); - } - return (1); -} - - -/*************************************************** - * Superpage management routines. - ***************************************************/ - -static PMAP_INLINE struct pv_entry * -pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) -{ - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - - pv = pmap_find_pv(pvh, pmap, va); - if (pv != NULL) - TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); - - return (pv); -} - -static void -pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va) -{ - pv_entry_t pv; - - pv = pmap_pvh_remove(pvh, pmap, va); - KASSERT(pv != NULL, ("pmap_pvh_free: pv not found")); - pmap_free_pv_entry(pmap, pv); -} - -static boolean_t -pmap_pv_insert_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) -{ - struct md_page *pvh; - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - if (pv_entry_count < pv_entry_high_water && - (pv = pmap_get_pv_entry(pmap, TRUE)) != NULL) { - pv->pv_va = va; - pvh = pa_to_pvh(pa); - TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); - return (TRUE); - } else - return (FALSE); -} - -/* - * Create the pv entries for each of the pages within a superpage. - */ -static void -pmap_pv_demote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) -{ - struct md_page *pvh; - pv_entry_t pve, pv; - vm_offset_t va_last; - vm_page_t m; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - KASSERT((pa & L1_S_OFFSET) == 0, - ("pmap_pv_demote_section: pa is not 1mpage aligned")); - - /* - * Transfer the 1mpage's pv entry for this mapping to the first - * page's pv list. - */ - pvh = pa_to_pvh(pa); - va = trunc_1mpage(va); - pv = pmap_pvh_remove(pvh, pmap, va); - KASSERT(pv != NULL, ("pmap_pv_demote_section: pv not found")); - m = PHYS_TO_VM_PAGE(pa); - TAILQ_INSERT_HEAD(&m->md.pv_list, pv, pv_list); - /* Instantiate the remaining pv entries. */ - va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE; - do { - m++; - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_pv_demote_section: page %p is not managed", m)); - va += PAGE_SIZE; - pve = pmap_get_pv_entry(pmap, FALSE); - pmap_enter_pv(m, pve, pmap, va, pv->pv_flags); - } while (va < va_last); -} - -static void -pmap_pv_promote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) -{ - struct md_page *pvh; - pv_entry_t pv; - vm_offset_t va_last; - vm_page_t m; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - KASSERT((pa & L1_S_OFFSET) == 0, - ("pmap_pv_promote_section: pa is not 1mpage aligned")); - - /* - * Transfer the first page's pv entry for this mapping to the - * 1mpage's pv list. Aside from avoiding the cost of a call - * to get_pv_entry(), a transfer avoids the possibility that - * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim() - * removes one of the mappings that is being promoted. - */ - m = PHYS_TO_VM_PAGE(pa); - va = trunc_1mpage(va); - pv = pmap_pvh_remove(&m->md, pmap, va); - KASSERT(pv != NULL, ("pmap_pv_promote_section: pv not found")); - pvh = pa_to_pvh(pa); - TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); - /* Free the remaining pv entries in the newly mapped section pages */ - va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE; - do { - m++; - va += PAGE_SIZE; - /* - * Don't care the flags, first pv contains sufficient - * information for all of the pages so nothing is really lost. - */ - pmap_pvh_free(&m->md, pmap, va); - } while (va < va_last); -} - -/* - * Tries to create a 1MB page mapping. Returns TRUE if successful and - * FALSE otherwise. Fails if (1) page is unmanageg, kernel pmap or vectors - * page, (2) a mapping already exists at the specified virtual address, or - * (3) a pv entry cannot be allocated without reclaiming another pv entry. - */ -static boolean_t -pmap_enter_section(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) -{ - pd_entry_t *pl1pd; - vm_offset_t pa; - struct l2_bucket *l2b; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); - - /* Skip kernel, vectors page and unmanaged mappings */ - if ((pmap == pmap_kernel()) || (L1_IDX(va) == L1_IDX(vector_page)) || - ((m->oflags & VPO_UNMANAGED) != 0)) { - CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx" - " in pmap %p", va, pmap); - return (FALSE); - } - /* - * Check whether this is a valid section superpage entry or - * there is a l2_bucket associated with that L1 page directory. - */ - va = trunc_1mpage(va); - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - l2b = pmap_get_l2_bucket(pmap, va); - if ((*pl1pd & L1_S_PROTO) || (l2b != NULL)) { - CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx" - " in pmap %p", va, pmap); - return (FALSE); - } - pa = VM_PAGE_TO_PHYS(m); - /* - * Abort this mapping if its PV entry could not be created. - */ - if (!pmap_pv_insert_section(pmap, va, VM_PAGE_TO_PHYS(m))) { - CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx" - " in pmap %p", va, pmap); - return (FALSE); - } - /* - * Increment counters. - */ - pmap->pm_stats.resident_count += L2_PTE_NUM_TOTAL; - /* - * Despite permissions, mark the superpage read-only. - */ - prot &= ~VM_PROT_WRITE; - /* - * Map the superpage. - */ - pmap_map_section(pmap, va, pa, prot, FALSE); - - pmap_section_mappings++; - CTR2(KTR_PMAP, "pmap_enter_section: success for va %#lx" - " in pmap %p", va, pmap); - return (TRUE); -} - -/* - * pmap_remove_section: do the things to unmap a superpage in a process - */ -static void -pmap_remove_section(pmap_t pmap, vm_offset_t sva) -{ - struct md_page *pvh; - struct l2_bucket *l2b; - pd_entry_t *pl1pd, l1pd; - vm_offset_t eva, va; - vm_page_t m; - - PMAP_ASSERT_LOCKED(pmap); - if ((pmap == pmap_kernel()) || (L1_IDX(sva) == L1_IDX(vector_page))) - return; - - KASSERT((sva & L1_S_OFFSET) == 0, - ("pmap_remove_section: sva is not 1mpage aligned")); - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)]; - l1pd = *pl1pd; - - m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME); - KASSERT((m != NULL && ((m->oflags & VPO_UNMANAGED) == 0)), - ("pmap_remove_section: no corresponding vm_page or " - "page unmanaged")); - - pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL; - pvh = pa_to_pvh(l1pd & L1_S_FRAME); - pmap_pvh_free(pvh, pmap, sva); - eva = L2_NEXT_BUCKET(sva); - for (va = sva, m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME); - va < eva; va += PAGE_SIZE, m++) { - /* - * Mark base pages referenced but skip marking them dirty. - * If the superpage is writeable, hence all base pages were - * already marked as dirty in pmap_fault_fixup() before - * promotion. Reference bit however, might not have been set - * for each base page when the superpage was created at once, - * not as a result of promotion. - */ - if (L1_S_REFERENCED(l1pd)) - vm_page_aflag_set(m, PGA_REFERENCED); - if (TAILQ_EMPTY(&m->md.pv_list) && - TAILQ_EMPTY(&pvh->pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - } - - l2b = pmap_get_l2_bucket(pmap, sva); - if (l2b != NULL) { - KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL, - ("pmap_remove_section: l2_bucket occupancy error")); - pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL); - } - /* Now invalidate L1 slot */ - *pl1pd = 0; - PTE_SYNC(pl1pd); - if (L1_S_EXECUTABLE(l1pd)) - cpu_tlb_flushID_SE(sva); - else - cpu_tlb_flushD_SE(sva); - cpu_cpwait(); -} - -/* - * Tries to promote the 256, contiguous 4KB page mappings that are - * within a single l2_bucket to a single 1MB section mapping. - * For promotion to occur, two conditions must be met: (1) the 4KB page - * mappings must map aligned, contiguous physical memory and (2) the 4KB page - * mappings must have identical characteristics. - */ -static void -pmap_promote_section(pmap_t pmap, vm_offset_t va) -{ - pt_entry_t *firstptep, firstpte, oldpte, pa, *pte; - vm_page_t m, oldm; - vm_offset_t first_va, old_va; - struct l2_bucket *l2b = NULL; - vm_prot_t prot; - struct pv_entry *pve, *first_pve; - - PMAP_ASSERT_LOCKED(pmap); - - prot = VM_PROT_ALL; - /* - * Skip promoting kernel pages. This is justified by following: - * 1. Kernel is already mapped using section mappings in each pmap - * 2. Managed mappings within the kernel are not to be promoted anyway - */ - if (pmap == pmap_kernel()) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x" - " in pmap %p", va, pmap); - return; - } - /* Do not attemp to promote vectors pages */ - if (L1_IDX(va) == L1_IDX(vector_page)) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x" - " in pmap %p", va, pmap); - return; - } - /* - * Examine the first PTE in the specified l2_bucket. Abort if this PTE - * is either invalid, unused, or does not map the first 4KB physical - * page within 1MB page. - */ - first_va = trunc_1mpage(va); - l2b = pmap_get_l2_bucket(pmap, first_va); - KASSERT(l2b != NULL, ("pmap_promote_section: trying to promote " - "not existing l2 bucket")); - firstptep = &l2b->l2b_kva[0]; - - firstpte = *firstptep; - if ((l2pte_pa(firstpte) & L1_S_OFFSET) != 0) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x" - " in pmap %p", va, pmap); - return; - } - - if ((firstpte & (L2_S_PROTO | L2_S_REF)) != (L2_S_PROTO | L2_S_REF)) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x" - " in pmap %p", va, pmap); - return; - } - /* - * ARM uses pv_entry to mark particular mapping WIRED so don't promote - * unmanaged pages since it is impossible to determine, whether the - * page is wired or not if there is no corresponding pv_entry. - */ - m = PHYS_TO_VM_PAGE(l2pte_pa(firstpte)); - if (m && ((m->oflags & VPO_UNMANAGED) != 0)) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x" - " in pmap %p", va, pmap); - return; - } - first_pve = pmap_find_pv(&m->md, pmap, first_va); - /* - * PTE is modified only on write due to modified bit - * emulation. If the entry is referenced and writable - * then it is modified and we don't clear write enable. - * Otherwise, writing is disabled in PTE anyway and - * we just configure protections for the section mapping - * that is going to be created. - */ - if ((first_pve->pv_flags & PVF_WRITE) != 0) { - if (!L2_S_WRITABLE(firstpte)) { - first_pve->pv_flags &= ~PVF_WRITE; - prot &= ~VM_PROT_WRITE; - } - } else - prot &= ~VM_PROT_WRITE; - - if (!L2_S_EXECUTABLE(firstpte)) - prot &= ~VM_PROT_EXECUTE; - - /* - * Examine each of the other PTEs in the specified l2_bucket. - * Abort if this PTE maps an unexpected 4KB physical page or - * does not have identical characteristics to the first PTE. - */ - pa = l2pte_pa(firstpte) + ((L2_PTE_NUM_TOTAL - 1) * PAGE_SIZE); - old_va = L2_NEXT_BUCKET(first_va) - PAGE_SIZE; - - for (pte = (firstptep + L2_PTE_NUM_TOTAL - 1); pte > firstptep; pte--) { - oldpte = *pte; - if (l2pte_pa(oldpte) != pa) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for " - "va %#x in pmap %p", va, pmap); - return; - } - if ((oldpte & L2_S_PROMOTE) != (firstpte & L2_S_PROMOTE)) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for " - "va %#x in pmap %p", va, pmap); - return; - } - oldm = PHYS_TO_VM_PAGE(l2pte_pa(oldpte)); - if (oldm && ((oldm->oflags & VPO_UNMANAGED) != 0)) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for " - "va %#x in pmap %p", va, pmap); - return; - } - - pve = pmap_find_pv(&oldm->md, pmap, old_va); - if (pve == NULL) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for " - "va %#x old_va %x - no pve", va, old_va); - return; - } - - if (!L2_S_WRITABLE(oldpte) && (pve->pv_flags & PVF_WRITE)) - pve->pv_flags &= ~PVF_WRITE; - if (pve->pv_flags != first_pve->pv_flags) { - pmap_section_p_failures++; - CTR2(KTR_PMAP, "pmap_promote_section: failure for " - "va %#x in pmap %p", va, pmap); - return; - } - - old_va -= PAGE_SIZE; - pa -= PAGE_SIZE; - } - /* - * Promote the pv entries. - */ - pmap_pv_promote_section(pmap, first_va, l2pte_pa(firstpte)); - /* - * Map the superpage. - */ - pmap_map_section(pmap, first_va, l2pte_pa(firstpte), prot, TRUE); - /* - * Invalidate all possible TLB mappings for small - * pages within the newly created superpage. - * Rely on the first PTE's attributes since they - * have to be consistent across all of the base pages - * within the superpage. If page is not executable it - * is at least referenced. - * The fastest way to do that is to invalidate whole - * TLB at once instead of executing 256 CP15 TLB - * invalidations by single entry. TLBs usually maintain - * several dozen entries so loss of unrelated entries is - * still a less agresive approach. - */ - if (L2_S_EXECUTABLE(firstpte)) - cpu_tlb_flushID(); - else - cpu_tlb_flushD(); - cpu_cpwait(); - - pmap_section_promotions++; - CTR2(KTR_PMAP, "pmap_promote_section: success for va %#x" - " in pmap %p", first_va, pmap); -} - -/* - * Fills a l2_bucket with mappings to consecutive physical pages. - */ -static void -pmap_fill_l2b(struct l2_bucket *l2b, pt_entry_t newpte) -{ - pt_entry_t *ptep; - int i; - - for (i = 0; i < L2_PTE_NUM_TOTAL; i++) { - ptep = &l2b->l2b_kva[i]; - *ptep = newpte; - PTE_SYNC(ptep); - - newpte += PAGE_SIZE; - } - - l2b->l2b_occupancy = L2_PTE_NUM_TOTAL; -} - -/* - * Tries to demote a 1MB section mapping. If demotion fails, the - * 1MB section mapping is invalidated. - */ -static boolean_t -pmap_demote_section(pmap_t pmap, vm_offset_t va) -{ - struct l2_bucket *l2b; - struct pv_entry *l1pdpve; - struct md_page *pvh; - pd_entry_t *pl1pd, l1pd, newl1pd; - pt_entry_t *firstptep, newpte; - vm_offset_t pa; - vm_page_t m; - - PMAP_ASSERT_LOCKED(pmap); - /* - * According to assumptions described in pmap_promote_section, - * kernel is and always should be mapped using 1MB section mappings. - * What more, managed kernel pages were not to be promoted. - */ - KASSERT(pmap != pmap_kernel() && L1_IDX(va) != L1_IDX(vector_page), - ("pmap_demote_section: forbidden section mapping")); - - va = trunc_1mpage(va); - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - l1pd = *pl1pd; - KASSERT((l1pd & L1_TYPE_MASK) == L1_S_PROTO, - ("pmap_demote_section: not section or invalid section")); - - pa = l1pd & L1_S_FRAME; - m = PHYS_TO_VM_PAGE(pa); - KASSERT((m != NULL && (m->oflags & VPO_UNMANAGED) == 0), - ("pmap_demote_section: no vm_page for selected superpage or" - "unmanaged")); - - pvh = pa_to_pvh(pa); - l1pdpve = pmap_find_pv(pvh, pmap, va); - KASSERT(l1pdpve != NULL, ("pmap_demote_section: no pv entry for " - "managed page")); - - l2b = pmap_get_l2_bucket(pmap, va); - if (l2b == NULL) { - KASSERT((l1pdpve->pv_flags & PVF_WIRED) == 0, - ("pmap_demote_section: No l2_bucket for wired mapping")); - /* - * Invalidate the 1MB section mapping and return - * "failure" if the mapping was never accessed or the - * allocation of the new l2_bucket fails. - */ - if (!L1_S_REFERENCED(l1pd) || - (l2b = pmap_alloc_l2_bucket(pmap, va)) == NULL) { - /* Unmap and invalidate superpage. */ - pmap_remove_section(pmap, trunc_1mpage(va)); - CTR2(KTR_PMAP, "pmap_demote_section: failure for " - "va %#x in pmap %p", va, pmap); - return (FALSE); - } - } - - /* - * Now we should have corresponding l2_bucket available. - * Let's process it to recreate 256 PTEs for each base page - * within superpage. - */ - newpte = pa | L1_S_DEMOTE(l1pd); - if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE) - newpte |= pte_l2_s_cache_mode; - - /* - * If the l2_bucket is new, initialize it. - */ - if (l2b->l2b_occupancy == 0) - pmap_fill_l2b(l2b, newpte); - else { - firstptep = &l2b->l2b_kva[0]; - KASSERT(l2pte_pa(*firstptep) == (pa), - ("pmap_demote_section: firstpte and newpte map different " - "physical addresses")); - /* - * If the mapping has changed attributes, update the page table - * entries. - */ - if ((*firstptep & L2_S_PROMOTE) != (L1_S_DEMOTE(l1pd))) - pmap_fill_l2b(l2b, newpte); - } - /* Demote PV entry */ - pmap_pv_demote_section(pmap, va, pa); - - /* Now fix-up L1 */ - newl1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO; - *pl1pd = newl1pd; - PTE_SYNC(pl1pd); - /* Invalidate old TLB mapping */ - if (L1_S_EXECUTABLE(l1pd)) - cpu_tlb_flushID_SE(va); - else if (L1_S_REFERENCED(l1pd)) - cpu_tlb_flushD_SE(va); - cpu_cpwait(); - - pmap_section_demotions++; - CTR2(KTR_PMAP, "pmap_demote_section: success for va %#x" - " in pmap %p", va, pmap); - return (TRUE); -} - -/*************************************************** - * page management routines. - ***************************************************/ - -/* - * We are in a serious low memory condition. Resort to - * drastic measures to free some pages so we can allocate - * another pv entry chunk. - */ -static vm_page_t -pmap_pv_reclaim(pmap_t locked_pmap) -{ - struct pch newtail; - struct pv_chunk *pc; - struct l2_bucket *l2b = NULL; - pmap_t pmap; - pd_entry_t *pl1pd; - pt_entry_t *ptep; - pv_entry_t pv; - vm_offset_t va; - vm_page_t free, m, m_pc; - uint32_t inuse; - int bit, field, freed, idx; - - PMAP_ASSERT_LOCKED(locked_pmap); - pmap = NULL; - free = m_pc = NULL; - TAILQ_INIT(&newtail); - while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 || - free == NULL)) { - TAILQ_REMOVE(&pv_chunks, pc, pc_lru); - if (pmap != pc->pc_pmap) { - if (pmap != NULL) { - cpu_tlb_flushID(); - cpu_cpwait(); - if (pmap != locked_pmap) - PMAP_UNLOCK(pmap); - } - pmap = pc->pc_pmap; - /* Avoid deadlock and lock recursion. */ - if (pmap > locked_pmap) - PMAP_LOCK(pmap); - else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) { - pmap = NULL; - TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); - continue; - } - } - - /* - * Destroy every non-wired, 4 KB page mapping in the chunk. - */ - freed = 0; - for (field = 0; field < _NPCM; field++) { - for (inuse = ~pc->pc_map[field] & pc_freemask[field]; - inuse != 0; inuse &= ~(1UL << bit)) { - bit = ffs(inuse) - 1; - idx = field * sizeof(inuse) * NBBY + bit; - pv = &pc->pc_pventry[idx]; - va = pv->pv_va; - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) - continue; - if (pv->pv_flags & PVF_WIRED) - continue; - - l2b = pmap_get_l2_bucket(pmap, va); - KASSERT(l2b != NULL, ("No l2 bucket")); - ptep = &l2b->l2b_kva[l2pte_index(va)]; - m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep)); - KASSERT((vm_offset_t)m >= KERNBASE, - ("Trying to access non-existent page " - "va %x pte %x", va, *ptep)); - *ptep = 0; - PTE_SYNC(ptep); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - pc->pc_map[field] |= 1UL << bit; - freed++; - } - } - - if (freed == 0) { - TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); - continue; - } - /* Every freed mapping is for a 4 KB page. */ - pmap->pm_stats.resident_count -= freed; - PV_STAT(pv_entry_frees += freed); - PV_STAT(pv_entry_spare += freed); - pv_entry_count -= freed; - TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); - for (field = 0; field < _NPCM; field++) - if (pc->pc_map[field] != pc_freemask[field]) { - TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, - pc_list); - TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); - - /* - * One freed pv entry in locked_pmap is - * sufficient. - */ - if (pmap == locked_pmap) - goto out; - break; - } - if (field == _NPCM) { - PV_STAT(pv_entry_spare -= _NPCPV); - PV_STAT(pc_chunk_count--); - PV_STAT(pc_chunk_frees++); - /* Entire chunk is free; return it. */ - m_pc = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc)); - pmap_qremove((vm_offset_t)pc, 1); - pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc); - break; - } - } -out: - TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru); - if (pmap != NULL) { - cpu_tlb_flushID(); - cpu_cpwait(); - if (pmap != locked_pmap) - PMAP_UNLOCK(pmap); - } - return (m_pc); -} - -/* - * free the pv_entry back to the free list - */ -static void -pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv) -{ - struct pv_chunk *pc; - int bit, field, idx; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); - PV_STAT(pv_entry_frees++); - PV_STAT(pv_entry_spare++); - pv_entry_count--; - pc = pv_to_chunk(pv); - idx = pv - &pc->pc_pventry[0]; - field = idx / (sizeof(u_long) * NBBY); - bit = idx % (sizeof(u_long) * NBBY); - pc->pc_map[field] |= 1ul << bit; - for (idx = 0; idx < _NPCM; idx++) - if (pc->pc_map[idx] != pc_freemask[idx]) { - /* - * 98% of the time, pc is already at the head of the - * list. If it isn't already, move it to the head. - */ - if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) != - pc)) { - TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); - TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, - pc_list); - } - return; - } - TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); - pmap_free_pv_chunk(pc); -} - -static void -pmap_free_pv_chunk(struct pv_chunk *pc) -{ - vm_page_t m; - - TAILQ_REMOVE(&pv_chunks, pc, pc_lru); - PV_STAT(pv_entry_spare -= _NPCPV); - PV_STAT(pc_chunk_count--); - PV_STAT(pc_chunk_frees++); - /* entire chunk is free, return it */ - m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc)); - pmap_qremove((vm_offset_t)pc, 1); - vm_page_unwire(m, PQ_NONE); - vm_page_free(m); - pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc); - -} - -static pv_entry_t -pmap_get_pv_entry(pmap_t pmap, boolean_t try) -{ - static const struct timeval printinterval = { 60, 0 }; - static struct timeval lastprint; - struct pv_chunk *pc; - pv_entry_t pv; - vm_page_t m; - int bit, field, idx; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); - PV_STAT(pv_entry_allocs++); - pv_entry_count++; - - if (pv_entry_count > pv_entry_high_water) - if (ratecheck(&lastprint, &printinterval)) - printf("%s: Approaching the limit on PV entries.\n", - __func__); -retry: - pc = TAILQ_FIRST(&pmap->pm_pvchunk); - if (pc != NULL) { - for (field = 0; field < _NPCM; field++) { - if (pc->pc_map[field]) { - bit = ffs(pc->pc_map[field]) - 1; - break; - } - } - if (field < _NPCM) { - idx = field * sizeof(pc->pc_map[field]) * NBBY + bit; - pv = &pc->pc_pventry[idx]; - pc->pc_map[field] &= ~(1ul << bit); - /* If this was the last item, move it to tail */ - for (field = 0; field < _NPCM; field++) - if (pc->pc_map[field] != 0) { - PV_STAT(pv_entry_spare--); - return (pv); /* not full, return */ - } - TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); - TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list); - PV_STAT(pv_entry_spare--); - return (pv); - } - } - /* - * Access to the ptelist "pv_vafree" is synchronized by the pvh - * global lock. If "pv_vafree" is currently non-empty, it will - * remain non-empty until pmap_ptelist_alloc() completes. - */ - if (pv_vafree == 0 || (m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | - VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) { - if (try) { - pv_entry_count--; - PV_STAT(pc_chunk_tryfail++); - return (NULL); - } - m = pmap_pv_reclaim(pmap); - if (m == NULL) - goto retry; - } - PV_STAT(pc_chunk_count++); - PV_STAT(pc_chunk_allocs++); - pc = (struct pv_chunk *)pmap_ptelist_alloc(&pv_vafree); - pmap_qenter((vm_offset_t)pc, &m, 1); - pc->pc_pmap = pmap; - pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */ - for (field = 1; field < _NPCM; field++) - pc->pc_map[field] = pc_freemask[field]; - TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru); - pv = &pc->pc_pventry[0]; - TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list); - PV_STAT(pv_entry_spare += _NPCPV - 1); - return (pv); -} - -/* - * Remove the given range of addresses from the specified map. - * - * It is assumed that the start and end are properly - * rounded to the page size. - */ -#define PMAP_REMOVE_CLEAN_LIST_SIZE 3 -void -pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) -{ - struct l2_bucket *l2b; - vm_offset_t next_bucket; - pd_entry_t l1pd; - pt_entry_t *ptep; - u_int total; - u_int mappings, is_exec, is_refd; - int flushall = 0; - - - /* - * we lock in the pmap => pv_head direction - */ - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - total = 0; - while (sva < eva) { - next_bucket = L2_NEXT_BUCKET(sva); - - /* - * Check for large page. - */ - l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)]; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - KASSERT((l1pd & L1_S_DOM_MASK) != - L1_S_DOM(PMAP_DOMAIN_KERNEL), ("pmap_remove: " - "Trying to remove kernel section mapping")); - /* - * Are we removing the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + L1_S_SIZE == next_bucket && - eva >= next_bucket) { - pmap_remove_section(pmap, sva); - sva = next_bucket; - continue; - } else if (!pmap_demote_section(pmap, sva)) { - /* The large page mapping was destroyed. */ - sva = next_bucket; - continue; - } - } - /* - * Do one L2 bucket's worth at a time. - */ - if (next_bucket > eva) - next_bucket = eva; - - l2b = pmap_get_l2_bucket(pmap, sva); - if (l2b == NULL) { - sva = next_bucket; - continue; - } - - ptep = &l2b->l2b_kva[l2pte_index(sva)]; - mappings = 0; - - while (sva < next_bucket) { - struct vm_page *m; - pt_entry_t pte; - vm_paddr_t pa; - - pte = *ptep; - - if (pte == 0) { - /* - * Nothing here, move along - */ - sva += PAGE_SIZE; - ptep++; - continue; - } - - pmap->pm_stats.resident_count--; - pa = l2pte_pa(pte); - is_exec = 0; - is_refd = 1; - - /* - * Update flags. In a number of circumstances, - * we could cluster a lot of these and do a - * number of sequential pages in one go. - */ - if ((m = PHYS_TO_VM_PAGE(pa)) != NULL) { - struct pv_entry *pve; - - pve = pmap_remove_pv(m, pmap, sva); - if (pve) { - is_exec = PTE_BEEN_EXECD(pte); - is_refd = PTE_BEEN_REFD(pte); - pmap_free_pv_entry(pmap, pve); - } - } - - *ptep = 0; - PTE_SYNC(ptep); - if (pmap_is_current(pmap)) { - total++; - if (total < PMAP_REMOVE_CLEAN_LIST_SIZE) { - if (is_exec) - cpu_tlb_flushID_SE(sva); - else if (is_refd) - cpu_tlb_flushD_SE(sva); - } else if (total == PMAP_REMOVE_CLEAN_LIST_SIZE) - flushall = 1; - } - - sva += PAGE_SIZE; - ptep++; - mappings++; - } - - pmap_free_l2_bucket(pmap, l2b, mappings); - } - - rw_wunlock(&pvh_global_lock); - if (flushall) - cpu_tlb_flushID(); - cpu_cpwait(); - - PMAP_UNLOCK(pmap); -} - -/* - * pmap_zero_page() - * - * Zero a given physical page by mapping it at a page hook point. - * In doing the zero page op, the page we zero is mapped cachable, as with - * StrongARM accesses to non-cached pages are non-burst making writing - * _any_ bulk data very slow. - */ -static void -pmap_zero_page_gen(vm_page_t m, int off, int size) -{ - struct czpages *czp; - - KASSERT(TAILQ_EMPTY(&m->md.pv_list), - ("pmap_zero_page_gen: page has mappings")); - - vm_paddr_t phys = VM_PAGE_TO_PHYS(m); - - sched_pin(); - czp = &cpu_czpages[PCPU_GET(cpuid)]; - mtx_lock(&czp->lock); - - /* - * Hook in the page, zero it. - */ - *czp->dstptep = L2_S_PROTO | phys | pte_l2_s_cache_mode | L2_S_REF; - pmap_set_prot(czp->dstptep, VM_PROT_WRITE, 0); - PTE_SYNC(czp->dstptep); - cpu_tlb_flushD_SE(czp->dstva); - cpu_cpwait(); - - if (off || size != PAGE_SIZE) - bzero((void *)(czp->dstva + off), size); - else - bzero_page(czp->dstva); - - /* - * Although aliasing is not possible, if we use temporary mappings with - * memory that will be mapped later as non-cached or with write-through - * caches, we might end up overwriting it when calling wbinv_all. So - * make sure caches are clean after the operation. - */ - cpu_idcache_wbinv_range(czp->dstva, size); - pmap_l2cache_wbinv_range(czp->dstva, phys, size); - - mtx_unlock(&czp->lock); - sched_unpin(); -} - -/* - * pmap_zero_page zeros the specified hardware page by mapping - * the page into KVM and using bzero to clear its contents. - */ -void -pmap_zero_page(vm_page_t m) -{ - pmap_zero_page_gen(m, 0, PAGE_SIZE); -} - - -/* - * pmap_zero_page_area zeros the specified hardware page by mapping - * the page into KVM and using bzero to clear its contents. - * - * off and size may not cover an area beyond a single hardware page. - */ -void -pmap_zero_page_area(vm_page_t m, int off, int size) -{ - - pmap_zero_page_gen(m, off, size); -} - - -/* - * pmap_zero_page_idle zeros the specified hardware page by mapping - * the page into KVM and using bzero to clear its contents. This - * is intended to be called from the vm_pagezero process only and - * outside of Giant. - */ -void -pmap_zero_page_idle(vm_page_t m) -{ - - pmap_zero_page(m); -} - -/* - * pmap_copy_page copies the specified (machine independent) - * page by mapping the page into virtual memory and using - * bcopy to copy the page, one machine dependent page at a - * time. - */ - -/* - * pmap_copy_page() - * - * Copy one physical page into another, by mapping the pages into - * hook points. The same comment regarding cachability as in - * pmap_zero_page also applies here. - */ -void -pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst) -{ - struct czpages *czp; - - sched_pin(); - czp = &cpu_czpages[PCPU_GET(cpuid)]; - mtx_lock(&czp->lock); - - /* - * Map the pages into the page hook points, copy them, and purge the - * cache for the appropriate page. - */ - *czp->srcptep = L2_S_PROTO | src | pte_l2_s_cache_mode | L2_S_REF; - pmap_set_prot(czp->srcptep, VM_PROT_READ, 0); - PTE_SYNC(czp->srcptep); - cpu_tlb_flushD_SE(czp->srcva); - *czp->dstptep = L2_S_PROTO | dst | pte_l2_s_cache_mode | L2_S_REF; - pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0); - PTE_SYNC(czp->dstptep); - cpu_tlb_flushD_SE(czp->dstva); - cpu_cpwait(); - - bcopy_page(czp->srcva, czp->dstva); - - /* - * Although aliasing is not possible, if we use temporary mappings with - * memory that will be mapped later as non-cached or with write-through - * caches, we might end up overwriting it when calling wbinv_all. So - * make sure caches are clean after the operation. - */ - cpu_idcache_wbinv_range(czp->dstva, PAGE_SIZE); - pmap_l2cache_wbinv_range(czp->dstva, dst, PAGE_SIZE); - - mtx_unlock(&czp->lock); - sched_unpin(); -} - -int unmapped_buf_allowed = 1; - -void -pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], - vm_offset_t b_offset, int xfersize) -{ - vm_page_t a_pg, b_pg; - vm_offset_t a_pg_offset, b_pg_offset; - int cnt; - struct czpages *czp; - - sched_pin(); - czp = &cpu_czpages[PCPU_GET(cpuid)]; - mtx_lock(&czp->lock); - - while (xfersize > 0) { - a_pg = ma[a_offset >> PAGE_SHIFT]; - a_pg_offset = a_offset & PAGE_MASK; - cnt = min(xfersize, PAGE_SIZE - a_pg_offset); - b_pg = mb[b_offset >> PAGE_SHIFT]; - b_pg_offset = b_offset & PAGE_MASK; - cnt = min(cnt, PAGE_SIZE - b_pg_offset); - *czp->srcptep = L2_S_PROTO | VM_PAGE_TO_PHYS(a_pg) | - pte_l2_s_cache_mode | L2_S_REF; - pmap_set_prot(czp->srcptep, VM_PROT_READ, 0); - PTE_SYNC(czp->srcptep); - cpu_tlb_flushD_SE(czp->srcva); - *czp->dstptep = L2_S_PROTO | VM_PAGE_TO_PHYS(b_pg) | - pte_l2_s_cache_mode | L2_S_REF; - pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0); - PTE_SYNC(czp->dstptep); - cpu_tlb_flushD_SE(czp->dstva); - cpu_cpwait(); - bcopy((char *)czp->srcva + a_pg_offset, (char *)czp->dstva + b_pg_offset, - cnt); - cpu_idcache_wbinv_range(czp->dstva + b_pg_offset, cnt); - pmap_l2cache_wbinv_range(czp->dstva + b_pg_offset, - VM_PAGE_TO_PHYS(b_pg) + b_pg_offset, cnt); - xfersize -= cnt; - a_offset += cnt; - b_offset += cnt; - } - - mtx_unlock(&czp->lock); - sched_unpin(); -} - -void -pmap_copy_page(vm_page_t src, vm_page_t dst) -{ - - if (_arm_memcpy && PAGE_SIZE >= _min_memcpy_size && - _arm_memcpy((void *)VM_PAGE_TO_PHYS(dst), - (void *)VM_PAGE_TO_PHYS(src), PAGE_SIZE, IS_PHYSICAL) == 0) - return; - - pmap_copy_page_generic(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst)); -} - -vm_offset_t -pmap_quick_enter_page(vm_page_t m) -{ - pt_entry_t *qmap_pte; - vm_offset_t qmap_addr; - - critical_enter(); - - qmap_addr = PCPU_GET(qmap_addr); - qmap_pte = PCPU_GET(qmap_pte); - - KASSERT(*qmap_pte == 0, ("pmap_quick_enter_page: PTE busy")); - - *qmap_pte = L2_S_PROTO | VM_PAGE_TO_PHYS(m) | L2_S_REF; - if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE) - *qmap_pte |= pte_l2_s_cache_mode; - pmap_set_prot(qmap_pte, VM_PROT_READ | VM_PROT_WRITE, 0); - PTE_SYNC(qmap_pte); - cpu_tlb_flushD_SE(qmap_addr); - cpu_cpwait(); - - return (qmap_addr); -} - -void -pmap_quick_remove_page(vm_offset_t addr) -{ - pt_entry_t *qmap_pte; - - qmap_pte = PCPU_GET(qmap_pte); - - KASSERT(addr == PCPU_GET(qmap_addr), - ("pmap_quick_remove_page: invalid address")); - KASSERT(*qmap_pte != 0, - ("pmap_quick_remove_page: PTE not in use")); - - cpu_idcache_wbinv_range(addr, PAGE_SIZE); - pmap_l2cache_wbinv_range(addr, *qmap_pte & L2_S_FRAME, PAGE_SIZE); - *qmap_pte = 0; - PTE_SYNC(qmap_pte); - critical_exit(); -} - -/* - * this routine returns true if a physical page resides - * in the given pmap. - */ -boolean_t -pmap_page_exists_quick(pmap_t pmap, vm_page_t m) -{ - struct md_page *pvh; - pv_entry_t pv; - int loops = 0; - boolean_t rv; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_page_exists_quick: page %p is not managed", m)); - rv = FALSE; - rw_wlock(&pvh_global_lock); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { - if (PV_PMAP(pv) == pmap) { - rv = TRUE; - break; - } - loops++; - if (loops >= 16) - break; - } - if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) { - pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { - if (PV_PMAP(pv) == pmap) { - rv = TRUE; - break; - } - loops++; - if (loops >= 16) - break; - } - } - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * pmap_page_wired_mappings: - * - * Return the number of managed mappings to the given physical page - * that are wired. - */ -int -pmap_page_wired_mappings(vm_page_t m) -{ - int count; - - count = 0; - if ((m->oflags & VPO_UNMANAGED) != 0) - return (count); - rw_wlock(&pvh_global_lock); - count = pmap_pvh_wired_mappings(&m->md, count); - if ((m->flags & PG_FICTITIOUS) == 0) { - count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)), - count); - } - rw_wunlock(&pvh_global_lock); - return (count); -} - -/* - * pmap_pvh_wired_mappings: - * - * Return the updated number "count" of managed mappings that are wired. - */ -static int -pmap_pvh_wired_mappings(struct md_page *pvh, int count) -{ - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { - if ((pv->pv_flags & PVF_WIRED) != 0) - count++; - } - return (count); -} - -/* - * Returns TRUE if any of the given mappings were referenced and FALSE - * otherwise. Both page and section mappings are supported. - */ -static boolean_t -pmap_is_referenced_pvh(struct md_page *pvh) -{ - struct l2_bucket *l2b; - pv_entry_t pv; - pd_entry_t *pl1pd; - pt_entry_t *ptep; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)]; - if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) - rv = L1_S_REFERENCED(*pl1pd); - else { - l2b = pmap_get_l2_bucket(pmap, pv->pv_va); - ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)]; - rv = L2_S_REFERENCED(*ptep); - } - PMAP_UNLOCK(pmap); - if (rv) - break; - } - return (rv); -} - -/* - * pmap_is_referenced: - * - * Return whether or not the specified physical page was referenced - * in any physical maps. - */ -boolean_t -pmap_is_referenced(vm_page_t m) -{ - boolean_t rv; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_is_referenced: page %p is not managed", m)); - rw_wlock(&pvh_global_lock); - rv = pmap_is_referenced_pvh(&m->md) || - ((m->flags & PG_FICTITIOUS) == 0 && - pmap_is_referenced_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m)))); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * pmap_ts_referenced: - * - * Return the count of reference bits for a page, clearing all of them. - */ -int -pmap_ts_referenced(vm_page_t m) -{ - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_ts_referenced: page %p is not managed", m)); - return (pmap_clearbit(m, PVF_REF)); -} - -/* - * Returns TRUE if any of the given mappings were used to modify - * physical memory. Otherwise, returns FALSE. Both page and 1MB section - * mappings are supported. - */ -static boolean_t -pmap_is_modified_pvh(struct md_page *pvh) -{ - pd_entry_t *pl1pd; - struct l2_bucket *l2b; - pv_entry_t pv; - pt_entry_t *ptep; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)]; - if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) - rv = L1_S_WRITABLE(*pl1pd); - else { - l2b = pmap_get_l2_bucket(pmap, pv->pv_va); - ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)]; - rv = L2_S_WRITABLE(*ptep); - } - PMAP_UNLOCK(pmap); - if (rv) - break; - } - - return (rv); -} - -boolean_t -pmap_is_modified(vm_page_t m) -{ - boolean_t rv; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_is_modified: page %p is not managed", m)); - /* - * If the page is not exclusive busied, then PGA_WRITEABLE cannot be - * concurrently set while the object is locked. Thus, if PGA_WRITEABLE - * is clear, no PTEs can have APX cleared. - */ - VM_OBJECT_ASSERT_WLOCKED(m->object); - if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0) - return (FALSE); - rw_wlock(&pvh_global_lock); - rv = pmap_is_modified_pvh(&m->md) || - ((m->flags & PG_FICTITIOUS) == 0 && - pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m)))); - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * Apply the given advice to the specified range of addresses within the - * given pmap. Depending on the advice, clear the referenced and/or - * modified flags in each mapping. - */ -void -pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice) -{ - struct l2_bucket *l2b; - struct pv_entry *pve; - pd_entry_t l1pd; - pt_entry_t *ptep, opte, pte; - vm_offset_t next_bucket; - vm_page_t m; - - if (advice != MADV_DONTNEED && advice != MADV_FREE) - return; - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - for (; sva < eva; sva = next_bucket) { - next_bucket = L2_NEXT_BUCKET(sva); - if (next_bucket < sva) - next_bucket = eva; - l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)]; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - if (pmap == pmap_kernel()) - continue; - if (!pmap_demote_section(pmap, sva)) { - /* - * The large page mapping was destroyed. - */ - continue; - } - /* - * Unless the page mappings are wired, remove the - * mapping to a single page so that a subsequent - * access may repromote. Since the underlying - * l2_bucket is fully populated, this removal - * never frees an entire l2_bucket. - */ - l2b = pmap_get_l2_bucket(pmap, sva); - KASSERT(l2b != NULL, - ("pmap_advise: no l2 bucket for " - "va 0x%#x, pmap 0x%p", sva, pmap)); - ptep = &l2b->l2b_kva[l2pte_index(sva)]; - opte = *ptep; - m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep)); - KASSERT(m != NULL, - ("pmap_advise: no vm_page for demoted superpage")); - pve = pmap_find_pv(&m->md, pmap, sva); - KASSERT(pve != NULL, - ("pmap_advise: no PV entry for managed mapping")); - if ((pve->pv_flags & PVF_WIRED) == 0) { - pmap_free_l2_bucket(pmap, l2b, 1); - pve = pmap_remove_pv(m, pmap, sva); - pmap_free_pv_entry(pmap, pve); - *ptep = 0; - PTE_SYNC(ptep); - if (pmap_is_current(pmap)) { - if (PTE_BEEN_EXECD(opte)) - cpu_tlb_flushID_SE(sva); - else if (PTE_BEEN_REFD(opte)) - cpu_tlb_flushD_SE(sva); - } - } - } - if (next_bucket > eva) - next_bucket = eva; - l2b = pmap_get_l2_bucket(pmap, sva); - if (l2b == NULL) - continue; - for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; - sva != next_bucket; ptep++, sva += PAGE_SIZE) { - opte = pte = *ptep; - if ((opte & L2_S_PROTO) == 0) - continue; - m = PHYS_TO_VM_PAGE(l2pte_pa(opte)); - if (m == NULL || (m->oflags & VPO_UNMANAGED) != 0) - continue; - else if (L2_S_WRITABLE(opte)) { - if (advice == MADV_DONTNEED) { - /* - * Don't need to mark the page - * dirty as it was already marked as - * such in pmap_fault_fixup() or - * pmap_enter_locked(). - * Just clear the state. - */ - } else - pte |= L2_APX; - - pte &= ~L2_S_REF; - *ptep = pte; - PTE_SYNC(ptep); - } else if (L2_S_REFERENCED(opte)) { - pte &= ~L2_S_REF; - *ptep = pte; - PTE_SYNC(ptep); - } else - continue; - if (pmap_is_current(pmap)) { - if (PTE_BEEN_EXECD(opte)) - cpu_tlb_flushID_SE(sva); - else if (PTE_BEEN_REFD(opte)) - cpu_tlb_flushD_SE(sva); - } - } - } - cpu_cpwait(); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); -} - -/* - * Clear the modify bits on the specified physical page. - */ -void -pmap_clear_modify(vm_page_t m) -{ - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_clear_modify: page %p is not managed", m)); - VM_OBJECT_ASSERT_WLOCKED(m->object); - KASSERT(!vm_page_xbusied(m), - ("pmap_clear_modify: page %p is exclusive busied", m)); - - /* - * If the page is not PGA_WRITEABLE, then no mappings can be modified. - * If the object containing the page is locked and the page is not - * exclusive busied, then PGA_WRITEABLE cannot be concurrently set. - */ - if ((m->aflags & PGA_WRITEABLE) == 0) - return; - if (pmap_is_modified(m)) - pmap_clearbit(m, PVF_MOD); -} - - -/* - * Clear the write and modified bits in each of the given page's mappings. - */ -void -pmap_remove_write(vm_page_t m) -{ - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_remove_write: page %p is not managed", m)); - - /* - * If the page is not exclusive busied, then PGA_WRITEABLE cannot be - * set by another thread while the object is locked. Thus, - * if PGA_WRITEABLE is clear, no page table entries need updating. - */ - VM_OBJECT_ASSERT_WLOCKED(m->object); - if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0) - pmap_clearbit(m, PVF_WRITE); -} - - -/* - * perform the pmap work for mincore - */ -int -pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa) -{ - struct l2_bucket *l2b; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep, pte; - vm_paddr_t pa; - vm_page_t m; - int val; - boolean_t managed; - - PMAP_LOCK(pmap); -retry: - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(addr)]; - l1pd = *pl1pd; - if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { - pa = (l1pd & L1_S_FRAME); - val = MINCORE_SUPER | MINCORE_INCORE; - if (L1_S_WRITABLE(l1pd)) - val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; - managed = FALSE; - m = PHYS_TO_VM_PAGE(pa); - if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0) - managed = TRUE; - if (managed) { - if (L1_S_REFERENCED(l1pd)) - val |= MINCORE_REFERENCED | - MINCORE_REFERENCED_OTHER; - } - } else { - l2b = pmap_get_l2_bucket(pmap, addr); - if (l2b == NULL) { - val = 0; - goto out; - } - ptep = &l2b->l2b_kva[l2pte_index(addr)]; - pte = *ptep; - if (!l2pte_valid(pte)) { - val = 0; - goto out; - } - val = MINCORE_INCORE; - if (L2_S_WRITABLE(pte)) - val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; - managed = FALSE; - pa = l2pte_pa(pte); - m = PHYS_TO_VM_PAGE(pa); - if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0) - managed = TRUE; - if (managed) { - if (L2_S_REFERENCED(pte)) - val |= MINCORE_REFERENCED | - MINCORE_REFERENCED_OTHER; - } - } - if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) != - (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) { - /* Ensure that "PHYS_TO_VM_PAGE(pa)->object" doesn't change. */ - if (vm_page_pa_tryrelock(pmap, pa, locked_pa)) - goto retry; - } else -out: - PA_UNLOCK_COND(*locked_pa); - PMAP_UNLOCK(pmap); - return (val); -} - -void -pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz) -{ -} - -/* - * Increase the starting virtual address of the given mapping if a - * different alignment might result in more superpage mappings. - */ -void -pmap_align_superpage(vm_object_t object, vm_ooffset_t offset, - vm_offset_t *addr, vm_size_t size) -{ - vm_offset_t superpage_offset; - - if (size < NBPDR) - return; - if (object != NULL && (object->flags & OBJ_COLORED) != 0) - offset += ptoa(object->pg_color); - superpage_offset = offset & PDRMASK; - if (size - ((NBPDR - superpage_offset) & PDRMASK) < NBPDR || - (*addr & PDRMASK) == superpage_offset) - return; - if ((*addr & PDRMASK) < superpage_offset) - *addr = (*addr & ~PDRMASK) + superpage_offset; - else - *addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset; -} - -/* - * pmap_map_section: - * - * Create a single section mapping. - */ -void -pmap_map_section(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, - boolean_t ref) -{ - pd_entry_t *pl1pd, l1pd; - pd_entry_t fl; - - KASSERT(((va | pa) & L1_S_OFFSET) == 0, - ("Not a valid section mapping")); - - fl = pte_l1_s_cache_mode; - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - l1pd = L1_S_PROTO | pa | L1_S_PROT(PTE_USER, prot) | fl | - L1_S_DOM(pmap->pm_domain); - - /* Mark page referenced if this section is a result of a promotion. */ - if (ref == TRUE) - l1pd |= L1_S_REF; -#ifdef SMP - l1pd |= L1_SHARED; -#endif - *pl1pd = l1pd; - PTE_SYNC(pl1pd); -} - -/* - * pmap_link_l2pt: - * - * Link the L2 page table specified by l2pv.pv_pa into the L1 - * page table at the slot for "va". - */ -void -pmap_link_l2pt(vm_offset_t l1pt, vm_offset_t va, struct pv_addr *l2pv) -{ - pd_entry_t *pde = (pd_entry_t *) l1pt, proto; - u_int slot = va >> L1_S_SHIFT; - - proto = L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_C_PROTO; - -#ifdef VERBOSE_INIT_ARM - printf("pmap_link_l2pt: pa=0x%x va=0x%x\n", l2pv->pv_pa, l2pv->pv_va); -#endif - - pde[slot + 0] = proto | (l2pv->pv_pa + 0x000); - PTE_SYNC(&pde[slot]); - - SLIST_INSERT_HEAD(&kernel_pt_list, l2pv, pv_list); - -} - -/* - * pmap_map_entry - * - * Create a single page mapping. - */ -void -pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot, - int cache) -{ - pd_entry_t *pde = (pd_entry_t *) l1pt; - pt_entry_t fl; - pt_entry_t *ptep; - - KASSERT(((va | pa) & PAGE_MASK) == 0, ("ouin")); - - fl = l2s_mem_types[cache]; - - if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C) - panic("pmap_map_entry: no L2 table for VA 0x%08x", va); - - ptep = (pt_entry_t *)kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK); - - if (ptep == NULL) - panic("pmap_map_entry: can't find L2 table for VA 0x%08x", va); - - ptep[l2pte_index(va)] = L2_S_PROTO | pa | fl | L2_S_REF; - pmap_set_prot(&ptep[l2pte_index(va)], prot, 0); - PTE_SYNC(&ptep[l2pte_index(va)]); -} - -/* - * pmap_map_chunk: - * - * Map a chunk of memory using the most efficient mappings - * possible (section. large page, small page) into the - * provided L1 and L2 tables at the specified virtual address. - */ -vm_size_t -pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, - vm_size_t size, int prot, int type) -{ - pd_entry_t *pde = (pd_entry_t *) l1pt; - pt_entry_t *ptep, f1, f2s, f2l; - vm_size_t resid; - int i; - - resid = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - - if (l1pt == 0) - panic("pmap_map_chunk: no L1 table provided"); - -#ifdef VERBOSE_INIT_ARM - printf("pmap_map_chunk: pa=0x%x va=0x%x size=0x%x resid=0x%x " - "prot=0x%x type=%d\n", pa, va, size, resid, prot, type); -#endif - - f1 = l1_mem_types[type]; - f2l = l2l_mem_types[type]; - f2s = l2s_mem_types[type]; - - size = resid; - - while (resid > 0) { - /* See if we can use a section mapping. */ - if (L1_S_MAPPABLE_P(va, pa, resid)) { -#ifdef VERBOSE_INIT_ARM - printf("S"); -#endif - pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa | - L1_S_PROT(PTE_KERNEL, prot | VM_PROT_EXECUTE) | - f1 | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_REF; - PTE_SYNC(&pde[va >> L1_S_SHIFT]); - va += L1_S_SIZE; - pa += L1_S_SIZE; - resid -= L1_S_SIZE; - continue; - } - - /* - * Ok, we're going to use an L2 table. Make sure - * one is actually in the corresponding L1 slot - * for the current VA. - */ - if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C) - panic("pmap_map_chunk: no L2 table for VA 0x%08x", va); - - ptep = (pt_entry_t *) kernel_pt_lookup( - pde[L1_IDX(va)] & L1_C_ADDR_MASK); - if (ptep == NULL) - panic("pmap_map_chunk: can't find L2 table for VA" - "0x%08x", va); - /* See if we can use a L2 large page mapping. */ - if (L2_L_MAPPABLE_P(va, pa, resid)) { -#ifdef VERBOSE_INIT_ARM - printf("L"); -#endif - for (i = 0; i < 16; i++) { - ptep[l2pte_index(va) + i] = - L2_L_PROTO | pa | - L2_L_PROT(PTE_KERNEL, prot) | f2l; - PTE_SYNC(&ptep[l2pte_index(va) + i]); - } - va += L2_L_SIZE; - pa += L2_L_SIZE; - resid -= L2_L_SIZE; - continue; - } - - /* Use a small page mapping. */ -#ifdef VERBOSE_INIT_ARM - printf("P"); -#endif - ptep[l2pte_index(va)] = L2_S_PROTO | pa | f2s | L2_S_REF; - pmap_set_prot(&ptep[l2pte_index(va)], prot, 0); - PTE_SYNC(&ptep[l2pte_index(va)]); - va += PAGE_SIZE; - pa += PAGE_SIZE; - resid -= PAGE_SIZE; - } -#ifdef VERBOSE_INIT_ARM - printf("\n"); -#endif - return (size); - -} - -void -pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) -{ - /* - * Remember the memattr in a field that gets used to set the appropriate - * bits in the PTEs as mappings are established. - */ - m->md.pv_memattr = ma; - - /* - * It appears that this function can only be called before any mappings - * for the page are established on ARM. If this ever changes, this code - * will need to walk the pv_list and make each of the existing mappings - * uncacheable, being careful to sync caches and PTEs (and maybe - * invalidate TLB?) for any current mapping it modifies. - */ - if (TAILQ_FIRST(&m->md.pv_list) != NULL) - panic("Can't change memattr on page with existing mappings"); -} diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S index ee6368553bcc..d7571ec37071 100644 --- a/sys/arm/arm/swtch.S +++ b/sys/arm/arm/swtch.S @@ -114,7 +114,7 @@ __FBSDID("$FreeBSD$"); .word _C_LABEL(blocked_lock) -#ifndef ARM_NEW_PMAP +#if __ARM_ARCH < 6 #define DOMAIN_CLIENT 0x01 @@ -418,7 +418,7 @@ ENTRY(cpu_switch) END(cpu_switch) -#else /* !ARM_NEW_PMAP */ +#else /* __ARM_ARCH < 6 */ #include ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */ @@ -789,7 +789,7 @@ sw4_panic_str: END(cpu_switch) -#endif /* !ARM_NEW_PMAP */ +#endif /* __ARM_ARCH < 6 */ ENTRY(savectx) stmfd sp!, {lr} diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 6d8015137939..adc29c6534e8 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -334,13 +334,11 @@ abort_handler(struct trapframe *tf, int prefetch) * they are not from KVA space. Thus, no action is needed here. */ -#ifdef ARM_NEW_PMAP rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode); if (rv == KERN_SUCCESS) return; if (rv == KERN_INVALID_ADDRESS) goto nogo; -#endif /* * Now, when we handled imprecise and debug aborts, the rest of * aborts should be really related to mapping. @@ -488,13 +486,6 @@ abort_handler(struct trapframe *tf, int prefetch) last_fault_code = fsr; #endif -#ifndef ARM_NEW_PMAP - if (pmap_fault_fixup(vmspace_pmap(td->td_proc->p_vmspace), va, ftype, - usermode)) { - goto out; - } -#endif - #ifdef INVARIANTS onfault = pcb->pcb_onfault; pcb->pcb_onfault = NULL; diff --git a/sys/arm/conf/std.armv6 b/sys/arm/conf/std.armv6 index 8e5df24ae12f..35f60a3345e7 100644 --- a/sys/arm/conf/std.armv6 +++ b/sys/arm/conf/std.armv6 @@ -37,8 +37,6 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) options VFP # Enable floating point hardware support -options ARM_NEW_PMAP # Use new pmap code. - # DTrace support options KDTRACE_HOOKS # Kernel DTrace hooks options DDB_CTF # all architectures - kernel ELF linker loads CTF data diff --git a/sys/arm/include/machdep.h b/sys/arm/include/machdep.h index fdf59beedb33..36c2f44daed9 100644 --- a/sys/arm/include/machdep.h +++ b/sys/arm/include/machdep.h @@ -4,8 +4,10 @@ #ifndef _MACHDEP_BOOT_MACHDEP_H_ #define _MACHDEP_BOOT_MACHDEP_H_ +#include + /* Structs that need to be initialised by initarm */ -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 extern vm_offset_t irqstack; extern vm_offset_t undstack; extern vm_offset_t abtstack; diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index a0b0d94255b8..dc7fd38a20eb 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -46,9 +46,11 @@ * * $FreeBSD$ */ -#ifdef ARM_NEW_PMAP + #include + +#if __ARM_ARCH >= 6 #include -#else /* ARM_NEW_PMAP */ +#else /* __ARM_ARCH >= 6 */ #ifndef _MACHINE_PMAP_H_ #define _MACHINE_PMAP_H_ @@ -704,4 +706,4 @@ extern vm_paddr_t dump_avail[]; #endif /* !LOCORE */ #endif /* !_MACHINE_PMAP_H_ */ -#endif /* !ARM_NEW_PMAP */ +#endif /* __ARM_ARCH >= 6 */ diff --git a/sys/arm/include/pte.h b/sys/arm/include/pte.h index 42e26ab61584..8c26aabe5ce7 100644 --- a/sys/arm/include/pte.h +++ b/sys/arm/include/pte.h @@ -33,9 +33,11 @@ * * $FreeBSD$ */ -#ifdef ARM_NEW_PMAP +#include + +#if __ARM_ARCH >= 6 #include -#else /* ARM_NEW_PMAP */ +#else /* __ARM_ARCH >= 6 */ #ifndef _MACHINE_PTE_H_ #define _MACHINE_PTE_H_ @@ -356,6 +358,6 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */ * 1 X 1 1 1 Y Y WT Y Y */ #endif /* !_MACHINE_PTE_H_ */ -#endif /* !ARM_NEW_PMAP */ +#endif /* __ARM_ARCH >= 6 */ /* End of pte.h */ diff --git a/sys/arm/include/sf_buf.h b/sys/arm/include/sf_buf.h index eba8488e8f9c..5228864946c0 100644 --- a/sys/arm/include/sf_buf.h +++ b/sys/arm/include/sf_buf.h @@ -29,11 +29,13 @@ #ifndef _MACHINE_SF_BUF_H_ #define _MACHINE_SF_BUF_H_ +#include + static inline void sf_buf_map(struct sf_buf *sf, int flags) { -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 pmap_qenter(sf->kva, &(sf->m), 1); #else pmap_kenter(sf->kva, VM_PAGE_TO_PHYS(sf->m)); @@ -44,7 +46,7 @@ static inline int sf_buf_unmap(struct sf_buf *sf) { -#ifdef ARM_NEW_PMAP +#if __ARM_ARCH >= 6 pmap_qremove(sf->kva, 1); #else pmap_kremove(sf->kva); diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 8fb230e23de8..70a4ab9700bc 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -29,7 +29,9 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -#ifdef ARM_NEW_PMAP +#include + +#if __ARM_ARCH >= 6 #include #define VM_MEMATTR_WB_WA ((vm_memattr_t)PTE2_ATTR_WB_WA) @@ -40,9 +42,11 @@ #define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA #define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */ +#ifdef _KERNEL +/* Don't export aliased VM_MEMATTR to userland */ #define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WT /* for DRM */ #define VM_MEMATTR_WRITE_BACK VM_MEMATTR_WB_WA /* for DRM */ - +#endif #else /* Memory attribute configuration. */ #define VM_MEMATTR_DEFAULT 0 diff --git a/sys/conf/files.arm b/sys/conf/files.arm index 33bdd94265cb..67b94df2386c 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -64,8 +64,7 @@ arm/arm/pl310.c optional pl310 arm/arm/platform.c optional platform arm/arm/platform_if.m optional platform arm/arm/pmap.c optional !armv6 -arm/arm/pmap-v6.c optional armv6 !arm_new_pmap -arm/arm/pmap-v6-new.c optional armv6 arm_new_pmap +arm/arm/pmap-v6-new.c optional armv6 arm/arm/pmu.c optional pmu | fdt hwpmc arm/arm/sc_machdep.c optional sc arm/arm/setcpsr.S standard diff --git a/sys/conf/options.arm b/sys/conf/options.arm index 8720ac24a168..ef664136547c 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -5,7 +5,6 @@ ARM_INTRNG opt_global.h ARM_KERN_DIRECTMAP opt_vm.h ARM_L2_PIPT opt_global.h ARM_MANY_BOARD opt_global.h -ARM_NEW_PMAP opt_global.h NKPT2PG opt_pmap.h ARM_WANT_TP_ADDRESS opt_global.h COUNTS_PER_SEC opt_timer.h From 310b52971c5166f73d3a7705faf243335a452580 Mon Sep 17 00:00:00 2001 From: mmel Date: Fri, 29 Jan 2016 11:00:33 +0000 Subject: [PATCH 031/236] ARM: After removal of old pmap-v6 code, rename pmap-v6-new.c to pmap-v6.c. --- sys/arm/arm/{pmap-v6-new.c => pmap-v6.c} | 0 sys/conf/files.arm | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename sys/arm/arm/{pmap-v6-new.c => pmap-v6.c} (100%) diff --git a/sys/arm/arm/pmap-v6-new.c b/sys/arm/arm/pmap-v6.c similarity index 100% rename from sys/arm/arm/pmap-v6-new.c rename to sys/arm/arm/pmap-v6.c diff --git a/sys/conf/files.arm b/sys/conf/files.arm index 67b94df2386c..e6b89a197be6 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -64,7 +64,7 @@ arm/arm/pl310.c optional pl310 arm/arm/platform.c optional platform arm/arm/platform_if.m optional platform arm/arm/pmap.c optional !armv6 -arm/arm/pmap-v6-new.c optional armv6 +arm/arm/pmap-v6.c optional armv6 arm/arm/pmu.c optional pmu | fdt hwpmc arm/arm/sc_machdep.c optional sc arm/arm/setcpsr.S standard From 047ea0e83b66f348bad2128bff3bc3e763acb3c3 Mon Sep 17 00:00:00 2001 From: wma Date: Fri, 29 Jan 2016 13:06:30 +0000 Subject: [PATCH 032/236] Framework for ARM64 instruction disassembler Provide an easy to use framework for ARM64 DDB disassembler. This commit does not contain full list of instruction opcodes. Obtained from: Semihalf Sponsored by: Cavium Approved by: cognet (mentor) Reviewed by: zbb, andrew, cognet Differential revision: https://reviews.freebsd.org/D5114 --- sys/arm64/arm64/db_disasm.c | 31 +++- sys/arm64/arm64/disassem.c | 330 +++++++++++++++++++++++++++++++++++ sys/arm64/include/armreg.h | 2 + sys/arm64/include/disassem.h | 42 +++++ sys/conf/files.arm64 | 1 + 5 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 sys/arm64/arm64/disassem.c create mode 100644 sys/arm64/include/disassem.h diff --git a/sys/arm64/arm64/db_disasm.c b/sys/arm64/arm64/db_disasm.c index 03784837b074..e24e0998fff5 100644 --- a/sys/arm64/arm64/db_disasm.c +++ b/sys/arm64/arm64/db_disasm.c @@ -31,11 +31,40 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include + +#include + +static u_int db_disasm_read_word(vm_offset_t); +static void db_disasm_printaddr(vm_offset_t); + +/* Glue code to interface db_disasm to the generic ARM disassembler */ +static const struct disasm_interface db_disasm_interface = { + db_disasm_read_word, + db_disasm_printaddr, + db_printf +}; + +static u_int +db_disasm_read_word(vm_offset_t address) +{ + + return (db_get_value(address, INSN_SIZE, 0)); +} + +static void +db_disasm_printaddr(vm_offset_t address) +{ + + db_printsym((db_addr_t)address, DB_STGY_ANY); +} vm_offset_t db_disasm(vm_offset_t loc, bool altfmt) { - return 0; + + return (disasm(&db_disasm_interface, loc, altfmt)); } /* End of db_disasm.c */ diff --git a/sys/arm64/arm64/disassem.c b/sys/arm64/arm64/disassem.c new file mode 100644 index 000000000000..46b62285f385 --- /dev/null +++ b/sys/arm64/arm64/disassem.c @@ -0,0 +1,330 @@ +/*- + * Copyright (c) 2016 Cavium + * All rights reserved. + * + * This software was developed by Semihalf. + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); +#include + +#include +#include +#include +#include + +#define ARM64_MAX_TOKEN_LEN 8 +#define ARM64_MAX_TOKEN_CNT 10 + +static const char *w_reg[] = { + "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", + "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", + "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", + "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wSP", +}; + +static const char *x_reg[] = { + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", + "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", + "x24", "x25", "x26", "x27", "x28", "x29", "LR", "SP", +}; + +static const char *shift_2[] = { + "LSL", "LSR", "ASR", "RSV" +}; + +/* + * Structure representing single token (operand) inside instruction. + * name - name of operand + * pos - position within the instruction (in bits) + * len - operand length (in bits) + */ +struct arm64_insn_token { + char name[ARM64_MAX_TOKEN_LEN]; + int pos; + int len; +}; + +/* + * Define generic types for instruction printing. + */ +enum arm64_format_type { + TYPE_01, /* OP , , {, #} SF32/64 + OP , , #{, } SF32/64 */ +}; + +/* + * Structure representing single parsed instruction format. + * name - opcode name + * format - opcode format in a human-readable way + * type - syntax type for printing + * special_ops - special options passed to a printer (if any) + * mask - bitmask for instruction matching + * pattern - pattern to look for + * tokens - array of tokens (operands) inside instruction + */ +struct arm64_insn { + char* name; + char* format; + enum arm64_format_type type; + uint64_t special_ops; + uint32_t mask; + uint32_t pattern; + struct arm64_insn_token tokens[ARM64_MAX_TOKEN_CNT]; +}; + +/* + * Specify instruction opcode format in a human-readable way. Use notation + * obtained from ARM Architecture Reference Manual for ARMv8-A. + * + * Format string description: + * Each group must be separated by "|". Group made of 0/1 is used to + * generate mask and pattern for instruction matching. Groups containing + * an operand token (in format NAME(length_bits)) are used to retrieve any + * operand data from the instruction. Names here must be meaningful + * and match the one described in the Manual. + * + * Token description: + * SF - "0" represents 32-bit access, "1" represents 64-bit access + * SHIFT - type of shift (instruction dependent) + * IMM - immediate value + * Rx - register number + */ +static struct arm64_insn arm64_i[] = { + { "add", "SF(1)|0001011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", TYPE_01, 0 }, + { "mov", "SF(1)|001000100000000000000|RN(5)|RD(5)", TYPE_01, 0 }, + { "add", "SF(1)|0010001|SHIFT(2)|IMM(12)|RN(5)|RD(5)", TYPE_01, 0 }, + { NULL, NULL } +}; + +static void +arm64_disasm_generate_masks(struct arm64_insn *tab) +{ + uint32_t mask, val; + int a, i; + int len, ret; + int token = 0; + char *format; + int error; + + while (tab->name != NULL) { + mask = 0; + val = 0; + format = tab->format; + token = 0; + error = 0; + + /* + * For each entry analyze format strings from the + * left (i.e. from the MSB). + */ + a = (INSN_SIZE * NBBY) - 1; + while (*format != '\0' && (a >= 0)) { + switch(*format) { + case '0': + /* Bit is 0, add to mask and pattern */ + mask |= (1 << a); + a--; + format++; + break; + case '1': + /* Bit is 1, add to mask and pattern */ + mask |= (1 << a); + val |= (1 << a); + a--; + format++; + break; + case '|': + /* skip */ + format++; + break; + default: + /* Token found, copy the name */ + memset(tab->tokens[token].name, 0, + sizeof(tab->tokens[token].name)); + i = 0; + while (*format != '(') { + tab->tokens[token].name[i] = *format; + i++; + format++; + if (i >= ARM64_MAX_TOKEN_LEN) { + printf("ERROR: token too long in op %s\n", + tab->name); + error = 1; + break; + } + } + if (error != 0) + break; + + /* Read the length value */ + ret = sscanf(format, "(%d)", &len); + if (ret == 1) { + if (token >= ARM64_MAX_TOKEN_CNT) { + printf("ERROR: to many tokens in op %s\n", + tab->name); + error = 1; + break; + } + + a -= len; + tab->tokens[token].pos = a + 1; + tab->tokens[token].len = len; + token++; + } + + /* Skip to the end of the token */ + while (*format != 0 && *format != '|') + format++; + } + } + + /* Write mask and pattern to the instruction array */ + tab->mask = mask; + tab->pattern = val; + + /* + * If we got here, format string must be parsed and "a" + * should point to -1. If it's not, wrong number of bits + * in format string. Mark this as invalid and prevent + * from being matched. + */ + if (*format != 0 || (a != -1) || (error != 0)) { + tab->mask = 0; + tab->pattern = 0xffffffff; + printf("ERROR: skipping instruction op %s\n", + tab->name); + } + + tab++; + } +} + +static int +arm64_disasm_read_token(struct arm64_insn *insn, u_int opcode, + const char *token, int *val) +{ + int i; + + for (i = 0; i < ARM64_MAX_TOKEN_CNT; i++) { + if (strcmp(insn->tokens[i].name, token) == 0) { + *val = (opcode >> insn->tokens[i].pos & + ((1 << insn->tokens[i].len) - 1)); + return (0); + } + } + + return (EINVAL); +} + +static const char * +arm64_reg(int b64, int num) +{ + + if (b64 != 0) + return (x_reg[num]); + + return (w_reg[num]); +} + +vm_offset_t +disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt) +{ + struct arm64_insn *i_ptr = arm64_i; + uint32_t insn; + int matchp; + int ret; + int shift, rm, rd, rn, imm, sf; + int rm_absent; + + /* Initialize defaults, all are 0 except SF indicating 64bit access */ + shift = rd = rm = rn = imm = 0; + sf = 1; + + matchp = 0; + insn = di->di_readword(loc); + while (i_ptr->name) { + /* If mask is 0 then the parser was not initialized yet */ + if ((i_ptr->mask != 0) && + ((insn & i_ptr->mask) == i_ptr->pattern)) { + matchp = 1; + break; + } + i_ptr++; + } + if (matchp == 0) + goto undefined; + + switch (i_ptr->type) { + case TYPE_01: + /* OP , , {, #} SF32/64 + OP , , #{, } SF32/64 */ + + /* Mandatory tokens */ + ret = arm64_disasm_read_token(i_ptr, insn, "SF", &sf); + ret |= arm64_disasm_read_token(i_ptr, insn, "RD", &rd); + ret |= arm64_disasm_read_token(i_ptr, insn, "RN", &rn); + if (ret != 0) { + printf("ERROR: Missing mandatory token for op %s type %d\n", + i_ptr->name, i_ptr->type); + goto undefined; + } + + /* Optional tokens */ + arm64_disasm_read_token(i_ptr, insn, "IMM", &imm); + arm64_disasm_read_token(i_ptr, insn, "SHIFT", &shift); + rm_absent = arm64_disasm_read_token(i_ptr, insn, "RM", &rm); + + di->di_printf("%s\t%s, %s", i_ptr->name, arm64_reg(sf, rd), + arm64_reg(sf, rn)); + + /* If RM is present use it, otherwise use immediate notation */ + if (rm_absent == 0) { + di->di_printf(", %s", arm64_reg(sf, rm)); + if (imm != 0) + di->di_printf(", %s #%d", shift_2[shift], imm); + } else { + if (imm != 0 || shift != 0) + di->di_printf(", #0x%x", imm); + if (shift != 0) + di->di_printf(" LSL #12"); + } + break; + default: + goto undefined; + } + + di->di_printf("\n"); + return(loc + INSN_SIZE); + +undefined: + di->di_printf("undefined\t%08x\n", insn); + return(loc + INSN_SIZE); +} + +/* Parse format strings at the very beginning */ +SYSINIT(arm64_disasm_generate_masks, SI_SUB_DDB_SERVICES, + SI_ORDER_FIRST, arm64_disasm_generate_masks, arm64_i); diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index f8d19960139e..ffcf98982187 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -33,6 +33,8 @@ #ifndef _MACHINE_ARMREG_H_ #define _MACHINE_ARMREG_H_ +#define INSN_SIZE 4 + #define READ_SPECIALREG(reg) \ ({ uint64_t val; \ __asm __volatile("mrs %0, " __STRING(reg) : "=&r" (val)); \ diff --git a/sys/arm64/include/disassem.h b/sys/arm64/include/disassem.h new file mode 100644 index 000000000000..1a555117a066 --- /dev/null +++ b/sys/arm64/include/disassem.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2016 Cavium + * All rights reserved. + * + * This software was developed by Semihalf. + * + * 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 __DISASSEM_H_ +#define __DISASSEM_H_ + +struct disasm_interface { + u_int (*di_readword)(vm_offset_t); + void (*di_printaddr)(vm_offset_t); + int (*di_printf)(const char *, ...) __printflike(1, 2); +}; + +vm_offset_t disasm(const struct disasm_interface *, vm_offset_t, int); + +#endif /* __DISASSEM_H_ */ diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 3d5fc4679a79..bbc77c19d010 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -20,6 +20,7 @@ arm64/arm64/db_disasm.c optional ddb arm64/arm64/db_interface.c optional ddb arm64/arm64/db_trace.c optional ddb arm64/arm64/debug_monitor.c optional kdb +arm64/arm64/disassem.c optional ddb arm64/arm64/dump_machdep.c standard arm64/arm64/elf_machdep.c standard arm64/arm64/exception.S standard From 6c0e620fdbcd382232aa0d3be852301f2a75876d Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 29 Jan 2016 14:12:12 +0000 Subject: [PATCH 033/236] Add implementations of sendmmsg(3) and recvmmsg(3) functions which wraps sendmsg(2) and recvmsg(2) into batch send and receive operation. The goal of this implementation is only to provide API compatibility with Linux. The cancellation behaviour of the functions is not quite right, but due to relative rare use of cancellation it is considered acceptable comparing with the complexity of the correct implementation. If functions are reimplemented as syscalls, the fix would come almost trivial. The direct use of the syscall trampolines instead of libc wrappers for sendmsg(2) and recvmsg(2) is to avoid data loss on cancellation. Submitted by: Boris Astardzhiev Discussed with: jilles (cancellation behaviour) MFC after: 1 month --- lib/libc/gen/Makefile.inc | 4 ++ lib/libc/gen/recvmmsg.c | 96 +++++++++++++++++++++++++++++++++ lib/libc/gen/sendmmsg.c | 64 ++++++++++++++++++++++ lib/libc/include/namespace.h | 2 + lib/libc/include/un-namespace.h | 2 + lib/libc/sys/Symbol.map | 2 + lib/libc/sys/recv.2 | 95 ++++++++++++++++++++++++++++---- lib/libc/sys/send.2 | 58 ++++++++++++++++---- sys/sys/socket.h | 15 ++++++ 9 files changed, 318 insertions(+), 20 deletions(-) create mode 100644 lib/libc/gen/recvmmsg.c create mode 100644 lib/libc/gen/sendmmsg.c diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index b44846131f45..7de8ce33d647 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -99,11 +99,13 @@ SRCS+= __getosreldate.c \ raise.c \ readdir.c \ readpassphrase.c \ + recvmmsg.c \ rewinddir.c \ scandir.c \ seed48.c \ seekdir.c \ semctl.c \ + sendmmsg.c \ setdomainname.c \ sethostname.c \ setjmperr.c \ @@ -451,10 +453,12 @@ MLINKS+=rand48.3 _rand48.3 \ rand48.3 nrand48.3 \ rand48.3 seed48.3 \ rand48.3 srand48.3 +MLINKS+=recv.2 recvmmsg.2 MLINKS+=scandir.3 alphasort.3 MLINKS+=sem_open.3 sem_close.3 \ sem_open.3 sem_unlink.3 MLINKS+=sem_wait.3 sem_trywait.3 +MLINKS+=send.2 sendmmsg.2 MLINKS+=setjmp.3 _longjmp.3 \ setjmp.3 _setjmp.3 \ setjmp.3 longjmp.3 \ diff --git a/lib/libc/gen/recvmmsg.c b/lib/libc/gen/recvmmsg.c new file mode 100644 index 000000000000..0db9e1acab17 --- /dev/null +++ b/lib/libc/gen/recvmmsg.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include "libc_private.h" + +ssize_t +recvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags, + const struct timespec *__restrict timeout) +{ + struct pollfd pfd[1]; + size_t i, rcvd; + ssize_t ret; + int res; + short ev; + + if (timeout != NULL) { + pfd[0].fd = s; + pfd[0].revents = 0; + pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND | + POLLPRI; + res = ppoll(&pfd[0], 1, timeout, NULL); + if (res == -1 || res == 0) + return (res); + if (pfd[0].revents & POLLNVAL) { + errno = EBADF; + return (-1); + } + if ((pfd[0].revents & ev) == 0) { + errno = ETIMEDOUT; + return (-1); + } + } + + ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags); + if (ret == -1) + return (ret); + + /* + * Do non-blocking receive for second and later messages if + * WAITFORONE is set. + */ + if (flags & MSG_WAITFORONE) + flags |= MSG_DONTWAIT; + + rcvd = 1; + for (i = rcvd; i < vlen; i++, rcvd++) { + ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags); + if (ret == -1) { + /* We have received messages. Let caller know + * about the data received, socket + * error is returned on next + * invocation. + */ + return (rcvd); + } + + /* Save received bytes. */ + msgvec[i].msg_len = ret; + } + + return (rcvd); +} diff --git a/lib/libc/gen/sendmmsg.c b/lib/libc/gen/sendmmsg.c new file mode 100644 index 000000000000..7b3e8f357613 --- /dev/null +++ b/lib/libc/gen/sendmmsg.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "libc_private.h" + +ssize_t +sendmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags) +{ + size_t i, sent; + ssize_t ret; + + sent = 0; + for (i = 0; i < vlen; i++, sent++) { + ret = __sys_sendmsg(s, &msgvec[i].msg_hdr, flags); + if (ret == -1) { + if (sent != 0) { + /* + * We have sent messages. Let caller + * know about the data sent, socket + * error is returned on next + * invocation. + */ + return (sent); + } + return (ret); + } + + /* Save sent bytes. */ + msgvec[i].msg_len = ret; + } + + return (sent); +} diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 739d7b112392..c95829e401f1 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -208,6 +208,7 @@ #define readv _readv #define recvfrom _recvfrom #define recvmsg _recvmsg +#define recvmmsg _recvmmsg #define select _select #define sem_close _sem_close #define sem_destroy _sem_destroy @@ -220,6 +221,7 @@ #define sem_unlink _sem_unlink #define sem_wait _sem_wait #define sendmsg _sendmsg +#define sendmmsg _sendmmsg #define sendto _sendto #define setsockopt _setsockopt /*#define sigaction _sigaction*/ diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index f31fa7ade9e7..023334858572 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -189,6 +189,7 @@ #undef readv #undef recvfrom #undef recvmsg +#undef recvmmsg #undef select #undef sem_close #undef sem_destroy @@ -201,6 +202,7 @@ #undef sem_unlink #undef sem_wait #undef sendmsg +#undef sendmmsg #undef sendto #undef setsockopt #undef sigaction diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 7b3257c6a812..dc2ed0ed6e57 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -399,6 +399,8 @@ FBSD_1.4 { utimensat; numa_setaffinity; numa_getaffinity; + sendmmsg; + recvmmsg; }; FBSDprivate_1.0 { diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2 index 326e7ffd130a..4867ea77e3e5 100644 --- a/lib/libc/sys/recv.2 +++ b/lib/libc/sys/recv.2 @@ -28,14 +28,15 @@ .\" @(#)recv.2 8.3 (Berkeley) 2/21/94 .\" $FreeBSD$ .\" -.Dd October 15, 2014 +.Dd January 29, 2016 .Dt RECV 2 .Os .Sh NAME .Nm recv , .Nm recvfrom , -.Nm recvmsg -.Nd receive a message from a socket +.Nm recvmsg , +.Nm recvmmsg +.Nd receive message(s) from a socket .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -47,11 +48,14 @@ .Fn recvfrom "int s" "void *buf" "size_t len" "int flags" "struct sockaddr * restrict from" "socklen_t * restrict fromlen" .Ft ssize_t .Fn recvmsg "int s" "struct msghdr *msg" "int flags" +.Ft ssize_t +.Fn recvmmsg "int s" "struct mmsghdr * restrict msgvec" "size_t vlen" "int flags" "const struct timespec * restrict timeout" .Sh DESCRIPTION The -.Fn recvfrom +.Fn recvfrom , +.Fn recvmsg , and -.Fn recvmsg +.Fn recvmmsg system calls are used to receive messages from a socket, and may be used to receive data on a socket whether or not @@ -84,8 +88,39 @@ null pointer passed as its .Fa from argument. .Pp -All three routines return the length of the message on successful -completion. +The +.Fn recvmmsg +function is used to receive multiple +messages at a call. +Their number is supplied by +.Fa vlen . +The messages are placed in the buffers described by +.Fa msgvec +vector, after reception. +The size of each received message is placed in the +.Fa msg_len +field of each element of the vector. +If +.Fa timeout +is NULL the call blocks until the data is available for each +supplied message buffer. +Otherwise it waits for data for the specified amount of time. +If the timeout expired and there is no data received, +a value 0 is returned. +The +.Xr ppoll 2 +system call is used to implement the timeout mechanism, +before first receive is performed. +.Pp +The +.Fn recv , +.Fn recvfrom +and +.Fn recvmsg +return the length of the message on successful +completion, whereas +.Fn recvmmsg +returns the number of received messages. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from (see @@ -100,7 +135,9 @@ in which case the value .Va errno is set to .Er EAGAIN . -The receive calls normally return any data available, +The receive calls except +.Fn recvmmsg +normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested; this behavior is affected by the socket-level options @@ -109,6 +146,9 @@ and .Dv SO_RCVTIMEO described in .Xr getsockopt 2 . +The +.Fn recvmmsg +function implements this behaviour for each message in the vector. .Pp The .Xr select 2 @@ -127,6 +167,10 @@ one or more of the values: .It Dv MSG_WAITALL Ta wait for full request or error .It Dv MSG_DONTWAIT Ta do not block .It Dv MSG_CMSG_CLOEXEC Ta set received fds close-on-exec +.It Dv MSG_WAITFORONE Ta do not block after receiving the first message +(only for +.Fn recvmmsg +) .El .Pp The @@ -158,6 +202,11 @@ is set to This flag is not available in strict .Tn ANSI or C99 compilation mode. +The +.Dv MSG_WAITFORONE +flag sets MSG_DONTWAIT after the first message has been received. +This flag is only relevant for +.Fn recvmmsg . .Pp The .Fn recvmsg @@ -290,9 +339,31 @@ control data were discarded due to lack of space in the buffer for ancillary data. .Dv MSG_OOB is returned to indicate that expedited or out-of-band data were received. +.Pp +The +.Fn recvmmsg +system call uses the +.Fa mmsghdr +structure, defined as follows in the +.In sys/socket.h +header : +.Bd -literal +struct mmsghdr { + struct msghdr msg_hdr; /* message header */ + ssize_t msg_len; /* message length */ +}; +.Ed +.Pp +On data reception the +.Fa msg_len +field is updated to the length of the received message. .Sh RETURN VALUES -These calls return the number of bytes received, or -1 -if an error occurred. +These calls except +.Fn recvmmsg +return the number of bytes received. +.Fn recvmmsg +returns the number of messages received. +A value of -1 is returned if an error occurred. .Sh ERRORS The calls fail if: .Bl -tag -width Er @@ -347,3 +418,7 @@ The .Fn recv function appeared in .Bx 4.2 . +The +.Fn recvmmsg +function appeared in +.Fx 11.0 . diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2 index 8fa2c64354d0..db2f4ee2a880 100644 --- a/lib/libc/sys/send.2 +++ b/lib/libc/sys/send.2 @@ -28,14 +28,15 @@ .\" From: @(#)send.2 8.2 (Berkeley) 2/21/94 .\" $FreeBSD$ .\" -.Dd February 5, 2009 +.Dd January 29, 2016 .Dt SEND 2 .Os .Sh NAME .Nm send , .Nm sendto , -.Nm sendmsg -.Nd send a message from a socket +.Nm sendmsg , +.Nm sendmmsg +.Nd send message(s) from a socket .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -47,25 +48,33 @@ .Fn sendto "int s" "const void *msg" "size_t len" "int flags" "const struct sockaddr *to" "socklen_t tolen" .Ft ssize_t .Fn sendmsg "int s" "const struct msghdr *msg" "int flags" +.Ft ssize_t +.Fn sendmmsg "int s" "struct mmsghdr * restrict msgvec" "size_t vlen" "int flags" .Sh DESCRIPTION The .Fn send -function, +and +.Fn sendmmsg +functions, and .Fn sendto and .Fn sendmsg system calls -are used to transmit a message to another socket. +are used to transmit one or more messages (with the +.Fn sendmmsg +call) to +another socket. The .Fn send function may be used only when the socket is in a .Em connected state, while -.Fn sendto -and +.Fn sendto , .Fn sendmsg +and +.Fn sendmmsg may be used at any time. .Pp The address of the target is given by @@ -81,6 +90,18 @@ underlying protocol, the error is returned, and the message is not transmitted. .Pp +The +.Fn sendmmsg +function sends multiple messages at a call. +They are given by the +.Fa msgvec +vector along with +.Fa vlen +specifying the vector size. +The number of octets sent per each message is placed in the +.Fa msg_len +field of each processed element of the vector after transmission. +.Pp No indication of failure to deliver is implicit in a .Fn send . Locally detected errors are indicated by a return value of -1. @@ -138,14 +159,27 @@ See .Xr recv 2 for a description of the .Fa msghdr +structure and the +.Fa mmsghdr structure. .Sh RETURN VALUES -The call returns the number of characters sent, or -1 -if an error occurred. +The +.Fn send , +.Fn sendto +and +.Fn sendmsg +calls +return the number of octets sent. +The +.Fn sendmmsg +call returns the number of messages sent. +If an error occurred a value of -1 is returned. .Sh ERRORS The .Fn send -function and +and +.Fn sendmmsg +functions and .Fn sendto and .Fn sendmsg @@ -215,6 +249,10 @@ The .Fn send function appeared in .Bx 4.2 . +The +.Fn sendmmsg +function appeared in +.Fx 11.0 . .Sh BUGS Because .Fn sendmsg diff --git a/sys/sys/socket.h b/sys/sys/socket.h index ee621d9dd1e8..c20b07522c97 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -431,6 +431,7 @@ struct msghdr { #define MSG_NBIO 0x4000 /* FIONBIO mode, used by fifofs */ #define MSG_COMPAT 0x8000 /* used in sendit() */ #define MSG_CMSG_CLOEXEC 0x40000 /* make received fds close-on-exec */ +#define MSG_WAITFORONE 0x80000 /* for recvmmsg() */ #endif #ifdef _KERNEL #define MSG_SOCALLBCK 0x10000 /* for use by socket callbacks - soreceive (TCP) */ @@ -596,6 +597,14 @@ struct sf_hdtr { #define SFK_COMPAT 0x00000001 #define SF_READAHEAD(flags) ((flags) >> 16) #endif /* _KERNEL */ + +/* + * Sendmmsg/recvmmsg specific structure(s) + */ +struct mmsghdr { + struct msghdr msg_hdr; /* message header */ + ssize_t msg_len; /* message length */ +}; #endif /* __BSD_VISIBLE */ #ifndef _KERNEL @@ -618,12 +627,18 @@ int listen(int, int); ssize_t recv(int, void *, size_t, int); ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict); ssize_t recvmsg(int, struct msghdr *, int); +#if __BSD_VISIBLE +struct timespec; +ssize_t recvmmsg(int, struct mmsghdr * __restrict, size_t, int, + const struct timespec * __restrict); +#endif ssize_t send(int, const void *, size_t, int); ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); ssize_t sendmsg(int, const struct msghdr *, int); #if __BSD_VISIBLE int sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int); +ssize_t sendmmsg(int, struct mmsghdr * __restrict, size_t, int); int setfib(int); #endif int setsockopt(int, int, int, const void *, socklen_t); From 778a34fa2a878f3f49f6793fe0729d5203e9539a Mon Sep 17 00:00:00 2001 From: br Date: Fri, 29 Jan 2016 15:12:31 +0000 Subject: [PATCH 034/236] Welcome the RISC-V 64-bit kernel. This is the final step required allowing to compile and to run RISC-V kernel and userland from HEAD. RISC-V is a completely open ISA that is freely available to academia and industry. Thanks to all the people involved! Special thanks to Andrew Turner, David Chisnall, Ed Maste, Konstantin Belousov, John Baldwin and Arun Thomas for their help. Thanks to Robert Watson for organizing this project. This project sponsored by UK Higher Education Innovation Fund (HEIF5) and DARPA CTSRD project at the University of Cambridge Computer Laboratory. FreeBSD/RISC-V project home: https://wiki.freebsd.org/riscv Reviewed by: andrew, emaste, kib Relnotes: Yes Sponsored by: DARPA, AFRL Sponsored by: HEIF5 Differential Revision: https://reviews.freebsd.org/D4982 --- sys/boot/fdt/dts/riscv/spike.dts | 92 + sys/boot/ficl/riscv/sysdep.c | 99 + sys/boot/ficl/riscv/sysdep.h | 411 +++ sys/cddl/compat/opensolaris/sys/atomic.h | 2 +- .../opensolaris/uts/common/sys/isa_defs.h | 42 + sys/conf/Makefile.riscv | 49 + sys/conf/files.riscv | 44 + sys/conf/kern.mk | 4 + sys/conf/kern.pre.mk | 1 + sys/conf/ldscript.riscv | 136 + sys/conf/options.riscv | 4 + sys/dev/hwpmc/hwpmc_riscv.h | 51 + sys/riscv/conf/DEFAULTS | 13 + sys/riscv/conf/GENERIC | 104 + sys/riscv/htif/htif.c | 284 ++ sys/riscv/htif/htif.h | 93 + sys/riscv/htif/htif_block.c | 289 ++ sys/riscv/htif/htif_console.c | 361 ++ sys/riscv/riscv/autoconf.c | 94 + sys/riscv/riscv/bcopy.c | 139 + sys/riscv/riscv/bus_machdep.c | 144 + sys/riscv/riscv/busdma_machdep.c | 102 + sys/riscv/riscv/clock.c | 46 + sys/riscv/riscv/copyinout.S | 137 + sys/riscv/riscv/copystr.c | 59 + sys/riscv/riscv/cpufunc_asm.S | 101 + sys/riscv/riscv/devmap.c | 61 + sys/riscv/riscv/dump_machdep.c | 57 + sys/riscv/riscv/elf_machdep.c | 169 + sys/riscv/riscv/exception.S | 456 +++ sys/riscv/riscv/genassym.c | 98 + sys/riscv/riscv/identcpu.c | 149 + sys/riscv/riscv/in_cksum.c | 241 ++ sys/riscv/riscv/intr_machdep.c | 223 ++ sys/riscv/riscv/locore.S | 274 ++ sys/riscv/riscv/machdep.c | 795 ++++ sys/riscv/riscv/mem.c | 124 + sys/riscv/riscv/minidump_machdep.c | 59 + sys/riscv/riscv/nexus.c | 387 ++ sys/riscv/riscv/pmap.c | 3197 +++++++++++++++++ sys/riscv/riscv/support.S | 295 ++ sys/riscv/riscv/swtch.S | 272 ++ sys/riscv/riscv/sys_machdep.c | 49 + sys/riscv/riscv/timer.c | 298 ++ sys/riscv/riscv/trap.c | 311 ++ sys/riscv/riscv/uio_machdep.c | 134 + sys/riscv/riscv/uma_machdep.c | 55 + sys/riscv/riscv/vm_machdep.c | 259 ++ sys/sys/cdefs.h | 2 +- sys/sys/kerneldump.h | 1 + 50 files changed, 10865 insertions(+), 2 deletions(-) create mode 100644 sys/boot/fdt/dts/riscv/spike.dts create mode 100644 sys/boot/ficl/riscv/sysdep.c create mode 100644 sys/boot/ficl/riscv/sysdep.h create mode 100644 sys/conf/Makefile.riscv create mode 100644 sys/conf/files.riscv create mode 100644 sys/conf/ldscript.riscv create mode 100644 sys/conf/options.riscv create mode 100644 sys/dev/hwpmc/hwpmc_riscv.h create mode 100644 sys/riscv/conf/DEFAULTS create mode 100644 sys/riscv/conf/GENERIC create mode 100644 sys/riscv/htif/htif.c create mode 100644 sys/riscv/htif/htif.h create mode 100644 sys/riscv/htif/htif_block.c create mode 100644 sys/riscv/htif/htif_console.c create mode 100644 sys/riscv/riscv/autoconf.c create mode 100644 sys/riscv/riscv/bcopy.c create mode 100644 sys/riscv/riscv/bus_machdep.c create mode 100644 sys/riscv/riscv/busdma_machdep.c create mode 100644 sys/riscv/riscv/clock.c create mode 100644 sys/riscv/riscv/copyinout.S create mode 100644 sys/riscv/riscv/copystr.c create mode 100644 sys/riscv/riscv/cpufunc_asm.S create mode 100644 sys/riscv/riscv/devmap.c create mode 100644 sys/riscv/riscv/dump_machdep.c create mode 100644 sys/riscv/riscv/elf_machdep.c create mode 100644 sys/riscv/riscv/exception.S create mode 100644 sys/riscv/riscv/genassym.c create mode 100644 sys/riscv/riscv/identcpu.c create mode 100644 sys/riscv/riscv/in_cksum.c create mode 100644 sys/riscv/riscv/intr_machdep.c create mode 100644 sys/riscv/riscv/locore.S create mode 100644 sys/riscv/riscv/machdep.c create mode 100644 sys/riscv/riscv/mem.c create mode 100644 sys/riscv/riscv/minidump_machdep.c create mode 100644 sys/riscv/riscv/nexus.c create mode 100644 sys/riscv/riscv/pmap.c create mode 100644 sys/riscv/riscv/support.S create mode 100644 sys/riscv/riscv/swtch.S create mode 100644 sys/riscv/riscv/sys_machdep.c create mode 100644 sys/riscv/riscv/timer.c create mode 100644 sys/riscv/riscv/trap.c create mode 100644 sys/riscv/riscv/uio_machdep.c create mode 100644 sys/riscv/riscv/uma_machdep.c create mode 100644 sys/riscv/riscv/vm_machdep.c diff --git a/sys/boot/fdt/dts/riscv/spike.dts b/sys/boot/fdt/dts/riscv/spike.dts new file mode 100644 index 000000000000..c5013340d538 --- /dev/null +++ b/sys/boot/fdt/dts/riscv/spike.dts @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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$ + */ + +/dts-v1/; + +/ { + model = "UC Berkeley Spike Simulator RV64I"; + compatible = "riscv,rv64i"; + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <1>; + + aliases { + console0 = &console0; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x8000000>; /* 128MB at 0x0 */ + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + #interrupt-cells = <1>; + + compatible = "simple-bus"; + ranges; + + pic0: pic@0 { + compatible = "riscv,pic"; + interrupt-controller; + }; + + timer0: timer@0 { + compatible = "riscv,timer"; + interrupts = < 1 >; + interrupt-parent = < &pic0 >; + clock-frequency = < 1000000 >; + }; + + htif0: htif@0 { + compatible = "riscv,htif"; + interrupts = < 0 >; + interrupt-parent = < &pic0 >; + + console0: console@0 { + compatible = "htif,console"; + status = "okay"; + }; + }; + }; + + chosen { + bootargs = "-v"; + stdin = "console0"; + stdout = "console0"; + }; +}; diff --git a/sys/boot/ficl/riscv/sysdep.c b/sys/boot/ficl/riscv/sysdep.c new file mode 100644 index 000000000000..ad38660843cd --- /dev/null +++ b/sys/boot/ficl/riscv/sysdep.c @@ -0,0 +1,99 @@ +/******************************************************************* +** s y s d e p . c +** Forth Inspired Command Language +** Author: John Sadler (john_sadler@alum.mit.edu) +** Created: 16 Oct 1997 +** Implementations of FICL external interface functions... +** +*******************************************************************/ + +/* $FreeBSD$ */ + +#ifdef TESTMAIN +#include +#include +#else +#include +#endif +#include "ficl.h" + +/* +******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith +*/ + +#if PORTABLE_LONGMULDIV == 0 +DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) +{ + DPUNS q; + u_int64_t qx; + + qx = (u_int64_t)x * (u_int64_t) y; + + q.hi = (u_int32_t)( qx >> 32 ); + q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + + return q; +} + +UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) +{ + UNSQR result; + u_int64_t qx, qh; + + qh = q.hi; + qx = (qh << 32) | q.lo; + + result.quot = qx / y; + result.rem = qx % y; + + return result; +} +#endif + +void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) +{ + IGNORE(pVM); + + while(*msg != 0) + putchar(*(msg++)); + if (fNewline) + putchar('\n'); + + return; +} + +void *ficlMalloc (size_t size) +{ + return malloc(size); +} + +void *ficlRealloc (void *p, size_t size) +{ + return realloc(p, size); +} + +void ficlFree (void *p) +{ + free(p); +} + + +/* +** Stub function for dictionary access control - does nothing +** by default, user can redefine to guarantee exclusive dict +** access to a single thread for updates. All dict update code +** is guaranteed to be bracketed as follows: +** ficlLockDictionary(TRUE); +** +** ficlLockDictionary(FALSE); +** +** Returns zero if successful, nonzero if unable to acquire lock +** befor timeout (optional - could also block forever) +*/ +#if FICL_MULTITHREAD +int ficlLockDictionary(short fLock) +{ + IGNORE(fLock); + return 0; +} +#endif /* FICL_MULTITHREAD */ diff --git a/sys/boot/ficl/riscv/sysdep.h b/sys/boot/ficl/riscv/sysdep.h new file mode 100644 index 000000000000..3726b9ef838f --- /dev/null +++ b/sys/boot/ficl/riscv/sysdep.h @@ -0,0 +1,411 @@ +/******************************************************************* + s y s d e p . h +** Forth Inspired Command Language +** Author: John Sadler (john_sadler@alum.mit.edu) +** Created: 16 Oct 1997 +** Ficl system dependent types and prototypes... +** +** Note: Ficl also depends on the use of "assert" when +** FICL_ROBUST is enabled. This may require some consideration +** in firmware systems since assert often +** assumes stderr/stdout. +** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $ +*******************************************************************/ +/* +** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +** All rights reserved. +** +** Get the latest Ficl release at http://ficl.sourceforge.net +** +** L I C E N S E and D I S C L A I M E R +** +** 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. +** +** I am interested in hearing from anyone who uses ficl. If you have +** a problem, a success story, a defect, an enhancement request, or +** if you would like to contribute to the ficl release, please send +** contact me by email at the address above. +** +** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $ +** $FreeBSD$ +*/ + +#if !defined (__SYSDEP_H__) +#define __SYSDEP_H__ + +#include + +#include /* size_t, NULL */ +#include +#include + +#if !defined IGNORE /* Macro to silence unused param warnings */ +#define IGNORE(x) (void)(x) +#endif + +/* +** TRUE and FALSE for C boolean operations, and +** portable 32 bit types for CELLs +** +*/ +#if !defined TRUE +#define TRUE 1 +#endif +#if !defined FALSE +#define FALSE 0 +#endif + + +/* +** System dependent data type declarations... +*/ +#if !defined INT32 +#define INT32 int +#endif + +#if !defined UNS32 +#define UNS32 unsigned int +#endif + +#if !defined UNS16 +#define UNS16 unsigned short +#endif + +#if !defined UNS8 +#define UNS8 unsigned char +#endif + +#if !defined NULL +#define NULL ((void *)0) +#endif + +/* +** FICL_UNS and FICL_INT must have the same size as a void* on +** the target system. A CELL is a union of void*, FICL_UNS, and +** FICL_INT. +** (11/2000: same for FICL_FLOAT) +*/ +#if !defined FICL_INT +#define FICL_INT long +#endif + +#if !defined FICL_UNS +#define FICL_UNS unsigned long +#endif + +#if !defined FICL_FLOAT +#define FICL_FLOAT float +#endif + +/* +** Ficl presently supports values of 32 and 64 for BITS_PER_CELL +*/ +#if !defined BITS_PER_CELL +#define BITS_PER_CELL 64 +#endif + +#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64)) + Error! +#endif + +typedef struct +{ + FICL_UNS hi; + FICL_UNS lo; +} DPUNS; + +typedef struct +{ + FICL_UNS quot; + FICL_UNS rem; +} UNSQR; + +typedef struct +{ + FICL_INT hi; + FICL_INT lo; +} DPINT; + +typedef struct +{ + FICL_INT quot; + FICL_INT rem; +} INTQR; + + +/* +** B U I L D C O N T R O L S +*/ + +#if !defined (FICL_MINIMAL) +#define FICL_MINIMAL 0 +#endif +#if (FICL_MINIMAL) +#define FICL_WANT_SOFTWORDS 0 +#define FICL_WANT_FLOAT 0 +#define FICL_WANT_USER 0 +#define FICL_WANT_LOCALS 0 +#define FICL_WANT_DEBUGGER 0 +#define FICL_WANT_OOP 0 +#define FICL_PLATFORM_EXTEND 0 +#define FICL_MULTITHREAD 0 +#define FICL_ROBUST 0 +#define FICL_EXTENDED_PREFIX 0 +#endif + +/* +** FICL_PLATFORM_EXTEND +** Includes words defined in ficlCompilePlatform +*/ +#if !defined (FICL_PLATFORM_EXTEND) +#define FICL_PLATFORM_EXTEND 1 +#endif + +/* +** FICL_WANT_FLOAT +** Includes a floating point stack for the VM, and words to do float operations. +** Contributed by Guy Carver +*/ +#if !defined (FICL_WANT_FLOAT) +#define FICL_WANT_FLOAT 0 +#endif + +/* +** FICL_WANT_DEBUGGER +** Inludes a simple source level debugger +*/ +#if !defined (FICL_WANT_DEBUGGER) +#define FICL_WANT_DEBUGGER 1 +#endif + +/* +** User variables: per-instance variables bound to the VM. +** Kinda like thread-local storage. Could be implemented in a +** VM private dictionary, but I've chosen the lower overhead +** approach of an array of CELLs instead. +*/ +#if !defined FICL_WANT_USER +#define FICL_WANT_USER 1 +#endif + +#if !defined FICL_USER_CELLS +#define FICL_USER_CELLS 16 +#endif + +/* +** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and +** a private dictionary for local variable compilation. +*/ +#if !defined FICL_WANT_LOCALS +#define FICL_WANT_LOCALS 1 +#endif + +/* Max number of local variables per definition */ +#if !defined FICL_MAX_LOCALS +#define FICL_MAX_LOCALS 16 +#endif + +/* +** FICL_WANT_OOP +** Inludes object oriented programming support (in softwords) +** OOP support requires locals and user variables! +*/ +#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER) +#if !defined (FICL_WANT_OOP) +#define FICL_WANT_OOP 0 +#endif +#endif + +#if !defined (FICL_WANT_OOP) +#define FICL_WANT_OOP 1 +#endif + +/* +** FICL_WANT_SOFTWORDS +** Controls inclusion of all softwords in softcore.c +*/ +#if !defined (FICL_WANT_SOFTWORDS) +#define FICL_WANT_SOFTWORDS 1 +#endif + +/* +** FICL_MULTITHREAD enables dictionary mutual exclusion +** wia the ficlLockDictionary system dependent function. +** Note: this implementation is experimental and poorly +** tested. Further, it's unnecessary unless you really +** intend to have multiple SESSIONS (poor choice of name +** on my part) - that is, threads that modify the dictionary +** at the same time. +*/ +#if !defined FICL_MULTITHREAD +#define FICL_MULTITHREAD 0 +#endif + +/* +** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be +** defined in C in sysdep.c. Use this if you cannot easily +** generate an inline asm definition +*/ +#if !defined (PORTABLE_LONGMULDIV) +#define PORTABLE_LONGMULDIV 0 +#endif + +/* +** INLINE_INNER_LOOP causes the inner interpreter to be inline code +** instead of a function call. This is mainly because MS VC++ 5 +** chokes with an internal compiler error on the function version. +** in release mode. Sheesh. +*/ +#if !defined INLINE_INNER_LOOP +#if defined _DEBUG +#define INLINE_INNER_LOOP 0 +#else +#define INLINE_INNER_LOOP 1 +#endif +#endif + +/* +** FICL_ROBUST enables bounds checking of stacks and the dictionary. +** This will detect stack over and underflows and dictionary overflows. +** Any exceptional condition will result in an assertion failure. +** (As generated by the ANSI assert macro) +** FICL_ROBUST == 1 --> stack checking in the outer interpreter +** FICL_ROBUST == 2 also enables checking in many primitives +*/ + +#if !defined FICL_ROBUST +#define FICL_ROBUST 2 +#endif + +/* +** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of +** a new virtual machine's stacks, unless overridden at +** create time. +*/ +#if !defined FICL_DEFAULT_STACK +#define FICL_DEFAULT_STACK 128 +#endif + +/* +** FICL_DEFAULT_DICT specifies the number of CELLs to allocate +** for the system dictionary by default. The value +** can be overridden at startup time as well. +** FICL_DEFAULT_ENV specifies the number of cells to allot +** for the environment-query dictionary. +*/ +#if !defined FICL_DEFAULT_DICT +#define FICL_DEFAULT_DICT 12288 +#endif + +#if !defined FICL_DEFAULT_ENV +#define FICL_DEFAULT_ENV 260 +#endif + +/* +** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in +** the dictionary search order. See Forth DPANS sec 16.3.3 +** (file://dpans16.htm#16.3.3) +*/ +#if !defined FICL_DEFAULT_VOCS +#define FICL_DEFAULT_VOCS 16 +#endif + +/* +** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure +** that stores pointers to parser extension functions. I would never expect to have +** more than 8 of these, so that's the default limit. Too many of these functions +** will probably exact a nasty performance penalty. +*/ +#if !defined FICL_MAX_PARSE_STEPS +#define FICL_MAX_PARSE_STEPS 8 +#endif + +/* +** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if +** included as part of softcore.c) +*/ +#if !defined FICL_EXTENDED_PREFIX +#define FICL_EXTENDED_PREFIX 0 +#endif + +/* +** FICL_ALIGN is the power of two to which the dictionary +** pointer address must be aligned. This value is usually +** either 1 or 2, depending on the memory architecture +** of the target system; 2 is safe on any 16 or 32 bit +** machine. 3 would be appropriate for a 64 bit machine. +*/ +#if !defined FICL_ALIGN +#define FICL_ALIGN 3 +#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1) +#endif + +/* +** System dependent routines -- +** edit the implementations in sysdep.c to be compatible +** with your runtime environment... +** ficlTextOut sends a NULL terminated string to the +** default output device - used for system error messages +** ficlMalloc and ficlFree have the same semantics as malloc and free +** in standard C +** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned +** product +** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient +** and remainder +*/ +struct vm; +void ficlTextOut(struct vm *pVM, char *msg, int fNewline); +void *ficlMalloc (size_t size); +void ficlFree (void *p); +void *ficlRealloc(void *p, size_t size); +/* +** Stub function for dictionary access control - does nothing +** by default, user can redefine to guarantee exclusive dict +** access to a single thread for updates. All dict update code +** must be bracketed as follows: +** ficlLockDictionary(TRUE); +** +** ficlLockDictionary(FALSE); +** +** Returns zero if successful, nonzero if unable to acquire lock +** before timeout (optional - could also block forever) +** +** NOTE: this function must be implemented with lock counting +** semantics: nested calls must behave properly. +*/ +#if FICL_MULTITHREAD +int ficlLockDictionary(short fLock); +#else +#define ficlLockDictionary(x) 0 /* ignore */ +#endif + +/* +** 64 bit integer math support routines: multiply two UNS32s +** to get a 64 bit product, & divide the product by an UNS32 +** to get an UNS32 quotient and remainder. Much easier in asm +** on a 32 bit CPU than in C, which usually doesn't support +** the double length result (but it should). +*/ +DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y); +UNSQR ficlLongDiv(DPUNS q, FICL_UNS y); + +#endif /*__SYSDEP_H__*/ diff --git a/sys/cddl/compat/opensolaris/sys/atomic.h b/sys/cddl/compat/opensolaris/sys/atomic.h index 363d55893532..81f75da80772 100644 --- a/sys/cddl/compat/opensolaris/sys/atomic.h +++ b/sys/cddl/compat/opensolaris/sys/atomic.h @@ -51,7 +51,7 @@ extern uint8_t atomic_or_8_nv(volatile uint8_t *target, uint8_t value); extern void membar_producer(void); #if defined(__sparc64__) || defined(__powerpc__) || defined(__arm__) || \ - defined(__mips__) || defined(__aarch64__) + defined(__mips__) || defined(__aarch64__) || defined(__riscv__) extern void atomic_or_8(volatile uint8_t *target, uint8_t value); #else static __inline void diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h index 281abd755919..e46330c4ec4a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h @@ -388,6 +388,48 @@ extern "C" { #define _DONT_USE_1275_GENERIC_NAMES #define _HAVE_CPUID_INSN +#elif defined(__riscv__) + +/* + * Define the appropriate "processor characteristics" + */ +#define _STACK_GROWS_DOWNWARD +#define _LONG_LONG_LTOH +#define _BIT_FIELDS_LTOH +#define _IEEE_754 +#define _CHAR_IS_UNSIGNED +#define _BOOL_ALIGNMENT 1 +#define _CHAR_ALIGNMENT 1 +#define _SHORT_ALIGNMENT 2 +#define _INT_ALIGNMENT 4 +#define _FLOAT_ALIGNMENT 4 +#define _FLOAT_COMPLEX_ALIGNMENT 4 +#define _LONG_ALIGNMENT 8 +#define _LONG_LONG_ALIGNMENT 8 +#define _DOUBLE_ALIGNMENT 8 +#define _DOUBLE_COMPLEX_ALIGNMENT 8 +#define _LONG_DOUBLE_ALIGNMENT 16 +#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16 +#define _POINTER_ALIGNMENT 8 +#define _MAX_ALIGNMENT 16 +#define _ALIGNMENT_REQUIRED 1 + +#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT + +/* + * Define the appropriate "implementation choices" + */ +#if !defined(_LP64) +#define _LP64 +#endif +#define _SUNOS_VTOC_16 +#define _DMA_USES_PHYSADDR +#define _FIRMWARE_NEEDS_FDISK +#define _PSM_MODULES +#define _RTC_CONFIG +#define _DONT_USE_1275_GENERIC_NAMES +#define _HAVE_CPUID_INSN + #elif defined(__arm__) /* diff --git a/sys/conf/Makefile.riscv b/sys/conf/Makefile.riscv new file mode 100644 index 000000000000..27338b470413 --- /dev/null +++ b/sys/conf/Makefile.riscv @@ -0,0 +1,49 @@ +# Makefile.riscv -- with config changes. +# Copyright 1990 W. Jolitz +# from: @(#)Makefile.i386 7.1 5/10/91 +# from FreeBSD: src/sys/conf/Makefile.i386,v 1.255 2002/02/20 23:35:49 +# $FreeBSD$ +# +# Makefile for FreeBSD +# +# RISCVTODO: copy pasted from aarch64, needs to be +# constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/riscv/conf/``machineid'' +# after which you should do +# config machineid +# Generic makefile changes should be made in +# /sys/conf/Makefile.riscv +# after which config should be rerun for all machines. +# + +# Which version of config(8) is required. +%VERSREQ= 600012 + +.if !defined(S) +S= ../../.. +.endif +.include "$S/conf/kern.pre.mk" + +INCLUDES+= -I$S/contrib/libfdt + +.if !empty(DDB_ENABLED) +CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer +.endif + +%BEFORE_DEPEND + +%OBJS + +%FILES.c + +%FILES.s + +%FILES.m + +%CLEAN + +%RULES + +.include "$S/conf/kern.post.mk" diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv new file mode 100644 index 000000000000..a101b57cfe2f --- /dev/null +++ b/sys/conf/files.riscv @@ -0,0 +1,44 @@ +# $FreeBSD$ +crypto/blowfish/bf_enc.c optional crypto | ipsec +crypto/des/des_enc.c optional crypto | ipsec | netsmb +kern/kern_clocksource.c standard +kern/subr_dummy_vdso_tc.c standard +libkern/bcmp.c standard +libkern/ffs.c standard +libkern/ffsl.c standard +libkern/fls.c standard +libkern/flsl.c standard +libkern/flsll.c standard +libkern/memmove.c standard +libkern/memset.c standard +riscv/htif/htif.c standard +riscv/htif/htif_block.c standard +riscv/htif/htif_console.c standard +riscv/riscv/autoconf.c standard +riscv/riscv/bcopy.c standard +riscv/riscv/bus_machdep.c standard +riscv/riscv/busdma_machdep.c standard +riscv/riscv/clock.c standard +riscv/riscv/copyinout.S standard +riscv/riscv/copystr.c standard +riscv/riscv/cpufunc_asm.S standard +riscv/riscv/devmap.c standard +riscv/riscv/dump_machdep.c standard +riscv/riscv/elf_machdep.c standard +riscv/riscv/intr_machdep.c standard +riscv/riscv/in_cksum.c optional inet | inet6 +riscv/riscv/identcpu.c standard +riscv/riscv/locore.S standard no-obj +riscv/riscv/minidump_machdep.c standard +riscv/riscv/machdep.c standard +riscv/riscv/mem.c standard +riscv/riscv/nexus.c standard +riscv/riscv/pmap.c standard +riscv/riscv/sys_machdep.c standard +riscv/riscv/support.S standard +riscv/riscv/swtch.S standard +riscv/riscv/trap.c standard +riscv/riscv/timer.c standard +riscv/riscv/uio_machdep.c standard +riscv/riscv/uma_machdep.c standard +riscv/riscv/vm_machdep.c standard diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk index 56ddbda4996e..fb72a9789482 100644 --- a/sys/conf/kern.mk +++ b/sys/conf/kern.mk @@ -104,6 +104,10 @@ CFLAGS += -mgeneral-regs-only CFLAGS += -ffixed-x18 .endif +.if ${MACHINE_CPUARCH} == "riscv" +INLINE_LIMIT?= 8000 +.endif + # # For sparc64 we want the medany code model so modules may be located # anywhere in the 64-bit address space. We also tell GCC to use floating diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 7860701e8440..c9623cbfc512 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -252,6 +252,7 @@ EMBEDFS_FORMAT.mips?= elf32-tradbigmips EMBEDFS_FORMAT.mipsel?= elf32-tradlittlemips EMBEDFS_FORMAT.mips64?= elf64-tradbigmips EMBEDFS_FORMAT.mips64el?= elf64-tradlittlemips +EMBEDFS_FORMAT.riscv?= elf64-littleriscv .endif # Detect kernel config options that force stack frames to be turned on. diff --git a/sys/conf/ldscript.riscv b/sys/conf/ldscript.riscv new file mode 100644 index 000000000000..31fd5df9ce4e --- /dev/null +++ b/sys/conf/ldscript.riscv @@ -0,0 +1,136 @@ +/* $FreeBSD$ */ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +SEARCH_DIR(/usr/lib); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = kernbase + 0x100; + .text : AT(ADDR(.text) - kernbase) + { + *(.text) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0x9090 + _etext = .; + PROVIDE (etext = .); + .fini : { *(.fini) } =0x9090 + .rodata : { *(.rodata) *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x9090 + .plt : { *(.plt) } + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x1000) + (. & (0x1000 - 1)) ; + .data : + { + *(.data) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + . = ALIGN(32 / 8); + _start_ctors = .; + PROVIDE (start_ctors = .); + .ctors : + { + *(.ctors) + } + _stop_ctors = .; + PROVIDE (stop_ctors = .); + .dtors : + { + *(.dtors) + } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + . = ALIGN(8); + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + . = ALIGN(8); + _end = . ; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/sys/conf/options.riscv b/sys/conf/options.riscv new file mode 100644 index 000000000000..c263bd860875 --- /dev/null +++ b/sys/conf/options.riscv @@ -0,0 +1,4 @@ +# $FreeBSD$ + +RISCV opt_global.h +VFP opt_global.h diff --git a/sys/dev/hwpmc/hwpmc_riscv.h b/sys/dev/hwpmc/hwpmc_riscv.h new file mode 100644 index 000000000000..3f1f5999f6bc --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_riscv.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory with support from ARM Ltd. + * + * 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 _DEV_HWPMC_RISCV_H_ +#define _DEV_HWPMC_RISCV_H_ + +#define RISCV_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ + PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ + PMC_CAP_THRESHOLD | PMC_CAP_READ | \ + PMC_CAP_WRITE | PMC_CAP_INVERT | \ + PMC_CAP_QUALIFIER) + +#define RISCV_RELOAD_COUNT_TO_PERFCTR_VALUE(R) (-(R)) +#define RISCV_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P)) +#define EVENT_ID_MASK 0xFF + +#ifdef _KERNEL +/* MD extension for 'struct pmc' */ +struct pmc_md_riscv_pmc { + uint32_t pm_riscv_evsel; +}; +#endif /* _KERNEL */ +#endif /* _DEV_HWPMC_RISCV_H_ */ diff --git a/sys/riscv/conf/DEFAULTS b/sys/riscv/conf/DEFAULTS new file mode 100644 index 000000000000..5451decf822d --- /dev/null +++ b/sys/riscv/conf/DEFAULTS @@ -0,0 +1,13 @@ +# +# DEFAULTS -- Default kernel configuration file for FreeBSD/RISC-V +# +# $FreeBSD$ + +machine riscv riscv64 + +# Pseudo devices. +device mem # Memory and kernel memory devices + +# Default partitioning schemes +options GEOM_PART_BSD +options GEOM_PART_MBR diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC new file mode 100644 index 000000000000..a32a1f24ecfb --- /dev/null +++ b/sys/riscv/conf/GENERIC @@ -0,0 +1,104 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/RISC-V +# +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +cpu RISCV +ident GENERIC + +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +# makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support +makeoptions NO_MODULES=1 # We don't yet support modules on RISC-V + +options SCHED_ULE # ULE scheduler +options PREEMPTION # Enable kernel thread preemption +options INET # InterNETworking +options INET6 # IPv6 communications protocols +options IPSEC # IP (v4/v6) security +options TCP_OFFLOAD # TCP offload +options SCTP # Stream Control Transmission Protocol +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options MD_ROOT # MD is a potential root device +options NFSCL # Network Filesystem Client +options NFSD # Network Filesystem Server +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options GEOM_PART_GPT # GUID Partition Tables. +# options GEOM_RAID # Soft RAID functionality. +options GEOM_LABEL # Provides labelization +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +# options STACK # stack(9) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +# options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) +options AUDIT # Security event auditing +options CAPABILITY_MODE # Capsicum capability mode +options CAPABILITIES # Capsicum capabilities +options MAC # TrustedBSD MAC Framework +# options KDTRACE_FRAME # Ensure frames are compiled in +# options KDTRACE_HOOKS # Kernel DTrace hooks +# options VFP # Floating-point support +options RACCT # Resource accounting framework +options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default +options RCTL # Resource limits +# options SMP + +# Debugging support. Always need this: +# options KDB # Enable kernel debugger support. +# options KDB_TRACE # Print a stack trace for a panic. +# For full debugger support use (turn off in stable branch): +# options DDB # Support DDB. +# options GDB # Support remote GDB. +options DEADLKRES # Enable the deadlock resolver +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +# options WITNESS # Enable checks to detect deadlocks and cycles +# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones + +options ROOTDEVNAME=\"ufs:/dev/htif_blk0\" +# options EARLY_PRINTF + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +device vlan # 802.1Q VLAN support +device tun # Packet tunnel. +device md # Memory "disks" +device gif # IPv6 and IPv4 tunneling +device firmware # firmware assist module + +# RISCVTODO: This needs to be done via loader (when it's available). +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=spike.dts diff --git a/sys/riscv/htif/htif.c b/sys/riscv/htif/htif.c new file mode 100644 index 000000000000..08e6a43c2b94 --- /dev/null +++ b/sys/riscv/htif/htif.c @@ -0,0 +1,284 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "htif.h" + +static struct resource_spec htif_spec[] = { + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +struct intr_entry { + void (*func) (void *, uint64_t); + void *arg; +}; + +struct intr_entry intrs[HTIF_NDEV]; + +uint64_t +htif_command(uint64_t arg) +{ + + return (machine_command(ECALL_HTIF_CMD, arg)); +} + +int +htif_setup_intr(int id, void *func, void *arg) +{ + + if (id >= HTIF_NDEV) + return (-1); + + intrs[id].func = func; + intrs[id].arg = arg; + + return (0); +} + +static void +htif_handle_entry(struct htif_softc *sc) +{ + uint64_t entry; + uint8_t devcmd; + uint8_t devid; + + entry = machine_command(ECALL_HTIF_GET_ENTRY, 0); + while (entry) { + devid = HTIF_DEV_ID(entry); + devcmd = HTIF_DEV_CMD(entry); + + if (devcmd == HTIF_CMD_IDENTIFY) { + /* Enumeration interrupt */ + if (devid == sc->identify_id) + sc->identify_done = 1; + } else { + /* Device interrupt */ + if (intrs[devid].func != NULL) + intrs[devid].func(intrs[devid].arg, entry); + } + + entry = machine_command(ECALL_HTIF_GET_ENTRY, 0); + } +} + +static int +htif_intr(void *arg) +{ + struct htif_softc *sc; + + sc = arg; + + htif_handle_entry(sc); + + csr_clear(sip, SIE_SSIE); + + return (FILTER_HANDLED); +} + +static int +htif_add_device(struct htif_softc *sc, int i, char *id, char *name) +{ + struct htif_dev_ivars *di; + + di = malloc(sizeof(struct htif_dev_ivars), M_DEVBUF, M_WAITOK | M_ZERO); + di->sc = sc; + di->index = i; + di->id = malloc(HTIF_ID_LEN, M_DEVBUF, M_WAITOK | M_ZERO); + memcpy(di->id, id, HTIF_ID_LEN); + + di->dev = device_add_child(sc->dev, name, -1); + device_set_ivars(di->dev, di); + + return (0); +} + +static int +htif_enumerate(struct htif_softc *sc) +{ + char id[HTIF_ID_LEN] __aligned(HTIF_ALIGN); + uint64_t paddr; + uint64_t data; + uint64_t cmd; + int len; + int i; + + device_printf(sc->dev, "Enumerating devices\n"); + + for (i = 0; i < HTIF_NDEV; i++) { + paddr = pmap_kextract((vm_offset_t)&id); + data = (paddr << IDENTIFY_PADDR_SHIFT); + data |= IDENTIFY_IDENT; + + sc->identify_id = i; + sc->identify_done = 0; + + cmd = i; + cmd <<= HTIF_DEV_ID_SHIFT; + cmd |= (HTIF_CMD_IDENTIFY << HTIF_CMD_SHIFT); + cmd |= data; + + htif_command(cmd); + + /* Do poll as interrupts are disabled yet */ + while (sc->identify_done == 0) { + htif_handle_entry(sc); + } + + len = strnlen(id, sizeof(id)); + if (len <= 0) { + continue; + } + + if (bootverbose) + printf(" %d %s\n", i, id); + + if (strncmp(id, "disk", 4) == 0) + htif_add_device(sc, i, id, "htif_blk"); + else if (strncmp(id, "bcd", 3) == 0) + htif_add_device(sc, i, id, "htif_console"); + else if (strncmp(id, "syscall_proxy", 13) == 0) + htif_add_device(sc, i, id, "htif_syscall_proxy"); + } + + return (bus_generic_attach(sc->dev)); +} + +int +htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct htif_dev_ivars *ivars; + + ivars = device_get_ivars(child); + + switch (which) { + case HTIF_IVAR_INDEX: + *result = ivars->index; + break; + case HTIF_IVAR_ID: + *result = (uintptr_t)ivars->id; + default: + return (EINVAL); + } + + return (0); +} + +static int +htif_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "riscv,htif")) + return (ENXIO); + + device_set_desc(dev, "HTIF bus device"); + return (BUS_PROBE_DEFAULT); +} + +static int +htif_attach(device_t dev) +{ + struct htif_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, htif_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Setup IRQs handler */ + error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK, + htif_intr, NULL, sc, &sc->ihl[0]); + if (error) { + device_printf(dev, "Unable to alloc int resource.\n"); + return (ENXIO); + } + + csr_set(sie, SIE_SSIE); + + return (htif_enumerate(sc)); +} + +static device_method_t htif_methods[] = { + DEVMETHOD(device_probe, htif_probe), + DEVMETHOD(device_attach, htif_attach), + + /* Bus interface */ + DEVMETHOD(bus_read_ivar, htif_read_ivar), + + DEVMETHOD_END +}; + +static driver_t htif_driver = { + "htif", + htif_methods, + sizeof(struct htif_softc) +}; + +static devclass_t htif_devclass; + +DRIVER_MODULE(htif, simplebus, htif_driver, + htif_devclass, 0, 0); diff --git a/sys/riscv/htif/htif.h b/sys/riscv/htif/htif.h new file mode 100644 index 000000000000..a1183d97c08e --- /dev/null +++ b/sys/riscv/htif/htif.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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 HTIF_DEV_ID_SHIFT (56) +#define HTIF_DEV_ID_MASK (0xfful << HTIF_DEV_ID_SHIFT) +#define HTIF_CMD_SHIFT (48) +#define HTIF_CMD_MASK (0xfful << HTIF_CMD_SHIFT) +#define HTIF_DATA_SHIFT (0) +#define HTIF_DATA_MASK (0xffffffff << HTIF_DATA_SHIFT) + +#define HTIF_CMD_READ (0x00ul) +#define HTIF_CMD_WRITE (0x01ul) +#define HTIF_CMD_READ_CONTROL_REG (0x02ul) +#define HTIF_CMD_WRITE_CONTROL_REG (0x03ul) +#define HTIF_CMD_IDENTIFY (0xfful) +#define IDENTIFY_PADDR_SHIFT 8 +#define IDENTIFY_IDENT 0xff + +#define HTIF_NDEV (256) +#define HTIF_ID_LEN (64) +#define HTIF_ALIGN (64) + +#define HTIF_DEV_CMD(entry) ((entry & HTIF_CMD_MASK) >> HTIF_CMD_SHIFT) +#define HTIF_DEV_ID(entry) ((entry & HTIF_DEV_ID_MASK) >> HTIF_DEV_ID_SHIFT) +#define HTIF_DEV_DATA(entry) ((entry & HTIF_DATA_MASK) >> HTIF_DATA_SHIFT) + +/* bus softc */ +struct htif_softc { + struct resource *res[1]; + void *ihl[1]; + device_t dev; + uint64_t identify_id; + uint64_t identify_done; +}; + +/* device private data */ +struct htif_dev_ivars { + char *id; + int index; + device_t dev; + struct htif_softc *sc; +}; + +uint64_t htif_command(uint64_t); +int htif_setup_intr(int id, void *func, void *arg); +int htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); + +enum htif_device_ivars { + HTIF_IVAR_INDEX, + HTIF_IVAR_ID, +}; + +/* + * Simplified accessors for HTIF devices + */ +#define HTIF_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(htif, var, HTIF, ivar, type) + +HTIF_ACCESSOR(index, INDEX, int); +HTIF_ACCESSOR(id, ID, char *); diff --git a/sys/riscv/htif/htif_block.c b/sys/riscv/htif/htif_block.c new file mode 100644 index 000000000000..58804d7aeb88 --- /dev/null +++ b/sys/riscv/htif/htif_block.c @@ -0,0 +1,289 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "htif.h" + +#define SECTOR_SIZE_SHIFT (9) +#define SECTOR_SIZE (1 << SECTOR_SIZE_SHIFT) + +#define HTIF_BLK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define HTIF_BLK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define HTIF_BLK_LOCK_INIT(_sc) \ + mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ + "htif_blk", MTX_DEF) +#define HTIF_BLK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); +#define HTIF_BLK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); +#define HTIF_BLK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); + +static void htif_blk_task(void *arg); + +static disk_open_t htif_blk_open; +static disk_close_t htif_blk_close; +static disk_strategy_t htif_blk_strategy; + +struct htif_blk_softc { + device_t dev; + struct disk *disk; + struct mtx htif_io_mtx; + struct mtx sc_mtx; + struct proc *p; + struct bio_queue_head bio_queue; + int running; + int intr_chan; + int cmd_done; + int index; + uint16_t curtag; +}; + +struct htif_blk_request { + uint64_t addr; + uint64_t offset; /* offset in bytes */ + uint64_t size; /* length in bytes */ + uint64_t tag; +}; + +static void +htif_blk_intr(void *arg, uint64_t entry) +{ + struct htif_blk_softc *sc; + uint64_t devcmd; + uint64_t data; + + sc = arg; + + devcmd = HTIF_DEV_CMD(entry); + data = HTIF_DEV_DATA(entry); + + if (sc->curtag == data) { + sc->cmd_done = 1; + wakeup(&sc->intr_chan); + } +} + +static int +htif_blk_probe(device_t dev) +{ + + return (0); +} + +static int +htif_blk_attach(device_t dev) +{ + struct htif_blk_softc *sc; + char prefix[] = " size="; + char *str; + long size; + + sc = device_get_softc(dev); + sc->dev = dev; + + mtx_init(&sc->htif_io_mtx, device_get_nameunit(dev), "htif_blk", MTX_DEF); + HTIF_BLK_LOCK_INIT(sc); + + str = strstr(htif_get_id(dev), prefix); + + size = strtol((str + 6), NULL, 10); + if (size == 0) { + return (ENXIO); + } + + sc->index = htif_get_index(dev); + if (sc->index < 0) + return (EINVAL); + htif_setup_intr(sc->index, htif_blk_intr, sc); + + sc->disk = disk_alloc(); + sc->disk->d_drv1 = sc; + + sc->disk->d_maxsize = 4096; /* Max transfer */ + sc->disk->d_name = "htif_blk"; + sc->disk->d_open = htif_blk_open; + sc->disk->d_close = htif_blk_close; + sc->disk->d_strategy = htif_blk_strategy; + sc->disk->d_unit = 0; + sc->disk->d_sectorsize = SECTOR_SIZE; + sc->disk->d_mediasize = size; + disk_create(sc->disk, DISK_VERSION); + + bioq_init(&sc->bio_queue); + + sc->running = 1; + + kproc_create(&htif_blk_task, sc, &sc->p, 0, 0, "%s: transfer", + device_get_nameunit(dev)); + + return (0); +} + +static int +htif_blk_open(struct disk *dp) +{ + + return (0); +} + +static int +htif_blk_close(struct disk *dp) +{ + + return (0); +} + +static void +htif_blk_task(void *arg) +{ + struct htif_blk_request req __aligned(HTIF_ALIGN); + struct htif_blk_softc *sc; + struct bio *bp; + uint64_t paddr; + uint64_t cmd; + int i; + + sc = (struct htif_blk_softc *)arg; + + while (1) { + HTIF_BLK_LOCK(sc); + do { + bp = bioq_takefirst(&sc->bio_queue); + if (bp == NULL) + msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); + } while (bp == NULL); + HTIF_BLK_UNLOCK(sc); + + if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { + req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize); + req.size = bp->bio_bcount; + paddr = vtophys(bp->bio_data); + KASSERT(paddr != 0, ("paddr is 0")); + req.addr = paddr; + req.tag = sc->curtag; + + cmd = sc->index; + cmd <<= HTIF_DEV_ID_SHIFT; + if (bp->bio_cmd == BIO_READ) + cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT); + else + cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT); + paddr = vtophys(&req); + KASSERT(paddr != 0, ("paddr is 0")); + cmd |= paddr; + + sc->cmd_done = 0; + htif_command(cmd); + + /* Wait for interrupt */ + HTIF_BLK_LOCK(sc); + i = 0; + while (sc->cmd_done == 0) { + msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2); + + if (i++ > 2) { + /* TODO: try to re-issue operation on timeout ? */ + bp->bio_error = EIO; + bp->bio_flags |= BIO_ERROR; + disk_err(bp, "hard error", -1, 1); + break; + } + } + HTIF_BLK_UNLOCK(sc); + + biodone(bp); + } else { + printf("unknown op %d\n", bp->bio_cmd); + } + } +} + +static void +htif_blk_strategy(struct bio *bp) +{ + struct htif_blk_softc *sc; + + sc = bp->bio_disk->d_drv1; + + HTIF_BLK_LOCK(sc); + if (sc->running > 0) { + bioq_disksort(&sc->bio_queue, bp); + HTIF_BLK_UNLOCK(sc); + wakeup(sc); + } else { + HTIF_BLK_UNLOCK(sc); + biofinish(bp, NULL, ENXIO); + } +} + +static device_method_t htif_blk_methods[] = { + DEVMETHOD(device_probe, htif_blk_probe), + DEVMETHOD(device_attach, htif_blk_attach), +}; + +static driver_t htif_blk_driver = { + "htif_blk", + htif_blk_methods, + sizeof(struct htif_blk_softc) +}; + +static devclass_t htif_blk_devclass; + +DRIVER_MODULE(htif_blk, htif, htif_blk_driver, htif_blk_devclass, 0, 0); diff --git a/sys/riscv/htif/htif_console.c b/sys/riscv/htif/htif_console.c new file mode 100644 index 000000000000..b4a46766949e --- /dev/null +++ b/sys/riscv/htif/htif_console.c @@ -0,0 +1,361 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "htif.h" + +#include + +#include + +extern uint64_t console_intr; + +static tsw_outwakeup_t riscvtty_outwakeup; + +static struct ttydevsw riscv_ttydevsw = { + .tsw_flags = TF_NOPREFIX, + .tsw_outwakeup = riscvtty_outwakeup, +}; + +static int polltime; +static struct callout riscv_callout; +static struct tty *tp = NULL; + +#if defined(KDB) +static int alt_break_state; +#endif + +static void riscv_timeout(void *); + +static cn_probe_t riscv_cnprobe; +static cn_init_t riscv_cninit; +static cn_term_t riscv_cnterm; +static cn_getc_t riscv_cngetc; +static cn_putc_t riscv_cnputc; +static cn_grab_t riscv_cngrab; +static cn_ungrab_t riscv_cnungrab; + +CONSOLE_DRIVER(riscv); + +#define MAX_BURST_LEN 1 +#define QUEUE_SIZE 256 +#define CONSOLE_DEFAULT_ID 1ul + +struct queue_entry { + uint64_t data; + uint64_t used; + struct queue_entry *next; +}; + +struct queue_entry cnqueue[QUEUE_SIZE]; +struct queue_entry *entry_last; +struct queue_entry *entry_served; + +static void +htif_putc(int c) +{ + uint64_t cmd; + + cmd = (HTIF_CMD_WRITE << HTIF_CMD_SHIFT); + cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT); + cmd |= c; + + htif_command(cmd); +} + +static uint8_t +htif_getc(void) +{ + uint64_t cmd; + uint8_t res; + + cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT); + cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT); + + res = htif_command(cmd); + + return (res); +} + +static void +riscv_putc(int c) +{ + uint64_t counter; + uint64_t *cc; + uint64_t val; + + val = 0; + counter = 0; + + cc = (uint64_t*)&console_intr; + *cc = 0; + + htif_putc(c); + + /* Wait for an interrupt */ + __asm __volatile( + "li %0, 1\n" /* counter = 1 */ + "slli %0, %0, 12\n" /* counter <<= 12 */ + "1:" + "addi %0, %0, -1\n" /* counter -= 1 */ + "beqz %0, 2f\n" /* counter == 0 ? finish */ + "ld %1, 0(%2)\n" /* val = *cc */ + "beqz %1, 1b\n" /* val == 0 ? repeat */ + "2:" + : "=&r"(counter), "=&r"(val) : "r"(cc) + ); +} + +#ifdef EARLY_PRINTF +early_putc_t *early_putc = riscv_putc; +#endif + +static void +cn_drvinit(void *unused) +{ + + if (riscv_consdev.cn_pri != CN_DEAD && + riscv_consdev.cn_name[0] != '\0') { + tp = tty_alloc(&riscv_ttydevsw, NULL); + tty_init_console(tp, 0); + tty_makedev(tp, NULL, "%s", "rcons"); + + polltime = 1; + + callout_init(&riscv_callout, 1); + callout_reset(&riscv_callout, polltime, riscv_timeout, NULL); + } +} + +SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); + +static void +riscvtty_outwakeup(struct tty *tp) +{ + u_char buf[MAX_BURST_LEN]; + int len; + int i; + + for (;;) { + len = ttydisc_getc(tp, buf, sizeof(buf)); + if (len == 0) + break; + + KASSERT(len == 1, ("tty error")); + + for (i = 0; i < len; i++) + riscv_putc(buf[i]); + } +} + +static void +riscv_timeout(void *v) +{ + int c; + + tty_lock(tp); + while ((c = riscv_cngetc(NULL)) != -1) + ttydisc_rint(tp, c, 0); + ttydisc_rint_done(tp); + tty_unlock(tp); + + callout_reset(&riscv_callout, polltime, riscv_timeout, NULL); +} + +static void +riscv_cnprobe(struct consdev *cp) +{ + + cp->cn_pri = CN_NORMAL; +} + +static void +riscv_cninit(struct consdev *cp) +{ + int i; + + strcpy(cp->cn_name, "rcons"); + + for (i = 0; i < QUEUE_SIZE; i++) { + if (i == (QUEUE_SIZE - 1)) + cnqueue[i].next = &cnqueue[0]; + else + cnqueue[i].next = &cnqueue[i+1]; + cnqueue[i].data = 0; + cnqueue[i].used = 0; + } + + entry_last = &cnqueue[0]; + entry_served = &cnqueue[0]; +} + +static void +riscv_cnterm(struct consdev *cp) +{ + +} + +static void +riscv_cngrab(struct consdev *cp) +{ + +} + +static void +riscv_cnungrab(struct consdev *cp) +{ + +} + +static int +riscv_cngetc(struct consdev *cp) +{ + uint8_t data; + int ch; + + ch = htif_getc(); + + if (entry_served->used == 1) { + data = entry_served->data; + entry_served->used = 0; + entry_served = entry_served->next; + ch = (data & 0xff); + if (ch > 0 && ch < 0xff) { +#if defined(KDB) + kdb_alt_break(ch, &alt_break_state); +#endif + return (ch); + } + } + + return (-1); +} + +static void +riscv_cnputc(struct consdev *cp, int c) +{ + + riscv_putc(c); +} + +/* + * Bus interface. + */ + +struct htif_console_softc { + device_t dev; + int running; + int intr_chan; + int cmd_done; + int curtag; + int index; +}; + +static void +htif_console_intr(void *arg, uint64_t entry) +{ + struct htif_console_softc *sc; + uint8_t devcmd; + uint64_t data; + + sc = arg; + + devcmd = HTIF_DEV_CMD(entry); + data = HTIF_DEV_DATA(entry); + + if (devcmd == 0) { + entry_last->data = data; + entry_last->used = 1; + entry_last = entry_last->next; + } +} + +static int +htif_console_probe(device_t dev) +{ + + return (0); +} + +static int +htif_console_attach(device_t dev) +{ + struct htif_console_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + + sc->index = htif_get_index(dev); + if (sc->index < 0) + return (EINVAL); + + htif_setup_intr(sc->index, htif_console_intr, sc); + + return (0); +} + +static device_method_t htif_console_methods[] = { + DEVMETHOD(device_probe, htif_console_probe), + DEVMETHOD(device_attach, htif_console_attach), + DEVMETHOD_END +}; + +static driver_t htif_console_driver = { + "htif_console", + htif_console_methods, + sizeof(struct htif_console_softc) +}; + +static devclass_t htif_console_devclass; + +DRIVER_MODULE(htif_console, htif, htif_console_driver, + htif_console_devclass, 0, 0); diff --git a/sys/riscv/riscv/autoconf.c b/sys/riscv/riscv/autoconf.c new file mode 100644 index 000000000000..d6afb42754d1 --- /dev/null +++ b/sys/riscv/riscv/autoconf.c @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Setup the system to run on the current machine. + * + * Configure() is called at boot time and initializes the vba + * device tables and the memory controller monitoring. Available + * devices are determined (from possibilities mentioned in ioconf.c), + * and the drivers are initialized. + */ + +#include +#include +#include +#include +#include + +static void configure_first(void *); +static void configure(void *); +static void configure_final(void *); + +SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); +/* SI_ORDER_SECOND is hookable */ +SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); +/* SI_ORDER_MIDDLE is hookable */ +SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); + +/* + * Determine i/o configuration for a machine. + */ +static void +configure_first(void *dummy) +{ + + /* nexus0 is the top of the riscv device tree */ + device_add_child(root_bus, "nexus", 0); +} + +static void +configure(void *dummy) +{ + + /* initialize new bus architecture */ + root_bus_configure(); +} + +static void +configure_final(void *dummy) +{ + + intr_enable(); + + cninit_finish(); + + if (bootverbose) + printf("Device configuration finished.\n"); + + cold = 0; +} diff --git a/sys/riscv/riscv/bcopy.c b/sys/riscv/riscv/bcopy.c new file mode 100644 index 000000000000..613ca97e5430 --- /dev/null +++ b/sys/riscv/riscv/bcopy.c @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: sys/powerpc/powerpc/bcopy.c + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +/* + * sizeof(word) MUST BE A POWER OF TWO + * SO THAT wmask BELOW IS ALL ONES + */ +typedef long word; /* "word" used for optimal copy speed */ + +#define wsize sizeof(word) +#define wmask (wsize - 1) + +/* + * Copy a block of memory, handling overlap. + * This is the routine that actually implements + * (the portable versions of) bcopy, memcpy, and memmove. + */ +void * +memcpy(void *dst0, const void *src0, size_t length) +{ + char *dst; + const char *src; + size_t t; + + dst = dst0; + src = src0; + + if (length == 0 || dst == src) { /* nothing to do */ + goto done; + } + + /* + * Macros: loop-t-times; and loop-t-times, t>0 + */ +#define TLOOP(s) if (t) TLOOP1(s) +#define TLOOP1(s) do { s; } while (--t) + + if ((unsigned long)dst < (unsigned long)src) { + /* + * Copy forward. + */ + t = (size_t)src; /* only need low bits */ + + if ((t | (uintptr_t)dst) & wmask) { + /* + * Try to align operands. This cannot be done + * unless the low bits match. + */ + if ((t ^ (uintptr_t)dst) & wmask || length < wsize) { + t = length; + } else { + t = wsize - (t & wmask); + } + + length -= t; + TLOOP1(*dst++ = *src++); + } + /* + * Copy whole words, then mop up any trailing bytes. + */ + t = length / wsize; + TLOOP(*(word *)dst = *(const word *)src; src += wsize; + dst += wsize); + t = length & wmask; + TLOOP(*dst++ = *src++); + } else { + /* + * Copy backwards. Otherwise essentially the same. + * Alignment works as before, except that it takes + * (t&wmask) bytes to align, not wsize-(t&wmask). + */ + src += length; + dst += length; + t = (uintptr_t)src; + + if ((t | (uintptr_t)dst) & wmask) { + if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) { + t = length; + } else { + t &= wmask; + } + + length -= t; + TLOOP1(*--dst = *--src); + } + t = length / wsize; + TLOOP(src -= wsize; dst -= wsize; + *(word *)dst = *(const word *)src); + t = length & wmask; + TLOOP(*--dst = *--src); + } +done: + return (dst0); +} + +void +bcopy(const void *src0, void *dst0, size_t length) +{ + + memcpy(dst0, src0, length); +} + diff --git a/sys/riscv/riscv/bus_machdep.c b/sys/riscv/riscv/bus_machdep.c new file mode 100644 index 000000000000..54e3419be5ee --- /dev/null +++ b/sys/riscv/riscv/bus_machdep.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include + +struct bus_space memmap_bus = { + /* cookie */ + .bs_cookie = NULL, + + /* mapping/unmapping */ + .bs_map = NULL, + .bs_unmap = NULL, + .bs_subregion = NULL, + + /* allocation/deallocation */ + .bs_alloc = NULL, + .bs_free = NULL, + + /* barrier */ + .bs_barrier = NULL, + + /* read single */ + .bs_r_1 = NULL, + .bs_r_2 = NULL, + .bs_r_4 = NULL, + .bs_r_8 = NULL, + + /* read multiple */ + .bs_rm_1 = NULL, + .bs_rm_2 = NULL, + .bs_rm_4 = NULL, + .bs_rm_8 = NULL, + + /* write single */ + .bs_w_1 = NULL, + .bs_w_2 = NULL, + .bs_w_4 = NULL, + .bs_w_8 = NULL, + + /* write multiple */ + .bs_wm_1 = NULL, + .bs_wm_2 = NULL, + .bs_wm_4 = NULL, + .bs_wm_8 = NULL, + + /* write region */ + .bs_wr_1 = NULL, + .bs_wr_2 = NULL, + .bs_wr_4 = NULL, + .bs_wr_8 = NULL, + + /* set multiple */ + .bs_sm_1 = NULL, + .bs_sm_2 = NULL, + .bs_sm_4 = NULL, + .bs_sm_8 = NULL, + + /* set region */ + .bs_sr_1 = NULL, + .bs_sr_2 = NULL, + .bs_sr_4 = NULL, + .bs_sr_8 = NULL, + + /* copy */ + .bs_c_1 = NULL, + .bs_c_2 = NULL, + .bs_c_4 = NULL, + .bs_c_8 = NULL, + + /* read single stream */ + .bs_r_1_s = NULL, + .bs_r_2_s = NULL, + .bs_r_4_s = NULL, + .bs_r_8_s = NULL, + + /* read multiple stream */ + .bs_rm_1_s = NULL, + .bs_rm_2_s = NULL, + .bs_rm_4_s = NULL, + .bs_rm_8_s = NULL, + + /* read region stream */ + .bs_rr_1_s = NULL, + .bs_rr_2_s = NULL, + .bs_rr_4_s = NULL, + .bs_rr_8_s = NULL, + + /* write single stream */ + .bs_w_1_s = NULL, + .bs_w_2_s = NULL, + .bs_w_4_s = NULL, + .bs_w_8_s = NULL, + + /* write multiple stream */ + .bs_wm_1_s = NULL, + .bs_wm_2_s = NULL, + .bs_wm_4_s = NULL, + .bs_wm_8_s = NULL, + + /* write region stream */ + .bs_wr_1_s = NULL, + .bs_wr_2_s = NULL, + .bs_wr_4_s = NULL, + .bs_wr_8_s = NULL, +}; diff --git a/sys/riscv/riscv/busdma_machdep.c b/sys/riscv/riscv/busdma_machdep.c new file mode 100644 index 000000000000..ec0fea91252f --- /dev/null +++ b/sys/riscv/riscv/busdma_machdep.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 1997, 1998 Justin T. Gibbs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) +{ + + panic("busdma"); +} + +int +_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, + bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, + int *segp) +{ + + panic("busdma"); +} + +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, + int *segp) +{ + + panic("busdma"); +} + +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) +{ + + panic("busdma"); +} + +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) +{ + + panic("busdma"); +} + +/* + * Release the mapping held by map. + */ +void +_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + + panic("busdma"); +} + +void +_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) +{ + + panic("busdma"); +} diff --git a/sys/riscv/riscv/clock.c b/sys/riscv/riscv/clock.c new file mode 100644 index 000000000000..e0c2d4ba3c0b --- /dev/null +++ b/sys/riscv/riscv/clock.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +void +cpu_initclocks(void) +{ + + cpu_initclocks_bsp(); +} diff --git a/sys/riscv/riscv/copyinout.S b/sys/riscv/riscv/copyinout.S new file mode 100644 index 000000000000..44d68390d7b6 --- /dev/null +++ b/sys/riscv/riscv/copyinout.S @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include "assym.s" + +/* + * Fault handler for the copy{in,out} functions below. + */ +ENTRY(copyio_fault) + SET_FAULT_HANDLER(x0, a1) /* Clear the handler */ +copyio_fault_nopcb: + li a0, EFAULT + ret +END(copyio_fault) + +/* + * Copies from a kernel to user address + * + * int copyout(const void *kaddr, void *udaddr, size_t len) + */ +ENTRY(copyout) + beqz a2, 2f /* If len == 0 then skip loop */ + add a3, a1, a2 + li a4, VM_MAXUSER_ADDRESS + bgt a3, a4, copyio_fault_nopcb + + la a6, copyio_fault /* Get the handler address */ + SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + +1: lb a4, 0(a0) /* Load from kaddr */ + addi a0, a0, 1 + sb a4, 0(a1) /* Store in uaddr */ + addi a1, a1, 1 + addi a2, a2, -1 /* len-- */ + bnez a2, 1b + + SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ + +2: li a0, 0 /* return 0 */ + ret +END(copyout) + +/* + * Copies from a user to kernel address + * + * int copyin(const void *uaddr, void *kdaddr, size_t len) + */ +ENTRY(copyin) + beqz a2, 2f /* If len == 0 then skip loop */ + add a3, a0, a2 + li a4, VM_MAXUSER_ADDRESS + bgt a3, a4, copyio_fault_nopcb + + la a6, copyio_fault /* Get the handler address */ + SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + +1: lb a4, 0(a0) /* Load from uaddr */ + addi a0, a0, 1 + sb a4, 0(a1) /* Store in kaddr */ + addi a1, a1, 1 + addi a2, a2, -1 /* len-- */ + bnez a2, 1b + + SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ + +2: li a0, 0 /* return 0 */ + ret +END(copyin) + +/* + * Copies a string from a user to kernel address + * + * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) + */ +ENTRY(copyinstr) + mv a5, x0 /* count = 0 */ + beqz a2, 3f /* If len == 0 then skip loop */ + li a7, VM_MAXUSER_ADDRESS + + la a6, copyio_fault /* Get the handler address */ + SET_FAULT_HANDLER(a6, a7) /* Set the handler */ + +1: bgt a7, a0, copyio_fault + lb a4, 0(a0) /* Load from uaddr */ + addi a0, a0, 1 + sb a4, 0(a1) /* Store in kaddr */ + addi a1, a1, 1 + beqz a4, 2f + addi a2, a2, -1 /* len-- */ + addi a5, a5, 1 /* count++ */ + bnez a2, 1b + +2: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ + +3: beqz a3, 4f /* Check if done != NULL */ + addi a5, a5, 1 /* count++ */ + sd a5, 0(a3) /* done = count */ + +4: mv a0, x0 /* return 0 */ + ret +END(copyinstr) diff --git a/sys/riscv/riscv/copystr.c b/sys/riscv/riscv/copystr.c new file mode 100644 index 000000000000..261dbc81ef76 --- /dev/null +++ b/sys/riscv/riscv/copystr.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2014 Andrew Turner + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +int +copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len, + size_t * __restrict lencopied) +{ + const char *src; + size_t pos; + char *dst; + int error; + + error = ENAMETOOLONG; + src = kfaddr; + dst = kdaddr; + for (pos = 0; pos < len; pos++) { + dst[pos] = src[pos]; + if (src[pos] == '\0') { + /* Increment pos to hold the number of bytes copied */ + pos++; + error = 0; + break; + } + } + + if (lencopied != NULL) + *lencopied = pos; + + return (error); +} diff --git a/sys/riscv/riscv/cpufunc_asm.S b/sys/riscv/riscv/cpufunc_asm.S new file mode 100644 index 000000000000..21bce533187a --- /dev/null +++ b/sys/riscv/riscv/cpufunc_asm.S @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +#include +__FBSDID("$FreeBSD$"); + + .text + .align 2 + +.Lpage_mask: + .word PAGE_MASK + +ENTRY(riscv_nullop) + ret +END(riscv_nullop) + +/* + * Generic functions to read/modify/write the internal coprocessor registers + */ + +ENTRY(riscv_tlb_flushID) + sfence.vm + ret +END(riscv_tlb_flushID) + +ENTRY(riscv_tlb_flushID_SE) + sfence.vm + ret +END(riscv_tlb_flushID_SE) + +/* + * void riscv_dcache_wb_range(vm_offset_t, vm_size_t) + */ +ENTRY(riscv_dcache_wb_range) + /* RISCVTODO */ + ret +END(riscv_dcache_wb_range) + +/* + * void riscv_dcache_wbinv_range(vm_offset_t, vm_size_t) + */ +ENTRY(riscv_dcache_wbinv_range) + /* RISCVTODO */ + ret +END(riscv_dcache_wbinv_range) + +/* + * void riscv_dcache_inv_range(vm_offset_t, vm_size_t) + */ +ENTRY(riscv_dcache_inv_range) + /* RISCVTODO */ + ret +END(riscv_dcache_inv_range) + +/* + * void riscv_idcache_wbinv_range(vm_offset_t, vm_size_t) + */ +ENTRY(riscv_idcache_wbinv_range) + /* RISCVTODO */ + ret +END(riscv_idcache_wbinv_range) + +/* + * void riscv_icache_sync_range(vm_offset_t, vm_size_t) + */ +ENTRY(riscv_icache_sync_range) + /* RISCVTODO */ + ret +END(riscv_icache_sync_range) diff --git a/sys/riscv/riscv/devmap.c b/sys/riscv/riscv/devmap.c new file mode 100644 index 000000000000..092532aa7bf4 --- /dev/null +++ b/sys/riscv/riscv/devmap.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* RISC-V doesn't provide memory-mapped devices yet */ + +#include "opt_ddb.h" + +#include +#include +#include +#include +#include +#include +#include + +void * +pmap_mapdev(vm_offset_t pa, vm_size_t size) +{ + + return (NULL); +} + +void +pmap_unmapdev(vm_offset_t va, vm_size_t size) +{ + +} diff --git a/sys/riscv/riscv/dump_machdep.c b/sys/riscv/riscv/dump_machdep.c new file mode 100644 index 000000000000..b8473314e27b --- /dev/null +++ b/sys/riscv/riscv/dump_machdep.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_watchdog.h" + +#include +#include +#include +#include +#include +#include +#include + +int do_minidump = 1; +SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0, + "Enable mini crash dumps"); + +void +dumpsys_map_chunk(vm_paddr_t pa, size_t chunk, void **va) +{ + + printf("dumpsys_map_chunk\n"); +} diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c new file mode 100644 index 000000000000..1e4480121d1b --- /dev/null +++ b/sys/riscv/riscv/elf_machdep.c @@ -0,0 +1,169 @@ +/*- + * Copyright 1996-1998 John D. Polstra. + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +struct sysentvec elf64_freebsd_sysvec = { + .sv_size = SYS_MAXSYSCALL, + .sv_table = sysent, + .sv_mask = 0, + .sv_errsize = 0, + .sv_errtbl = NULL, + .sv_transtrap = NULL, + .sv_fixup = __elfN(freebsd_fixup), + .sv_sendsig = sendsig, + .sv_sigcode = sigcode, + .sv_szsigcode = &szsigcode, + .sv_name = "FreeBSD ELF64", + .sv_coredump = __elfN(coredump), + .sv_imgact_try = NULL, + .sv_minsigstksz = MINSIGSTKSZ, + .sv_pagesize = PAGE_SIZE, + .sv_minuser = VM_MIN_ADDRESS, + .sv_maxuser = VM_MAXUSER_ADDRESS, + .sv_usrstack = USRSTACK, + .sv_psstrings = PS_STRINGS, + .sv_stackprot = VM_PROT_ALL, + .sv_copyout_strings = exec_copyout_strings, + .sv_setregs = exec_setregs, + .sv_fixlimit = NULL, + .sv_maxssiz = NULL, + .sv_flags = SV_ABI_FREEBSD | SV_LP64, + .sv_set_syscall_retval = cpu_set_syscall_retval, + .sv_fetch_syscall_args = cpu_fetch_syscall_args, + .sv_syscallnames = syscallnames, + .sv_schedtail = NULL, + .sv_thread_detach = NULL, + .sv_trap = NULL, +}; +INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); + +static Elf64_Brandinfo freebsd_brand_info = { + .brand = ELFOSABI_FREEBSD, + .machine = EM_RISCV, + .compat_3_brand = "FreeBSD", + .emul_path = NULL, + .interp_path = "/libexec/ld-elf.so.1", + .sysvec = &elf64_freebsd_sysvec, + .interp_newpath = NULL, + .brand_note = &elf64_freebsd_brandnote, + .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE +}; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); + +static Elf64_Brandinfo freebsd_brand_oinfo = { + .brand = ELFOSABI_FREEBSD, + .machine = EM_RISCV, + .compat_3_brand = "FreeBSD", + .emul_path = NULL, + .interp_path = "/usr/libexec/ld-elf.so.1", + .sysvec = &elf64_freebsd_sysvec, + .interp_newpath = NULL, + .brand_note = &elf64_freebsd_brandnote, + .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE +}; + +SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_oinfo); + +void +elf64_dump_thread(struct thread *td, void *dst, size_t *off) +{ + +} + +/* Process one elf relocation with addend. */ +static int +elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, int local, elf_lookup_fn lookup) +{ + + panic("elf_reloc_internal"); +} + +int +elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, + elf_lookup_fn lookup) +{ + + return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); +} + +int +elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, elf_lookup_fn lookup) +{ + + return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); +} + +int +elf_cpu_load_file(linker_file_t lf __unused) +{ + + return (0); +} + +int +elf_cpu_unload_file(linker_file_t lf __unused) +{ + + return (0); +} diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S new file mode 100644 index 000000000000..07fcfc52787a --- /dev/null +++ b/sys/riscv/riscv/exception.S @@ -0,0 +1,456 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "assym.s" + +#include +#include + +.macro save_registers el + addi sp, sp, -280 + + sd ra, (TF_RA)(sp) + sd gp, (TF_GP)(sp) + sd tp, (TF_TP)(sp) + + sd t0, (TF_T + 0 * 8)(sp) + sd t1, (TF_T + 1 * 8)(sp) + sd t2, (TF_T + 2 * 8)(sp) + sd t3, (TF_T + 3 * 8)(sp) + sd t4, (TF_T + 4 * 8)(sp) + sd t5, (TF_T + 5 * 8)(sp) + sd t6, (TF_T + 6 * 8)(sp) + + sd s0, (TF_S + 0 * 8)(sp) + sd s1, (TF_S + 1 * 8)(sp) + sd s2, (TF_S + 2 * 8)(sp) + sd s3, (TF_S + 3 * 8)(sp) + sd s4, (TF_S + 4 * 8)(sp) + sd s5, (TF_S + 5 * 8)(sp) + sd s6, (TF_S + 6 * 8)(sp) + sd s7, (TF_S + 7 * 8)(sp) + sd s8, (TF_S + 8 * 8)(sp) + sd s9, (TF_S + 9 * 8)(sp) + sd s10, (TF_S + 10 * 8)(sp) + sd s11, (TF_S + 11 * 8)(sp) + + sd a0, (TF_A + 0 * 8)(sp) + sd a1, (TF_A + 1 * 8)(sp) + sd a2, (TF_A + 2 * 8)(sp) + sd a3, (TF_A + 3 * 8)(sp) + sd a4, (TF_A + 4 * 8)(sp) + sd a5, (TF_A + 5 * 8)(sp) + sd a6, (TF_A + 6 * 8)(sp) + sd a7, (TF_A + 7 * 8)(sp) + +#if 0 + /* XXX: temporary test: spin if stack is not kernel one */ +.if \el == 1 /* kernel */ + mv t0, sp + srli t0, t0, 63 +1: + beqz t0, 1b +.endif +#endif + +.if \el == 1 + /* Store kernel sp */ + sd sp, (TF_SP)(sp) +.else + /* Store user sp */ + csrr t0, sscratch + sd t0, (TF_SP)(sp) +.endif + li t0, 0 + csrw sscratch, t0 + csrr t0, sepc + sd t0, (TF_SEPC)(sp) + csrr t0, sstatus + sd t0, (TF_SSTATUS)(sp) + csrr t0, sbadaddr + sd t0, (TF_SBADADDR)(sp) + csrr t0, scause + sd t0, (TF_SCAUSE)(sp) +.endm + +.macro load_registers el + ld t0, (TF_SSTATUS)(sp) +.if \el == 0 + /* Ensure user interrupts will be enabled on eret. */ + ori t0, t0, SSTATUS_PIE +.else + /* + * Disable interrupts for supervisor mode exceptions. + * For user mode exceptions we have already done this + * in do_ast. + */ + li t1, ~SSTATUS_IE + and t0, t0, t1 +.endif + csrw sstatus, t0 + + ld t0, (TF_SEPC)(sp) + csrw sepc, t0 + +.if \el == 0 + /* Load user sp */ + ld t0, (TF_SP)(sp) + csrw sscratch, t0 +.endif + + ld ra, (TF_RA)(sp) + ld gp, (TF_GP)(sp) + ld tp, (TF_TP)(sp) + + ld t0, (TF_T + 0 * 8)(sp) + ld t1, (TF_T + 1 * 8)(sp) + ld t2, (TF_T + 2 * 8)(sp) + ld t3, (TF_T + 3 * 8)(sp) + ld t4, (TF_T + 4 * 8)(sp) + ld t5, (TF_T + 5 * 8)(sp) + ld t6, (TF_T + 6 * 8)(sp) + + ld s0, (TF_S + 0 * 8)(sp) + ld s1, (TF_S + 1 * 8)(sp) + ld s2, (TF_S + 2 * 8)(sp) + ld s3, (TF_S + 3 * 8)(sp) + ld s4, (TF_S + 4 * 8)(sp) + ld s5, (TF_S + 5 * 8)(sp) + ld s6, (TF_S + 6 * 8)(sp) + ld s7, (TF_S + 7 * 8)(sp) + ld s8, (TF_S + 8 * 8)(sp) + ld s9, (TF_S + 9 * 8)(sp) + ld s10, (TF_S + 10 * 8)(sp) + ld s11, (TF_S + 11 * 8)(sp) + + ld a0, (TF_A + 0 * 8)(sp) + ld a1, (TF_A + 1 * 8)(sp) + ld a2, (TF_A + 2 * 8)(sp) + ld a3, (TF_A + 3 * 8)(sp) + ld a4, (TF_A + 4 * 8)(sp) + ld a5, (TF_A + 5 * 8)(sp) + ld a6, (TF_A + 6 * 8)(sp) + ld a7, (TF_A + 7 * 8)(sp) + + addi sp, sp, 280 +.endm + +.macro do_ast + /* Disable interrupts */ + csrr a4, sstatus +1: + csrci sstatus, SSTATUS_IE + + la a1, pcpup + ld a1, 0(a1) + ld a1, PC_CURTHREAD(a1) + lw a2, TD_FLAGS(a1) + + li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED) + and a2, a2, a3 + beqz a2, 2f + + /* Restore interrupts */ + andi a4, a4, SSTATUS_IE + csrs sstatus, a4 + + /* Handle the ast */ + mv a0, sp + call _C_LABEL(ast) + + /* Re-check for new ast scheduled */ + j 1b +2: +.endm + +ENTRY(cpu_exception_handler_supervisor) + save_registers 1 + mv a0, sp + call _C_LABEL(do_trap_supervisor) + load_registers 1 + eret +END(cpu_exception_handler_supervisor) + +ENTRY(cpu_exception_handler_user) + csrrw sp, sscratch, sp + save_registers 0 + mv a0, sp + call _C_LABEL(do_trap_user) + do_ast + load_registers 0 + csrrw sp, sscratch, sp + eret +END(cpu_exception_handler_user) + +/* + * Trap handlers + */ + .text +bad_trap: + j bad_trap + +user_trap: + csrrw sp, mscratch, sp + addi sp, sp, -64 + sd t0, (8 * 0)(sp) + sd t1, (8 * 1)(sp) + sd t2, (8 * 2)(sp) + sd t3, (8 * 3)(sp) + sd t4, (8 * 4)(sp) + sd t5, (8 * 5)(sp) + sd a0, (8 * 7)(sp) + + la t2, _C_LABEL(cpu_exception_handler_user) + + csrr t0, mcause + bltz t0, machine_interrupt + j exit_mrts + +supervisor_trap: + /* Save state */ + csrrw sp, mscratch, sp + addi sp, sp, -64 + sd t0, (8 * 0)(sp) + sd t1, (8 * 1)(sp) + sd t2, (8 * 2)(sp) + sd t3, (8 * 3)(sp) + sd t4, (8 * 4)(sp) + sd t5, (8 * 5)(sp) + sd a0, (8 * 7)(sp) + + la t2, _C_LABEL(cpu_exception_handler_supervisor) + + csrr t0, mcause + bltz t0, machine_interrupt + + li t1, EXCP_SMODE_ENV_CALL + beq t0, t1, supervisor_call + j exit_mrts + +machine_interrupt: + /* Type of interrupt ? */ + csrr t0, mcause + andi t0, t0, 3 + li t1, 0 + beq t1, t0, software_interrupt + li t1, 1 + beq t1, t0, timer_interrupt + li t1, 2 + beq t1, t0, htif_interrupt + + /* not reached */ +1: + j 1b + +software_interrupt: + /* Redirect to supervisor */ + j exit_mrts + +timer_interrupt: + /* Disable machine timer interrupts */ + li t0, MIE_MTIE + csrc mie, t0 + + /* Clear machine pending */ + li t0, MIP_MTIP + csrc mip, t0 + + /* Post supervisor software interrupt */ + li t0, MIP_STIP + csrs mip, t0 + + /* If PRV1 is PRV_U (user) then serve a trap */ + csrr t0, mstatus + li t1, (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT) + and t0, t0, t1 + beqz t0, 1f + + /* If PRV1 is supervisor and interrupts were enabled, then serve a trap */ + csrr t0, mstatus + li t1, (SR_IE1 | (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT)) + and t0, t0, t1 + li t1, (SR_IE1 | (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT)) + beq t0, t1, 1f + + j exit + +1: + /* Serve a trap in supervisor mode */ + j exit_mrts + +htif_interrupt: +1: + li t5, 0 + csrrw t5, mfromhost, t5 + beqz t5, 3f + + /* Console PUT intr ? */ + mv t1, t5 + li t0, 0x101 + srli t1, t1, 48 + bne t1, t0, 2f + /* Yes */ + la t0, console_intr + li t1, 1 + sd t1, 0(t0) + j 3f + +2: + /* Save entry */ + la t0, htif_ring_cursor + beqz t0, 3f /* not initialized */ + ld t0, 0(t0) /* load struct */ + sd t5, 0(t0) /* put entry */ + li t4, 1 + sd t4, 8(t0) /* mark used */ + ld t4, 16(t0) /* take next */ + /* Update cursor */ + la t0, htif_ring_cursor + sd t4, 0(t0) + + /* Post supervisor software interrupt */ + li t0, MIP_SSIP + csrs mip, t0 + +3: + j exit + +supervisor_call: + csrr t1, mepc + addi t1, t1, 4 /* Next instruction in t1 */ + li t4, ECALL_HTIF_CMD + beq t5, t4, htif_cmd + li t4, ECALL_HTIF_GET_ENTRY + beq t5, t4, htif_get_entry + li t4, ECALL_MTIMECMP + beq t5, t4, set_mtimecmp + li t4, ECALL_CLEAR_PENDING + beq t5, t4, clear_pending + li t4, ECALL_MCPUID_GET + beq t5, t4, mcpuid_get + li t4, ECALL_MIMPID_GET + beq t5, t4, mimpid_get + j exit_next_instr + +mcpuid_get: + csrr t6, mcpuid + j exit_next_instr + +mimpid_get: + csrr t6, mimpid + j exit_next_instr + +htif_get_entry: + li t6, 0 /* preset return value */ + la t0, htif_ring_last + ld t0, 0(t0) /* load struct */ + ld t4, 8(t0) /* get used */ + beqz t4, 1f + ld t6, 0(t0) /* get entry */ + li t4, 0 + sd t4, 8(t0) /* mark free */ + sd t4, 0(t0) /* free entry, just in case */ + ld t4, 16(t0) /* take next */ + la t0, htif_ring_last + sd t4, 0(t0) +1: + /* Exit. Result is stored in t6 */ + j exit_next_instr + +htif_cmd: + mv t0, t6 +1: + csrrw t0, mtohost, t0 + bnez t0, 1b + j exit_next_instr + +set_mtimecmp: + csrr t2, stime + add t6, t6, t2 + csrw mtimecmp, t6 + + /* Enable interrupts */ + li t0, (MIE_MTIE | MIE_STIE) + csrs mie, t0 + j exit_next_instr + +clear_pending: + li t0, MIP_STIP + csrc mip, t0 + j exit_next_instr + +/* + * Trap exit functions + */ +exit_next_instr: + /* Next instruction is in t1 */ + csrw mepc, t1 +exit: + /* Restore state */ + ld t0, (8 * 0)(sp) + ld t1, (8 * 1)(sp) + ld t2, (8 * 2)(sp) + ld t3, (8 * 3)(sp) + ld t4, (8 * 4)(sp) + ld t5, (8 * 5)(sp) + ld a0, (8 * 7)(sp) + addi sp, sp, 64 + csrrw sp, mscratch, sp + eret + +/* + * Redirect to supervisor + */ +exit_mrts: + /* Setup exception handler */ + li t1, KERNBASE + add t2, t2, t1 + csrw stvec, t2 + + /* Restore state */ + ld t0, (8 * 0)(sp) + ld t1, (8 * 1)(sp) + ld t2, (8 * 2)(sp) + ld t3, (8 * 3)(sp) + ld t4, (8 * 4)(sp) + ld t5, (8 * 5)(sp) + ld a0, (8 * 7)(sp) + addi sp, sp, 64 + csrrw sp, mscratch, sp + + /* Redirect to supervisor */ + mrts diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c new file mode 100644 index 000000000000..f5c971d178a7 --- /dev/null +++ b/sys/riscv/riscv/genassym.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ASSYM(KERNBASE, KERNBASE); +ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); +ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); +ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); + +ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); +ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr)); +ASSYM(PCB_SIZE, sizeof(struct pcb)); +ASSYM(PCB_RA, offsetof(struct pcb, pcb_ra)); +ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp)); +ASSYM(PCB_GP, offsetof(struct pcb, pcb_gp)); +ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp)); +ASSYM(PCB_T, offsetof(struct pcb, pcb_t)); +ASSYM(PCB_S, offsetof(struct pcb, pcb_s)); +ASSYM(PCB_A, offsetof(struct pcb, pcb_a)); + +ASSYM(SF_UC, offsetof(struct sigframe, sf_uc)); + +ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); +ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); + +ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); +ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); +ASSYM(TD_PROC, offsetof(struct thread, td_proc)); +ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); +ASSYM(TD_MD, offsetof(struct thread, td_md)); +ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); + +ASSYM(TF_RA, offsetof(struct trapframe, tf_ra)); +ASSYM(TF_SP, offsetof(struct trapframe, tf_sp)); +ASSYM(TF_GP, offsetof(struct trapframe, tf_gp)); +ASSYM(TF_TP, offsetof(struct trapframe, tf_tp)); +ASSYM(TF_T, offsetof(struct trapframe, tf_t)); +ASSYM(TF_S, offsetof(struct trapframe, tf_s)); +ASSYM(TF_A, offsetof(struct trapframe, tf_a)); +ASSYM(TF_SEPC, offsetof(struct trapframe, tf_sepc)); +ASSYM(TF_SBADADDR, offsetof(struct trapframe, tf_sbadaddr)); +ASSYM(TF_SCAUSE, offsetof(struct trapframe, tf_scause)); +ASSYM(TF_SSTATUS, offsetof(struct trapframe, tf_sstatus)); diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c new file mode 100644 index 000000000000..dd1f2ba13382 --- /dev/null +++ b/sys/riscv/riscv/identcpu.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +char machine[] = "riscv"; + +SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, + "Machine class"); + +struct cpu_desc { + u_int cpu_impl; + u_int cpu_part_num; + const char *cpu_impl_name; + const char *cpu_part_name; +}; + +struct cpu_desc cpu_desc[MAXCPU]; + +struct cpu_parts { + u_int part_id; + const char *part_name; +}; +#define CPU_PART_NONE { -1, "Unknown Processor" } + +struct cpu_implementers { + u_int impl_id; + const char *impl_name; + /* + * Part number is implementation defined + * so each vendor will have its own set of values and names. + */ + const struct cpu_parts *cpu_parts; +}; +#define CPU_IMPLEMENTER_NONE { 0, "Unknown Implementer", cpu_parts_none } + +/* + * Per-implementer table of (PartNum, CPU Name) pairs. + */ +/* UC Berkeley */ +static const struct cpu_parts cpu_parts_ucb[] = { + { CPU_PART_RV32I, "RV32I" }, + { CPU_PART_RV32E, "RV32E" }, + { CPU_PART_RV64I, "RV64I" }, + { CPU_PART_RV128I, "RV128I" }, + CPU_PART_NONE, +}; + +/* Unknown */ +static const struct cpu_parts cpu_parts_none[] = { + CPU_PART_NONE, +}; + +/* + * Implementers table. + */ +const struct cpu_implementers cpu_implementers[] = { + { CPU_IMPL_UCB_ROCKET, "UC Berkeley Rocket", cpu_parts_ucb }, + CPU_IMPLEMENTER_NONE, +}; + +void +identify_cpu(void) +{ + const struct cpu_parts *cpu_partsp; + uint32_t part_id; + uint32_t impl_id; + uint64_t mimpid; + uint64_t mcpuid; + u_int cpu; + size_t i; + + cpu_partsp = NULL; + + mimpid = machine_command(ECALL_MIMPID_GET, 0); + mcpuid = machine_command(ECALL_MCPUID_GET, 0); + + /* SMPTODO: use mhartid ? */ + cpu = PCPU_GET(cpuid); + + impl_id = CPU_IMPL(mimpid); + for (i = 0; i < nitems(cpu_implementers); i++) { + if (impl_id == cpu_implementers[i].impl_id || + cpu_implementers[i].impl_id == 0) { + cpu_desc[cpu].cpu_impl = impl_id; + cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name; + cpu_partsp = cpu_implementers[i].cpu_parts; + break; + } + } + + part_id = CPU_PART(mcpuid); + for (i = 0; &cpu_partsp[i] != NULL; i++) { + if (part_id == cpu_partsp[i].part_id || + cpu_partsp[i].part_id == -1) { + cpu_desc[cpu].cpu_part_num = part_id; + cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name; + break; + } + } + + /* Print details for boot CPU or if we want verbose output */ + if (cpu == 0 || bootverbose) { + printf("CPU(%d): %s %s\n", cpu, + cpu_desc[cpu].cpu_impl_name, + cpu_desc[cpu].cpu_part_name); + } +} diff --git a/sys/riscv/riscv/in_cksum.c b/sys/riscv/riscv/in_cksum.c new file mode 100644 index 000000000000..ae02e91d9203 --- /dev/null +++ b/sys/riscv/riscv/in_cksum.c @@ -0,0 +1,241 @@ +/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */ + +/*- + * Copyright (c) 1988, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1996 + * Matt Thomas + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 + */ + +#include /* RCS ID & Copyright macro defns */ +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +/* + * Checksum routine for Internet Protocol family headers + * (Portable Alpha version). + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + */ + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } + +static const u_int32_t in_masks[] = { + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ + 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ + 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */ + 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */ +}; + +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +static u_int64_t +in_cksumdata(const void *buf, int len) +{ + const u_int32_t *lw = (const u_int32_t *) buf; + u_int64_t sum = 0; + u_int64_t prefilled; + int offset; + union q_util q_util; + + if ((3 & (long) lw) == 0 && len == 20) { + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; + } + + if ((offset = 3 & (long) lw) != 0) { + const u_int32_t *masks = in_masks + (offset << 2); + lw = (u_int32_t *) (((long) lw) - offset); + sum = *lw++ & masks[len >= 3 ? 3 : len]; + len -= 4 - offset; + if (len <= 0) { + REDUCE32; + return sum; + } + } +#if 0 + /* + * Force to cache line boundary. + */ + offset = 32 - (0x1f & (long) lw); + if (offset < 32 && len > offset) { + len -= offset; + if (4 & offset) { + sum += (u_int64_t) lw[0]; + lw += 1; + } + if (8 & offset) { + sum += (u_int64_t) lw[0] + lw[1]; + lw += 2; + } + if (16 & offset) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + } +#endif + /* + * access prefilling to start load of next cache line. + * then add current cache line + * save result of prefilling for loop iteration. + */ + prefilled = lw[0]; + while ((len -= 32) >= 4) { + u_int64_t prefilling = lw[8]; + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + prefilled = prefilling; + } + if (len >= 0) { + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + } else { + len += 32; + } + while ((len -= 16) >= 0) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + len += 16; + while ((len -= 4) >= 0) { + sum += (u_int64_t) *lw++; + } + len += 4; + if (len > 0) + sum += (u_int64_t) (in_masks[len] & *lw); + REDUCE32; + return sum; +} + +u_short +in_addword(u_short a, u_short b) +{ + u_int64_t sum = a + b; + + ADDCARRY(sum); + return (sum); +} + +u_short +in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c) +{ + u_int64_t sum; + union q_util q_util; + union l_util l_util; + + sum = (u_int64_t) a + b + c; + REDUCE16; + return (sum); +} + +u_short +in_cksum_skip(struct mbuf *m, int len, int skip) +{ + u_int64_t sum = 0; + int mlen = 0; + int clen = 0; + caddr_t addr; + union q_util q_util; + union l_util l_util; + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + addr = mtod(m, caddr_t) + skip; + goto skip_start; + } else { + skip -= m->m_len; + } + } + + for (; m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + mlen = m->m_len; + addr = mtod(m, caddr_t); +skip_start: + if (len < mlen) + mlen = len; + if ((clen ^ (long) addr) & 1) + sum += in_cksumdata(addr, mlen) << 8; + else + sum += in_cksumdata(addr, mlen); + + clen += mlen; + len -= mlen; + } + REDUCE16; + return (~sum & 0xffff); +} + +u_int in_cksum_hdr(const struct ip *ip) +{ + u_int64_t sum = in_cksumdata(ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + REDUCE16; + return (~sum & 0xffff); +} diff --git a/sys/riscv/riscv/intr_machdep.c b/sys/riscv/riscv/intr_machdep.c new file mode 100644 index 000000000000..c51075c8a24b --- /dev/null +++ b/sys/riscv/riscv/intr_machdep.c @@ -0,0 +1,223 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +enum { + IRQ_SOFTWARE, + IRQ_TIMER, + IRQ_HTIF, + NIRQS +}; + +u_long intrcnt[NIRQS]; +size_t sintrcnt = sizeof(intrcnt); + +char intrnames[NIRQS * (MAXCOMLEN + 1) * 2]; +size_t sintrnames = sizeof(intrnames); + +static struct intr_event *intr_events[NIRQS]; +static riscv_intrcnt_t riscv_intr_counters[NIRQS]; + +static int intrcnt_index; + +riscv_intrcnt_t +riscv_intrcnt_create(const char* name) +{ + riscv_intrcnt_t counter; + + counter = &intrcnt[intrcnt_index++]; + riscv_intrcnt_setname(counter, name); + + return (counter); +} + +void +riscv_intrcnt_setname(riscv_intrcnt_t counter, const char *name) +{ + int i; + + i = (counter - intrcnt); + + KASSERT(counter != NULL, ("riscv_intrcnt_setname: NULL counter")); + + snprintf(intrnames + (MAXCOMLEN + 1) * i, + MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name); +} + +static void +riscv_mask_irq(void *source) +{ + uintptr_t irq; + + irq = (uintptr_t)source; + + switch (irq) { + case IRQ_TIMER: + csr_clear(sie, SIE_STIE); + break; + case IRQ_SOFTWARE: + csr_clear(sie, SIE_SSIE); + break; + default: + panic("Unknown irq %d\n", irq); + } +} + +static void +riscv_unmask_irq(void *source) +{ + uintptr_t irq; + + irq = (uintptr_t)source; + + switch (irq) { + case IRQ_TIMER: + csr_set(sie, SIE_STIE); + break; + case IRQ_SOFTWARE: + csr_set(sie, SIE_SSIE); + break; + default: + panic("Unknown irq %d\n", irq); + } +} + +void +riscv_init_interrupts(void) +{ + char name[MAXCOMLEN + 1]; + int i; + + for (i = 0; i < NIRQS; i++) { + snprintf(name, MAXCOMLEN + 1, "int%d:", i); + riscv_intr_counters[i] = riscv_intrcnt_create(name); + } +} + +int +riscv_setup_intr(const char *name, driver_filter_t *filt, + void (*handler)(void*), void *arg, int irq, int flags, void **cookiep) +{ + struct intr_event *event; + int error; + + if (irq < 0 || irq >= NIRQS) + panic("%s: unknown intr %d", __func__, irq); + + event = intr_events[irq]; + if (event == NULL) { + error = intr_event_create(&event, (void *)(uintptr_t)irq, 0, + irq, riscv_mask_irq, riscv_unmask_irq, + NULL, NULL, "int%d", irq); + if (error) + return (error); + intr_events[irq] = event; + riscv_unmask_irq((void*)(uintptr_t)irq); + } + + intr_event_add_handler(event, name, filt, handler, arg, + intr_priority(flags), flags, cookiep); + + riscv_intrcnt_setname(riscv_intr_counters[irq], + event->ie_fullname); + + return (0); +} + +int +riscv_teardown_intr(void *ih) +{ + + /* TODO */ + + return (0); +} + +int +riscv_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) +{ + + /* There is no configuration for interrupts */ + + return (0); +} + +void +riscv_cpu_intr(struct trapframe *frame) +{ + struct intr_event *event; + int active_irq; + + critical_enter(); + + KASSERT(frame->tf_scause & EXCP_INTR, + ("riscv_cpu_intr: wrong frame passed")); + + active_irq = (frame->tf_scause & EXCP_MASK); + + switch (active_irq) { + case IRQ_SOFTWARE: + case IRQ_TIMER: + event = intr_events[active_irq]; + /* Update counters */ + atomic_add_long(riscv_intr_counters[active_irq], 1); + PCPU_INC(cnt.v_intr); + break; + case IRQ_HTIF: + /* HTIF interrupts are only handled in machine mode */ + panic("%s: HTIF interrupt", __func__); + break; + default: + event = NULL; + } + + if (!event || TAILQ_EMPTY(&event->ie_handlers) || + (intr_event_handle(event, frame) != 0)) + printf("stray interrupt %d\n", active_irq); + + critical_exit(); +} diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S new file mode 100644 index 000000000000..8dc424e7fc4e --- /dev/null +++ b/sys/riscv/riscv/locore.S @@ -0,0 +1,274 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "assym.s" + +#include +#include +#include +#include +#include +#include + +#define HTIF_RING_SIZE (64) +#define HTIF_RING_LAST (24 * (HTIF_RING_SIZE - 1)) + + .globl kernbase + .set kernbase, KERNBASE + + /* Trap entries */ + .text + +mentry: + /* User mode entry point (mtvec + 0x000) */ + .align 6 + j user_trap + + /* Supervisor mode entry point (mtvec + 0x040) */ + .align 6 + j supervisor_trap + + /* Hypervisor mode entry point (mtvec + 0x080) */ + .align 6 + j bad_trap + + /* Machine mode entry point (mtvec + 0x0C0) */ + .align 6 + j bad_trap + + /* Reset vector */ + .text + .align 8 + .globl _start +_start: + li s11, KERNBASE + + /* Build ring */ + la t0, htif_ring + li t1, 0 + sd t1, 0(t0) /* zero data */ + sd t1, 8(t0) /* zero used */ + mv t2, t0 + mv t3, t0 + li t5, HTIF_RING_LAST + li t6, 0 + add t4, t0, t5 +1: + addi t3, t3, 24 /* pointer to next */ + beq t3, t4, 2f /* finish */ + sd t3, 16(t2) /* store pointer */ + addi t2, t2, 24 /* next entry */ + addi t6, t6, 1 /* counter */ + j 1b +2: + sd t0, 16(t3) /* last -> first */ + la t1, htif_ring_cursor + sd t0, 0(t1) + la t1, htif_ring_last + sd t0, 0(t1) + /* finish building ring */ + + la t0, hardstack_end + sub t0, t0, s11 + csrw mscratch, t0 + + la t0, mentry + csrw mtvec, t0 + + li t0, 0 + csrw sscratch, t0 + + li s10, PAGE_SIZE + li s9, (PAGE_SIZE * KSTACK_PAGES) + + /* Page tables */ + + /* Level 0 */ + la s1, pagetable_l0 + la s2, pagetable_l1 /* Link to next level PN */ + srli s2, s2, PAGE_SHIFT + + li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) + slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ + or t6, t4, t5 + + /* Store single level0 PTE entry to position */ + li a5, 0x1ff + li a6, PTE_SIZE + mulw a5, a5, a6 + add t0, s1, a5 + sd t6, 0(t0) + + /* Level 1 */ + la s1, pagetable_l1 + la s2, pagetable_l2 /* Link to next level PN */ + srli s2, s2, PAGE_SHIFT + + li a5, KERNBASE + srli a5, a5, 0x1e /* >> 30 */ + andi a5, a5, 0x1ff /* & 0x1ff */ + li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) + slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ + or t6, t4, t5 + + /* Store single level1 PTE entry to position */ + li a6, PTE_SIZE + mulw a5, a5, a6 + add t0, s1, a5 + sd t6, (t0) + + /* Level 2 superpages (512 x 2MiB) */ + la s1, pagetable_l2 + li t3, 512 /* Build 512 entries */ + li t4, 0 /* Counter */ + li t5, 0 +2: + li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S)) + slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ + or t5, t0, t2 + sd t5, (s1) /* Store PTE entry to position */ + addi s1, s1, PTE_SIZE + + addi t4, t4, 1 + bltu t4, t3, 2b + + /* Set page tables base register */ + la s1, pagetable_l0 + csrw sptbr, s1 + + /* Page tables END */ + + /* Enter supervisor mode */ + li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \ + (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \ + (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \ + (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT)); + csrw mstatus, s0 + + /* Exit from machine mode */ + la t0, .Lmmu_on + add t0, t0, s11 + csrw mepc, t0 + eret + +.Lmmu_on: + /* Initialize stack pointer */ + la s3, initstack_end + mv sp, s3 + addi sp, sp, -PCB_SIZE + + /* Clear BSS */ + la a0, _C_LABEL(__bss_start) + la s1, _C_LABEL(_end) +1: + sd zero, 0(a0) + addi a0, a0, 8 + bltu a0, s1, 1b + + /* Fill riscv_bootparams */ + addi sp, sp, -16 + la t0, pagetable_l1 + sd t0, 0(sp) /* kern_l1pt */ + la t0, initstack_end + sd t0, 8(sp) /* kern_stack */ + + mv a0, sp + call _C_LABEL(initriscv) /* Off we go */ + call _C_LABEL(mi_startup) + + .align 4 +initstack: + .space (PAGE_SIZE * KSTACK_PAGES) +initstack_end: +hardstack: + .space (PAGE_SIZE) +hardstack_end: + + .globl htif_ring +htif_ring: + .space (24 * 1024) + + .globl htif_ring_cursor +htif_ring_cursor: + .space (8) + + .globl htif_ring_last +htif_ring_last: + .space (8) + + .globl console_intr +console_intr: + .space (8) + +ENTRY(sigcode) + mv a0, sp + addi a0, a0, SF_UC + +1: + li t0, SYS_sigreturn + ecall + + /* sigreturn failed, exit */ + li t0, SYS_exit + ecall + + j 1b +END(sigcode) + /* This may be copied to the stack, keep it 16-byte aligned */ + .align 3 +esigcode: + + .data + .align 3 + .global szsigcode +szsigcode: + .quad esigcode - sigcode + + .align 12 + .globl pagetable_l0 +pagetable_l0: + .space PAGE_SIZE +pagetable_l1: + .space PAGE_SIZE +pagetable_l2: + .space PAGE_SIZE +pagetable_end: + + .globl init_pt_va +init_pt_va: + .quad pagetable_l2 /* XXX: Keep page tables VA */ + +#include "exception.S" diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c new file mode 100644 index 000000000000..5f9bd1f283f2 --- /dev/null +++ b/sys/riscv/riscv/machdep.c @@ -0,0 +1,795 @@ +/*- + * Copyright (c) 2014 Andrew Turner + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef VFP +#include +#endif + +#ifdef FDT +#include +#include +#endif + +struct pcpu __pcpu[MAXCPU]; + +static struct trapframe proc0_tf; + +vm_paddr_t phys_avail[PHYS_AVAIL_SIZE + 2]; +vm_paddr_t dump_avail[PHYS_AVAIL_SIZE + 2]; + +int early_boot = 1; +int cold = 1; +long realmem = 0; +long Maxmem = 0; + +#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) +vm_paddr_t physmap[PHYSMAP_SIZE]; +u_int physmap_idx; + +struct kva_md_info kmi; + +int64_t dcache_line_size; /* The minimum D cache line size */ +int64_t icache_line_size; /* The minimum I cache line size */ +int64_t idcache_line_size; /* The minimum cache line size */ + +extern int *end; +extern int *initstack_end; + +struct pcpu *pcpup; + +uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs); + +uintptr_t +mcall_trap(uintptr_t mcause, uintptr_t* regs) +{ + + return (0); +} + +static void +cpu_startup(void *dummy) +{ + + identify_cpu(); + + vm_ksubmap_init(&kmi); + bufinit(); + vm_pager_bufferinit(); +} + +SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); + +int +cpu_idle_wakeup(int cpu) +{ + + return (0); +} + +void +bzero(void *buf, size_t len) +{ + uint8_t *p; + + p = buf; + while(len-- > 0) + *p++ = 0; +} + +int +fill_regs(struct thread *td, struct reg *regs) +{ + struct trapframe *frame; + + frame = td->td_frame; + regs->sepc = frame->tf_sepc; + regs->sstatus = frame->tf_sstatus; + regs->ra = frame->tf_ra; + regs->sp = frame->tf_sp; + regs->gp = frame->tf_gp; + regs->tp = frame->tf_tp; + + memcpy(regs->t, frame->tf_t, sizeof(regs->t)); + memcpy(regs->s, frame->tf_s, sizeof(regs->s)); + memcpy(regs->a, frame->tf_a, sizeof(regs->a)); + + return (0); +} + +int +set_regs(struct thread *td, struct reg *regs) +{ + struct trapframe *frame; + + frame = td->td_frame; + frame->tf_sepc = regs->sepc; + frame->tf_sstatus = regs->sstatus; + frame->tf_ra = regs->ra; + frame->tf_sp = regs->sp; + frame->tf_gp = regs->gp; + frame->tf_tp = regs->tp; + + memcpy(frame->tf_t, regs->t, sizeof(frame->tf_t)); + memcpy(frame->tf_s, regs->s, sizeof(frame->tf_s)); + memcpy(frame->tf_a, regs->a, sizeof(frame->tf_a)); + + return (0); +} + +int +fill_fpregs(struct thread *td, struct fpreg *regs) +{ + + /* TODO */ + bzero(regs, sizeof(*regs)); + return (0); +} + +int +set_fpregs(struct thread *td, struct fpreg *regs) +{ + + /* TODO */ + return (0); +} + +int +fill_dbregs(struct thread *td, struct dbreg *regs) +{ + + panic("fill_dbregs"); +} + +int +set_dbregs(struct thread *td, struct dbreg *regs) +{ + + panic("set_dbregs"); +} + +int +ptrace_set_pc(struct thread *td, u_long addr) +{ + + panic("ptrace_set_pc"); + return (0); +} + +int +ptrace_single_step(struct thread *td) +{ + + /* TODO; */ + return (0); +} + +int +ptrace_clear_single_step(struct thread *td) +{ + + /* TODO; */ + return (0); +} + +void +exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) +{ + struct trapframe *tf = td->td_frame; + + memset(tf, 0, sizeof(struct trapframe)); + + /* + * We need to set a0 for init as it doesn't call + * cpu_set_syscall_retval to copy the value. We also + * need to set td_retval for the cases where we do. + */ + tf->tf_a[0] = td->td_retval[0] = stack; + tf->tf_sp = STACKALIGN(stack); + tf->tf_ra = imgp->entry_addr; + tf->tf_sepc = imgp->entry_addr; +} + +/* Sanity check these are the same size, they will be memcpy'd to and fro */ +CTASSERT(sizeof(((struct trapframe *)0)->tf_a) == + sizeof((struct gpregs *)0)->gp_a); +CTASSERT(sizeof(((struct trapframe *)0)->tf_s) == + sizeof((struct gpregs *)0)->gp_s); +CTASSERT(sizeof(((struct trapframe *)0)->tf_t) == + sizeof((struct gpregs *)0)->gp_t); +CTASSERT(sizeof(((struct trapframe *)0)->tf_a) == + sizeof((struct reg *)0)->a); +CTASSERT(sizeof(((struct trapframe *)0)->tf_s) == + sizeof((struct reg *)0)->s); +CTASSERT(sizeof(((struct trapframe *)0)->tf_t) == + sizeof((struct reg *)0)->t); + +int +get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) +{ + struct trapframe *tf = td->td_frame; + + memcpy(mcp->mc_gpregs.gp_t, tf->tf_t, sizeof(mcp->mc_gpregs.gp_t)); + memcpy(mcp->mc_gpregs.gp_s, tf->tf_s, sizeof(mcp->mc_gpregs.gp_s)); + memcpy(mcp->mc_gpregs.gp_a, tf->tf_a, sizeof(mcp->mc_gpregs.gp_a)); + + if (clear_ret & GET_MC_CLEAR_RET) { + mcp->mc_gpregs.gp_a[0] = 0; + mcp->mc_gpregs.gp_t[0] = 0; /* clear syscall error */ + } + + mcp->mc_gpregs.gp_ra = tf->tf_ra; + mcp->mc_gpregs.gp_sp = tf->tf_sp; + mcp->mc_gpregs.gp_gp = tf->tf_gp; + mcp->mc_gpregs.gp_tp = tf->tf_tp; + mcp->mc_gpregs.gp_sepc = tf->tf_sepc; + mcp->mc_gpregs.gp_sstatus = tf->tf_sstatus; + + return (0); +} + +int +set_mcontext(struct thread *td, mcontext_t *mcp) +{ + struct trapframe *tf; + + tf = td->td_frame; + + memcpy(tf->tf_t, mcp->mc_gpregs.gp_t, sizeof(tf->tf_t)); + memcpy(tf->tf_s, mcp->mc_gpregs.gp_s, sizeof(tf->tf_s)); + memcpy(tf->tf_a, mcp->mc_gpregs.gp_a, sizeof(tf->tf_a)); + + tf->tf_ra = mcp->mc_gpregs.gp_ra; + tf->tf_sp = mcp->mc_gpregs.gp_sp; + tf->tf_gp = mcp->mc_gpregs.gp_gp; + tf->tf_tp = mcp->mc_gpregs.gp_tp; + tf->tf_sepc = mcp->mc_gpregs.gp_sepc; + tf->tf_sstatus = mcp->mc_gpregs.gp_sstatus; + + return (0); +} + +static void +get_fpcontext(struct thread *td, mcontext_t *mcp) +{ + /* TODO */ +} + +static void +set_fpcontext(struct thread *td, mcontext_t *mcp) +{ + /* TODO */ +} + +void +cpu_idle(int busy) +{ + + spinlock_enter(); + if (!busy) + cpu_idleclock(); + if (!sched_runnable()) + __asm __volatile( + "fence \n" + "wfi \n"); + if (!busy) + cpu_activeclock(); + spinlock_exit(); +} + +void +cpu_halt(void) +{ + + panic("cpu_halt"); +} + +/* + * Flush the D-cache for non-DMA I/O so that the I-cache can + * be made coherent later. + */ +void +cpu_flush_dcache(void *ptr, size_t len) +{ + + /* TBD */ +} + +/* Get current clock frequency for the given CPU ID. */ +int +cpu_est_clockrate(int cpu_id, uint64_t *rate) +{ + + panic("cpu_est_clockrate"); +} + +void +cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) +{ + +} + +void +spinlock_enter(void) +{ + struct thread *td; + + td = curthread; + if (td->td_md.md_spinlock_count == 0) { + td->td_md.md_spinlock_count = 1; + td->td_md.md_saved_sstatus_ie = intr_disable(); + } else + td->td_md.md_spinlock_count++; + critical_enter(); +} + +void +spinlock_exit(void) +{ + struct thread *td; + register_t sstatus_ie; + + td = curthread; + critical_exit(); + sstatus_ie = td->td_md.md_saved_sstatus_ie; + td->td_md.md_spinlock_count--; + if (td->td_md.md_spinlock_count == 0) + intr_restore(sstatus_ie); +} + +#ifndef _SYS_SYSPROTO_H_ +struct sigreturn_args { + ucontext_t *ucp; +}; +#endif + +int +sys_sigreturn(struct thread *td, struct sigreturn_args *uap) +{ + uint64_t sstatus; + ucontext_t uc; + int error; + + if (uap == NULL) + return (EFAULT); + if (copyin(uap->sigcntxp, &uc, sizeof(uc))) + return (EFAULT); + + /* + * Make sure the processor mode has not been tampered with and + * interrupts have not been disabled. + */ + sstatus = uc.uc_mcontext.mc_gpregs.gp_sstatus; + if ((sstatus & SSTATUS_PS) != 0 || + (sstatus & SSTATUS_PIE) == 0) + return (EINVAL); + + error = set_mcontext(td, &uc.uc_mcontext); + if (error != 0) + return (error); + + set_fpcontext(td, &uc.uc_mcontext); + + /* Restore signal mask. */ + kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); + + return (EJUSTRETURN); +} + +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + memcpy(pcb->pcb_t, tf->tf_t, sizeof(tf->tf_t)); + memcpy(pcb->pcb_s, tf->tf_s, sizeof(tf->tf_s)); + memcpy(pcb->pcb_a, tf->tf_a, sizeof(tf->tf_a)); + + pcb->pcb_ra = tf->tf_ra; + pcb->pcb_sp = tf->tf_sp; + pcb->pcb_gp = tf->tf_gp; + pcb->pcb_tp = tf->tf_tp; + pcb->pcb_sepc = tf->tf_sepc; +} + +void +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) +{ + struct sigframe *fp, frame; + struct sysentvec *sysent; + struct trapframe *tf; + struct sigacts *psp; + struct thread *td; + struct proc *p; + int onstack; + int code; + int sig; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + + sig = ksi->ksi_signo; + code = ksi->ksi_code; + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + + tf = td->td_frame; + onstack = sigonstack(tf->tf_sp); + + CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, + catcher, sig); + + /* Allocate and validate space for the signal handler context. */ + if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp + + td->td_sigstk.ss_size); + } else { + fp = (struct sigframe *)td->td_frame->tf_sp; + } + + /* Make room, keeping the stack aligned */ + fp--; + fp = (struct sigframe *)STACKALIGN(fp); + + /* Fill in the frame to copy out */ + get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); + get_fpcontext(td, &frame.sf_uc.uc_mcontext); + frame.sf_si = ksi->ksi_info; + frame.sf_uc.uc_sigmask = *mask; + frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? + ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; + frame.sf_uc.uc_stack = td->td_sigstk; + mtx_unlock(&psp->ps_mtx); + PROC_UNLOCK(td->td_proc); + + /* Copy the sigframe out to the user's stack. */ + if (copyout(&frame, fp, sizeof(*fp)) != 0) { + /* Process has trashed its stack. Kill it. */ + CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp); + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + tf->tf_a[0] = sig; + tf->tf_a[1] = (register_t)&fp->sf_si; + tf->tf_a[2] = (register_t)&fp->sf_uc; + + tf->tf_sepc = (register_t)catcher; + tf->tf_sp = (register_t)fp; + + sysent = p->p_sysent; + if (sysent->sv_sigcode_base != 0) + tf->tf_ra = (register_t)sysent->sv_sigcode_base; + else + tf->tf_ra = (register_t)(sysent->sv_psstrings - + *(sysent->sv_szsigcode)); + + CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr, + tf->tf_sp); + + PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); +} + +static void +init_proc0(vm_offset_t kstack) +{ + pcpup = &__pcpu[0]; + + proc_linkup0(&proc0, &thread0); + thread0.td_kstack = kstack; + thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1; + thread0.td_frame = &proc0_tf; + pcpup->pc_curpcb = thread0.td_pcb; +} + +static int +add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap, + u_int *physmap_idxp) +{ + u_int i, insert_idx, _physmap_idx; + + _physmap_idx = *physmap_idxp; + + if (length == 0) + return (1); + + /* + * Find insertion point while checking for overlap. Start off by + * assuming the new entry will be added to the end. + */ + insert_idx = _physmap_idx; + for (i = 0; i <= _physmap_idx; i += 2) { + if (base < physmap[i + 1]) { + if (base + length <= physmap[i]) { + insert_idx = i; + break; + } + if (boothowto & RB_VERBOSE) + printf( + "Overlapping memory regions, ignoring second region\n"); + return (1); + } + } + + /* See if we can prepend to the next entry. */ + if (insert_idx <= _physmap_idx && + base + length == physmap[insert_idx]) { + physmap[insert_idx] = base; + return (1); + } + + /* See if we can append to the previous entry. */ + if (insert_idx > 0 && base == physmap[insert_idx - 1]) { + physmap[insert_idx - 1] += length; + return (1); + } + + _physmap_idx += 2; + *physmap_idxp = _physmap_idx; + if (_physmap_idx == PHYSMAP_SIZE) { + printf( + "Too many segments in the physical address map, giving up\n"); + return (0); + } + + /* + * Move the last 'N' entries down to make room for the new + * entry if needed. + */ + for (i = _physmap_idx; i > insert_idx; i -= 2) { + physmap[i] = physmap[i - 2]; + physmap[i + 1] = physmap[i - 1]; + } + + /* Insert the new entry. */ + physmap[insert_idx] = base; + physmap[insert_idx + 1] = base + length; + + printf("physmap[%d] = 0x%016lx\n", insert_idx, base); + printf("physmap[%d] = 0x%016lx\n", insert_idx + 1, base + length); + return (1); +} + +#ifdef FDT +static void +try_load_dtb(caddr_t kmdp) +{ + vm_offset_t dtbp; + + dtbp = (vm_offset_t)&fdt_static_dtb; + if (dtbp == (vm_offset_t)NULL) { + printf("ERROR loading DTB\n"); + return; + } + + if (OF_install(OFW_FDT, 0) == FALSE) + panic("Cannot install FDT"); + + if (OF_init((void *)dtbp) != 0) + panic("OF_init failed with the found device tree"); +} +#endif + +static void +cache_setup(void) +{ + + /* TODO */ +} + +/* + * Fake up a boot descriptor table. + * RISCVTODO: This needs to be done via loader (when it's available). + */ +vm_offset_t +fake_preload_metadata(struct riscv_bootparams *rvbp __unused) +{ +#ifdef DDB + vm_offset_t zstart = 0, zend = 0; +#endif + vm_offset_t lastaddr; + int i = 0; + static uint32_t fake_preload[35]; + + fake_preload[i++] = MODINFO_NAME; + fake_preload[i++] = strlen("kernel") + 1; + strcpy((char*)&fake_preload[i++], "kernel"); + i += 1; + fake_preload[i++] = MODINFO_TYPE; + fake_preload[i++] = strlen("elf64 kernel") + 1; + strcpy((char*)&fake_preload[i++], "elf64 kernel"); + i += 3; + fake_preload[i++] = MODINFO_ADDR; + fake_preload[i++] = sizeof(vm_offset_t); + fake_preload[i++] = (uint64_t)(KERNBASE + KERNENTRY); + i += 1; + fake_preload[i++] = MODINFO_SIZE; + fake_preload[i++] = sizeof(uint64_t); + printf("end is 0x%016lx\n", (uint64_t)&end); + fake_preload[i++] = (uint64_t)&end - (uint64_t)(KERNBASE + KERNENTRY); + i += 1; +#ifdef DDB +#if 0 + /* RISCVTODO */ + if (*(uint32_t *)KERNVIRTADDR == MAGIC_TRAMP_NUMBER) { + fake_preload[i++] = MODINFO_METADATA|MODINFOMD_SSYM; + fake_preload[i++] = sizeof(vm_offset_t); + fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 4); + fake_preload[i++] = MODINFO_METADATA|MODINFOMD_ESYM; + fake_preload[i++] = sizeof(vm_offset_t); + fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 8); + lastaddr = *(uint32_t *)(KERNVIRTADDR + 8); + zend = lastaddr; + zstart = *(uint32_t *)(KERNVIRTADDR + 4); + db_fetch_ksymtab(zstart, zend); + } else +#endif +#endif + lastaddr = (vm_offset_t)&end; + fake_preload[i++] = 0; + fake_preload[i] = 0; + preload_metadata = (void *)fake_preload; + + return (lastaddr); +} + +void +initriscv(struct riscv_bootparams *rvbp) +{ + vm_offset_t lastaddr; + vm_size_t kernlen; + caddr_t kmdp; + + /* Set the module data location */ + lastaddr = fake_preload_metadata(rvbp); + + /* Find the kernel address */ + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type("elf64 kernel"); + + boothowto = 0; + + kern_envp = NULL; + +#ifdef FDT + try_load_dtb(kmdp); +#endif + + /* Load the physical memory ranges */ + physmap_idx = 0; + + /* + * RISCVTODO: figure out whether platform provides ranges, + * or grab from FDT. + */ + add_physmap_entry(0, 0x8000000, physmap, &physmap_idx); + + /* Set the pcpu data, this is needed by pmap_bootstrap */ + pcpup = &__pcpu[0]; + pcpu_init(pcpup, 0, sizeof(struct pcpu)); + + /* Set the pcpu pointer */ +#if 0 + /* SMP TODO: try re-use gp for pcpu pointer */ + __asm __volatile( + "mv gp, %0" :: "r"(pcpup)); +#endif + + PCPU_SET(curthread, &thread0); + + /* Do basic tuning, hz etc */ + init_param1(); + + cache_setup(); + + /* Bootstrap enough of pmap to enter the kernel proper */ + kernlen = (lastaddr - KERNBASE); + pmap_bootstrap(rvbp->kern_l1pt, KERNENTRY, kernlen); + + cninit(); + + init_proc0(rvbp->kern_stack); + + /* set page table base register for thread0 */ + thread0.td_pcb->pcb_l1addr = (rvbp->kern_l1pt - KERNBASE); + + msgbufinit(msgbufp, msgbufsize); + mutex_init(); + init_param2(physmem); + kdb_init(); + + riscv_init_interrupts(); + + early_boot = 0; +} diff --git a/sys/riscv/riscv/mem.c b/sys/riscv/riscv/mem.c new file mode 100644 index 000000000000..38488a2c9a87 --- /dev/null +++ b/sys/riscv/riscv/mem.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2014 Andrew Turner + * 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. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +struct mem_range_softc mem_range_softc; + +int +memrw(struct cdev *dev, struct uio *uio, int flags) +{ + ssize_t orig_resid; + vm_offset_t off, v; + struct iovec *iov; + struct vm_page m; + vm_page_t marr; + u_int cnt; + int error; + + error = 0; + orig_resid = uio->uio_resid; + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("memrw"); + continue; + } + + v = uio->uio_offset; + off = v & PAGE_MASK; + cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off); + if (cnt == 0) + continue; + + switch(dev2unit(dev)) { + case CDEV_MINOR_KMEM: + /* If the address is in the DMAP just copy it */ + if (VIRT_IN_DMAP(v)) { + error = uiomove((void *)v, cnt, uio); + break; + } + + if (!kernacc((void *)v, cnt, uio->uio_rw == UIO_READ ? + VM_PROT_READ : VM_PROT_WRITE)) { + error = EFAULT; + break; + } + + /* Get the physical address to read */ + v = pmap_extract(kernel_pmap, v); + if (v == 0) { + error = EFAULT; + break; + } + + /* FALLTHROUGH */ + case CDEV_MINOR_MEM: + /* If within the DMAP use this to copy from */ + if (PHYS_IN_DMAP(v)) { + v = PHYS_TO_DMAP(v); + error = uiomove((void *)v, cnt, uio); + break; + } + + /* Have uiomove_fromphys handle the data */ + m.phys_addr = trunc_page(v); + marr = &m; + uiomove_fromphys(&marr, off, cnt, uio); + break; + } + } + + /* + * Don't return error if any byte was written. Read and write + * can return error only if no i/o was performed. + */ + if (uio->uio_resid != orig_resid) + error = 0; + + return (error); +} + diff --git a/sys/riscv/riscv/minidump_machdep.c b/sys/riscv/riscv/minidump_machdep.c new file mode 100644 index 000000000000..ca51cfc77e50 --- /dev/null +++ b/sys/riscv/riscv/minidump_machdep.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2006 Peter Wemm + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_watchdog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CTASSERT(sizeof(struct kerneldumpheader) == 512); +CTASSERT(sizeof(*vm_page_dump) == 8); + +int +minidumpsys(struct dumperinfo *di) +{ + + panic("minidumpsys"); +} diff --git a/sys/riscv/riscv/nexus.c b/sys/riscv/riscv/nexus.c new file mode 100644 index 000000000000..83b57959edab --- /dev/null +++ b/sys/riscv/riscv/nexus.c @@ -0,0 +1,387 @@ +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. 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 code implements a `root nexus' for RISC-V Architecture + * machines. The function of the root nexus is to serve as an + * attachment point for both processors and buses, and to manage + * resources which are common to all of them. In particular, + * this code implements the core resource managers for interrupt + * requests, DMA requests (which rightfully should be a part of the + * ISA code but it's easier to do it here for now), I/O port addresses, + * and I/O memory address space. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "opt_platform.h" + +#include +#include "ofw_bus_if.h" + +extern struct bus_space memmap_bus; + +static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); + +struct nexus_device { + struct resource_list nx_resources; +}; + +#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) + +static struct rman mem_rman; +static struct rman irq_rman; + +static device_probe_t nexus_fdt_probe; +static int nexus_attach(device_t); + +static int nexus_print_child(device_t, device_t); +static device_t nexus_add_child(device_t, u_int, const char *, int); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol); +static struct resource_list *nexus_get_reslist(device_t, device_t); +static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); + +static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); +static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); + +static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, + int icells, pcell_t *intr); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_fdt_probe), + DEVMETHOD(device_attach, nexus_attach), + + /* OFW interface */ + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), + + /* Bus interface */ + DEVMETHOD(bus_print_child, nexus_print_child), + DEVMETHOD(bus_add_child, nexus_add_child), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_get_resource_list, nexus_get_reslist), + DEVMETHOD(bus_set_resource, nexus_set_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_fdt_driver = { + "nexus", + nexus_methods, + 1 /* no softc */ +}; + +static int +nexus_fdt_probe(device_t dev) +{ + + device_quiet(dev); + return (BUS_PROBE_DEFAULT); +} + +static int +nexus_attach(device_t dev) +{ + + mem_rman.rm_start = 0; + mem_rman.rm_end = ~0ul; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "I/O memory addresses"; + if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) + panic("nexus_attach mem_rman"); + irq_rman.rm_start = 0; + irq_rman.rm_end = ~0ul; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupts"; + if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0)) + panic("nexus_attach irq_rman"); + + nexus_add_child(dev, 10, "ofwbus", 0); + + bus_generic_probe(dev); + bus_generic_attach(dev); + + return (0); +} + +static int +nexus_print_child(device_t bus, device_t child) +{ + int retval = 0; + + retval += bus_print_child_header(bus, child); + retval += printf("\n"); + + return (retval); +} + +static device_t +nexus_add_child(device_t bus, u_int order, const char *name, int unit) +{ + device_t child; + struct nexus_device *ndev; + + ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO); + if (!ndev) + return (0); + resource_list_init(&ndev->nx_resources); + + child = device_add_child_ordered(bus, order, name, unit); + + /* should we free this in nexus_child_detached? */ + device_set_ivars(child, ndev); + + return (child); +} + + +/* + * Allocate a resource on behalf of child. NB: child is usually going to be a + * child of one of our descendants, not a direct child of nexus0. + * (Exceptions include footbridge.) + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct nexus_device *ndev = DEVTONX(child); + struct resource *rv; + struct resource_list_entry *rle; + struct rman *rm; + int needactivate = flags & RF_ACTIVE; + + /* + * If this is an allocation of the "default" range for a given + * RID, and we know what the resources for this device are + * (ie. they aren't maintained by a child bus), then work out + * the start/end values. + */ + if ((start == 0UL) && (end == ~0UL) && (count == 1)) { + if (device_get_parent(child) != bus || ndev == NULL) + return(NULL); + rle = resource_list_find(&ndev->nx_resources, type, *rid); + if (rle == NULL) + return(NULL); + start = rle->start; + end = rle->end; + count = rle->count; + } + + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + rm = &mem_rman; + break; + + default: + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return (NULL); + + rman_set_rid(rv, *rid); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol) +{ + + return (riscv_config_intr(irq, trig, pol)); +} + +static int +nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, + driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) +{ + int error; + + if ((rman_get_flags(res) & RF_SHAREABLE) == 0) + flags |= INTR_EXCL; + + /* We depend here on rman_activate_resource() being idempotent. */ + error = rman_activate_resource(res); + if (error) + return (error); + + error = riscv_setup_intr(device_get_nameunit(child), filt, intr, + arg, rman_get_start(res), flags, cookiep); + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + + return (riscv_teardown_intr(ih)); +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + int err; + bus_addr_t paddr; + bus_size_t psize; + bus_space_handle_t vaddr; + + if ((err = rman_activate_resource(r)) != 0) + return (err); + + /* + * If this is a memory resource, map it into the kernel. + */ + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + paddr = (bus_addr_t)rman_get_start(r); + psize = (bus_size_t)rman_get_size(r); + err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr); + if (err != 0) { + rman_deactivate_resource(r); + return (err); + } + rman_set_bustag(r, &memmap_bus); + rman_set_virtual(r, (void *)vaddr); + rman_set_bushandle(r, vaddr); + } + return (0); +} + +static struct resource_list * +nexus_get_reslist(device_t dev, device_t child) +{ + struct nexus_device *ndev = DEVTONX(child); + + return (&ndev->nx_resources); +} + +static int +nexus_set_resource(device_t dev, device_t child, int type, int rid, + u_long start, u_long count) +{ + struct nexus_device *ndev = DEVTONX(child); + struct resource_list *rl = &ndev->nx_resources; + + /* XXX this should return a success/failure indicator */ + resource_list_add(rl, type, rid, start, start + count - 1, count); + + return(0); +} + + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + bus_size_t psize; + bus_space_handle_t vaddr; + + psize = (bus_size_t)rman_get_size(r); + vaddr = rman_get_bushandle(r); + + if (vaddr != 0) { + bus_space_unmap(&memmap_bus, vaddr, psize); + rman_set_virtual(r, NULL); + rman_set_bushandle(r, 0); + } + + return (rman_deactivate_resource(r)); +} + +static devclass_t nexus_fdt_devclass; + +EARLY_DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass, + 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); + +static int +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *intr) +{ + int irq; + + if (icells == 3) { + irq = intr[1]; + if (intr[0] == 0) + irq += 32; /* SPI */ + else + irq += 16; /* PPI */ + } else + irq = intr[0]; + + return (irq); +} diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c new file mode 100644 index 000000000000..e4ca19fff330 --- /dev/null +++ b/sys/riscv/riscv/pmap.c @@ -0,0 +1,3197 @@ +/*- + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * Copyright (c) 1994 John S. Dyson + * All rights reserved. + * Copyright (c) 1994 David Greenman + * All rights reserved. + * Copyright (c) 2003 Peter Wemm + * All rights reserved. + * Copyright (c) 2005-2010 Alan L. Cox + * All rights reserved. + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and William Jolitz of UUNET Technologies Inc. + * + * Portions of this software were developed by Andrew Turner under + * sponsorship from The FreeBSD Foundation. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 + */ +/*- + * Copyright (c) 2003 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Jake Burkholder, + * Safeport Network Services, and Network Associates Laboratories, the + * Security Research Division of Network Associates, Inc. under + * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA + * CHATS research program. + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Manages physical address maps. + * + * Since the information managed by this module is + * also stored by the logical address mapping module, + * this module may throw away valid virtual-to-physical + * mappings at almost any time. However, invalidations + * of virtual-to-physical mappings must be done as + * requested. + * + * In order to cope with hardware architectures which + * make virtual-to-physical map invalidates expensive, + * this module may delay invalidate or reduced protection + * operations until such time as they are actually + * necessary. This module is given full information as + * to which processors are currently using which maps, + * and to when physical maps must be made correct. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define NPDEPG (PAGE_SIZE/(sizeof (pd_entry_t))) +#define NUPDE (NPDEPG * NPDEPG) +#define NUSERPGTBLS (NUPDE + NPDEPG) + +#if !defined(DIAGNOSTIC) +#ifdef __GNUC_GNU_INLINE__ +#define PMAP_INLINE __attribute__((__gnu_inline__)) inline +#else +#define PMAP_INLINE extern inline +#endif +#else +#define PMAP_INLINE +#endif + +#ifdef PV_STATS +#define PV_STAT(x) do { x ; } while (0) +#else +#define PV_STAT(x) do { } while (0) +#endif + +#define pmap_l2_pindex(v) ((v) >> L2_SHIFT) + +#define NPV_LIST_LOCKS MAXCPU + +#define PHYS_TO_PV_LIST_LOCK(pa) \ + (&pv_list_locks[pa_index(pa) % NPV_LIST_LOCKS]) + +#define CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, pa) do { \ + struct rwlock **_lockp = (lockp); \ + struct rwlock *_new_lock; \ + \ + _new_lock = PHYS_TO_PV_LIST_LOCK(pa); \ + if (_new_lock != *_lockp) { \ + if (*_lockp != NULL) \ + rw_wunlock(*_lockp); \ + *_lockp = _new_lock; \ + rw_wlock(*_lockp); \ + } \ +} while (0) + +#define CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m) \ + CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, VM_PAGE_TO_PHYS(m)) + +#define RELEASE_PV_LIST_LOCK(lockp) do { \ + struct rwlock **_lockp = (lockp); \ + \ + if (*_lockp != NULL) { \ + rw_wunlock(*_lockp); \ + *_lockp = NULL; \ + } \ +} while (0) + +#define VM_PAGE_TO_PV_LIST_LOCK(m) \ + PHYS_TO_PV_LIST_LOCK(VM_PAGE_TO_PHYS(m)) + +struct pmap kernel_pmap_store; + +vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ +vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ +vm_offset_t kernel_vm_end = 0; + +struct msgbuf *msgbufp = NULL; + +static struct rwlock_padalign pvh_global_lock; + +extern uint64_t pagetable_l0; + +/* + * Data for the pv entry allocation mechanism + */ +static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks); +static struct mtx pv_chunks_mutex; +static struct rwlock pv_list_locks[NPV_LIST_LOCKS]; + +static void free_pv_chunk(struct pv_chunk *pc); +static void free_pv_entry(pmap_t pmap, pv_entry_t pv); +static pv_entry_t get_pv_entry(pmap_t pmap, struct rwlock **lockp); +static vm_page_t reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp); +static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); +static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, + vm_offset_t va); +static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, + vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp); +static int pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t sva, + pd_entry_t ptepde, struct spglist *free, struct rwlock **lockp); +static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, + vm_page_t m, struct rwlock **lockp); + +static vm_page_t _pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, + struct rwlock **lockp); + +static void _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, + struct spglist *free); +static int pmap_unuse_l3(pmap_t, vm_offset_t, pd_entry_t, struct spglist *); + +/* + * These load the old table data and store the new value. + * They need to be atomic as the System MMU may write to the table at + * the same time as the CPU. + */ +#define pmap_load_store(table, entry) atomic_swap_64(table, entry) +#define pmap_set(table, mask) atomic_set_64(table, mask) +#define pmap_load_clear(table) atomic_swap_64(table, 0) +#define pmap_load(table) (*table) + +/********************/ +/* Inline functions */ +/********************/ + +static __inline void +pagecopy(void *s, void *d) +{ + + memcpy(d, s, PAGE_SIZE); +} + +static __inline void +pagezero(void *p) +{ + + bzero(p, PAGE_SIZE); +} + +#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK) +#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK) +#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK) + +#define PTE_TO_PHYS(pte) ((pte >> PTE_PPN0_S) * PAGE_SIZE) + +static __inline pd_entry_t * +pmap_l1(pmap_t pmap, vm_offset_t va) +{ + + return (&pmap->pm_l1[pmap_l1_index(va)]); +} + +static __inline pd_entry_t * +pmap_l1_to_l2(pd_entry_t *l1, vm_offset_t va) +{ + vm_paddr_t phys; + pd_entry_t *l2; + + phys = PTE_TO_PHYS(pmap_load(l1)); + l2 = (pd_entry_t *)PHYS_TO_DMAP(phys); + + return (&l2[pmap_l2_index(va)]); +} + +static __inline pd_entry_t * +pmap_l2(pmap_t pmap, vm_offset_t va) +{ + pd_entry_t *l1; + + l1 = pmap_l1(pmap, va); + + if ((pmap_load(l1) & PTE_VALID) == 0) + return (NULL); + if ((pmap_load(l1) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) + return (NULL); + + return (pmap_l1_to_l2(l1, va)); +} + +static __inline pt_entry_t * +pmap_l2_to_l3(pd_entry_t *l2, vm_offset_t va) +{ + vm_paddr_t phys; + pt_entry_t *l3; + + phys = PTE_TO_PHYS(pmap_load(l2)); + l3 = (pd_entry_t *)PHYS_TO_DMAP(phys); + + return (&l3[pmap_l3_index(va)]); +} + +static __inline pt_entry_t * +pmap_l3(pmap_t pmap, vm_offset_t va) +{ + pd_entry_t *l2; + + l2 = pmap_l2(pmap, va); + if (l2 == NULL) + return (NULL); + if ((pmap_load(l2) & PTE_VALID) == 0) + return (NULL); + if (l2 == NULL || (pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) + return (NULL); + + return (pmap_l2_to_l3(l2, va)); +} + + +static __inline int +pmap_is_write(pt_entry_t entry) +{ + + if (entry & (1 << PTE_TYPE_S)) + return (1); + + return (0); +} + +static __inline int +pmap_is_current(pmap_t pmap) +{ + + return ((pmap == pmap_kernel()) || + (pmap == curthread->td_proc->p_vmspace->vm_map.pmap)); +} + +static __inline int +pmap_l3_valid(pt_entry_t l3) +{ + + return (l3 & PTE_VALID); +} + +static __inline int +pmap_l3_valid_cacheable(pt_entry_t l3) +{ + + /* TODO */ + + return (0); +} + +#define PTE_SYNC(pte) cpu_dcache_wb_range((vm_offset_t)pte, sizeof(*pte)) + +/* Checks if the page is dirty. */ +static inline int +pmap_page_dirty(pt_entry_t pte) +{ + + return (pte & PTE_DIRTY); +} + +static __inline void +pmap_resident_count_inc(pmap_t pmap, int count) +{ + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + pmap->pm_stats.resident_count += count; +} + +static __inline void +pmap_resident_count_dec(pmap_t pmap, int count) +{ + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT(pmap->pm_stats.resident_count >= count, + ("pmap %p resident count underflow %ld %d", pmap, + pmap->pm_stats.resident_count, count)); + pmap->pm_stats.resident_count -= count; +} + +static pt_entry_t * +pmap_early_page_idx(vm_offset_t l1pt, vm_offset_t va, u_int *l1_slot, + u_int *l2_slot) +{ + pt_entry_t *l2; + pd_entry_t *l1; + + l1 = (pd_entry_t *)l1pt; + *l1_slot = (va >> L1_SHIFT) & Ln_ADDR_MASK; + + /* Check locore has used a table L1 map */ + KASSERT((l1[*l1_slot] & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S), + ("Invalid bootstrap L1 table")); + + /* Find the address of the L2 table */ + l2 = (pt_entry_t *)init_pt_va; + *l2_slot = pmap_l2_index(va); + + return (l2); +} + +static vm_paddr_t +pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va) +{ + u_int l1_slot, l2_slot; + pt_entry_t *l2; + u_int ret; + + l2 = pmap_early_page_idx(l1pt, va, &l1_slot, &l2_slot); + + /* L2 is superpages */ + ret = (l2[l2_slot] >> PTE_PPN1_S) << L2_SHIFT; + ret += (va & L2_OFFSET); + + return (ret); +} + +static void +pmap_bootstrap_dmap(vm_offset_t l2pt) +{ + vm_offset_t va; + vm_paddr_t pa; + pd_entry_t *l2; + u_int l2_slot; + pt_entry_t entry; + u_int pn; + + va = DMAP_MIN_ADDRESS; + l2 = (pd_entry_t *)l2pt; + l2_slot = pmap_l2_index(DMAP_MIN_ADDRESS); + + for (pa = 0; va < DMAP_MAX_ADDRESS; pa += L2_SIZE, va += L2_SIZE, l2_slot++) { + KASSERT(l2_slot < Ln_ENTRIES, ("Invalid L2 index")); + + /* superpages */ + pn = ((pa >> L2_SHIFT) & Ln_ADDR_MASK); + entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S)); + entry |= (pn << PTE_PPN1_S); + + pmap_load_store(&l2[l2_slot], entry); + } + + cpu_dcache_wb_range((vm_offset_t)l2, PAGE_SIZE); + cpu_tlb_flushID(); +} + +/* + * Bootstrap the system enough to run with virtual memory. + */ +void +pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) +{ + u_int l1_slot, l2_slot, avail_slot, map_slot, used_map_slot; + uint64_t kern_delta; + pt_entry_t *l2; + vm_offset_t va, freemempos; + vm_offset_t dpcpu, msgbufpv; + vm_paddr_t pa, min_pa; + vm_offset_t l2pt; + int i; + + kern_delta = KERNBASE - kernstart; + physmem = 0; + + printf("pmap_bootstrap %lx %lx %lx\n", l1pt, kernstart, kernlen); + printf("%lx\n", l1pt); + printf("%lx\n", (KERNBASE >> L1_SHIFT) & Ln_ADDR_MASK); + + /* Set this early so we can use the pagetable walking functions */ + kernel_pmap_store.pm_l1 = (pd_entry_t *)l1pt; + PMAP_LOCK_INIT(kernel_pmap); + + /* + * Initialize the global pv list lock. + */ + rw_init(&pvh_global_lock, "pmap pv global"); + + /* Assume the address we were loaded to is a valid physical address */ + min_pa = KERNBASE - kern_delta; + + /* + * Find the minimum physical address. physmap is sorted, + * but may contain empty ranges. + */ + for (i = 0; i < (physmap_idx * 2); i += 2) { + if (physmap[i] == physmap[i + 1]) + continue; + if (physmap[i] <= min_pa) + min_pa = physmap[i]; + break; + } + + /* Create a direct map region early so we can use it for pa -> va */ + l2pt = (l1pt + PAGE_SIZE); + pmap_bootstrap_dmap(l2pt); + + va = KERNBASE; + pa = KERNBASE - kern_delta; + + /* + * Start to initialize phys_avail by copying from physmap + * up to the physical address KERNBASE points at. + */ + map_slot = avail_slot = 0; + for (; map_slot < (physmap_idx * 2); map_slot += 2) { + if (physmap[map_slot] == physmap[map_slot + 1]) + continue; + + phys_avail[avail_slot] = physmap[map_slot]; + phys_avail[avail_slot + 1] = physmap[map_slot + 1]; + physmem += (phys_avail[avail_slot + 1] - + phys_avail[avail_slot]) >> PAGE_SHIFT; + avail_slot += 2; + } + + /* Add the memory before the kernel */ + if (physmap[avail_slot] < pa) { + phys_avail[avail_slot] = physmap[map_slot]; + phys_avail[avail_slot + 1] = pa; + physmem += (phys_avail[avail_slot + 1] - + phys_avail[avail_slot]) >> PAGE_SHIFT; + avail_slot += 2; + } + used_map_slot = map_slot; + + /* + * Read the page table to find out what is already mapped. + * This assumes we have mapped a block of memory from KERNBASE + * using a single L1 entry. + */ + l2 = pmap_early_page_idx(l1pt, KERNBASE, &l1_slot, &l2_slot); + + /* Sanity check the index, KERNBASE should be the first VA */ + KASSERT(l2_slot == 0, ("The L2 index is non-zero")); + + /* Find how many pages we have mapped */ + for (; l2_slot < Ln_ENTRIES; l2_slot++) { + if ((l2[l2_slot] & PTE_VALID) == 0) + break; + + /* Check locore used L2 superpages */ + KASSERT((l2[l2_slot] & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S), + ("Invalid bootstrap L2 table")); + + va += L2_SIZE; + pa += L2_SIZE; + } + + va = roundup2(va, L2_SIZE); + + freemempos = KERNBASE + kernlen; + freemempos = roundup2(freemempos, PAGE_SIZE); + + cpu_tlb_flushID(); + +#define alloc_pages(var, np) \ + (var) = freemempos; \ + freemempos += (np * PAGE_SIZE); \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + + /* Allocate dynamic per-cpu area. */ + alloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); + dpcpu_init((void *)dpcpu, 0); + + /* Allocate memory for the msgbuf, e.g. for /sbin/dmesg */ + alloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); + msgbufp = (void *)msgbufpv; + + virtual_avail = roundup2(freemempos, L2_SIZE); + virtual_end = VM_MAX_KERNEL_ADDRESS - L2_SIZE; + kernel_vm_end = virtual_avail; + + pa = pmap_early_vtophys(l1pt, freemempos); + + /* Finish initialising physmap */ + map_slot = used_map_slot; + for (; avail_slot < (PHYS_AVAIL_SIZE - 2) && + map_slot < (physmap_idx * 2); map_slot += 2) { + if (physmap[map_slot] == physmap[map_slot + 1]) + continue; + + /* Have we used the current range? */ + if (physmap[map_slot + 1] <= pa) + continue; + + /* Do we need to split the entry? */ + if (physmap[map_slot] < pa) { + phys_avail[avail_slot] = pa; + phys_avail[avail_slot + 1] = physmap[map_slot + 1]; + } else { + phys_avail[avail_slot] = physmap[map_slot]; + phys_avail[avail_slot + 1] = physmap[map_slot + 1]; + } + physmem += (phys_avail[avail_slot + 1] - + phys_avail[avail_slot]) >> PAGE_SHIFT; + + avail_slot += 2; + } + phys_avail[avail_slot] = 0; + phys_avail[avail_slot + 1] = 0; + + /* + * Maxmem isn't the "maximum memory", it's one larger than the + * highest page of the physical address space. It should be + * called something like "Maxphyspage". + */ + Maxmem = atop(phys_avail[avail_slot - 1]); + + cpu_tlb_flushID(); +} + +/* + * Initialize a vm_page's machine-dependent fields. + */ +void +pmap_page_init(vm_page_t m) +{ + + TAILQ_INIT(&m->md.pv_list); + m->md.pv_memattr = VM_MEMATTR_WRITE_BACK; +} + +/* + * Initialize the pmap module. + * Called by vm_init, to initialize any structures that the pmap + * system needs to map virtual memory. + */ +void +pmap_init(void) +{ + int i; + + /* + * Initialize the pv chunk list mutex. + */ + mtx_init(&pv_chunks_mutex, "pmap pv chunk list", NULL, MTX_DEF); + + /* + * Initialize the pool of pv list locks. + */ + for (i = 0; i < NPV_LIST_LOCKS; i++) + rw_init(&pv_list_locks[i], "pmap pv list"); +} + +/* + * Normal, non-SMP, invalidation functions. + * We inline these within pmap.c for speed. + */ +PMAP_INLINE void +pmap_invalidate_page(pmap_t pmap, vm_offset_t va) +{ + + /* TODO */ + + sched_pin(); + __asm __volatile("sfence.vm"); + sched_unpin(); +} + +PMAP_INLINE void +pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + + /* TODO */ + + sched_pin(); + __asm __volatile("sfence.vm"); + sched_unpin(); +} + +PMAP_INLINE void +pmap_invalidate_all(pmap_t pmap) +{ + + /* TODO */ + + sched_pin(); + __asm __volatile("sfence.vm"); + sched_unpin(); +} + +/* + * Routine: pmap_extract + * Function: + * Extract the physical page address associated + * with the given map/virtual_address pair. + */ +vm_paddr_t +pmap_extract(pmap_t pmap, vm_offset_t va) +{ + pd_entry_t *l2p, l2; + pt_entry_t *l3p, l3; + vm_paddr_t pa; + + pa = 0; + PMAP_LOCK(pmap); + /* + * Start with the l2 tabel. We are unable to allocate + * pages in the l1 table. + */ + l2p = pmap_l2(pmap, va); + if (l2p != NULL) { + l2 = pmap_load(l2p); + if ((l2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S)) { + l3p = pmap_l2_to_l3(l2p, va); + if (l3p != NULL) { + l3 = pmap_load(l3p); + pa = PTE_TO_PHYS(l3); + pa |= (va & L3_OFFSET); + } + } else { + /* L2 is superpages */ + pa = (l2 >> PTE_PPN1_S) << L2_SHIFT; + pa |= (va & L2_OFFSET); + } + } + PMAP_UNLOCK(pmap); + return (pa); +} + +/* + * Routine: pmap_extract_and_hold + * Function: + * Atomically extract and hold the physical page + * with the given pmap and virtual address pair + * if that mapping permits the given protection. + */ +vm_page_t +pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) +{ + pt_entry_t *l3p, l3; + vm_paddr_t phys; + vm_paddr_t pa; + vm_page_t m; + + pa = 0; + m = NULL; + PMAP_LOCK(pmap); +retry: + l3p = pmap_l3(pmap, va); + if (l3p != NULL && (l3 = pmap_load(l3p)) != 0) { + if ((pmap_is_write(l3)) || ((prot & VM_PROT_WRITE) == 0)) { + phys = PTE_TO_PHYS(l3); + if (vm_page_pa_tryrelock(pmap, phys, &pa)) + goto retry; + m = PHYS_TO_VM_PAGE(phys); + vm_page_hold(m); + } + } + PA_UNLOCK_COND(pa); + PMAP_UNLOCK(pmap); + return (m); +} + +vm_paddr_t +pmap_kextract(vm_offset_t va) +{ + pd_entry_t *l2; + pt_entry_t *l3; + vm_paddr_t pa; + + if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { + pa = DMAP_TO_PHYS(va); + } else { + l2 = pmap_l2(kernel_pmap, va); + if (l2 == NULL) + panic("pmap_kextract: No l2"); + if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) { + /* superpages */ + pa = (pmap_load(l2) >> PTE_PPN1_S) << L2_SHIFT; + pa |= (va & L2_OFFSET); + return (pa); + } + + l3 = pmap_l2_to_l3(l2, va); + if (l3 == NULL) + panic("pmap_kextract: No l3..."); + pa = PTE_TO_PHYS(pmap_load(l3)); + pa |= (va & PAGE_MASK); + } + return (pa); +} + +/*************************************************** + * Low level mapping routines..... + ***************************************************/ + +void +pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa) +{ + pt_entry_t *l3; + vm_offset_t va; + + panic("%s: implement me\n", __func__); + + KASSERT((pa & L3_OFFSET) == 0, + ("pmap_kenter_device: Invalid physical address")); + KASSERT((sva & L3_OFFSET) == 0, + ("pmap_kenter_device: Invalid virtual address")); + KASSERT((size & PAGE_MASK) == 0, + ("pmap_kenter_device: Mapping is not page-sized")); + + va = sva; + while (size != 0) { + l3 = pmap_l3(kernel_pmap, va); + KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va)); + panic("%s: unimplemented", __func__); +#if 0 /* implement me */ + pmap_load_store(l3, (pa & ~L3_OFFSET) | ATTR_DEFAULT | + ATTR_IDX(DEVICE_MEMORY) | L3_PAGE); +#endif + PTE_SYNC(l3); + + va += PAGE_SIZE; + pa += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_invalidate_range(kernel_pmap, sva, va); +} + +/* + * Remove a page from the kernel pagetables. + * Note: not SMP coherent. + */ +PMAP_INLINE void +pmap_kremove(vm_offset_t va) +{ + pt_entry_t *l3; + + l3 = pmap_l3(kernel_pmap, va); + KASSERT(l3 != NULL, ("pmap_kremove: Invalid address")); + + if (pmap_l3_valid_cacheable(pmap_load(l3))) + cpu_dcache_wb_range(va, L3_SIZE); + pmap_load_clear(l3); + PTE_SYNC(l3); + pmap_invalidate_page(kernel_pmap, va); +} + +void +pmap_kremove_device(vm_offset_t sva, vm_size_t size) +{ + pt_entry_t *l3; + vm_offset_t va; + + KASSERT((sva & L3_OFFSET) == 0, + ("pmap_kremove_device: Invalid virtual address")); + KASSERT((size & PAGE_MASK) == 0, + ("pmap_kremove_device: Mapping is not page-sized")); + + va = sva; + while (size != 0) { + l3 = pmap_l3(kernel_pmap, va); + KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va)); + pmap_load_clear(l3); + PTE_SYNC(l3); + + va += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_invalidate_range(kernel_pmap, sva, va); +} + +/* + * Used to map a range of physical addresses into kernel + * virtual address space. + * + * The value passed in '*virt' is a suggested virtual address for + * the mapping. Architectures which can support a direct-mapped + * physical to virtual region can return the appropriate address + * within that region, leaving '*virt' unchanged. Other + * architectures should map the pages starting at '*virt' and + * update '*virt' with the first usable address after the mapped + * region. + */ +vm_offset_t +pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) +{ + + return PHYS_TO_DMAP(start); +} + + +/* + * Add a list of wired pages to the kva + * this routine is only used for temporary + * kernel mappings that do not need to have + * page modification or references recorded. + * Note that old mappings are simply written + * over. The page *must* be wired. + * Note: SMP coherent. Uses a ranged shootdown IPI. + */ +void +pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) +{ + pt_entry_t *l3, pa; + vm_offset_t va; + vm_page_t m; + pt_entry_t entry; + u_int pn; + int i; + + va = sva; + for (i = 0; i < count; i++) { + m = ma[i]; + pa = VM_PAGE_TO_PHYS(m); + pn = (pa / PAGE_SIZE); + l3 = pmap_l3(kernel_pmap, va); + + entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + pmap_load_store(l3, entry); + + PTE_SYNC(l3); + va += L3_SIZE; + } + pmap_invalidate_range(kernel_pmap, sva, va); +} + +/* + * This routine tears out page mappings from the + * kernel -- it is meant only for temporary mappings. + * Note: SMP coherent. Uses a ranged shootdown IPI. + */ +void +pmap_qremove(vm_offset_t sva, int count) +{ + pt_entry_t *l3; + vm_offset_t va; + + KASSERT(sva >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", sva)); + + va = sva; + while (count-- > 0) { + l3 = pmap_l3(kernel_pmap, va); + KASSERT(l3 != NULL, ("pmap_kremove: Invalid address")); + + if (pmap_l3_valid_cacheable(pmap_load(l3))) + cpu_dcache_wb_range(va, L3_SIZE); + pmap_load_clear(l3); + PTE_SYNC(l3); + + va += PAGE_SIZE; + } + pmap_invalidate_range(kernel_pmap, sva, va); +} + +/*************************************************** + * Page table page management routines..... + ***************************************************/ +static __inline void +pmap_free_zero_pages(struct spglist *free) +{ + vm_page_t m; + + while ((m = SLIST_FIRST(free)) != NULL) { + SLIST_REMOVE_HEAD(free, plinks.s.ss); + /* Preserve the page's PG_ZERO setting. */ + vm_page_free_toq(m); + } +} + +/* + * Schedule the specified unused page table page to be freed. Specifically, + * add the page to the specified list of pages that will be released to the + * physical memory manager after the TLB has been updated. + */ +static __inline void +pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, + boolean_t set_PG_ZERO) +{ + + if (set_PG_ZERO) + m->flags |= PG_ZERO; + else + m->flags &= ~PG_ZERO; + SLIST_INSERT_HEAD(free, m, plinks.s.ss); +} + +/* + * Decrements a page table page's wire count, which is used to record the + * number of valid page table entries within the page. If the wire count + * drops to zero, then the page table page is unmapped. Returns TRUE if the + * page table page was unmapped and FALSE otherwise. + */ +static inline boolean_t +pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free) +{ + + --m->wire_count; + if (m->wire_count == 0) { + _pmap_unwire_l3(pmap, va, m, free); + return (TRUE); + } else { + return (FALSE); + } +} + +static void +_pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free) +{ + vm_paddr_t phys; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + /* + * unmap the page table page + */ + if (m->pindex >= NUPDE) { + /* PD page */ + pd_entry_t *l1; + l1 = pmap_l1(pmap, va); + pmap_load_clear(l1); + PTE_SYNC(l1); + } else { + /* PTE page */ + pd_entry_t *l2; + l2 = pmap_l2(pmap, va); + pmap_load_clear(l2); + PTE_SYNC(l2); + } + pmap_resident_count_dec(pmap, 1); + if (m->pindex < NUPDE) { + pd_entry_t *l1; + /* We just released a PT, unhold the matching PD */ + vm_page_t pdpg; + + l1 = pmap_l1(pmap, va); + phys = PTE_TO_PHYS(pmap_load(l1)); + pdpg = PHYS_TO_VM_PAGE(phys); + pmap_unwire_l3(pmap, va, pdpg, free); + } + pmap_invalidate_page(pmap, va); + + /* + * This is a release store so that the ordinary store unmapping + * the page table page is globally performed before TLB shoot- + * down is begun. + */ + atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1); + + /* + * Put page on a list so that it is released after + * *ALL* TLB shootdown is done + */ + pmap_add_delayed_free_list(m, free, TRUE); +} + +/* + * After removing an l3 entry, this routine is used to + * conditionally free the page, and manage the hold/wire counts. + */ +static int +pmap_unuse_l3(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde, + struct spglist *free) +{ + vm_paddr_t phys; + vm_page_t mpte; + + if (va >= VM_MAXUSER_ADDRESS) + return (0); + KASSERT(ptepde != 0, ("pmap_unuse_pt: ptepde != 0")); + + phys = PTE_TO_PHYS(ptepde); + + mpte = PHYS_TO_VM_PAGE(phys); + return (pmap_unwire_l3(pmap, va, mpte, free)); +} + +void +pmap_pinit0(pmap_t pmap) +{ + + PMAP_LOCK_INIT(pmap); + bzero(&pmap->pm_stats, sizeof(pmap->pm_stats)); + pmap->pm_l1 = kernel_pmap->pm_l1; +} + +int +pmap_pinit(pmap_t pmap) +{ + vm_paddr_t l1phys; + vm_page_t l1pt; + + /* + * allocate the l1 page + */ + while ((l1pt = vm_page_alloc(NULL, 0xdeadbeef, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) + VM_WAIT; + + l1phys = VM_PAGE_TO_PHYS(l1pt); + pmap->pm_l1 = (pd_entry_t *)PHYS_TO_DMAP(l1phys); + + if ((l1pt->flags & PG_ZERO) == 0) + pagezero(pmap->pm_l1); + + bzero(&pmap->pm_stats, sizeof(pmap->pm_stats)); + + return (1); +} + +/* + * This routine is called if the desired page table page does not exist. + * + * If page table page allocation fails, this routine may sleep before + * returning NULL. It sleeps only if a lock pointer was given. + * + * Note: If a page allocation fails at page table level two or three, + * one or two pages may be held during the wait, only to be released + * afterwards. This conservative approach is easily argued to avoid + * race conditions. + */ +static vm_page_t +_pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp) +{ + vm_page_t m, /*pdppg, */pdpg; + pt_entry_t entry; + vm_paddr_t phys; + int pn; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + /* + * Allocate a page table page. + */ + if ((m = vm_page_alloc(NULL, ptepindex, VM_ALLOC_NOOBJ | + VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) { + if (lockp != NULL) { + RELEASE_PV_LIST_LOCK(lockp); + PMAP_UNLOCK(pmap); + rw_runlock(&pvh_global_lock); + VM_WAIT; + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + } + + /* + * Indicate the need to retry. While waiting, the page table + * page may have been allocated. + */ + return (NULL); + } + + if ((m->flags & PG_ZERO) == 0) + pmap_zero_page(m); + + /* + * Map the pagetable page into the process address space, if + * it isn't already there. + */ + + if (ptepindex >= NUPDE) { + pd_entry_t *l1; + vm_pindex_t l1index; + + l1index = ptepindex - NUPDE; + l1 = &pmap->pm_l1[l1index]; + + pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + pmap_load_store(l1, entry); + + PTE_SYNC(l1); + + } else { + vm_pindex_t l1index; + pd_entry_t *l1, *l2; + + l1index = ptepindex >> (L1_SHIFT - L2_SHIFT); + l1 = &pmap->pm_l1[l1index]; + if (pmap_load(l1) == 0) { + /* recurse for allocating page dir */ + if (_pmap_alloc_l3(pmap, NUPDE + l1index, + lockp) == NULL) { + --m->wire_count; + atomic_subtract_int(&vm_cnt.v_wire_count, 1); + vm_page_free_zero(m); + return (NULL); + } + } else { + phys = PTE_TO_PHYS(pmap_load(l1)); + pdpg = PHYS_TO_VM_PAGE(phys); + pdpg->wire_count++; + } + + phys = PTE_TO_PHYS(pmap_load(l1)); + l2 = (pd_entry_t *)PHYS_TO_DMAP(phys); + l2 = &l2[ptepindex & Ln_ADDR_MASK]; + + pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + pmap_load_store(l2, entry); + + PTE_SYNC(l2); + } + + pmap_resident_count_inc(pmap, 1); + + return (m); +} + +static vm_page_t +pmap_alloc_l3(pmap_t pmap, vm_offset_t va, struct rwlock **lockp) +{ + vm_pindex_t ptepindex; + pd_entry_t *l2; + vm_paddr_t phys; + vm_page_t m; + + /* + * Calculate pagetable page index + */ + ptepindex = pmap_l2_pindex(va); +retry: + /* + * Get the page directory entry + */ + l2 = pmap_l2(pmap, va); + + /* + * If the page table page is mapped, we just increment the + * hold count, and activate it. + */ + if (l2 != NULL && pmap_load(l2) != 0) { + phys = PTE_TO_PHYS(pmap_load(l2)); + m = PHYS_TO_VM_PAGE(phys); + m->wire_count++; + } else { + /* + * Here if the pte page isn't mapped, or if it has been + * deallocated. + */ + m = _pmap_alloc_l3(pmap, ptepindex, lockp); + if (m == NULL && lockp != NULL) + goto retry; + } + return (m); +} + + +/*************************************************** + * Pmap allocation/deallocation routines. + ***************************************************/ + +/* + * Release any resources held by the given physical map. + * Called when a pmap initialized by pmap_pinit is being released. + * Should only be called if the map contains no valid mappings. + */ +void +pmap_release(pmap_t pmap) +{ + vm_page_t m; + + KASSERT(pmap->pm_stats.resident_count == 0, + ("pmap_release: pmap resident count %ld != 0", + pmap->pm_stats.resident_count)); + + m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_l1)); + m->wire_count--; + atomic_subtract_int(&vm_cnt.v_wire_count, 1); + vm_page_free_zero(m); +} + +#if 0 +static int +kvm_size(SYSCTL_HANDLER_ARGS) +{ + unsigned long ksize = VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS; + + return sysctl_handle_long(oidp, &ksize, 0, req); +} +SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD, + 0, 0, kvm_size, "LU", "Size of KVM"); + +static int +kvm_free(SYSCTL_HANDLER_ARGS) +{ + unsigned long kfree = VM_MAX_KERNEL_ADDRESS - kernel_vm_end; + + return sysctl_handle_long(oidp, &kfree, 0, req); +} +SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD, + 0, 0, kvm_free, "LU", "Amount of KVM free"); +#endif /* 0 */ + +/* + * grow the number of kernel page table entries, if needed + */ +void +pmap_growkernel(vm_offset_t addr) +{ + vm_paddr_t paddr; + vm_page_t nkpg; + pd_entry_t *l1, *l2; + pt_entry_t entry; + int pn; + + mtx_assert(&kernel_map->system_mtx, MA_OWNED); + + addr = roundup2(addr, L2_SIZE); + if (addr - 1 >= kernel_map->max_offset) + addr = kernel_map->max_offset; + while (kernel_vm_end < addr) { + l1 = pmap_l1(kernel_pmap, kernel_vm_end); + if (pmap_load(l1) == 0) { + /* We need a new PDP entry */ + nkpg = vm_page_alloc(NULL, kernel_vm_end >> L1_SHIFT, + VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | + VM_ALLOC_WIRED | VM_ALLOC_ZERO); + if (nkpg == NULL) + panic("pmap_growkernel: no memory to grow kernel"); + if ((nkpg->flags & PG_ZERO) == 0) + pmap_zero_page(nkpg); + paddr = VM_PAGE_TO_PHYS(nkpg); + + panic("%s: implement grow l1\n", __func__); +#if 0 + pmap_load_store(l1, paddr | L1_TABLE); +#endif + PTE_SYNC(l1); + continue; /* try again */ + } + l2 = pmap_l1_to_l2(l1, kernel_vm_end); + if ((pmap_load(l2) & PTE_REF) != 0) { + kernel_vm_end = (kernel_vm_end + L2_SIZE) & ~L2_OFFSET; + if (kernel_vm_end - 1 >= kernel_map->max_offset) { + kernel_vm_end = kernel_map->max_offset; + break; + } + continue; + } + + nkpg = vm_page_alloc(NULL, kernel_vm_end >> L2_SHIFT, + VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | + VM_ALLOC_ZERO); + if (nkpg == NULL) + panic("pmap_growkernel: no memory to grow kernel"); + if ((nkpg->flags & PG_ZERO) == 0) + pmap_zero_page(nkpg); + paddr = VM_PAGE_TO_PHYS(nkpg); + + pn = (paddr / PAGE_SIZE); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + pmap_load_store(l2, entry); + + PTE_SYNC(l2); + pmap_invalidate_page(kernel_pmap, kernel_vm_end); + + kernel_vm_end = (kernel_vm_end + L2_SIZE) & ~L2_OFFSET; + if (kernel_vm_end - 1 >= kernel_map->max_offset) { + kernel_vm_end = kernel_map->max_offset; + break; + } + } +} + + +/*************************************************** + * page management routines. + ***************************************************/ + +CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE); +CTASSERT(_NPCM == 3); +CTASSERT(_NPCPV == 168); + +static __inline struct pv_chunk * +pv_to_chunk(pv_entry_t pv) +{ + + return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK)); +} + +#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap) + +#define PC_FREE0 0xfffffffffffffffful +#define PC_FREE1 0xfffffffffffffffful +#define PC_FREE2 0x000000fffffffffful + +static const uint64_t pc_freemask[_NPCM] = { PC_FREE0, PC_FREE1, PC_FREE2 }; + +#if 0 +#ifdef PV_STATS +static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail; + +SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0, + "Current number of pv entry chunks"); +SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0, + "Current number of pv entry chunks allocated"); +SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0, + "Current number of pv entry chunks frees"); +SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0, + "Number of times tried to get a chunk page but failed."); + +static long pv_entry_frees, pv_entry_allocs, pv_entry_count; +static int pv_entry_spare; + +SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0, + "Current number of pv entry frees"); +SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0, + "Current number of pv entry allocs"); +SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0, + "Current number of pv entries"); +SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0, + "Current number of spare pv entries"); +#endif +#endif /* 0 */ + +/* + * We are in a serious low memory condition. Resort to + * drastic measures to free some pages so we can allocate + * another pv entry chunk. + * + * Returns NULL if PV entries were reclaimed from the specified pmap. + * + * We do not, however, unmap 2mpages because subsequent accesses will + * allocate per-page pv entries until repromotion occurs, thereby + * exacerbating the shortage of free pv entries. + */ +static vm_page_t +reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp) +{ + + panic("RISCVTODO: reclaim_pv_chunk"); +} + +/* + * free the pv_entry back to the free list + */ +static void +free_pv_entry(pmap_t pmap, pv_entry_t pv) +{ + struct pv_chunk *pc; + int idx, field, bit; + + rw_assert(&pvh_global_lock, RA_LOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + PV_STAT(atomic_add_long(&pv_entry_frees, 1)); + PV_STAT(atomic_add_int(&pv_entry_spare, 1)); + PV_STAT(atomic_subtract_long(&pv_entry_count, 1)); + pc = pv_to_chunk(pv); + idx = pv - &pc->pc_pventry[0]; + field = idx / 64; + bit = idx % 64; + pc->pc_map[field] |= 1ul << bit; + if (pc->pc_map[0] != PC_FREE0 || pc->pc_map[1] != PC_FREE1 || + pc->pc_map[2] != PC_FREE2) { + /* 98% of the time, pc is already at the head of the list. */ + if (__predict_false(pc != TAILQ_FIRST(&pmap->pm_pvchunk))) { + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list); + } + return; + } + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + free_pv_chunk(pc); +} + +static void +free_pv_chunk(struct pv_chunk *pc) +{ + vm_page_t m; + + mtx_lock(&pv_chunks_mutex); + TAILQ_REMOVE(&pv_chunks, pc, pc_lru); + mtx_unlock(&pv_chunks_mutex); + PV_STAT(atomic_subtract_int(&pv_entry_spare, _NPCPV)); + PV_STAT(atomic_subtract_int(&pc_chunk_count, 1)); + PV_STAT(atomic_add_int(&pc_chunk_frees, 1)); + /* entire chunk is free, return it */ + m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc)); +#if 0 /* TODO: For minidump */ + dump_drop_page(m->phys_addr); +#endif + vm_page_unwire(m, PQ_INACTIVE); + vm_page_free(m); +} + +/* + * Returns a new PV entry, allocating a new PV chunk from the system when + * needed. If this PV chunk allocation fails and a PV list lock pointer was + * given, a PV chunk is reclaimed from an arbitrary pmap. Otherwise, NULL is + * returned. + * + * The given PV list lock may be released. + */ +static pv_entry_t +get_pv_entry(pmap_t pmap, struct rwlock **lockp) +{ + int bit, field; + pv_entry_t pv; + struct pv_chunk *pc; + vm_page_t m; + + rw_assert(&pvh_global_lock, RA_LOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + PV_STAT(atomic_add_long(&pv_entry_allocs, 1)); +retry: + pc = TAILQ_FIRST(&pmap->pm_pvchunk); + if (pc != NULL) { + for (field = 0; field < _NPCM; field++) { + if (pc->pc_map[field]) { + bit = ffsl(pc->pc_map[field]) - 1; + break; + } + } + if (field < _NPCM) { + pv = &pc->pc_pventry[field * 64 + bit]; + pc->pc_map[field] &= ~(1ul << bit); + /* If this was the last item, move it to tail */ + if (pc->pc_map[0] == 0 && pc->pc_map[1] == 0 && + pc->pc_map[2] == 0) { + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, + pc_list); + } + PV_STAT(atomic_add_long(&pv_entry_count, 1)); + PV_STAT(atomic_subtract_int(&pv_entry_spare, 1)); + return (pv); + } + } + /* No free items, allocate another chunk */ + m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | + VM_ALLOC_WIRED); + if (m == NULL) { + if (lockp == NULL) { + PV_STAT(pc_chunk_tryfail++); + return (NULL); + } + m = reclaim_pv_chunk(pmap, lockp); + if (m == NULL) + goto retry; + } + PV_STAT(atomic_add_int(&pc_chunk_count, 1)); + PV_STAT(atomic_add_int(&pc_chunk_allocs, 1)); +#if 0 /* TODO: This is for minidump */ + dump_add_page(m->phys_addr); +#endif + pc = (void *)PHYS_TO_DMAP(m->phys_addr); + pc->pc_pmap = pmap; + pc->pc_map[0] = PC_FREE0 & ~1ul; /* preallocated bit 0 */ + pc->pc_map[1] = PC_FREE1; + pc->pc_map[2] = PC_FREE2; + mtx_lock(&pv_chunks_mutex); + TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru); + mtx_unlock(&pv_chunks_mutex); + pv = &pc->pc_pventry[0]; + TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list); + PV_STAT(atomic_add_long(&pv_entry_count, 1)); + PV_STAT(atomic_add_int(&pv_entry_spare, _NPCPV - 1)); + return (pv); +} + +/* + * First find and then remove the pv entry for the specified pmap and virtual + * address from the specified pv list. Returns the pv entry if found and NULL + * otherwise. This operation can be performed on pv lists for either 4KB or + * 2MB page mappings. + */ +static __inline pv_entry_t +pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + rw_assert(&pvh_global_lock, RA_LOCKED); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + if (pmap == PV_PMAP(pv) && va == pv->pv_va) { + TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); + pvh->pv_gen++; + break; + } + } + return (pv); +} + +/* + * First find and then destroy the pv entry for the specified pmap and virtual + * address. This operation can be performed on pv lists for either 4KB or 2MB + * page mappings. + */ +static void +pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + pv = pmap_pvh_remove(pvh, pmap, va); + + KASSERT(pv != NULL, ("pmap_pvh_free: pv not found")); + free_pv_entry(pmap, pv); +} + +/* + * Conditionally create the PV entry for a 4KB page mapping if the required + * memory can be allocated without resorting to reclamation. + */ +static boolean_t +pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m, + struct rwlock **lockp) +{ + pv_entry_t pv; + + rw_assert(&pvh_global_lock, RA_LOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + /* Pass NULL instead of the lock pointer to disable reclamation. */ + if ((pv = get_pv_entry(pmap, NULL)) != NULL) { + pv->pv_va = va; + CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + m->md.pv_gen++; + return (TRUE); + } else + return (FALSE); +} + +/* + * pmap_remove_l3: do the things to unmap a page in a process + */ +static int +pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t va, + pd_entry_t l2e, struct spglist *free, struct rwlock **lockp) +{ + pt_entry_t old_l3; + vm_paddr_t phys; + vm_page_t m; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (pmap_is_current(pmap) && pmap_l3_valid_cacheable(pmap_load(l3))) + cpu_dcache_wb_range(va, L3_SIZE); + old_l3 = pmap_load_clear(l3); + PTE_SYNC(l3); + pmap_invalidate_page(pmap, va); + if (old_l3 & PTE_SW_WIRED) + pmap->pm_stats.wired_count -= 1; + pmap_resident_count_dec(pmap, 1); + if (old_l3 & PTE_SW_MANAGED) { + phys = PTE_TO_PHYS(old_l3); + m = PHYS_TO_VM_PAGE(phys); + if (pmap_page_dirty(old_l3)) + vm_page_dirty(m); + if (old_l3 & PTE_REF) + vm_page_aflag_set(m, PGA_REFERENCED); + CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m); + pmap_pvh_free(&m->md, pmap, va); + } + + return (pmap_unuse_l3(pmap, va, l2e, free)); +} + +/* + * Remove the given range of addresses from the specified map. + * + * It is assumed that the start and end are properly + * rounded to the page size. + */ +void +pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + struct rwlock *lock; + vm_offset_t va, va_next; + pd_entry_t *l1, *l2; + pt_entry_t l3_pte, *l3; + struct spglist free; + int anyvalid; + + /* + * Perform an unsynchronized read. This is, however, safe. + */ + if (pmap->pm_stats.resident_count == 0) + return; + + anyvalid = 0; + SLIST_INIT(&free); + + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + + lock = NULL; + for (; sva < eva; sva = va_next) { + if (pmap->pm_stats.resident_count == 0) + break; + + l1 = pmap_l1(pmap, sva); + if (pmap_load(l1) == 0) { + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; + continue; + } + + /* + * Calculate index for next page table. + */ + va_next = (sva + L2_SIZE) & ~L2_OFFSET; + if (va_next < sva) + va_next = eva; + + l2 = pmap_l1_to_l2(l1, sva); + if (l2 == NULL) + continue; + + l3_pte = pmap_load(l2); + + /* + * Weed out invalid mappings. + */ + if (l3_pte == 0) + continue; + if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) + continue; + + /* + * Limit our scan to either the end of the va represented + * by the current page table page, or to the end of the + * range being removed. + */ + if (va_next > eva) + va_next = eva; + + va = va_next; + for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++, + sva += L3_SIZE) { + if (l3 == NULL) + panic("l3 == NULL"); + if (pmap_load(l3) == 0) { + if (va != va_next) { + pmap_invalidate_range(pmap, va, sva); + va = va_next; + } + continue; + } + if (va == va_next) + va = sva; + if (pmap_remove_l3(pmap, l3, sva, l3_pte, &free, + &lock)) { + sva += L3_SIZE; + break; + } + } + if (va != va_next) + pmap_invalidate_range(pmap, va, sva); + } + if (lock != NULL) + rw_wunlock(lock); + if (anyvalid) + pmap_invalidate_all(pmap); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + pmap_free_zero_pages(&free); +} + +/* + * Routine: pmap_remove_all + * Function: + * Removes this physical page from + * all physical maps in which it resides. + * Reflects back modify bits to the pager. + * + * Notes: + * Original versions of this routine were very + * inefficient because they iteratively called + * pmap_remove (slow...) + */ + +void +pmap_remove_all(vm_page_t m) +{ + pv_entry_t pv; + pmap_t pmap; + pt_entry_t *l3, tl3; + pd_entry_t *l2, tl2; + struct spglist free; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_remove_all: page %p is not managed", m)); + SLIST_INIT(&free); + rw_wlock(&pvh_global_lock); + while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pmap_resident_count_dec(pmap, 1); + l2 = pmap_l2(pmap, pv->pv_va); + KASSERT(l2 != NULL, ("pmap_remove_all: no l2 table found")); + tl2 = pmap_load(l2); + + KASSERT((tl2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S), + ("pmap_remove_all: found a table when expecting " + "a block in %p's pv list", m)); + + l3 = pmap_l2_to_l3(l2, pv->pv_va); + if (pmap_is_current(pmap) && + pmap_l3_valid_cacheable(pmap_load(l3))) + cpu_dcache_wb_range(pv->pv_va, L3_SIZE); + tl3 = pmap_load_clear(l3); + PTE_SYNC(l3); + pmap_invalidate_page(pmap, pv->pv_va); + if (tl3 & PTE_SW_WIRED) + pmap->pm_stats.wired_count--; + if ((tl3 & PTE_REF) != 0) + vm_page_aflag_set(m, PGA_REFERENCED); + + /* + * Update the vm_page_t clean and reference bits. + */ + if (pmap_page_dirty(tl3)) + vm_page_dirty(m); + pmap_unuse_l3(pmap, pv->pv_va, pmap_load(l2), &free); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + m->md.pv_gen++; + free_pv_entry(pmap, pv); + PMAP_UNLOCK(pmap); + } + vm_page_aflag_clear(m, PGA_WRITEABLE); + rw_wunlock(&pvh_global_lock); + pmap_free_zero_pages(&free); +} + +/* + * Set the physical protection on the + * specified range of this map as requested. + */ +void +pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) +{ + vm_offset_t va, va_next; + pd_entry_t *l1, *l2; + pt_entry_t *l3p, l3; + pt_entry_t entry; + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + + if ((prot & VM_PROT_WRITE) == VM_PROT_WRITE) + return; + + PMAP_LOCK(pmap); + for (; sva < eva; sva = va_next) { + + l1 = pmap_l1(pmap, sva); + if (pmap_load(l1) == 0) { + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; + continue; + } + + va_next = (sva + L2_SIZE) & ~L2_OFFSET; + if (va_next < sva) + va_next = eva; + + l2 = pmap_l1_to_l2(l1, sva); + if (l2 == NULL) + continue; + if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) + continue; + + if (va_next > eva) + va_next = eva; + + va = va_next; + for (l3p = pmap_l2_to_l3(l2, sva); sva != va_next; l3p++, + sva += L3_SIZE) { + l3 = pmap_load(l3p); + if (pmap_l3_valid(l3)) { + entry = pmap_load(l3p); + entry &= ~(1 << PTE_TYPE_S); + pmap_load_store(l3p, entry); + PTE_SYNC(l3p); + /* XXX: Use pmap_invalidate_range */ + pmap_invalidate_page(pmap, va); + } + } + } + PMAP_UNLOCK(pmap); + + /* TODO: Only invalidate entries we are touching */ + pmap_invalidate_all(pmap); +} + +/* + * Insert the given physical page (p) at + * the specified virtual address (v) in the + * target physical map with the protection requested. + * + * If specified, the page will be wired down, meaning + * that the related pte can not be reclaimed. + * + * NB: This is the only routine which MAY NOT lazy-evaluate + * or lose information. That is, this routine must actually + * insert this page into the given map NOW. + */ +int +pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, + u_int flags, int8_t psind __unused) +{ + struct rwlock *lock; + pd_entry_t *l1, *l2; + pt_entry_t new_l3, orig_l3; + pt_entry_t *l3; + pv_entry_t pv; + vm_paddr_t opa, pa, l2_pa, l3_pa; + vm_page_t mpte, om, l2_m, l3_m; + boolean_t nosleep; + pt_entry_t entry; + int l2_pn; + int l3_pn; + int pn; + + va = trunc_page(va); + if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m)) + VM_OBJECT_ASSERT_LOCKED(m->object); + pa = VM_PAGE_TO_PHYS(m); + pn = (pa / PAGE_SIZE); + + new_l3 = PTE_VALID; + + if ((prot & VM_PROT_WRITE) == 0) { /* Read-only */ + if ((va >> 63) == 0) /* USER */ + new_l3 |= (PTE_TYPE_SURX << PTE_TYPE_S); + else /* KERNEL */ + new_l3 |= (PTE_TYPE_SRX << PTE_TYPE_S); + } else { + if ((va >> 63) == 0) /* USER */ + new_l3 |= (PTE_TYPE_SURWX << PTE_TYPE_S); + else /* KERNEL */ + new_l3 |= (PTE_TYPE_SRWX << PTE_TYPE_S); + } + + new_l3 |= (pn << PTE_PPN0_S); + if ((flags & PMAP_ENTER_WIRED) != 0) + new_l3 |= PTE_SW_WIRED; + + CTR2(KTR_PMAP, "pmap_enter: %.16lx -> %.16lx", va, pa); + + mpte = NULL; + + lock = NULL; + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + + if (va < VM_MAXUSER_ADDRESS) { + nosleep = (flags & PMAP_ENTER_NOSLEEP) != 0; + mpte = pmap_alloc_l3(pmap, va, nosleep ? NULL : &lock); + if (mpte == NULL && nosleep) { + CTR0(KTR_PMAP, "pmap_enter: mpte == NULL"); + if (lock != NULL) + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + return (KERN_RESOURCE_SHORTAGE); + } + l3 = pmap_l3(pmap, va); + } else { + l3 = pmap_l3(pmap, va); + /* TODO: This is not optimal, but should mostly work */ + if (l3 == NULL) { + l2 = pmap_l2(pmap, va); + if (l2 == NULL) { + l2_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | + VM_ALLOC_ZERO); + if (l2_m == NULL) + panic("pmap_enter: l2 pte_m == NULL"); + if ((l2_m->flags & PG_ZERO) == 0) + pmap_zero_page(l2_m); + + l2_pa = VM_PAGE_TO_PHYS(l2_m); + l2_pn = (l2_pa / PAGE_SIZE); + + l1 = pmap_l1(pmap, va); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (l2_pn << PTE_PPN0_S); + pmap_load_store(l1, entry); + PTE_SYNC(l1); + + l2 = pmap_l1_to_l2(l1, va); + } + + KASSERT(l2 != NULL, + ("No l2 table after allocating one")); + + l3_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO); + if (l3_m == NULL) + panic("pmap_enter: l3 pte_m == NULL"); + if ((l3_m->flags & PG_ZERO) == 0) + pmap_zero_page(l3_m); + + l3_pa = VM_PAGE_TO_PHYS(l3_m); + l3_pn = (l3_pa / PAGE_SIZE); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (l3_pn << PTE_PPN0_S); + pmap_load_store(l2, entry); + PTE_SYNC(l2); + l3 = pmap_l2_to_l3(l2, va); + } + pmap_invalidate_page(pmap, va); + } + + om = NULL; + orig_l3 = pmap_load(l3); + opa = PTE_TO_PHYS(orig_l3); + + /* + * Is the specified virtual address already mapped? + */ + if (pmap_l3_valid(orig_l3)) { + /* + * Wiring change, just update stats. We don't worry about + * wiring PT pages as they remain resident as long as there + * are valid mappings in them. Hence, if a user page is wired, + * the PT page will be also. + */ + if ((flags & PMAP_ENTER_WIRED) != 0 && + (orig_l3 & PTE_SW_WIRED) == 0) + pmap->pm_stats.wired_count++; + else if ((flags & PMAP_ENTER_WIRED) == 0 && + (orig_l3 & PTE_SW_WIRED) != 0) + pmap->pm_stats.wired_count--; + + /* + * Remove the extra PT page reference. + */ + if (mpte != NULL) { + mpte->wire_count--; + KASSERT(mpte->wire_count > 0, + ("pmap_enter: missing reference to page table page," + " va: 0x%lx", va)); + } + + /* + * Has the physical page changed? + */ + if (opa == pa) { + /* + * No, might be a protection or wiring change. + */ + if ((orig_l3 & PTE_SW_MANAGED) != 0) { + new_l3 |= PTE_SW_MANAGED; + if (pmap_is_write(new_l3)) + vm_page_aflag_set(m, PGA_WRITEABLE); + } + goto validate; + } + + /* Flush the cache, there might be uncommitted data in it */ + if (pmap_is_current(pmap) && pmap_l3_valid_cacheable(orig_l3)) + cpu_dcache_wb_range(va, L3_SIZE); + } else { + /* + * Increment the counters. + */ + if ((new_l3 & PTE_SW_WIRED) != 0) + pmap->pm_stats.wired_count++; + pmap_resident_count_inc(pmap, 1); + } + /* + * Enter on the PV list if part of our managed memory. + */ + if ((m->oflags & VPO_UNMANAGED) == 0) { + new_l3 |= PTE_SW_MANAGED; + pv = get_pv_entry(pmap, &lock); + pv->pv_va = va; + CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, pa); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + m->md.pv_gen++; + if (pmap_is_write(new_l3)) + vm_page_aflag_set(m, PGA_WRITEABLE); + } + + /* + * Update the L3 entry. + */ + if (orig_l3 != 0) { +validate: + orig_l3 = pmap_load_store(l3, new_l3); + PTE_SYNC(l3); + opa = PTE_TO_PHYS(orig_l3); + + if (opa != pa) { + if ((orig_l3 & PTE_SW_MANAGED) != 0) { + om = PHYS_TO_VM_PAGE(opa); + if (pmap_page_dirty(orig_l3)) + vm_page_dirty(om); + if ((orig_l3 & PTE_REF) != 0) + vm_page_aflag_set(om, PGA_REFERENCED); + CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, opa); + pmap_pvh_free(&om->md, pmap, va); + } + } else if (pmap_page_dirty(orig_l3)) { + if ((orig_l3 & PTE_SW_MANAGED) != 0) + vm_page_dirty(m); + } + } else { + pmap_load_store(l3, new_l3); + PTE_SYNC(l3); + } + pmap_invalidate_page(pmap, va); + if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap)) + cpu_icache_sync_range(va, PAGE_SIZE); + + if (lock != NULL) + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); +} + +/* + * Maps a sequence of resident pages belonging to the same object. + * The sequence begins with the given page m_start. This page is + * mapped at the given virtual address start. Each subsequent page is + * mapped at a virtual address that is offset from start by the same + * amount as the page is offset from m_start within the object. The + * last page in the sequence is the page with the largest offset from + * m_start that can be mapped at a virtual address less than the given + * virtual address end. Not every virtual page between start and end + * is mapped; only those for which a resident page exists with the + * corresponding offset from m_start are mapped. + */ +void +pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end, + vm_page_t m_start, vm_prot_t prot) +{ + struct rwlock *lock; + vm_offset_t va; + vm_page_t m, mpte; + vm_pindex_t diff, psize; + + VM_OBJECT_ASSERT_LOCKED(m_start->object); + + psize = atop(end - start); + mpte = NULL; + m = m_start; + lock = NULL; + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { + va = start + ptoa(diff); + mpte = pmap_enter_quick_locked(pmap, va, m, prot, mpte, &lock); + m = TAILQ_NEXT(m, listq); + } + if (lock != NULL) + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); +} + +/* + * this code makes some *MAJOR* assumptions: + * 1. Current pmap & pmap exists. + * 2. Not wired. + * 3. Read access. + * 4. No page table pages. + * but is *MUCH* faster than pmap_enter... + */ + +void +pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) +{ + struct rwlock *lock; + + lock = NULL; + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL, &lock); + if (lock != NULL) + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); +} + +static vm_page_t +pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, + vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp) +{ + struct spglist free; + vm_paddr_t phys; + pd_entry_t *l2; + pt_entry_t *l3; + vm_paddr_t pa; + pt_entry_t entry; + int pn; + + KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva || + (m->oflags & VPO_UNMANAGED) != 0, + ("pmap_enter_quick_locked: managed mapping within the clean submap")); + rw_assert(&pvh_global_lock, RA_LOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + CTR2(KTR_PMAP, "pmap_enter_quick_locked: %p %lx", pmap, va); + /* + * In the case that a page table page is not + * resident, we are creating it here. + */ + if (va < VM_MAXUSER_ADDRESS) { + vm_pindex_t l2pindex; + + /* + * Calculate pagetable page index + */ + l2pindex = pmap_l2_pindex(va); + if (mpte && (mpte->pindex == l2pindex)) { + mpte->wire_count++; + } else { + /* + * Get the l2 entry + */ + l2 = pmap_l2(pmap, va); + + /* + * If the page table page is mapped, we just increment + * the hold count, and activate it. Otherwise, we + * attempt to allocate a page table page. If this + * attempt fails, we don't retry. Instead, we give up. + */ + if (l2 != NULL && pmap_load(l2) != 0) { + phys = PTE_TO_PHYS(pmap_load(l2)); + mpte = PHYS_TO_VM_PAGE(phys); + mpte->wire_count++; + } else { + /* + * Pass NULL instead of the PV list lock + * pointer, because we don't intend to sleep. + */ + mpte = _pmap_alloc_l3(pmap, l2pindex, NULL); + if (mpte == NULL) + return (mpte); + } + } + l3 = (pt_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mpte)); + l3 = &l3[pmap_l3_index(va)]; + } else { + mpte = NULL; + l3 = pmap_l3(kernel_pmap, va); + } + if (l3 == NULL) + panic("pmap_enter_quick_locked: No l3"); + if (pmap_load(l3) != 0) { + if (mpte != NULL) { + mpte->wire_count--; + mpte = NULL; + } + return (mpte); + } + + /* + * Enter on the PV list if part of our managed memory. + */ + if ((m->oflags & VPO_UNMANAGED) == 0 && + !pmap_try_insert_pv_entry(pmap, va, m, lockp)) { + if (mpte != NULL) { + SLIST_INIT(&free); + if (pmap_unwire_l3(pmap, va, mpte, &free)) { + pmap_invalidate_page(pmap, va); + pmap_free_zero_pages(&free); + } + mpte = NULL; + } + return (mpte); + } + + /* + * Increment counters + */ + pmap_resident_count_inc(pmap, 1); + + pa = VM_PAGE_TO_PHYS(m); + pn = (pa / PAGE_SIZE); + + /* RISCVTODO: check permissions */ + entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + + /* + * Now validate mapping with RO protection + */ + if ((m->oflags & VPO_UNMANAGED) == 0) + entry |= PTE_SW_MANAGED; + pmap_load_store(l3, entry); + + PTE_SYNC(l3); + pmap_invalidate_page(pmap, va); + return (mpte); +} + +/* + * This code maps large physical mmap regions into the + * processor address space. Note that some shortcuts + * are taken, but the code works. + */ +void +pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, + vm_pindex_t pindex, vm_size_t size) +{ + + VM_OBJECT_ASSERT_WLOCKED(object); + KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG, + ("pmap_object_init_pt: non-device object")); +} + +/* + * Clear the wired attribute from the mappings for the specified range of + * addresses in the given pmap. Every valid mapping within that range + * must have the wired attribute set. In contrast, invalid mappings + * cannot have the wired attribute set, so they are ignored. + * + * The wired attribute of the page table entry is not a hardware feature, + * so there is no need to invalidate any TLB entries. + */ +void +pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + vm_offset_t va_next; + pd_entry_t *l1, *l2; + pt_entry_t *l3; + boolean_t pv_lists_locked; + + pv_lists_locked = FALSE; + PMAP_LOCK(pmap); + for (; sva < eva; sva = va_next) { + l1 = pmap_l1(pmap, sva); + if (pmap_load(l1) == 0) { + va_next = (sva + L1_SIZE) & ~L1_OFFSET; + if (va_next < sva) + va_next = eva; + continue; + } + + va_next = (sva + L2_SIZE) & ~L2_OFFSET; + if (va_next < sva) + va_next = eva; + + l2 = pmap_l1_to_l2(l1, sva); + if (pmap_load(l2) == 0) + continue; + + if (va_next > eva) + va_next = eva; + for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++, + sva += L3_SIZE) { + if (pmap_load(l3) == 0) + continue; + if ((pmap_load(l3) & PTE_SW_WIRED) == 0) + panic("pmap_unwire: l3 %#jx is missing " + "PTE_SW_WIRED", (uintmax_t)*l3); + + /* + * PG_W must be cleared atomically. Although the pmap + * lock synchronizes access to PG_W, another processor + * could be setting PG_M and/or PG_A concurrently. + */ + atomic_clear_long(l3, PTE_SW_WIRED); + pmap->pm_stats.wired_count--; + } + } + if (pv_lists_locked) + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); +} + +/* + * Copy the range specified by src_addr/len + * from the source map to the range dst_addr/len + * in the destination map. + * + * This routine is only advisory and need not do anything. + */ + +void +pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len, + vm_offset_t src_addr) +{ + +} + +/* + * pmap_zero_page zeros the specified hardware page by mapping + * the page into KVM and using bzero to clear its contents. + */ +void +pmap_zero_page(vm_page_t m) +{ + vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); + + pagezero((void *)va); +} + +/* + * pmap_zero_page_area zeros the specified hardware page by mapping + * the page into KVM and using bzero to clear its contents. + * + * off and size may not cover an area beyond a single hardware page. + */ +void +pmap_zero_page_area(vm_page_t m, int off, int size) +{ + vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); + + if (off == 0 && size == PAGE_SIZE) + pagezero((void *)va); + else + bzero((char *)va + off, size); +} + +/* + * pmap_zero_page_idle zeros the specified hardware page by mapping + * the page into KVM and using bzero to clear its contents. This + * is intended to be called from the vm_pagezero process only and + * outside of Giant. + */ +void +pmap_zero_page_idle(vm_page_t m) +{ + vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); + + pagezero((void *)va); +} + +/* + * pmap_copy_page copies the specified (machine independent) + * page by mapping the page into virtual memory and using + * bcopy to copy the page, one machine dependent page at a + * time. + */ +void +pmap_copy_page(vm_page_t msrc, vm_page_t mdst) +{ + vm_offset_t src = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(msrc)); + vm_offset_t dst = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mdst)); + + pagecopy((void *)src, (void *)dst); +} + +int unmapped_buf_allowed = 1; + +void +pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], + vm_offset_t b_offset, int xfersize) +{ + void *a_cp, *b_cp; + vm_page_t m_a, m_b; + vm_paddr_t p_a, p_b; + vm_offset_t a_pg_offset, b_pg_offset; + int cnt; + + while (xfersize > 0) { + a_pg_offset = a_offset & PAGE_MASK; + m_a = ma[a_offset >> PAGE_SHIFT]; + p_a = m_a->phys_addr; + b_pg_offset = b_offset & PAGE_MASK; + m_b = mb[b_offset >> PAGE_SHIFT]; + p_b = m_b->phys_addr; + cnt = min(xfersize, PAGE_SIZE - a_pg_offset); + cnt = min(cnt, PAGE_SIZE - b_pg_offset); + if (__predict_false(!PHYS_IN_DMAP(p_a))) { + panic("!DMAP a %lx", p_a); + } else { + a_cp = (char *)PHYS_TO_DMAP(p_a) + a_pg_offset; + } + if (__predict_false(!PHYS_IN_DMAP(p_b))) { + panic("!DMAP b %lx", p_b); + } else { + b_cp = (char *)PHYS_TO_DMAP(p_b) + b_pg_offset; + } + bcopy(a_cp, b_cp, cnt); + a_offset += cnt; + b_offset += cnt; + xfersize -= cnt; + } +} + +vm_offset_t +pmap_quick_enter_page(vm_page_t m) +{ + + return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m))); +} + +void +pmap_quick_remove_page(vm_offset_t addr) +{ +} + +/* + * Returns true if the pmap's pv is one of the first + * 16 pvs linked to from this page. This count may + * be changed upwards or downwards in the future; it + * is only necessary that true be returned for a small + * subset of pmaps for proper page aging. + */ +boolean_t +pmap_page_exists_quick(pmap_t pmap, vm_page_t m) +{ + struct rwlock *lock; + pv_entry_t pv; + int loops = 0; + boolean_t rv; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_page_exists_quick: page %p is not managed", m)); + rv = FALSE; + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); + rw_rlock(lock); + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + if (PV_PMAP(pv) == pmap) { + rv = TRUE; + break; + } + loops++; + if (loops >= 16) + break; + } + rw_runlock(lock); + rw_runlock(&pvh_global_lock); + return (rv); +} + +/* + * pmap_page_wired_mappings: + * + * Return the number of managed mappings to the given physical page + * that are wired. + */ +int +pmap_page_wired_mappings(vm_page_t m) +{ + struct rwlock *lock; + pmap_t pmap; + pt_entry_t *l3; + pv_entry_t pv; + int count, md_gen; + + if ((m->oflags & VPO_UNMANAGED) != 0) + return (0); + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); + rw_rlock(lock); +restart: + count = 0; + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } + l3 = pmap_l3(pmap, pv->pv_va); + if (l3 != NULL && (pmap_load(l3) & PTE_SW_WIRED) != 0) + count++; + PMAP_UNLOCK(pmap); + } + rw_runlock(lock); + rw_runlock(&pvh_global_lock); + return (count); +} + +/* + * Destroy all managed, non-wired mappings in the given user-space + * pmap. This pmap cannot be active on any processor besides the + * caller. + * + * This function cannot be applied to the kernel pmap. Moreover, it + * is not intended for general use. It is only to be used during + * process termination. Consequently, it can be implemented in ways + * that make it faster than pmap_remove(). First, it can more quickly + * destroy mappings by iterating over the pmap's collection of PV + * entries, rather than searching the page table. Second, it doesn't + * have to test and clear the page table entries atomically, because + * no processor is currently accessing the user address space. In + * particular, a page table entry's dirty bit won't change state once + * this function starts. + */ +void +pmap_remove_pages(pmap_t pmap) +{ + pd_entry_t ptepde, *l2; + pt_entry_t *l3, tl3; + struct spglist free; + vm_page_t m; + pv_entry_t pv; + struct pv_chunk *pc, *npc; + struct rwlock *lock; + int64_t bit; + uint64_t inuse, bitmask; + int allfree, field, freed, idx; + vm_paddr_t pa; + + lock = NULL; + + SLIST_INIT(&free); + rw_rlock(&pvh_global_lock); + PMAP_LOCK(pmap); + TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) { + allfree = 1; + freed = 0; + for (field = 0; field < _NPCM; field++) { + inuse = ~pc->pc_map[field] & pc_freemask[field]; + while (inuse != 0) { + bit = ffsl(inuse) - 1; + bitmask = 1UL << bit; + idx = field * 64 + bit; + pv = &pc->pc_pventry[idx]; + inuse &= ~bitmask; + + l2 = pmap_l2(pmap, pv->pv_va); + ptepde = pmap_load(l2); + l3 = pmap_l2_to_l3(l2, pv->pv_va); + tl3 = pmap_load(l3); + +/* + * We cannot remove wired pages from a process' mapping at this time + */ + if (tl3 & PTE_SW_WIRED) { + allfree = 0; + continue; + } + + pa = PTE_TO_PHYS(tl3); + m = PHYS_TO_VM_PAGE(pa); + KASSERT(m->phys_addr == pa, + ("vm_page_t %p phys_addr mismatch %016jx %016jx", + m, (uintmax_t)m->phys_addr, + (uintmax_t)tl3)); + + KASSERT((m->flags & PG_FICTITIOUS) != 0 || + m < &vm_page_array[vm_page_array_size], + ("pmap_remove_pages: bad l3 %#jx", + (uintmax_t)tl3)); + + if (pmap_is_current(pmap) && + pmap_l3_valid_cacheable(pmap_load(l3))) + cpu_dcache_wb_range(pv->pv_va, L3_SIZE); + pmap_load_clear(l3); + PTE_SYNC(l3); + pmap_invalidate_page(pmap, pv->pv_va); + + /* + * Update the vm_page_t clean/reference bits. + */ + if (pmap_page_dirty(tl3)) + vm_page_dirty(m); + + CHANGE_PV_LIST_LOCK_TO_VM_PAGE(&lock, m); + + /* Mark free */ + pc->pc_map[field] |= bitmask; + + pmap_resident_count_dec(pmap, 1); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + m->md.pv_gen++; + + pmap_unuse_l3(pmap, pv->pv_va, ptepde, &free); + freed++; + } + } + PV_STAT(atomic_add_long(&pv_entry_frees, freed)); + PV_STAT(atomic_add_int(&pv_entry_spare, freed)); + PV_STAT(atomic_subtract_long(&pv_entry_count, freed)); + if (allfree) { + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + free_pv_chunk(pc); + } + } + pmap_invalidate_all(pmap); + if (lock != NULL) + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + pmap_free_zero_pages(&free); +} + +/* + * This is used to check if a page has been accessed or modified. As we + * don't have a bit to see if it has been modified we have to assume it + * has been if the page is read/write. + */ +static boolean_t +pmap_page_test_mappings(vm_page_t m, boolean_t accessed, boolean_t modified) +{ + struct rwlock *lock; + pv_entry_t pv; + pt_entry_t *l3, mask, value; + pmap_t pmap; + int md_gen; + boolean_t rv; + + rv = FALSE; + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); + rw_rlock(lock); +restart: + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_runlock(lock); + PMAP_LOCK(pmap); + rw_rlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + goto restart; + } + } + l3 = pmap_l3(pmap, pv->pv_va); + mask = 0; + value = 0; + if (modified) { + mask |= PTE_DIRTY; + value |= PTE_DIRTY; + } + if (accessed) { + mask |= PTE_REF; + value |= PTE_REF; + } + +#if 0 + if (modified) { + mask |= ATTR_AP_RW_BIT; + value |= ATTR_AP(ATTR_AP_RW); + } + if (accessed) { + mask |= ATTR_AF | ATTR_DESCR_MASK; + value |= ATTR_AF | L3_PAGE; + } +#endif + + rv = (pmap_load(l3) & mask) == value; + PMAP_UNLOCK(pmap); + if (rv) + goto out; + } +out: + rw_runlock(lock); + rw_runlock(&pvh_global_lock); + return (rv); +} + +/* + * pmap_is_modified: + * + * Return whether or not the specified physical page was modified + * in any physical maps. + */ +boolean_t +pmap_is_modified(vm_page_t m) +{ + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_is_modified: page %p is not managed", m)); + + /* + * If the page is not exclusive busied, then PGA_WRITEABLE cannot be + * concurrently set while the object is locked. Thus, if PGA_WRITEABLE + * is clear, no PTEs can have PG_M set. + */ + VM_OBJECT_ASSERT_WLOCKED(m->object); + if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0) + return (FALSE); + return (pmap_page_test_mappings(m, FALSE, TRUE)); +} + +/* + * pmap_is_prefaultable: + * + * Return whether or not the specified virtual address is eligible + * for prefault. + */ +boolean_t +pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr) +{ + pt_entry_t *l3; + boolean_t rv; + + rv = FALSE; + PMAP_LOCK(pmap); + l3 = pmap_l3(pmap, addr); + if (l3 != NULL && pmap_load(l3) != 0) { + rv = TRUE; + } + PMAP_UNLOCK(pmap); + return (rv); +} + +/* + * pmap_is_referenced: + * + * Return whether or not the specified physical page was referenced + * in any physical maps. + */ +boolean_t +pmap_is_referenced(vm_page_t m) +{ + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_is_referenced: page %p is not managed", m)); + return (pmap_page_test_mappings(m, TRUE, FALSE)); +} + +/* + * Clear the write and modified bits in each of the given page's mappings. + */ +void +pmap_remove_write(vm_page_t m) +{ + pmap_t pmap; + struct rwlock *lock; + pv_entry_t pv; + pt_entry_t *l3, oldl3; + pt_entry_t newl3; + int md_gen; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_remove_write: page %p is not managed", m)); + + /* + * If the page is not exclusive busied, then PGA_WRITEABLE cannot be + * set by another thread while the object is locked. Thus, + * if PGA_WRITEABLE is clear, no page table entries need updating. + */ + VM_OBJECT_ASSERT_WLOCKED(m->object); + if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0) + return; + rw_rlock(&pvh_global_lock); + lock = VM_PAGE_TO_PV_LIST_LOCK(m); +retry_pv_loop: + rw_wlock(lock); + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_wunlock(lock); + PMAP_LOCK(pmap); + rw_wlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + rw_wunlock(lock); + goto retry_pv_loop; + } + } + l3 = pmap_l3(pmap, pv->pv_va); +retry: + oldl3 = pmap_load(l3); + + if (pmap_is_write(oldl3)) { + newl3 = oldl3 & ~(1 << PTE_TYPE_S); + if (!atomic_cmpset_long(l3, oldl3, newl3)) + goto retry; + /* TODO: use pmap_page_dirty(oldl3) ? */ + if ((oldl3 & PTE_REF) != 0) + vm_page_dirty(m); + pmap_invalidate_page(pmap, pv->pv_va); + } + PMAP_UNLOCK(pmap); + } + rw_wunlock(lock); + vm_page_aflag_clear(m, PGA_WRITEABLE); + rw_runlock(&pvh_global_lock); +} + +static __inline boolean_t +safe_to_clear_referenced(pmap_t pmap, pt_entry_t pte) +{ + + return (FALSE); +} + +#define PMAP_TS_REFERENCED_MAX 5 + +/* + * pmap_ts_referenced: + * + * Return a count of reference bits for a page, clearing those bits. + * It is not necessary for every reference bit to be cleared, but it + * is necessary that 0 only be returned when there are truly no + * reference bits set. + * + * XXX: The exact number of bits to check and clear is a matter that + * should be tested and standardized at some point in the future for + * optimal aging of shared pages. + */ +int +pmap_ts_referenced(vm_page_t m) +{ + pv_entry_t pv, pvf; + pmap_t pmap; + struct rwlock *lock; + pd_entry_t *l2; + pt_entry_t *l3; + vm_paddr_t pa; + int cleared, md_gen, not_cleared; + struct spglist free; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_ts_referenced: page %p is not managed", m)); + SLIST_INIT(&free); + cleared = 0; + pa = VM_PAGE_TO_PHYS(m); + lock = PHYS_TO_PV_LIST_LOCK(pa); + rw_rlock(&pvh_global_lock); + rw_wlock(lock); +retry: + not_cleared = 0; + if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL) + goto out; + pv = pvf; + do { + if (pvf == NULL) + pvf = pv; + pmap = PV_PMAP(pv); + if (!PMAP_TRYLOCK(pmap)) { + md_gen = m->md.pv_gen; + rw_wunlock(lock); + PMAP_LOCK(pmap); + rw_wlock(lock); + if (md_gen != m->md.pv_gen) { + PMAP_UNLOCK(pmap); + goto retry; + } + } + l2 = pmap_l2(pmap, pv->pv_va); + + KASSERT((pmap_load(l2) & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S), + ("pmap_ts_referenced: found an invalid l2 table")); + + l3 = pmap_l2_to_l3(l2, pv->pv_va); + if ((pmap_load(l3) & PTE_REF) != 0) { + if (safe_to_clear_referenced(pmap, pmap_load(l3))) { + /* + * TODO: We don't handle the access flag + * at all. We need to be able to set it in + * the exception handler. + */ + panic("RISCVTODO: safe_to_clear_referenced\n"); + } else if ((pmap_load(l3) & PTE_SW_WIRED) == 0) { + /* + * Wired pages cannot be paged out so + * doing accessed bit emulation for + * them is wasted effort. We do the + * hard work for unwired pages only. + */ + pmap_remove_l3(pmap, l3, pv->pv_va, + pmap_load(l2), &free, &lock); + pmap_invalidate_page(pmap, pv->pv_va); + cleared++; + if (pvf == pv) + pvf = NULL; + pv = NULL; + KASSERT(lock == VM_PAGE_TO_PV_LIST_LOCK(m), + ("inconsistent pv lock %p %p for page %p", + lock, VM_PAGE_TO_PV_LIST_LOCK(m), m)); + } else + not_cleared++; + } + PMAP_UNLOCK(pmap); + /* Rotate the PV list if it has more than one entry. */ + if (pv != NULL && TAILQ_NEXT(pv, pv_next) != NULL) { + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + m->md.pv_gen++; + } + } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && cleared + + not_cleared < PMAP_TS_REFERENCED_MAX); +out: + rw_wunlock(lock); + rw_runlock(&pvh_global_lock); + pmap_free_zero_pages(&free); + return (cleared + not_cleared); +} + +/* + * Apply the given advice to the specified range of addresses within the + * given pmap. Depending on the advice, clear the referenced and/or + * modified flags in each mapping and set the mapped page's dirty field. + */ +void +pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice) +{ +} + +/* + * Clear the modify bits on the specified physical page. + */ +void +pmap_clear_modify(vm_page_t m) +{ + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_clear_modify: page %p is not managed", m)); + VM_OBJECT_ASSERT_WLOCKED(m->object); + KASSERT(!vm_page_xbusied(m), + ("pmap_clear_modify: page %p is exclusive busied", m)); + + /* + * If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set. + * If the object containing the page is locked and the page is not + * exclusive busied, then PGA_WRITEABLE cannot be concurrently set. + */ + if ((m->aflags & PGA_WRITEABLE) == 0) + return; + + /* RISCVTODO: We lack support for tracking if a page is modified */ +} + +void * +pmap_mapbios(vm_paddr_t pa, vm_size_t size) +{ + + return ((void *)PHYS_TO_DMAP(pa)); +} + +void +pmap_unmapbios(vm_paddr_t pa, vm_size_t size) +{ +} + +/* + * Sets the memory attribute for the specified page. + */ +void +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +{ + + m->md.pv_memattr = ma; + + /* + * RISCVTODO: Implement the below (from the amd64 pmap) + * If "m" is a normal page, update its direct mapping. This update + * can be relied upon to perform any cache operations that are + * required for data coherence. + */ + if ((m->flags & PG_FICTITIOUS) == 0 && + PHYS_IN_DMAP(VM_PAGE_TO_PHYS(m))) + panic("RISCVTODO: pmap_page_set_memattr"); +} + +/* + * perform the pmap work for mincore + */ +int +pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa) +{ + + panic("RISCVTODO: pmap_mincore"); +} + +void +pmap_activate(struct thread *td) +{ + uint64_t entry; + uint64_t pn; + pmap_t pmap; + + critical_enter(); + pmap = vmspace_pmap(td->td_proc->p_vmspace); + td->td_pcb->pcb_l1addr = vtophys(pmap->pm_l1); + + pn = (td->td_pcb->pcb_l1addr / PAGE_SIZE); + entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)); + entry |= (pn << PTE_PPN0_S); + pmap_load_store(&pagetable_l0, entry); + + pmap_invalidate_all(pmap); + critical_exit(); +} + +void +pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) +{ + + panic("RISCVTODO: pmap_sync_icache"); +} + +/* + * Increase the starting virtual address of the given mapping if a + * different alignment might result in more superpage mappings. + */ +void +pmap_align_superpage(vm_object_t object, vm_ooffset_t offset, + vm_offset_t *addr, vm_size_t size) +{ +} + +/** + * Get the kernel virtual address of a set of physical pages. If there are + * physical addresses not covered by the DMAP perform a transient mapping + * that will be removed when calling pmap_unmap_io_transient. + * + * \param page The pages the caller wishes to obtain the virtual + * address on the kernel memory map. + * \param vaddr On return contains the kernel virtual memory address + * of the pages passed in the page parameter. + * \param count Number of pages passed in. + * \param can_fault TRUE if the thread using the mapped pages can take + * page faults, FALSE otherwise. + * + * \returns TRUE if the caller must call pmap_unmap_io_transient when + * finished or FALSE otherwise. + * + */ +boolean_t +pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count, + boolean_t can_fault) +{ + vm_paddr_t paddr; + boolean_t needs_mapping; + int error, i; + + /* + * Allocate any KVA space that we need, this is done in a separate + * loop to prevent calling vmem_alloc while pinned. + */ + needs_mapping = FALSE; + for (i = 0; i < count; i++) { + paddr = VM_PAGE_TO_PHYS(page[i]); + if (__predict_false(paddr >= DMAP_MAX_PHYSADDR)) { + error = vmem_alloc(kernel_arena, PAGE_SIZE, + M_BESTFIT | M_WAITOK, &vaddr[i]); + KASSERT(error == 0, ("vmem_alloc failed: %d", error)); + needs_mapping = TRUE; + } else { + vaddr[i] = PHYS_TO_DMAP(paddr); + } + } + + /* Exit early if everything is covered by the DMAP */ + if (!needs_mapping) + return (FALSE); + + if (!can_fault) + sched_pin(); + for (i = 0; i < count; i++) { + paddr = VM_PAGE_TO_PHYS(page[i]); + if (paddr >= DMAP_MAX_PHYSADDR) { + panic( + "pmap_map_io_transient: TODO: Map out of DMAP data"); + } + } + + return (needs_mapping); +} + +void +pmap_unmap_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count, + boolean_t can_fault) +{ + vm_paddr_t paddr; + int i; + + if (!can_fault) + sched_unpin(); + for (i = 0; i < count; i++) { + paddr = VM_PAGE_TO_PHYS(page[i]); + if (paddr >= DMAP_MAX_PHYSADDR) { + panic("RISCVTODO: pmap_unmap_io_transient: Unmap data"); + } + } +} diff --git a/sys/riscv/riscv/support.S b/sys/riscv/riscv/support.S new file mode 100644 index 000000000000..59e2680fa33e --- /dev/null +++ b/sys/riscv/riscv/support.S @@ -0,0 +1,295 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include "assym.s" + +/* + * One of the fu* or su* functions failed, return -1. + */ +ENTRY(fsu_fault) + SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */ +fsu_fault_nopcb: + li a0, -1 + ret +END(fsu_fault) + +/* + * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t) + */ +ENTRY(casueword32) + li a4, (VM_MAXUSER_ADDRESS-3) + bgt a0, a4, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a4) /* And set it */ +1: lr.w a4, 0(a0) /* Load-exclusive the data */ + bne a4, a1, 2f /* If not equal then exit */ + sc.w a5, a3, 0(a0) /* Store the new data */ + bnez a5, 1b /* Retry on failure */ +2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ + sw a4, 0(a2) /* Store the read data */ + li a0, 0 /* Success */ + ret /* Return */ +END(casueword32) + +/* + * int casueword(volatile u_long *, u_long, u_long *, u_long) + */ +ENTRY(casueword) + li a4, (VM_MAXUSER_ADDRESS-7) + bgt a0, a4, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a4) /* And set it */ +1: lr.d a4, 0(a0) /* Load-exclusive the data */ + bne a4, a1, 2f /* If not equal then exit */ + sc.d a5, a3, 0(a0) /* Store the new data */ + bnez a5, 1b /* Retry on failure */ +2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */ + sd a4, 0(a2) /* Store the read data */ + li a0, 0 /* Success */ + ret /* Return */ +END(casueword) + +/* + * int fubyte(volatile const void *) + */ +ENTRY(fubyte) + li a1, VM_MAXUSER_ADDRESS + bgt a0, a1, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a1) /* And set it */ + lb a0, 0(a0) /* Try loading the data */ + SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */ + ret /* Return */ +END(fubyte) + +/* + * int fuword(volatile const void *) + */ +ENTRY(fuword16) + li a1, (VM_MAXUSER_ADDRESS-1) + bgt a0, a1, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a1) /* And set it */ + lh a0, 0(a0) /* Try loading the data */ + SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */ + ret /* Return */ +END(fuword16) + +/* + * int32_t fueword32(volatile const void *, int32_t *) + */ +ENTRY(fueword32) + li a2, (VM_MAXUSER_ADDRESS-3) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + lw a0, 0(a0) /* Try loading the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + sw a0, 0(a1) /* Save the data in kernel space */ + li a0, 0 /* Success */ + ret /* Return */ +END(fueword32) + +/* + * long fueword(volatile const void *, int64_t *) + * int64_t fueword64(volatile const void *, int64_t *) + */ +ENTRY(fueword) +EENTRY(fueword64) + li a2, (VM_MAXUSER_ADDRESS-7) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + ld a0, 0(a0) /* Try loading the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + sd a0, 0(a1) /* Save the data in kernel space */ + li a0, 0 /* Success */ + ret /* Return */ +EEND(fueword64) +END(fueword) + +/* + * int subyte(volatile void *, int) + */ +ENTRY(subyte) + li a2, VM_MAXUSER_ADDRESS + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + sb a1, 0(a0) /* Try storing the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + li a0, 0 /* Success */ + ret /* Return */ +END(subyte) + +/* + * int suword16(volatile void *, int) + */ +ENTRY(suword16) + li a2, (VM_MAXUSER_ADDRESS-1) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + sh a1, 0(a0) /* Try storing the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + li a0, 0 /* Success */ + ret /* Return */ +END(suword16) + +/* + * int suword32(volatile void *, int) + */ +ENTRY(suword32) + li a2, (VM_MAXUSER_ADDRESS-3) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + sw a1, 0(a0) /* Try storing the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + li a0, 0 /* Success */ + ret /* Return */ +END(suword32) + +/* + * int suword(volatile void *, long) + */ +ENTRY(suword) +EENTRY(suword64) + li a2, (VM_MAXUSER_ADDRESS-7) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + sd a1, 0(a0) /* Try storing the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + li a0, 0 /* Success */ + ret /* Return */ +EEND(suword64) +END(suword) + +/* + * fuswintr and suswintr are just like fusword and susword except that if + * the page is not in memory or would cause a trap, then we return an error. + * The important thing is to prevent sleep() and switch(). + */ + +/* + * Special handler so the trap code knows not to sleep. + */ +ENTRY(fsu_intr_fault) + SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */ + li a0, -1 + ret +END(fsu_fault) + +/* + * int fuswintr(void *) + */ +ENTRY(fuswintr) + li a1, (VM_MAXUSER_ADDRESS-3) + bgt a0, a1, fsu_fault_nopcb + la a6, fsu_intr_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a1) /* And set it */ + lw a0, 0(a0) /* Try loading the data */ + SET_FAULT_HANDLER(x0, x1) /* Reset the fault handler */ + ret /* Return */ +END(fuswintr) + +/* + * int suswintr(void *base, int word) + */ +ENTRY(suswintr) + li a2, (VM_MAXUSER_ADDRESS-3) + bgt a0, a2, fsu_fault_nopcb + la a6, fsu_intr_fault /* Load the fault handler */ + SET_FAULT_HANDLER(a6, a2) /* And set it */ + sw a1, 0(a0) /* Try storing the data */ + SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */ + li a0, 0 /* Success */ + ret /* Return */ +END(suswintr) + +ENTRY(setjmp) + /* Store the stack pointer */ + sd sp, 0(a0) + addi a0, a0, 8 + + /* Store the general purpose registers and ra */ + sd s0, (0 * 8)(a0) + sd s1, (1 * 8)(a0) + sd s2, (2 * 8)(a0) + sd s3, (3 * 8)(a0) + sd s4, (4 * 8)(a0) + sd s5, (5 * 8)(a0) + sd s6, (6 * 8)(a0) + sd s7, (7 * 8)(a0) + sd s8, (8 * 8)(a0) + sd s9, (9 * 8)(a0) + sd s10, (10 * 8)(a0) + sd s11, (11 * 8)(a0) + sd ra, (12 * 8)(a0) + + /* Return value */ + li a0, 0 + ret +END(setjmp) + +ENTRY(longjmp) + /* Restore the stack pointer */ + ld sp, 0(a0) + addi a0, a0, 8 + + /* Restore the general purpose registers and ra */ + ld s0, (0 * 8)(a0) + ld s1, (1 * 8)(a0) + ld s2, (2 * 8)(a0) + ld s3, (3 * 8)(a0) + ld s4, (4 * 8)(a0) + ld s5, (5 * 8)(a0) + ld s6, (6 * 8)(a0) + ld s7, (7 * 8)(a0) + ld s8, (8 * 8)(a0) + ld s9, (9 * 8)(a0) + ld s10, (10 * 8)(a0) + ld s11, (11 * 8)(a0) + ld ra, (12 * 8)(a0) + + /* Load the return value */ + mv a0, a1 + ret +END(longjmp) diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S new file mode 100644 index 000000000000..945fce354972 --- /dev/null +++ b/sys/riscv/riscv/swtch.S @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include "assym.s" +#include "opt_sched.h" + +#include +#include +#include +#include + +__FBSDID("$FreeBSD$"); + +/* + * void cpu_throw(struct thread *old, struct thread *new) + */ +ENTRY(cpu_throw) + /* Load pcpu */ + la x14, pcpup + ld x14, 0(x14) + /* Store the new curthread */ + sd a1, PC_CURTHREAD(x14) + /* And the new pcb */ + ld x13, TD_PCB(a1) + sd x13, PC_CURPCB(x14) + + sfence.vm + + /* Switch to the new pmap */ + la t0, pagetable_l0 + ld t1, PCB_L1ADDR(x13) /* Link to next level PN */ + srli t1, t1, PAGE_SHIFT /* PN no */ + li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) + slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */ + or t4, t2, t3 + /* Store single level0 PTE entry to position */ + sd t4, 0(t0) + + /* TODO: Invalidate the TLB */ + + sfence.vm + + /* Load registers */ + ld ra, (PCB_RA)(x13) + ld sp, (PCB_SP)(x13) + ld gp, (PCB_GP)(x13) + ld tp, (PCB_TP)(x13) + + /* s[0-11] */ + ld s0, (PCB_S + 0 * 8)(x13) + ld s1, (PCB_S + 1 * 8)(x13) + ld s2, (PCB_S + 2 * 8)(x13) + ld s3, (PCB_S + 3 * 8)(x13) + ld s4, (PCB_S + 4 * 8)(x13) + ld s5, (PCB_S + 5 * 8)(x13) + ld s6, (PCB_S + 6 * 8)(x13) + ld s7, (PCB_S + 7 * 8)(x13) + ld s8, (PCB_S + 8 * 8)(x13) + ld s9, (PCB_S + 9 * 8)(x13) + ld s10, (PCB_S + 10 * 8)(x13) + ld s11, (PCB_S + 11 * 8)(x13) + ret + +.Lcpu_throw_panic_str: + .asciz "cpu_throw: %p\0" +END(cpu_throw) + +/* + * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx) + * + * a0 = old + * a1 = new + * a2 = mtx + * x3 to x7, x16 and x17 are caller saved + */ +ENTRY(cpu_switch) + /* Load pcpu */ + la x14, pcpup + ld x14, 0(x14) + /* Store the new curthread */ + sd a1, PC_CURTHREAD(x14) + /* And the new pcb */ + ld x13, TD_PCB(a1) + sd x13, PC_CURPCB(x14) + + /* Save the old context. */ + ld x13, TD_PCB(a0) + + /* Store the callee-saved registers */ + sd ra, (PCB_RA)(x13) + sd sp, (PCB_SP)(x13) + sd gp, (PCB_GP)(x13) + sd tp, (PCB_TP)(x13) + + /* We use these in fork_trampoline */ + sd t0, (PCB_T + 0 * 8)(x13) + sd t1, (PCB_T + 1 * 8)(x13) + + /* s[0-11] */ + sd s0, (PCB_S + 0 * 8)(x13) + sd s1, (PCB_S + 1 * 8)(x13) + sd s2, (PCB_S + 2 * 8)(x13) + sd s3, (PCB_S + 3 * 8)(x13) + sd s4, (PCB_S + 4 * 8)(x13) + sd s5, (PCB_S + 5 * 8)(x13) + sd s6, (PCB_S + 6 * 8)(x13) + sd s7, (PCB_S + 7 * 8)(x13) + sd s8, (PCB_S + 8 * 8)(x13) + sd s9, (PCB_S + 9 * 8)(x13) + sd s10, (PCB_S + 10 * 8)(x13) + sd s11, (PCB_S + 11 * 8)(x13) + + /* + * Restore the saved context. + */ + ld x13, TD_PCB(a1) + + /* + * TODO: We may need to flush the cache here if switching + * to a user process. + */ + + sfence.vm + + /* Switch to the new pmap */ + la t0, pagetable_l0 + ld t1, PCB_L1ADDR(x13) /* Link to next level PN */ + srli t1, t1, PAGE_SHIFT /* PN no */ + li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) + slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */ + or t4, t2, t3 + /* Store single level0 PTE entry to position */ + sd t4, 0(t0) + + /* TODO: Invalidate the TLB */ + + sfence.vm + + /* Release the old thread */ + sd a2, TD_LOCK(a0) +#if defined(SCHED_ULE) && defined(SMP) + /* TODO */ +#endif + + /* Restore the registers */ + ld ra, (PCB_RA)(x13) + ld sp, (PCB_SP)(x13) + ld gp, (PCB_GP)(x13) + ld tp, (PCB_TP)(x13) + + /* We use these in fork_trampoline */ + ld t0, (PCB_T + 0 * 8)(x13) + ld t1, (PCB_T + 1 * 8)(x13) + + /* s[0-11] */ + ld s0, (PCB_S + 0 * 8)(x13) + ld s1, (PCB_S + 1 * 8)(x13) + ld s2, (PCB_S + 2 * 8)(x13) + ld s3, (PCB_S + 3 * 8)(x13) + ld s4, (PCB_S + 4 * 8)(x13) + ld s5, (PCB_S + 5 * 8)(x13) + ld s6, (PCB_S + 6 * 8)(x13) + ld s7, (PCB_S + 7 * 8)(x13) + ld s8, (PCB_S + 8 * 8)(x13) + ld s9, (PCB_S + 9 * 8)(x13) + ld s10, (PCB_S + 10 * 8)(x13) + ld s11, (PCB_S + 11 * 8)(x13) + ret +.Lcpu_switch_panic_str: + .asciz "cpu_switch: %p\0" +END(cpu_switch) + +/* + * fork_exit(void (*callout)(void *, struct trapframe *), void *arg, + * struct trapframe *frame) + */ + +ENTRY(fork_trampoline) + mv a0, x5 + mv a1, x6 + mv a2, sp + call _C_LABEL(fork_exit) + + /* Restore sstatus */ + ld t0, (TF_SSTATUS)(sp) + /* Ensure interrupts disabled */ + li t1, ~SSTATUS_IE + and t0, t0, t1 + csrw sstatus, t0 + + /* Restore exception program counter */ + ld t0, (TF_SEPC)(sp) + csrw sepc, t0 + + /* Restore the registers */ + ld t0, (TF_T + 0 * 8)(sp) + ld t1, (TF_T + 1 * 8)(sp) + ld t2, (TF_T + 2 * 8)(sp) + ld t3, (TF_T + 3 * 8)(sp) + ld t4, (TF_T + 4 * 8)(sp) + ld t5, (TF_T + 5 * 8)(sp) + ld t6, (TF_T + 6 * 8)(sp) + + ld s0, (TF_S + 0 * 8)(sp) + ld s1, (TF_S + 1 * 8)(sp) + ld s2, (TF_S + 2 * 8)(sp) + ld s3, (TF_S + 3 * 8)(sp) + ld s4, (TF_S + 4 * 8)(sp) + ld s5, (TF_S + 5 * 8)(sp) + ld s6, (TF_S + 6 * 8)(sp) + ld s7, (TF_S + 7 * 8)(sp) + ld s8, (TF_S + 8 * 8)(sp) + ld s9, (TF_S + 9 * 8)(sp) + ld s10, (TF_S + 10 * 8)(sp) + ld s11, (TF_S + 11 * 8)(sp) + + ld a0, (TF_A + 0 * 8)(sp) + ld a1, (TF_A + 1 * 8)(sp) + ld a2, (TF_A + 2 * 8)(sp) + ld a3, (TF_A + 3 * 8)(sp) + ld a4, (TF_A + 4 * 8)(sp) + ld a5, (TF_A + 5 * 8)(sp) + ld a6, (TF_A + 6 * 8)(sp) + ld a7, (TF_A + 7 * 8)(sp) + + /* Save kernel stack so we can use it doing a user trap */ + csrw sscratch, sp + + /* Load user ra and sp */ + ld ra, (TF_RA)(sp) + ld sp, (TF_SP)(sp) + + eret +END(fork_trampoline) + +ENTRY(savectx) + la a0, .Lsavectx_panic_str + call panic +.Lsavectx_panic_str: + .asciz "savectx_panic: %p\0" +END(savectx) diff --git a/sys/riscv/riscv/sys_machdep.c b/sys/riscv/riscv/sys_machdep.c new file mode 100644 index 000000000000..8fdc7dbe0aaf --- /dev/null +++ b/sys/riscv/riscv/sys_machdep.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +int +sysarch(struct thread *td, struct sysarch_args *uap) +{ + + return (ENOTSUP); +} diff --git a/sys/riscv/riscv/timer.c b/sys/riscv/riscv/timer.c new file mode 100644 index 000000000000..e3f3f22579a1 --- /dev/null +++ b/sys/riscv/riscv/timer.c @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +/* + * RISC-V Timer + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DEFAULT_FREQ 1000000 + +struct riscv_tmr_softc { + struct resource *res[1]; + void *ihl[1]; + uint32_t clkfreq; + struct eventtimer et; +}; + +static struct riscv_tmr_softc *riscv_tmr_sc = NULL; + +static struct resource_spec timer_spec[] = { + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static timecounter_get_t riscv_tmr_get_timecount; + +static struct timecounter riscv_tmr_timecount = { + .tc_name = "RISC-V Timecounter", + .tc_get_timecount = riscv_tmr_get_timecount, + .tc_poll_pps = NULL, + .tc_counter_mask = ~0u, + .tc_frequency = 0, + .tc_quality = 1000, +}; + +static long +get_counts(void) +{ + + return (csr_read(stime)); +} + +static unsigned +riscv_tmr_get_timecount(struct timecounter *tc) +{ + + return (get_counts()); +} + +static int +riscv_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period) +{ + struct riscv_tmr_softc *sc; + int counts; + + sc = (struct riscv_tmr_softc *)et->et_priv; + + if (first != 0) { + counts = ((uint32_t)et->et_frequency * first) >> 32; + machine_command(ECALL_MTIMECMP, counts); + return (0); + } + + return (EINVAL); + +} + +static int +riscv_tmr_stop(struct eventtimer *et) +{ + struct riscv_tmr_softc *sc; + + sc = (struct riscv_tmr_softc *)et->et_priv; + + /* TODO */ + + return (0); +} + +static int +riscv_tmr_intr(void *arg) +{ + struct riscv_tmr_softc *sc; + + sc = (struct riscv_tmr_softc *)arg; + + /* + * Clear interrupt pending bit. + * Note sip register is unimplemented in Spike simulator, + * so use machine command to clear in mip. + */ + machine_command(ECALL_CLEAR_PENDING, 0); + + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + + return (FILTER_HANDLED); +} + +static int +riscv_tmr_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_is_compatible(dev, "riscv,timer")) { + device_set_desc(dev, "RISC-V Timer"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +riscv_tmr_attach(device_t dev) +{ + struct riscv_tmr_softc *sc; + phandle_t node; + pcell_t clock; + int error; + + sc = device_get_softc(dev); + if (riscv_tmr_sc) + return (ENXIO); + + /* Get the base clock frequency */ + node = ofw_bus_get_node(dev); + if (node > 0) { + error = OF_getprop(node, "clock-frequency", &clock, + sizeof(clock)); + if (error > 0) { + sc->clkfreq = fdt32_to_cpu(clock); + } + } + + if (sc->clkfreq == 0) + sc->clkfreq = DEFAULT_FREQ; + + if (sc->clkfreq == 0) { + device_printf(dev, "No clock frequency specified\n"); + return (ENXIO); + } + + if (bus_alloc_resources(dev, timer_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + riscv_tmr_sc = sc; + + /* Setup IRQs handler */ + error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK, + riscv_tmr_intr, NULL, sc, &sc->ihl[0]); + if (error) { + device_printf(dev, "Unable to alloc int resource.\n"); + return (ENXIO); + } + + riscv_tmr_timecount.tc_frequency = sc->clkfreq; + tc_init(&riscv_tmr_timecount); + + sc->et.et_name = "RISC-V Eventtimer"; + sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; + sc->et.et_quality = 1000; + + sc->et.et_frequency = sc->clkfreq; + sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; + sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; + sc->et.et_start = riscv_tmr_start; + sc->et.et_stop = riscv_tmr_stop; + sc->et.et_priv = sc; + et_register(&sc->et); + + return (0); +} + +static device_method_t riscv_tmr_fdt_methods[] = { + DEVMETHOD(device_probe, riscv_tmr_fdt_probe), + DEVMETHOD(device_attach, riscv_tmr_attach), + { 0, 0 } +}; + +static driver_t riscv_tmr_fdt_driver = { + "timer", + riscv_tmr_fdt_methods, + sizeof(struct riscv_tmr_softc), +}; + +static devclass_t riscv_tmr_fdt_devclass; + +EARLY_DRIVER_MODULE(timer, simplebus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(timer, ofwbus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass, + 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); + +void +DELAY(int usec) +{ + int32_t counts, counts_per_usec; + uint32_t first, last; + + /* + * Check the timers are setup, if not just + * use a for loop for the meantime + */ + if (riscv_tmr_sc == NULL) { + for (; usec > 0; usec--) + for (counts = 200; counts > 0; counts--) + /* + * Prevent the compiler from optimizing + * out the loop + */ + cpufunc_nullop(); + return; + } + + /* Get the number of times to count */ + counts_per_usec = ((riscv_tmr_timecount.tc_frequency / 1000000) + 1); + + /* + * Clamp the timeout at a maximum value (about 32 seconds with + * a 66MHz clock). *Nobody* should be delay()ing for anywhere + * near that length of time and if they are, they should be hung + * out to dry. + */ + if (usec >= (0x80000000U / counts_per_usec)) + counts = (0x80000000U / counts_per_usec) - 1; + else + counts = usec * counts_per_usec; + + first = get_counts(); + + while (counts > 0) { + last = get_counts(); + counts -= (int32_t)(last - first); + first = last; + } +} diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c new file mode 100644 index 000000000000..c192b3135feb --- /dev/null +++ b/sys/riscv/riscv/trap.c @@ -0,0 +1,311 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern register_t fsu_intr_fault; + +/* Called from exception.S */ +void do_trap_supervisor(struct trapframe *); +void do_trap_user(struct trapframe *); + +static __inline void +call_trapsignal(struct thread *td, int sig, int code, void *addr) +{ + ksiginfo_t ksi; + + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = code; + ksi.ksi_addr = addr; + trapsignal(td, &ksi); +} + +int +cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +{ + struct proc *p; + register_t *ap; + int nap; + + nap = 8; + p = td->td_proc; + ap = &td->td_frame->tf_a[0]; + + sa->code = td->td_frame->tf_t[0]; + + if (sa->code == SYS_syscall || sa->code == SYS___syscall) { + sa->code = *ap++; + nap--; + } + + if (p->p_sysent->sv_mask) + sa->code &= p->p_sysent->sv_mask; + if (sa->code >= p->p_sysent->sv_size) + sa->callp = &p->p_sysent->sv_table[0]; + else + sa->callp = &p->p_sysent->sv_table[sa->code]; + + sa->narg = sa->callp->sy_narg; + memcpy(sa->args, ap, nap * sizeof(register_t)); + if (sa->narg > nap) + panic("TODO: Could we have more then 8 args?"); + + td->td_retval[0] = 0; + td->td_retval[1] = 0; + + return (0); +} + +#include "../../kern/subr_syscall.c" + +static void +dump_regs(struct trapframe *frame) +{ + int n; + int i; + + n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0])); + for (i = 0; i < n; i++) + printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]); + + n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0])); + for (i = 0; i < n; i++) + printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]); + + n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0])); + for (i = 0; i < n; i++) + printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]); + + printf("sepc == 0x%016lx\n", frame->tf_sepc); + printf("sstatus == 0x%016lx\n", frame->tf_sstatus); +} + +static void +svc_handler(struct trapframe *frame) +{ + struct syscall_args sa; + struct thread *td; + int error; + + td = curthread; + td->td_frame = frame; + + error = syscallenter(td, &sa); + syscallret(td, error, &sa); +} + +static void +data_abort(struct trapframe *frame, int lower) +{ + struct vm_map *map; + uint64_t sbadaddr; + struct thread *td; + struct pcb *pcb; + vm_prot_t ftype; + vm_offset_t va; + struct proc *p; + int ucode; + int error; + int sig; + + td = curthread; + pcb = td->td_pcb; + + /* + * Special case for fuswintr and suswintr. These can't sleep so + * handle them early on in the trap handler. + */ + if (__predict_false(pcb->pcb_onfault == (vm_offset_t)&fsu_intr_fault)) { + frame->tf_sepc = pcb->pcb_onfault; + return; + } + + sbadaddr = frame->tf_sbadaddr; + + p = td->td_proc; + + if (lower) + map = &td->td_proc->p_vmspace->vm_map; + else { + /* The top bit tells us which range to use */ + if ((sbadaddr >> 63) == 1) + map = kernel_map; + else + map = &td->td_proc->p_vmspace->vm_map; + } + + va = trunc_page(sbadaddr); + + if (frame->tf_scause == EXCP_STORE_ACCESS_FAULT) { + ftype = (VM_PROT_READ | VM_PROT_WRITE); + } else { + ftype = (VM_PROT_READ); + } + + if (map != kernel_map) { + /* + * Keep swapout from messing with us during this + * critical time. + */ + PROC_LOCK(p); + ++p->p_lock; + PROC_UNLOCK(p); + + /* Fault in the user page: */ + error = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + + PROC_LOCK(p); + --p->p_lock; + PROC_UNLOCK(p); + } else { + /* + * Don't have to worry about process locking or stacks in the + * kernel. + */ + error = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + } + + if (error != KERN_SUCCESS) { + if (lower) { + sig = SIGSEGV; + if (error == KERN_PROTECTION_FAILURE) + ucode = SEGV_ACCERR; + else + ucode = SEGV_MAPERR; + call_trapsignal(td, sig, ucode, (void *)sbadaddr); + } else { + if (td->td_intr_nesting_level == 0 && + pcb->pcb_onfault != 0) { + frame->tf_a[0] = error; + frame->tf_sepc = pcb->pcb_onfault; + return; + } + dump_regs(frame); + panic("vm_fault failed: %lx, va 0x%016lx", + frame->tf_sepc, sbadaddr); + } + } + + if (lower) + userret(td, frame); +} + +void +do_trap_supervisor(struct trapframe *frame) +{ + uint64_t exception; + + exception = (frame->tf_scause & EXCP_MASK); + if (frame->tf_scause & EXCP_INTR) { + /* Interrupt */ + riscv_cpu_intr(frame); + return; + } + + CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p", + curthread, frame->tf_sepc, frame); + + switch(exception) { + case EXCP_LOAD_ACCESS_FAULT: + case EXCP_STORE_ACCESS_FAULT: + case EXCP_INSTR_ACCESS_FAULT: + data_abort(frame, 0); + break; + default: + dump_regs(frame); + panic("Unknown kernel exception %x badaddr %lx\n", + exception, frame->tf_sbadaddr); + } +} + +void +do_trap_user(struct trapframe *frame) +{ + uint64_t exception; + + exception = (frame->tf_scause & EXCP_MASK); + if (frame->tf_scause & EXCP_INTR) { + /* Interrupt */ + riscv_cpu_intr(frame); + return; + } + + CTR3(KTR_TRAP, "do_trap_user: curthread: %p, sepc: %lx, frame: %p", + curthread, frame->tf_sepc, frame); + + switch(exception) { + case EXCP_LOAD_ACCESS_FAULT: + case EXCP_STORE_ACCESS_FAULT: + case EXCP_INSTR_ACCESS_FAULT: + data_abort(frame, 1); + break; + case EXCP_UMODE_ENV_CALL: + frame->tf_sepc += 4; /* Next instruction */ + svc_handler(frame); + break; + default: + dump_regs(frame); + panic("Unknown userland exception %x badaddr %lx\n", + exception, frame->tf_sbadaddr); + } +} diff --git a/sys/riscv/riscv/uio_machdep.c b/sys/riscv/riscv/uio_machdep.c new file mode 100644 index 000000000000..e6f6d39f02be --- /dev/null +++ b/sys/riscv/riscv/uio_machdep.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2004 Alan L. Cox + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/* + * Implement uiomove(9) from physical memory using the direct map to + * avoid the creation and destruction of ephemeral mappings. + */ +int +uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) +{ + struct thread *td = curthread; + struct iovec *iov; + void *cp; + vm_offset_t page_offset, vaddr; + size_t cnt; + int error = 0; + int save = 0; + boolean_t mapped; + + KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, + ("uiomove_fromphys: mode")); + KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, + ("uiomove_fromphys proc")); + save = td->td_pflags & TDP_DEADLKTREAT; + td->td_pflags |= TDP_DEADLKTREAT; + mapped = FALSE; + while (n > 0 && uio->uio_resid) { + iov = uio->uio_iov; + cnt = iov->iov_len; + if (cnt == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > n) + cnt = n; + page_offset = offset & PAGE_MASK; + cnt = min(cnt, PAGE_SIZE - page_offset); + if (uio->uio_segflg != UIO_NOCOPY) { + mapped = pmap_map_io_transient( + &ma[offset >> PAGE_SHIFT], &vaddr, 1, TRUE); + cp = (char *)vaddr + page_offset; + } + switch (uio->uio_segflg) { + case UIO_USERSPACE: + maybe_yield(); + if (uio->uio_rw == UIO_READ) + error = copyout(cp, iov->iov_base, cnt); + else + error = copyin(iov->iov_base, cp, cnt); + if (error) + goto out; + break; + case UIO_SYSSPACE: + if (uio->uio_rw == UIO_READ) + bcopy(cp, iov->iov_base, cnt); + else + bcopy(iov->iov_base, cp, cnt); + break; + case UIO_NOCOPY: + break; + } + if (__predict_false(mapped)) { + pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], + &vaddr, 1, TRUE); + mapped = FALSE; + } + iov->iov_base = (char *)iov->iov_base + cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + offset += cnt; + n -= cnt; + } +out: + if (__predict_false(mapped)) { + panic("TODO 3"); + pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1, + TRUE); + } + if (save == 0) + td->td_pflags &= ~TDP_DEADLKTREAT; + return (error); +} diff --git a/sys/riscv/riscv/uma_machdep.c b/sys/riscv/riscv/uma_machdep.c new file mode 100644 index 000000000000..ba480713fc75 --- /dev/null +++ b/sys/riscv/riscv/uma_machdep.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2003 Alan L. Cox + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void * +uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait) +{ + + panic("uma_small_alloc"); +} + +void +uma_small_free(void *mem, vm_size_t size, u_int8_t flags) +{ + + panic("uma_small_free"); +} diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c new file mode 100644 index 000000000000..62e466f9e19a --- /dev/null +++ b/sys/riscv/riscv/vm_machdep.c @@ -0,0 +1,259 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Finish a fork operation, with process p2 nearly set up. + * Copy and update the pcb, set up the stack so that the child + * ready to run and return to user mode. + */ +void +cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) +{ + struct pcb *pcb2; + struct trapframe *tf; + uint64_t val; + + if ((flags & RFPROC) == 0) + return; + + if (td1 == curthread) { + __asm __volatile("mv %0, tp" : "=&r"(val)); + td1->td_pcb->pcb_tp = val; + } + + pcb2 = (struct pcb *)(td2->td_kstack + + td2->td_kstack_pages * PAGE_SIZE) - 1; + + td2->td_pcb = pcb2; + bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); + + td2->td_pcb->pcb_l1addr = + vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1); + + tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1); + bcopy(td1->td_frame, tf, sizeof(*tf)); + + /* Clear syscall error flag */ + tf->tf_t[0] = 0; + + /* Arguments for child */ + tf->tf_a[0] = 0; + tf->tf_a[1] = 0; + tf->tf_sstatus = SSTATUS_PIE; + + td2->td_frame = tf; + + /* Set the return value registers for fork() */ + td2->td_pcb->pcb_t[0] = (uintptr_t)fork_return; + td2->td_pcb->pcb_t[1] = (uintptr_t)td2; + td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline; + td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame; + + /* Setup to release spin count in fork_exit(). */ + td2->td_md.md_spinlock_count = 1; + td2->td_md.md_saved_sstatus_ie = 1; +} + +void +cpu_reset(void) +{ + + printf("cpu_reset"); + while(1) + __asm volatile("wfi" ::: "memory"); +} + +void +cpu_thread_swapin(struct thread *td) +{ +} + +void +cpu_thread_swapout(struct thread *td) +{ +} + +void +cpu_set_syscall_retval(struct thread *td, int error) +{ + struct trapframe *frame; + + frame = td->td_frame; + + switch (error) { + case 0: + frame->tf_a[0] = td->td_retval[0]; + frame->tf_a[1] = td->td_retval[1]; + frame->tf_t[0] = 0; /* syscall succeeded */ + break; + case ERESTART: + frame->tf_sepc -= 4; /* prev instruction */ + break; + case EJUSTRETURN: + break; + default: + frame->tf_a[0] = error; + frame->tf_t[0] = 1; /* syscall error */ + break; + } +} + +/* + * Initialize machine state (pcb and trap frame) for a new thread about to + * upcall. Put enough state in the new thread's PCB to get it to go back + * userret(), where we can intercept it again to set the return (upcall) + * Address and stack, along with those from upcals that are from other sources + * such as those generated in thread_userret() itself. + */ +void +cpu_set_upcall(struct thread *td, struct thread *td0) +{ + + bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); + bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb)); + + td->td_pcb->pcb_t[0] = (uintptr_t)fork_return; + td->td_pcb->pcb_t[1] = (uintptr_t)td; + td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline; + td->td_pcb->pcb_sp = (uintptr_t)td->td_frame; + + /* Setup to release spin count in fork_exit(). */ + td->td_md.md_spinlock_count = 1; + td->td_md.md_saved_sstatus_ie = 1; +} + +/* + * Set that machine state for performing an upcall that has to + * be done in thread_userret() so that those upcalls generated + * in thread_userret() itself can be done as well. + */ +void +cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, + stack_t *stack) +{ + struct trapframe *tf = td->td_frame; + + tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size); + tf->tf_sepc = (register_t)entry; + tf->tf_a[0] = (register_t)arg; +} + +int +cpu_set_user_tls(struct thread *td, void *tls_base) +{ + struct pcb *pcb; + + if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS) + return (EINVAL); + + pcb = td->td_pcb; + pcb->pcb_tp = (register_t)tls_base; + + return (0); +} + +void +cpu_thread_exit(struct thread *td) +{ +} + +void +cpu_thread_alloc(struct thread *td) +{ + + td->td_pcb = (struct pcb *)(td->td_kstack + + td->td_kstack_pages * PAGE_SIZE) - 1; + td->td_frame = (struct trapframe *)STACKALIGN( + td->td_pcb - 1); +} + +void +cpu_thread_free(struct thread *td) +{ +} + +void +cpu_thread_clean(struct thread *td) +{ +} + +/* + * Intercept the return address from a freshly forked process that has NOT + * been scheduled yet. + * + * This is needed to make kernel threads stay in kernel mode. + */ +void +cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg) +{ + + td->td_pcb->pcb_t[0] = (uintptr_t)func; + td->td_pcb->pcb_t[1] = (uintptr_t)arg; + td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline; + td->td_pcb->pcb_sp = (uintptr_t)td->td_frame; +} + +void +cpu_exit(struct thread *td) +{ +} + +void +swi_vm(void *v) +{ + + /* Nothing to do here - busdma bounce buffers are not implemented. */ +} diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h index 59cc45f0e5fa..530359f6c1e4 100644 --- a/sys/sys/cdefs.h +++ b/sys/sys/cdefs.h @@ -776,7 +776,7 @@ #endif #endif -#if defined(__mips) || defined(__powerpc64__) +#if defined(__mips) || defined(__powerpc64__) || defined(__riscv__) #define __NO_TLS 1 #endif diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h index 763b7cd1c5aa..fd010181eb1d 100644 --- a/sys/sys/kerneldump.h +++ b/sys/sys/kerneldump.h @@ -72,6 +72,7 @@ struct kerneldumpheader { #define KERNELDUMP_I386_VERSION 2 #define KERNELDUMP_MIPS_VERSION 1 #define KERNELDUMP_POWERPC_VERSION 1 +#define KERNELDUMP_RISCV_VERSION 1 #define KERNELDUMP_SPARC64_VERSION 1 #define KERNELDUMP_TEXT_VERSION 1 uint64_t dumplength; /* excl headers */ From 168df4324339cc7a2f2c3d32c675f074421c43d1 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 29 Jan 2016 16:01:37 +0000 Subject: [PATCH 035/236] Use kernel_pmap directly instead of pmap_kernel(). The kernel_pmap is already used for __ARM_ARCH >= 6 and so even for __ARM_ARCH < 6 on some common places. --- sys/arm/arm/db_interface.c | 2 +- sys/arm/arm/machdep.c | 2 +- sys/arm/arm/pmap.c | 88 +++++++++++++++++++------------------- sys/arm/include/pmap-v6.h | 9 ---- sys/arm/include/pmap.h | 3 +- 5 files changed, 47 insertions(+), 57 deletions(-) diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c index 43831462d896..613dc08149cc 100644 --- a/sys/arm/arm/db_interface.c +++ b/sys/arm/arm/db_interface.c @@ -170,7 +170,7 @@ db_validate_address(vm_offset_t addr) addr >= VM_MIN_KERNEL_ADDRESS #endif ) - pmap = pmap_kernel(); + pmap = kernel_pmap; else pmap = p->p_vmspace->vm_map.pmap; diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 52413b89109e..c39d7d2b5508 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -455,7 +455,7 @@ cpu_startup(void *dummy) vm_pager_bufferinit(); pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack + USPACE_SVC_STACK_TOP; - pmap_set_pcb_pagedir(pmap_kernel(), pcb); + pmap_set_pcb_pagedir(kernel_pmap, pcb); #if __ARM_ARCH < 6 vector_page_setprot(VM_PROT_READ); pmap_postinit(); diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index 3dd998429dfc..688fe7bf906b 100644 --- a/sys/arm/arm/pmap.c +++ b/sys/arm/arm/pmap.c @@ -394,7 +394,7 @@ int pmap_needs_pte_sync; #define PMAP_SHPGPERPROC 200 #endif -#define pmap_is_current(pm) ((pm) == pmap_kernel() || \ +#define pmap_is_current(pm) ((pm) == kernel_pmap || \ curproc->p_vmspace->vm_map.pmap == (pm)) static uma_zone_t pvzone = NULL; uma_zone_t l2zone; @@ -437,10 +437,10 @@ pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt) /* * Copy the kernel's L1 entries to each new L1. */ - if (l1pt != pmap_kernel()->pm_l1->l1_kva) - memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE); + if (l1pt != kernel_pmap->pm_l1->l1_kva) + memcpy(l1pt, kernel_pmap->pm_l1->l1_kva, L1_TABLE_SIZE); - if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0) + if ((l1->l1_physaddr = pmap_extract(kernel_pmap, (vm_offset_t)l1pt)) == 0) panic("pmap_init_l1: can't get PA of L1 at %p", l1pt); SLIST_INSERT_HEAD(&l1_list, l1, l1_link); TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru); @@ -932,7 +932,7 @@ pmap_free_l2_bucket(pmap_t pm, struct l2_bucket *l2b, u_int count) * to a performance win over time as we don't need to continually * alloc/free. */ - if (l2b->l2b_occupancy > 0 || pm == pmap_kernel()) + if (l2b->l2b_occupancy > 0 || pm == kernel_pmap) return; /* @@ -1002,7 +1002,7 @@ pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags) * page tables, we simply fix up the cache-mode here if it's not * correct. */ - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); ptep = &l2b->l2b_kva[l2pte_index(va)]; pte = *ptep; @@ -1077,9 +1077,9 @@ pmap_idcache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len) vm_size_t rest; CTR4(KTR_PMAP, "pmap_dcache_wbinv_range: pmap %p is_kernel %d va 0x%08x" - " len 0x%x ", pm, pm == pmap_kernel(), va, len); + " len 0x%x ", pm, pm == kernel_pmap, va, len); - if (pmap_is_current(pm) || pm == pmap_kernel()) { + if (pmap_is_current(pm) || pm == kernel_pmap) { rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); while (len > 0) { if (pmap_has_valid_mapping(pm, va)) { @@ -1100,7 +1100,7 @@ pmap_dcache_wb_range(pmap_t pm, vm_offset_t va, vm_size_t len, boolean_t do_inv, vm_size_t rest; CTR4(KTR_PMAP, "pmap_dcache_wb_range: pmap %p is_kernel %d va 0x%08x " - "len 0x%x ", pm, pm == pmap_kernel(), va, len); + "len 0x%x ", pm, pm == kernel_pmap, va, len); CTR2(KTR_PMAP, " do_inv %d rd_only %d", do_inv, rd_only); if (pmap_is_current(pm)) { @@ -1230,13 +1230,13 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) { /* generate a count of the pv_entry uses */ if (pv->pv_flags & PVF_WRITE) { - if (pv->pv_pmap == pmap_kernel()) + if (pv->pv_pmap == kernel_pmap) kwritable++; else if (pv->pv_pmap == pm) uwritable++; writable++; } - if (pv->pv_pmap == pmap_kernel()) + if (pv->pv_pmap == kernel_pmap) kentries++; else { if (pv->pv_pmap == pm) @@ -1248,19 +1248,19 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) * check if the user duplicate mapping has * been removed. */ - if ((pm != pmap_kernel()) && (((uentries > 1) && uwritable) || + if ((pm != kernel_pmap) && (((uentries > 1) && uwritable) || (uwritable > 1))) pmwc = 1; TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) { /* check for user uncachable conditions - order is important */ - if (pm != pmap_kernel() && - (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel())) { + if (pm != kernel_pmap && + (pv->pv_pmap == pm || pv->pv_pmap == kernel_pmap)) { if ((uentries > 1 && uwritable) || uwritable > 1) { /* user duplicate mapping */ - if (pv->pv_pmap != pmap_kernel()) + if (pv->pv_pmap != kernel_pmap) pv->pv_flags |= PVF_MWC; if (!(pv->pv_flags & PVF_NC)) { @@ -1279,7 +1279,7 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) if ((kwritable && (entries || kentries > 1)) || (kwritable > 1) || ((kwritable != writable) && kentries && - (pv->pv_pmap == pmap_kernel() || + (pv->pv_pmap == kernel_pmap || (pv->pv_flags & PVF_WRITE) || (pv->pv_flags & PVF_MWC)))) { @@ -1291,7 +1291,7 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) } /* kernel and user are cachable */ - if ((pm == pmap_kernel()) && !(pv->pv_flags & PVF_MWC) && + if ((pm == kernel_pmap) && !(pv->pv_flags & PVF_MWC) && (pv->pv_flags & PVF_NC)) { pv->pv_flags &= ~PVF_NC; @@ -1300,8 +1300,8 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) continue; } /* user is no longer sharable and writable */ - if (pm != pmap_kernel() && - (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel()) && + if (pm != kernel_pmap && + (pv->pv_pmap == pm || pv->pv_pmap == kernel_pmap) && !pmwc && (pv->pv_flags & PVF_NC)) { pv->pv_flags &= ~(PVF_NC | PVF_MWC); @@ -1565,7 +1565,7 @@ vector_page_setprot(int prot) struct l2_bucket *l2b; pt_entry_t *ptep; - l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page); + l2b = pmap_get_l2_bucket(kernel_pmap, vector_page); ptep = &l2b->l2b_kva[l2pte_index(vector_page)]; @@ -1603,7 +1603,7 @@ pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve) pg->md.pvh_attrs &= ~PVF_REF; else vm_page_aflag_set(pg, PGA_REFERENCED); - if ((pve->pv_flags & PVF_NC) && ((pm == pmap_kernel()) || + if ((pve->pv_flags & PVF_NC) && ((pm == kernel_pmap) || (pve->pv_flags & PVF_WRITE) || !(pve->pv_flags & PVF_MWC))) pmap_fix_cache(pg, pm, 0); else if (pve->pv_flags & PVF_WRITE) { @@ -1972,7 +1972,7 @@ pmap_postinit(void) pl1pt = (pd_entry_t *)va; while (va < eva) { - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); ptep = &l2b->l2b_kva[l2pte_index(va)]; pte = *ptep; pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt; @@ -2122,7 +2122,7 @@ pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap, struct l2_bucket *l2b; if (ptep) { - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); if (l2b == NULL) panic("pmap_alloc_specials: no l2b for 0x%x", va); @@ -2381,7 +2381,7 @@ pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap) if (pap) *pap = pa; - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); ptep = &l2b->l2b_kva[l2pte_index(va)]; *ptep = L2_S_PROTO | pa | cache_mode | @@ -2494,7 +2494,7 @@ pmap_grow_l2_bucket(pmap_t pm, vm_offset_t va) void pmap_growkernel(vm_offset_t addr) { - pmap_t kpm = pmap_kernel(); + pmap_t kpm = kernel_pmap; if (addr <= pmap_curmaxkvaddr) return; /* we are OK */ @@ -2654,9 +2654,9 @@ pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags) (uint32_t) va, (uint32_t) pa)); - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); if (l2b == NULL) - l2b = pmap_grow_l2_bucket(pmap_kernel(), va); + l2b = pmap_grow_l2_bucket(kernel_pmap, va); KASSERT(l2b != NULL, ("No L2 Bucket")); pte = &l2b->l2b_kva[l2pte_index(va)]; opte = *pte; @@ -2690,11 +2690,11 @@ pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags) if (!TAILQ_EMPTY(&m->md.pv_list) || m->md.pv_kva != 0) { if ((pve = pmap_get_pv_entry()) == NULL) panic("pmap_kenter_internal: no pv entries"); - PMAP_LOCK(pmap_kernel()); - pmap_enter_pv(m, pve, pmap_kernel(), va, + PMAP_LOCK(kernel_pmap); + pmap_enter_pv(m, pve, kernel_pmap, va, PVF_WRITE | PVF_UNMAN); - pmap_fix_cache(m, pmap_kernel(), va); - PMAP_UNLOCK(pmap_kernel()); + pmap_fix_cache(m, kernel_pmap, va); + PMAP_UNLOCK(kernel_pmap); } else { m->md.pv_kva = va; } @@ -2758,7 +2758,7 @@ pmap_kenter_user(vm_offset_t va, vm_paddr_t pa) * at the first use of the new address, or bad things will happen, * as we use one of these addresses in the exception handlers. */ - pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1); + pmap_fault_fixup(kernel_pmap, va, VM_PROT_READ|VM_PROT_WRITE, 1); } vm_paddr_t @@ -2780,7 +2780,7 @@ pmap_kremove(vm_offset_t va) vm_page_t m; vm_offset_t pa; - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); if (!l2b) return; KASSERT(l2b != NULL, ("No L2 Bucket")); @@ -2796,11 +2796,11 @@ pmap_kremove(vm_offset_t va) * before the pvzone is initialized. */ rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap_kernel()); + PMAP_LOCK(kernel_pmap); if (pvzone != NULL && (m = vm_phys_paddr_to_vm_page(pa)) && - (pve = pmap_remove_pv(m, pmap_kernel(), va))) + (pve = pmap_remove_pv(m, kernel_pmap, va))) pmap_free_pv_entry(pve); - PMAP_UNLOCK(pmap_kernel()); + PMAP_UNLOCK(kernel_pmap); rw_wunlock(&pvh_global_lock); va = va & ~PAGE_MASK; cpu_dcache_wbinv_range(va, PAGE_SIZE); @@ -3027,7 +3027,7 @@ pmap_remove_all(vm_page_t m) curpm = vmspace_pmap(curproc->p_vmspace); while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { if (flush == FALSE && (pv->pv_pmap == curpm || - pv->pv_pmap == pmap_kernel())) + pv->pv_pmap == kernel_pmap)) flush = TRUE; PMAP_LOCK(pv->pv_pmap); @@ -3239,7 +3239,7 @@ pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, prot = %x, " "flags = %x\n", (uint32_t) pmap, va, (uint32_t) m, prot, flags)); - if (pmap == pmap_kernel()) { + if (pmap == kernel_pmap) { l2b = pmap_get_l2_bucket(pmap, va); if (l2b == NULL) l2b = pmap_grow_l2_bucket(pmap, va); @@ -3414,7 +3414,7 @@ pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, /* * Make sure userland mappings get the right permissions */ - if (pmap != pmap_kernel() && va != vector_page) { + if (pmap != kernel_pmap && va != vector_page) { npte |= L2_S_PROT_U; } @@ -3672,9 +3672,9 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) l1pd = pmap->pm_l1->l1_kva[l1idx]; if (l1pte_section_p(l1pd)) { /* - * These should only happen for pmap_kernel() + * These should only happen for kernel_pmap */ - KASSERT(pmap == pmap_kernel(), ("huh")); + KASSERT(pmap == kernel_pmap, ("huh")); /* XXX: what to do about the bits > 32 ? */ if (l1pd & L1_S_SUPERSEC) pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); @@ -4034,7 +4034,7 @@ pmap_use_minicache(vm_offset_t va, vm_size_t size) if (next_bucket > eva) next_bucket = eva; - l2b = pmap_get_l2_bucket(pmap_kernel(), va); + l2b = pmap_get_l2_bucket(kernel_pmap, va); sptep = ptep = &l2b->l2b_kva[l2pte_index(va)]; @@ -4137,10 +4137,10 @@ pmap_clean_page(struct pv_entry *pv, boolean_t is_src) if (curthread) pm = vmspace_pmap(curproc->p_vmspace); else - pm = pmap_kernel(); + pm = kernel_pmap; for (npv = pv; npv; npv = TAILQ_NEXT(npv, pv_list)) { - if (npv->pv_pmap == pmap_kernel() || npv->pv_pmap == pm) { + if (npv->pv_pmap == kernel_pmap || npv->pv_pmap == pm) { flags |= npv->pv_flags; /* * The page is mapped non-cacheable in diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index beaf638a179b..b1df78e4a6a6 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -271,15 +271,6 @@ void pmap_devmap_bootstrap(const struct pmap_devmap *); void pmap_pte_init_mmu_v6(void); void vector_page_setprot(int); - -/* - * sys/arm/arm/db_interface.c - * sys/arm/arm/machdep.c - * sys/arm/arm/minidump_machdep.c - * sys/arm/arm/pmap.c - */ -#define pmap_kernel() kernel_pmap - /* * sys/arm/arm/bus_space_generic.c (just comment) * sys/arm/arm/devmap.c diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index dc7fd38a20eb..8271cb03cc6b 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -176,7 +176,6 @@ typedef struct pmap *pmap_t; #ifdef _KERNEL extern struct pmap kernel_pmap_store; #define kernel_pmap (&kernel_pmap_store) -#define pmap_kernel() kernel_pmap #define PMAP_ASSERT_LOCKED(pmap) \ mtx_assert(&(pmap)->pm_mtx, MA_OWNED) @@ -247,7 +246,7 @@ vtopte(vm_offset_t va) pd_entry_t *pdep; pt_entry_t *ptep; - if (pmap_get_pde_pte(pmap_kernel(), va, &pdep, &ptep) == FALSE) + if (pmap_get_pde_pte(kernel_pmap, va, &pdep, &ptep) == FALSE) return (NULL); return (ptep); } From a6dbee3943e27268eda39568d19621ea61955211 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 29 Jan 2016 16:42:03 +0000 Subject: [PATCH 036/236] Remove NPTEPG definition which is not used anywhere now after introduction of new pmap dump interface (r294722). And do not expose pt_entry_t type. --- sys/arm/include/param.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/arm/include/param.h b/sys/arm/include/param.h index bbe9bcb08325..384891daf36a 100644 --- a/sys/arm/include/param.h +++ b/sys/arm/include/param.h @@ -110,7 +110,6 @@ #define PAGE_SHIFT 12 #define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */ #define PAGE_MASK (PAGE_SIZE - 1) -#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) #define PDR_SHIFT 20 /* log2(NBPDR) */ #define NBPDR (1 << PDR_SHIFT) From 94b986ee45d924260f255854d8022435a559b674 Mon Sep 17 00:00:00 2001 From: asomers Date: Fri, 29 Jan 2016 17:08:26 +0000 Subject: [PATCH 037/236] Add a sysctl to allow ZFS pools backed by zvols Change 294329 removed the ability to build ZFS pools that are backed by zvols, because having that ability (even if it's not used) leads to deadlocks. By popular demand, I'm adding an off-by-default sysctl to reenable that ability. Reviewed by: lidl, delphij MFC after: Never Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D4998 --- UPDATING | 7 ++++ .../opensolaris/uts/common/fs/zfs/zvol.c | 36 +++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/UPDATING b/UPDATING index 1b98e40cbaf2..123c05ae975e 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20160129: + Building ZFS pools on top of zvols is prohibited by default. That + feature has never worked safely; it's always been prone to deadlocks. + Using a zvol as the backing store for a VM guest's virtual disk will + still work, even if the guest is using ZFS. Legacy behavior can be + restored by setting vfs.zfs.vol.recursive=1. + 20160119: The NONE and HPN patches has been removed from OpenSSH. They are still available in the security/openssh-portable port. diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index 99d313b55faf..5eb9df13d611 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -134,6 +134,9 @@ SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTLFLAG_RW, 0, "ZFS VOLUME"); static int volmode = ZFS_VOLMODE_GEOM; SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, mode, CTLFLAG_RWTUN, &volmode, 0, "Expose as GEOM providers (1), device files (2) or neither"); +static boolean_t zpool_on_zvol = B_FALSE; +SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, recursive, CTLFLAG_RWTUN, &zpool_on_zvol, 0, + "Allow zpools to use zvols as vdevs (DANGEROUS)"); #endif typedef struct zvol_extent { @@ -1114,7 +1117,9 @@ zvol_open(struct g_provider *pp, int flag, int count) return (err); } #else /* !illumos */ - if (tsd_get(zfs_geom_probe_vdev_key) != NULL) { + boolean_t locked = B_FALSE; + + if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) { /* * if zfs_geom_probe_vdev_key is set, that means that zfs is * attempting to probe geom providers while looking for a @@ -1125,19 +1130,34 @@ zvol_open(struct g_provider *pp, int flag, int count) */ return (EOPNOTSUPP); } - - mutex_enter(&zfsdev_state_lock); + /* + * Protect against recursively entering spa_namespace_lock + * when spa_open() is used for a pool on a (local) ZVOL(s). + * This is needed since we replaced upstream zfsdev_state_lock + * with spa_namespace_lock in the ZVOL code. + * We are using the same trick as spa_open(). + * Note that calls in zvol_first_open which need to resolve + * pool name to a spa object will enter spa_open() + * recursively, but that function already has all the + * necessary protection. + */ + if (!MUTEX_HELD(&zfsdev_state_lock)) { + mutex_enter(&zfsdev_state_lock); + locked = B_TRUE; + } zv = pp->private; if (zv == NULL) { - mutex_exit(&zfsdev_state_lock); + if (locked) + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(ENXIO)); } if (zv->zv_total_opens == 0) { err = zvol_first_open(zv); if (err) { - mutex_exit(&zfsdev_state_lock); + if (locked) + mutex_exit(&zfsdev_state_lock); return (err); } pp->mediasize = zv->zv_volsize; @@ -1171,7 +1191,8 @@ zvol_open(struct g_provider *pp, int flag, int count) mutex_exit(&zfsdev_state_lock); #else zv->zv_total_opens += count; - mutex_exit(&zfsdev_state_lock); + if (locked) + mutex_exit(&zfsdev_state_lock); #endif return (err); @@ -1181,7 +1202,8 @@ zvol_open(struct g_provider *pp, int flag, int count) #ifdef illumos mutex_exit(&zfsdev_state_lock); #else - mutex_exit(&zfsdev_state_lock); + if (locked) + mutex_exit(&zfsdev_state_lock); #endif return (err); } From e0bef7b56ab0c598635299782cf1a502c6605ef1 Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 29 Jan 2016 17:20:59 +0000 Subject: [PATCH 038/236] MFV 295046: 6358 A faulted pool with only unavailable vdevs triggers assertion failure in libzfs Reviewed by: Matthew Ahrens Reviewed by: Andrew Stormont Reviewed by: Serban Maduta Approved by: Dan McDonald Author: Dan Vatca illumos/illumos-gate@b289d045e084af53efcc025255af8242e41f28fa --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c index d5ba20fde0cf..c3dafd6a777c 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c @@ -26,6 +26,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2015 by Syneto S.R.L. All rights reserved. */ /* @@ -246,8 +247,9 @@ zpool_get_features(zpool_handle_t *zhp) config = zpool_get_config(zhp, NULL); } - verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, - &features) == 0); + if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, + &features) != 0) + return (NULL); return (features); } From 18d86c1c9d2a2a9531145bee3aa15f7a036ee033 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 29 Jan 2016 17:43:03 +0000 Subject: [PATCH 039/236] Retire pmap_pte_init_mmu_v6() which was used by old pmap-v6. --- sys/arm/arm/cpufunc.c | 6 ------ sys/arm/arm/pmap-v6.c | 5 ----- sys/arm/include/pmap-v6.h | 1 - sys/arm/include/pmap.h | 3 --- 4 files changed, 15 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 0dd9241f27df..e479803006f7 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -889,9 +889,6 @@ set_cpufuncs() cpufuncs = arm1176_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ get_cachetype_cp15(); - - pmap_pte_init_mmu_v6(); - goto out; } #endif /* CPU_ARM1176 */ @@ -915,8 +912,6 @@ set_cpufuncs() cpufuncs = cortexa_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ get_cachetype_cp15(); - - pmap_pte_init_mmu_v6(); goto out; } #endif /* CPU_CORTEXA */ @@ -927,7 +922,6 @@ set_cpufuncs() cputype == CPU_ID_ARM_88SV581X_V7) { cpufuncs = pj4bv7_cpufuncs; get_cachetype_cp15(); - pmap_pte_init_mmu_v6(); goto out; } #endif /* CPU_MV_PJ4B */ diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 2996898a4510..4f774c487f76 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -6278,11 +6278,6 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode) } /* !!!! REMOVE !!!! */ -void -pmap_pte_init_mmu_v6(void) -{ -} - void vector_page_setprot(int p) { } diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index b1df78e4a6a6..5ca8f1767248 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -268,7 +268,6 @@ void pmap_devmap_bootstrap(const struct pmap_devmap *); /* * sys/arm/arm/cpufunc.c */ -void pmap_pte_init_mmu_v6(void); void vector_page_setprot(int); /* diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 8271cb03cc6b..009c61faf3a9 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -624,9 +624,6 @@ void pmap_copy_page_generic(vm_paddr_t, vm_paddr_t); void pmap_zero_page_generic(vm_paddr_t, int, int); void pmap_pte_init_generic(void); -#if (ARM_MMU_V6 + ARM_MMU_V7) != 0 -void pmap_pte_init_mmu_v6(void); -#endif /* (ARM_MMU_V6 + ARM_MMU_V7) != 0 */ #endif /* (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 */ #if ARM_MMU_XSCALE == 1 From 06c93e5cef7669f0580e7cd320df054124e95f35 Mon Sep 17 00:00:00 2001 From: zbb Date: Fri, 29 Jan 2016 18:43:51 +0000 Subject: [PATCH 040/236] Fix sending IPI to all CPUs on ARM64 There is no explanation why IPI ID is incremented here by "16". This should have been removed in r285533 but somehow survived. Reviewed by: wma Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5120 --- sys/arm64/arm64/intr_machdep.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/arm64/arm64/intr_machdep.c b/sys/arm64/arm64/intr_machdep.c index e297ff9f2279..3389c69da942 100644 --- a/sys/arm64/arm64/intr_machdep.c +++ b/sys/arm64/arm64/intr_machdep.c @@ -472,9 +472,6 @@ ipi_all_but_self(u_int ipi) other_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &other_cpus); - /* ARM64TODO: This will be fixed with arm_intrng */ - ipi += 16; - CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); PIC_IPI_SEND(root_pic, other_cpus, ipi); } From 4b996ada0978f0856e1d0e6d48c469fdee887f58 Mon Sep 17 00:00:00 2001 From: smh Date: Fri, 29 Jan 2016 21:06:59 +0000 Subject: [PATCH 041/236] Fix phy interrupts setup for ixl Fix the inverted set of interrupts being used as the mask for ixl. Without this ixl devices fail to detect link state changes. Reviewed by: erj, sbruno MFC after: 2 days Sponsored by: Multiplay --- sys/dev/ixl/if_ixl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index 505d4b4cbb12..d5ab42fb6025 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -674,9 +674,9 @@ ixl_attach(device_t dev) } /* Limit phy interrupts to link and modules failure */ - error = i40e_aq_set_phy_int_mask(hw, - I40E_AQ_EVENT_LINK_UPDOWN | I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL); - if (error) + error = i40e_aq_set_phy_int_mask(hw, ~(I40E_AQ_EVENT_LINK_UPDOWN | + I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL); + if (error) device_printf(dev, "set phy mask failed: %d\n", error); /* Get the bus configuration and set the shared code */ From 377cdb0ab1f7d246659c637faafe7c54af0665e5 Mon Sep 17 00:00:00 2001 From: jhb Date: Sat, 30 Jan 2016 01:00:54 +0000 Subject: [PATCH 042/236] Add a SYSDECODE_ABI_ prefix to the ABI enums to avoid potential collisions. Suggested by: jmallett Reviewed by: bdrewery, jmallett Differential Revision: https://reviews.freebsd.org/D5123 --- lib/libsysdecode/syscallnames.c | 10 +++++----- lib/libsysdecode/sysdecode.3 | 16 ++++++++-------- lib/libsysdecode/sysdecode.h | 12 ++++++------ usr.bin/kdump/kdump.c | 10 +++++----- usr.bin/truss/aarch64-cloudabi64.c | 2 +- usr.bin/truss/aarch64-freebsd.c | 2 +- usr.bin/truss/amd64-cloudabi64.c | 2 +- usr.bin/truss/amd64-freebsd.c | 2 +- usr.bin/truss/amd64-freebsd32.c | 4 ++-- usr.bin/truss/amd64-linux32.c | 2 +- usr.bin/truss/arm-freebsd.c | 2 +- usr.bin/truss/i386-freebsd.c | 4 ++-- usr.bin/truss/i386-linux.c | 2 +- usr.bin/truss/mips-freebsd.c | 2 +- usr.bin/truss/powerpc-freebsd.c | 2 +- usr.bin/truss/powerpc64-freebsd.c | 2 +- usr.bin/truss/powerpc64-freebsd32.c | 2 +- usr.bin/truss/sparc64-freebsd.c | 2 +- 18 files changed, 40 insertions(+), 40 deletions(-) diff --git a/lib/libsysdecode/syscallnames.c b/lib/libsysdecode/syscallnames.c index cfe50a6a6ea9..4ec2cd76ac73 100644 --- a/lib/libsysdecode/syscallnames.c +++ b/lib/libsysdecode/syscallnames.c @@ -70,30 +70,30 @@ sysdecode_syscallname(enum sysdecode_abi abi, unsigned int code) { switch (abi) { - case FREEBSD: + case SYSDECODE_ABI_FREEBSD: if (code < nitems(syscallnames)) return (syscallnames[code]); break; #if defined(__amd64__) || defined(__powerpc64__) - case FREEBSD32: + case SYSDECODE_ABI_FREEBSD32: if (code < nitems(freebsd32_syscallnames)) return (freebsd32_syscallnames[code]); break; #endif #if defined(__amd64__) || defined(__i386__) - case LINUX: + case SYSDECODE_ABI_LINUX: if (code < nitems(linux_syscallnames)) return (linux_syscallnames[code]); break; #endif #ifdef __amd64__ - case LINUX32: + case SYSDECODE_ABI_LINUX32: if (code < nitems(linux32_syscallnames)) return (linux32_syscallnames[code]); break; #endif #if defined(__amd64__) || defined(__aarch64__) - case CLOUDABI64: + case SYSDECODE_ABI_CLOUDABI64: if (code < nitems(cloudabi64_syscallnames)) return (cloudabi64_syscallnames[code]); break; diff --git a/lib/libsysdecode/sysdecode.3 b/lib/libsysdecode/sysdecode.3 index 994d278fe001..f058f59c60cf 100644 --- a/lib/libsysdecode/sysdecode.3 +++ b/lib/libsysdecode/sysdecode.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 24, 2016 +.Dd January 29, 2016 .Dt SYSDECODE 3 .Os .Sh NAME @@ -44,23 +44,23 @@ The supported ABIs are named by the .Vt enum sysdecode_abi enumeration. .Pp -.Bl -tag -width "Li UNKNOWN_ABI" -compact -.It Li FREEBSD +.Bl -tag -width "Li SYSDECODE_ABI_CLOUDABI64" -compact +.It Li SYSDECODE_ABI_FREEBSD Native FreeBSD binaries. Supported on all platforms. -.It Li FREEBSD32 +.It Li SYSDECODE_ABI_FREEBSD32 32-bit FreeBSD binaries. Supported on amd64 and powerpc64. -.It Li LINUX +.It Li SYSDECODE_ABI_LINUX Linux binaries of the same platform. Supported on amd64 and i386. -.It Li LINUX32 +.It Li SYSDECODE_ABI_LINUX32 32-bit Linux binaries. Supported on amd64. -.It Li CLOUDABI64 +.It Li SYSDECODE_ABI_CLOUDABI64 64-bit CloudABI binaries. Supported on aarch64 and amd64. -.It Li UNKNOWN_ABI +.It Li SYSDECODE_ABI_UNKNOWN A placeholder for use when the ABI is not known. .El .Sh SEE ALSO diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h index c2c3a9e801e5..fa00716826db 100644 --- a/lib/libsysdecode/sysdecode.h +++ b/lib/libsysdecode/sysdecode.h @@ -30,12 +30,12 @@ #define __SYSDECODE_H__ enum sysdecode_abi { - UNKNOWN_ABI = 0, - FREEBSD, - FREEBSD32, - LINUX, - LINUX32, - CLOUDABI64 + SYSDECODE_ABI_UNKNOWN = 0, + SYSDECODE_ABI_FREEBSD, + SYSDECODE_ABI_FREEBSD32, + SYSDECODE_ABI_LINUX, + SYSDECODE_ABI_LINUX32, + SYSDECODE_ABI_CLOUDABI64 }; const char *sysdecode_ioctlname(unsigned long _val); diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index d4406545fc4d..8fe03ea27766 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -690,20 +690,20 @@ syscallabi(u_int sv_flags) { if (sv_flags == 0) - return (FREEBSD); + return (SYSDECODE_ABI_FREEBSD); switch (sv_flags & SV_ABI_MASK) { case SV_ABI_FREEBSD: - return (FREEBSD); + return (SYSDECODE_ABI_FREEBSD); #if defined(__amd64__) || defined(__i386__) case SV_ABI_LINUX: #ifdef __amd64__ if (sv_flags & SV_ILP32) - return (LINUX32); + return (SYSDECODE_ABI_LINUX32); #endif - return (LINUX); + return (SYSDECODE_ABI_LINUX); #endif default: - return (UNKNOWN_ABI); + return (SYSDECODE_ABI_UNKNOWN); } } diff --git a/usr.bin/truss/aarch64-cloudabi64.c b/usr.bin/truss/aarch64-cloudabi64.c index 099cb1e7d746..f2891afe02a8 100644 --- a/usr.bin/truss/aarch64-cloudabi64.c +++ b/usr.bin/truss/aarch64-cloudabi64.c @@ -81,7 +81,7 @@ aarch64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval, static struct procabi aarch64_cloudabi64 = { "CloudABI ELF64", - CLOUDABI64, + SYSDECODE_ABI_CLOUDABI64, aarch64_cloudabi64_fetch_args, aarch64_cloudabi64_fetch_retval }; diff --git a/usr.bin/truss/aarch64-freebsd.c b/usr.bin/truss/aarch64-freebsd.c index 454bba7d77ca..534441c60b8c 100644 --- a/usr.bin/truss/aarch64-freebsd.c +++ b/usr.bin/truss/aarch64-freebsd.c @@ -99,7 +99,7 @@ aarch64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi aarch64_freebsd = { "FreeBSD ELF64", - FREEBSD, + SYSDECODE_ABI_FREEBSD, aarch64_fetch_args, aarch64_fetch_retval }; diff --git a/usr.bin/truss/amd64-cloudabi64.c b/usr.bin/truss/amd64-cloudabi64.c index 38768ff0074d..ce8b18918fd8 100644 --- a/usr.bin/truss/amd64-cloudabi64.c +++ b/usr.bin/truss/amd64-cloudabi64.c @@ -90,7 +90,7 @@ amd64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval, static struct procabi amd64_cloudabi64 = { "CloudABI ELF64", - CLOUDABI64, + SYSDECODE_ABI_CLOUDABI64, amd64_cloudabi64_fetch_args, amd64_cloudabi64_fetch_retval }; diff --git a/usr.bin/truss/amd64-freebsd.c b/usr.bin/truss/amd64-freebsd.c index 8a211a0ce474..a2f378ca8ea5 100644 --- a/usr.bin/truss/amd64-freebsd.c +++ b/usr.bin/truss/amd64-freebsd.c @@ -121,7 +121,7 @@ amd64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi amd64_freebsd = { "FreeBSD ELF64", - FREEBSD, + SYSDECODE_ABI_FREEBSD, amd64_fetch_args, amd64_fetch_retval }; diff --git a/usr.bin/truss/amd64-freebsd32.c b/usr.bin/truss/amd64-freebsd32.c index adce798b7c5c..cfcead2a6014 100644 --- a/usr.bin/truss/amd64-freebsd32.c +++ b/usr.bin/truss/amd64-freebsd32.c @@ -117,7 +117,7 @@ amd64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval, static struct procabi amd64_freebsd32 = { "FreeBSD ELF32", - FREEBSD32, + SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, amd64_freebsd32_fetch_retval }; @@ -126,7 +126,7 @@ PROCABI(amd64_freebsd32); static struct procabi amd64_freebsd32_aout = { "FreeBSD a.out", - FREEBSD32, + SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, amd64_freebsd32_fetch_retval }; diff --git a/usr.bin/truss/amd64-linux32.c b/usr.bin/truss/amd64-linux32.c index dd1d83361095..2ede61757b03 100644 --- a/usr.bin/truss/amd64-linux32.c +++ b/usr.bin/truss/amd64-linux32.c @@ -131,7 +131,7 @@ amd64_linux32_fetch_retval(struct trussinfo *trussinfo, long *retval, static struct procabi amd64_linux32 = { "Linux ELF32", - LINUX32, + SYSDECODE_ABI_LINUX32, amd64_linux32_fetch_args, amd64_linux32_fetch_retval }; diff --git a/usr.bin/truss/arm-freebsd.c b/usr.bin/truss/arm-freebsd.c index 5722c91442fb..a1b2b21313ba 100644 --- a/usr.bin/truss/arm-freebsd.c +++ b/usr.bin/truss/arm-freebsd.c @@ -128,7 +128,7 @@ arm_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi arm_freebsd = { "FreeBSD ELF32", - FREEBSD, + SYSDECODE_ABI_FREEBSD, arm_fetch_args, arm_fetch_retval }; diff --git a/usr.bin/truss/i386-freebsd.c b/usr.bin/truss/i386-freebsd.c index c166596dcb11..bf35af2f015b 100644 --- a/usr.bin/truss/i386-freebsd.c +++ b/usr.bin/truss/i386-freebsd.c @@ -110,7 +110,7 @@ i386_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi i386_freebsd = { "FreeBSD ELF32", - FREEBSD, + SYSDECODE_ABI_FREEBSD, i386_fetch_args, i386_fetch_retval }; @@ -119,7 +119,7 @@ PROCABI(i386_freebsd); static struct procabi i386_freebsd_aout = { "FreeBSD a.out", - FREEBSD, + SYSDECODE_ABI_FREEBSD, i386_fetch_args, i386_fetch_retval }; diff --git a/usr.bin/truss/i386-linux.c b/usr.bin/truss/i386-linux.c index 5fdae8ee958c..fbc54a096d4f 100644 --- a/usr.bin/truss/i386-linux.c +++ b/usr.bin/truss/i386-linux.c @@ -130,7 +130,7 @@ i386_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi i386_linux = { "Linux ELF32", - LINUX, + SYSDECODE_ABI_LINUX, i386_linux_fetch_args, i386_linux_fetch_retval }; diff --git a/usr.bin/truss/mips-freebsd.c b/usr.bin/truss/mips-freebsd.c index f4b5a7eb2aa0..3a42a59d7323 100644 --- a/usr.bin/truss/mips-freebsd.c +++ b/usr.bin/truss/mips-freebsd.c @@ -131,7 +131,7 @@ static struct procabi mips_freebsd = { #else "FreeBSD ELF32", #endif - FREEBSD, + SYSDECODE_ABI_FREEBSD, mips_fetch_args, mips_fetch_retval }; diff --git a/usr.bin/truss/powerpc-freebsd.c b/usr.bin/truss/powerpc-freebsd.c index 6a245df76c6a..ee78d038297a 100644 --- a/usr.bin/truss/powerpc-freebsd.c +++ b/usr.bin/truss/powerpc-freebsd.c @@ -112,7 +112,7 @@ powerpc_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi powerpc_freebsd = { "FreeBSD ELF32", - FREEBSD, + SYSDECODE_ABI_FREEBSD, powerpc_fetch_args, powerpc_fetch_retval }; diff --git a/usr.bin/truss/powerpc64-freebsd.c b/usr.bin/truss/powerpc64-freebsd.c index 68a0b5d36abe..cc64cd685e7e 100644 --- a/usr.bin/truss/powerpc64-freebsd.c +++ b/usr.bin/truss/powerpc64-freebsd.c @@ -108,7 +108,7 @@ powerpc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi powerpc64_freebsd = { "FreeBSD ELF64", - FREEBSD, + SYSDECODE_ABI_FREEBSD, powerpc64_fetch_args, powerpc64_fetch_retval }; diff --git a/usr.bin/truss/powerpc64-freebsd32.c b/usr.bin/truss/powerpc64-freebsd32.c index ee37ead3cc11..c6f3b10a7092 100644 --- a/usr.bin/truss/powerpc64-freebsd32.c +++ b/usr.bin/truss/powerpc64-freebsd32.c @@ -117,7 +117,7 @@ powerpc64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval, int static struct procabi powerpc64_freebsd32 = { "FreeBSD ELF32", - FREEBSD32, + SYSDECODE_ABI_FREEBSD32, powerpc64_freebsd32_fetch_args, powerpc64_freebsd32_fetch_retval }; diff --git a/usr.bin/truss/sparc64-freebsd.c b/usr.bin/truss/sparc64-freebsd.c index 23486d76baa4..a8569c010e06 100644 --- a/usr.bin/truss/sparc64-freebsd.c +++ b/usr.bin/truss/sparc64-freebsd.c @@ -115,7 +115,7 @@ sparc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) static struct procabi sparc64_freebsd = { "FreeBSD ELF64", - FREEBSD, + SYSDECODE_ABI_FREEBSD, sparc64_fetch_args, sparc64_fetch_retval }; From 77dfb0cf06204509dfe14b013c6bf4705630de54 Mon Sep 17 00:00:00 2001 From: sobomax Date: Sat, 30 Jan 2016 04:16:05 +0000 Subject: [PATCH 043/236] This seems like a very trivial bug that should have been squashed a long time ago, but for some reason it was not. Basically, without this change dlopen(3)'ing an empty .so file would just cause application to dump core with SIGSEGV. Make sure the file has enough data for at least the ELF header before mmap'ing it. Add a test case to check that dlopen an empty file return an error. There were a separate discussion as to whether it should be SIGBUS instead when you try to access region mapped from an empty file, but it's definitely SIGSEGV now, so if anyone want to check that please be my guest. Reviewed by: mjg, cem MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D5112 --- lib/libc/tests/gen/Makefile | 1 + lib/libc/tests/gen/dlopen_empty_test.c | 97 ++++++++++++++++++++++++++ libexec/rtld-elf/map_object.c | 12 +++- 3 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 lib/libc/tests/gen/dlopen_empty_test.c diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index b700312d8128..083097730cc0 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -11,6 +11,7 @@ ATF_TESTS_C+= ftw_test ATF_TESTS_C+= popen_test ATF_TESTS_C+= posix_spawn_test ATF_TESTS_C+= wordexp_test +ATF_TESTS_C+= dlopen_empty_test # TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep # TODO: t_siginfo (fixes require further inspection) diff --git a/lib/libc/tests/gen/dlopen_empty_test.c b/lib/libc/tests/gen/dlopen_empty_test.c new file mode 100644 index 000000000000..42f9269a10b2 --- /dev/null +++ b/lib/libc/tests/gen/dlopen_empty_test.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2016 Maksym Sobolyev + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static const char *funname; +static char *soname; + +static void +sigsegv_handler(int sig __unused) +{ + unlink(soname); + free(soname); + atf_tc_fail("got SIGSEGV in the %s(3)", funname); +} + +ATF_TC(dlopen_empty_test); +ATF_TC_HEAD(dlopen_empty_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the dlopen() of an empty file " + "returns an error"); +} +ATF_TC_BODY(dlopen_empty_test, tc) +{ + char tempname[] = "/tmp/temp.XXXXXX"; + char *fname; + int fd; + void *dlh; + struct sigaction act, oact; + + fname = mktemp(tempname); + ATF_REQUIRE_MSG(fname != NULL, "mktemp failed; errno=%d", errno); + asprintf(&soname, "%s.so", fname); + ATF_REQUIRE_MSG(soname != NULL, "asprintf failed; errno=%d", ENOMEM); + fd = open(soname, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE); + ATF_REQUIRE_MSG(fd != -1, "open(\"%s\") failed; errno=%d", soname, errno); + close(fd); + + act.sa_handler = sigsegv_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + ATF_CHECK_MSG(sigaction(SIGSEGV, &act, &oact) != -1, + "sigaction() failed"); + + funname = "dlopen"; + dlh = dlopen(soname, RTLD_LAZY); + if (dlh != NULL) { + funname = "dlclose"; + dlclose(dlh); + } + ATF_REQUIRE_MSG(dlh == NULL, "dlopen(\"%s\") did not fail", soname); + unlink(soname); + free(soname); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, dlopen_empty_test); + + return (atf_no_error()); +} diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index 6012015bcc28..f4f6f4221816 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -38,7 +38,7 @@ #include "debug.h" #include "rtld.h" -static Elf_Ehdr *get_elf_header(int, const char *); +static Elf_Ehdr *get_elf_header(int, const char *, const struct stat *); static int convert_prot(int); /* Elf flags -> mmap protection */ static int convert_flags(int); /* Elf flags -> mmap flags */ @@ -91,7 +91,7 @@ map_object(int fd, const char *path, const struct stat *sb) char *note_map; size_t note_map_len; - hdr = get_elf_header(fd, path); + hdr = get_elf_header(fd, path, sb); if (hdr == NULL) return (NULL); @@ -324,10 +324,16 @@ map_object(int fd, const char *path, const struct stat *sb) } static Elf_Ehdr * -get_elf_header(int fd, const char *path) +get_elf_header(int fd, const char *path, const struct stat *sbp) { Elf_Ehdr *hdr; + /* Make sure file has enough data for the ELF header */ + if (sbp != NULL && sbp->st_size < sizeof(Elf_Ehdr)) { + _rtld_error("%s: invalid file format", path); + return (NULL); + } + hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ, fd, 0); if (hdr == (Elf_Ehdr *)MAP_FAILED) { From 42f646d3a4d16eff32f3e5aed31e22dacdf62d37 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Jan 2016 06:18:37 +0000 Subject: [PATCH 044/236] Implement power command to list all power modes, find out the power mode we're in and to set the power mode. --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/nvmecontrol.8 | 17 +++ sbin/nvmecontrol/nvmecontrol.c | 1 + sbin/nvmecontrol/nvmecontrol.h | 4 + sbin/nvmecontrol/power.c | 185 +++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 sbin/nvmecontrol/power.c diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index ea60da3c2941..e8a23719a2a7 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -2,7 +2,7 @@ PROG= nvmecontrol SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \ - perftest.c reset.c nvme_util.c + perftest.c reset.c nvme_util.c power.c MAN= nvmecontrol.8 .PATH: ${.CURDIR}/../../sys/dev/nvme diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index 3b4b5c23aef3..ae8132ec5cbc 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -70,6 +70,11 @@ .Op Fl f Ar path_to_firmware .Op Fl a .Aq device id +.Nm +.Ic power +.Op Fl l +.Op Fl p power_state +.Op fl w workload_hint .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. @@ -120,6 +125,18 @@ Activate the firmware in slot 4 of the nvme0 controller on the next reset. .Pp Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the nvme0 controller and activate it on the next reset. +.Pp +.Dl nvmecontrol power -l nvme0 +.Pp +List all the current power modes. +.Pp +.Dl nvmecontrol power -p 3 nvme0 +.Pp +Set the current power mode. +.Pp +.Dl nvmecontrol power nvme0 +.Pp +Get the current power mode. .Sh AUTHORS .An -nosplit .Nm diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 4dee1909280a..cd7c19d0165d 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -58,6 +58,7 @@ static struct nvme_function { {"reset", reset, RESET_USAGE}, {"logpage", logpage, LOGPAGE_USAGE}, {"firmware", firmware, FIRMWARE_USAGE}, + {"power", power, POWER_USAGE}, {NULL, NULL, NULL}, }; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 8401dd7ccda3..b3cecd26dcea 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -55,12 +55,16 @@ #define FIRMWARE_USAGE \ " nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" +#define POWER_USAGE \ +" nvmecontrol power [-l] [-p new-state [-w workload-hint]] \n" + void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); void logpage(int argc, char *argv[]); void firmware(int argc, char *argv[]); +void power(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid); diff --git a/sbin/nvmecontrol/power.c b/sbin/nvmecontrol/power.c new file mode 100644 index 000000000000..e681ccd14dcc --- /dev/null +++ b/sbin/nvmecontrol/power.c @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2016 Netflix, 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 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +_Static_assert(sizeof(struct nvme_power_state) == 256 / NBBY, + "nvme_power_state size wrong"); + +static void +power_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, POWER_USAGE); + exit(1); +} + +static void +power_list_one(int i, struct nvme_power_state *nps) +{ + int mpower, apower, ipower; + + mpower = nps->mp; + if (nps->mps == 0) + mpower *= 100; + ipower = nps->idlp; + if (nps->ips == 1) + ipower *= 100; + apower = nps->actp; + if (nps->aps == 1) + apower *= 100; + printf("%2d: %2d.%04dW%c %3d.%03dms %3d.%03dms %2d %2d %2d %2d %2d.%04dW %2d.%04dW %d\n", + i, mpower / 10000, mpower % 10000, + nps->nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000, + nps->exlat / 1000, nps->exlat % 1000, nps->rrt, nps->rrl, + nps->rwt, nps->rwl, ipower / 10000, ipower % 10000, + apower / 10000, apower % 10000, nps->apw); +} + +static void +power_list(struct nvme_controller_data *cdata) +{ + int i; + + printf("\nPower States Supported: %d\n\n", cdata->npss + 1); + printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workloadd\n"); + printf("-- -------- --------- --------- -- -- -- -- -------- -------- --\n"); + for (i = 0; i <= cdata->npss; i++) + power_list_one(i, &cdata->power_state[i]); +} + +static void +power_set(int fd, int power, int workload, int perm) +{ + struct nvme_pt_command pt; + uint32_t p; + + p = perm ? (1u << 31) : 0; + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_SET_FEATURES; + pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT | p; + pt.cmd.cdw11 = power | (workload << 5); + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "set feature power mgmt request failed"); + + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "set feature power mgmt request returned error"); +} + +static void +power_show(int fd) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_GET_FEATURES; + pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "set feature power mgmt request failed"); + + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "set feature power mgmt request returned error"); + + printf("Current Power Mode is %d\n", pt.cpl.cdw0); +} + +void +power(int argc, char *argv[]) +{ + struct nvme_controller_data cdata; + int ch, listflag = 0, powerflag = 0, power = 0, fd; + int workload = 0; + char *end; + + while ((ch = getopt(argc, argv, "lp:w:")) != -1) { + switch ((char)ch) { + case 'l': + listflag = 1; + break; + case 'p': + powerflag = 1; + power = strtol(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "Invalid power state number: %s\n", optarg); + power_usage(); + } + break; + case 'w': + workload = strtol(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "Invalid workload hint: %s\n", optarg); + power_usage(); + } + break; + default: + power_usage(); + } + } + + /* Check that a controller was specified. */ + if (optind >= argc) + power_usage(); + + if (listflag && powerflag) { + fprintf(stderr, "Can't set power and list power states\n"); + power_usage(); + } + + open_dev(argv[optind], &fd, 1, 1); + read_controller_data(fd, &cdata); + + if (listflag) { + power_list(&cdata); + goto out; + } + + if (powerflag) { + power_set(fd, power, workload, 0); + goto out; + } + power_show(fd); + +out: + close(fd); + exit(0); +} From e10582eae6cf874d7138e815d880983b2d24c16f Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Jan 2016 07:00:28 +0000 Subject: [PATCH 045/236] Two new config files. One that has UEFI booting, and the other that can do both UEFI and BIOS/GPT booting. Support for nanobsd coming soon. Based in part in a patch from: andrew@ --- .../nanobsd/embedded/qemu-amd64-uefi-bios.cfg | 43 +++++++++++++++++++ .../nanobsd/embedded/qemu-amd64-uefi.cfg | 43 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg create mode 100644 tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg diff --git a/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg b/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg new file mode 100644 index 000000000000..7f4f4276bb90 --- /dev/null +++ b/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg @@ -0,0 +1,43 @@ +# $FreeBSD$ + +#- +# Copyright (c) 2015 Warner Losh. All Rights Reserved. +# Copyright (c) 2010-2011 iXsystems, 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 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 iXsystems, Inc. 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. +# + +NANO_ARCH=amd64 +NANO_NAME=qemu-amd64-uefi-bios +NANO_LAYOUT=std-uefi-bios + +. common # Pull in common definitions + +qemu_env + +# +# Run with +# qemu-system-x86_64 -serial stdio -bios OVMF.fd \ +# -hda _.disk.image.qemu-amd64-uefi.qcow2 +# OVMF.fd is from +# http://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip +# diff --git a/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg b/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg new file mode 100644 index 000000000000..a88e459a50c0 --- /dev/null +++ b/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg @@ -0,0 +1,43 @@ +# $FreeBSD$ + +#- +# Copyright (c) 2015 Warner Losh. All Rights Reserved. +# Copyright (c) 2010-2011 iXsystems, 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 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 iXsystems, Inc. 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. +# + +NANO_ARCH=amd64 +NANO_NAME=qemu-amd64-uefi +NANO_LAYOUT=std-uefi + +. common # Pull in common definitions + +qemu_env + +# +# Run with +# qemu-system-x86_64 -serial stdio -bios OVMF.fd \ +# -hda _.disk.image.qemu-amd64-uefi.qcow2 +# OVMF.fd is from +# http://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip +# From d9339d6f6dceda57f6d1de94a94fc54ea1ead268 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Jan 2016 07:00:29 +0000 Subject: [PATCH 046/236] Two new variables: NANO_ROOT and NANO_ALTROOT. These used to be spelled ${NANO_SLICE_ROOT}a and ${NANO_SLICE_ALTROOT}a respectively, and that's the default value. This will allow nanobsd on systems without a bsd label. That's rarely needed these days, even in an MBR world. The default will shift to this in the future, but remain an option. --- tools/tools/nanobsd/defaults.sh | 12 +++++++----- tools/tools/nanobsd/embedded/common | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh index 8084bfaf0fcb..a0e6be580b9b 100755 --- a/tools/tools/nanobsd/defaults.sh +++ b/tools/tools/nanobsd/defaults.sh @@ -156,6 +156,8 @@ NANO_SLICE_ROOT=s1 NANO_SLICE_ALTROOT=s2 NANO_SLICE_CFG=s3 NANO_SLICE_DATA=s4 +NANO_ROOT=s1a +NANO_ALTROOT=s2a # Default ownwership for nopriv build NANO_DEF_UNAME=root @@ -569,7 +571,7 @@ setup_nanobsd_etc ( ) ( # save config file for scripts echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf - echo "/dev/${NANO_DRIVE}${NANO_SLICE_ROOT}a / ufs ro 1 1" > etc/fstab + echo "/dev/${NANO_DRIVE}${NANO_ROOT} / ufs ro 1 1" > etc/fstab echo "/dev/${NANO_DRIVE}${NANO_SLICE_CFG} /cfg ufs rw,noauto 2 2" >> etc/fstab mkdir -p cfg ) @@ -731,8 +733,8 @@ create_diskimage ( ) ( bsdlabel ${MD}${NANO_SLICE_ROOT} # Create first image - populate_slice /dev/${MD}${NANO_SLICE_ROOT}a ${NANO_WORLDDIR} ${MNT} "${NANO_SLICE_ROOT}a" - mount /dev/${MD}${NANO_SLICE_ROOT}a ${MNT} + populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" + mount /dev/${MD}${NANO_ROOT} ${MNT} echo "Generating mtree..." ( cd "${MNT}" && mtree -c ) > ${NANO_OBJ}/_.mtree ( cd "${MNT}" && du -k ) > ${NANO_OBJ}/_.du @@ -742,7 +744,7 @@ create_diskimage ( ) ( # Duplicate to second image (if present) echo "Duplicating to second image..." dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k - mount /dev/${MD}${NANO_SLICE_ALTROOT}a ${MNT} + mount /dev/${MD}${NANO_ALTROOT} ${MNT} for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab do sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f @@ -751,7 +753,7 @@ create_diskimage ( ) ( # Override the label from the first partition so we # don't confuse glabel with duplicates. if [ -n "${NANO_LABEL}" ]; then - tunefs -L ${NANO_LABEL}"${NANO_SLICE_ALTROOT}a" /dev/${MD}${NANO_SLICE_ALTROOT}a + tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT} fi fi diff --git a/tools/tools/nanobsd/embedded/common b/tools/tools/nanobsd/embedded/common index a1d401a03782..dbce253b5794 100644 --- a/tools/tools/nanobsd/embedded/common +++ b/tools/tools/nanobsd/embedded/common @@ -664,6 +664,11 @@ powerpc64-apple) ;; esac +# For this config, no BSD labels so NANO_ROOT and NANO_ALTROOT need to be +# adjusted +NANO_ROOT=${NANO_SLICE_ROOT} +NANO_ALTROOT=${NANO_SLICE_ALTROOT} + NANO_SLICE_DATA= # Not included # Each major disk scheme has its own routine. Generally From 3dd69c60f3f9848f495b05d1e972b1475783eb41 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Jan 2016 07:00:36 +0000 Subject: [PATCH 047/236] Preliminary EFI support. Based, in part, on patches from Andy Turner. Add support for being able to boot off both UEFI and BIOS firmware, ala the memstick trick. Add support for writing to GPT volumes. Move away from using bsd labels at all for these embedded stuff. Minor tweaks to README. --- tools/tools/nanobsd/embedded/README | 2 -- tools/tools/nanobsd/embedded/common | 56 +++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/tools/nanobsd/embedded/README b/tools/tools/nanobsd/embedded/README index e8b1c8c6506e..ebaba4c7c97a 100644 --- a/tools/tools/nanobsd/embedded/README +++ b/tools/tools/nanobsd/embedded/README @@ -10,8 +10,6 @@ and DHCPd. This is a work in progress. Generally, to build this you should cd tools/tools/nanobsd/embedded sudo sh ../nanobsd.sh -c foo.cfg -but do be careful if things are interrupted. There may still be -bugs lurking that cause your entire FreeBSD tree to disappear. Some features: diff --git a/tools/tools/nanobsd/embedded/common b/tools/tools/nanobsd/embedded/common index dbce253b5794..bbac16205304 100644 --- a/tools/tools/nanobsd/embedded/common +++ b/tools/tools/nanobsd/embedded/common @@ -76,6 +76,8 @@ fi NANO_SLICE_FAT_SIZE=32m NANO_SLICE_CFG_SIZE=32m +NANO_BOOT2CFG="-D -h -S115200 comconsole_port=0x3e8" + NANO_RAM_ETCSIZE=8192 NANO_RAM_TMPVARSIZE=8192 NANO_IMAGES=2 @@ -292,7 +294,7 @@ create_diskimage_mbr ( ) ( bootbsd=${NANO_BOOT_BSD:+-b ${NANO_BOOT_BSD}} skiparg=${NANO_MBR_FIRST_SKIP:+-S ${NANO_MBR_FIRST_SKIP}} - for i in s1 s2 s3 s4 empty; do + for i in s1 s2 s3 s4 p1 p2 p3 p4 p5 empty; do rm -fr ${NANO_OBJ}/_.${i}* done @@ -317,10 +319,10 @@ create_diskimage_mbr ( ) ( # bsd label [ -z ${NANO_NOPRIV_BUILD} ] || extra="-F ${NANO_METALOG}" sz=${NANO_SLICE_ROOT_SIZE:+-s ${NANO_SLICE_ROOT_SIZE}} - eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_OBJ}/_.${NANO_SLICE_ROOT}a" \ + eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_OBJ}/_.${NANO_SLICE_ROOT}" \ "${NANO_WORLDDIR}" - mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_OBJ}/_.${NANO_SLICE_ROOT}a \ - -o ${NANO_OBJ}/_.${NANO_SLICE_ROOT} +# mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_OBJ}/_.${NANO_SLICE_ROOT} \ +# -o ${NANO_OBJ}/_.${NANO_SLICE_ROOT} # Populate the /cfg partition, empty if none given if [ -z "${NANO_CFGDIR}" ]; then @@ -339,8 +341,18 @@ create_diskimage_mbr ( ) ( if [ -n "$NANO_SLICE_FAT" ]; then eval $NANO_SLICE_FAT=fat16b fi - eval $NANO_SLICE_CFG=freebsd - eval $NANO_SLICE_ROOT=freebsd + case ${NANO_SLICE_CFG} in + s*) + echo slice + eval $NANO_SLICE_CFG=freebsd + eval $NANO_SLICE_ROOT=freebsd + ;; + p*) + echo part + eval $NANO_SLICE_CFG=freebsd-ufs + eval $NANO_SLICE_ROOT=freebsd-ufs + ;; + esac # below depends on https://reviews.freebsd.org/D4403 not yet in the tree # but there's problems: it marks all partitions as active, so you have to # boot off parittion 3 or 2 by hand if you're playing around with this WIP @@ -358,6 +370,25 @@ create_diskimage_mbr ( ) ( -p ${s2}:=${NANO_OBJ}/_.s2 \ -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} ;; + std-uefi) + # s1 is boot, s2 is cfg, s3 is /, not sure how to make that + # boot (marked as active) with mkimg yet + mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \ + -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ + -p ${s2}:=${NANO_OBJ}/_.s2 \ + -p ${s3}:=${NANO_OBJ}/_.s3 \ + -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + ;; + std-uefi-bios) + # p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is / + # and p5 is alt-root (after resize) + mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \ + -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ + -p freebsd-boot:=${NAANO_WORLDDIR}/boot/gptboot \ + -p ${p3}:=${NANO_OBJ}/_.p3 \ + -p ${p4}:=${NANO_OBJ}/_.p4 \ + -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + ;; powerpc64-ibm) # A lie to make the boot loader work, it boots the first BSD partition # it finds, regardless of the active flag. @@ -658,6 +689,19 @@ powerpc64-apple) echo Not yet exit 1 ;; +std-uefi) + NANO_SLICE_UEFI=s1 + NANO_SLICE_CFG=s2 + NANO_SLICE_ROOT=s3 + NANO_SLICE_ALTROOT=s4 + ;; +std-uefi-bios) + NANO_SLICE_UEFI=p1 + NANO_SLICE_BOOT=p2 + NANO_SLICE_CFG=p3 + NANO_SLICE_ROOT=p4 + NANO_SLICE_ALTROOT=p5 + ;; *) echo Unknown Layout ${NANO_LAYOUT} exit 1 From bbdaec0dbdbe131584f37ac48279de6eaa673980 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 30 Jan 2016 08:02:12 +0000 Subject: [PATCH 048/236] ARM: Split swtch.S into common, ARMv4 and ARMv6 parts. Cleanup them. --- sys/arm/arm/swtch-v4.S | 381 ++++++++++++++++++++++ sys/arm/arm/swtch-v6.S | 484 ++++++++++++++++++++++++++++ sys/arm/arm/swtch.S | 700 ----------------------------------------- sys/conf/files.arm | 2 + 4 files changed, 867 insertions(+), 700 deletions(-) create mode 100644 sys/arm/arm/swtch-v4.S create mode 100644 sys/arm/arm/swtch-v6.S diff --git a/sys/arm/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S new file mode 100644 index 000000000000..19933e1345be --- /dev/null +++ b/sys/arm/arm/swtch-v4.S @@ -0,0 +1,381 @@ +/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */ + +/*- + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/*- + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * cpuswitch.S + * + * cpu switching functions + * + * Created : 15/10/94 + * + */ + +#include "assym.s" +#include "opt_sched.h" + +#include +#include +#include +#include +#include + +__FBSDID("$FreeBSD$"); + + +#define GET_PCPU(tmp, tmp2) \ + ldr tmp, .Lcurpcpu + +#ifdef VFP + .fpu vfp /* allow VFP instructions */ +#endif + +.Lcurpcpu: + .word _C_LABEL(__pcpu) + .word PCPU_SIZE +.Lblocked_lock: + .word _C_LABEL(blocked_lock) + + +#define DOMAIN_CLIENT 0x01 + +.Lcpufuncs: + .word _C_LABEL(cpufuncs) + +/* + * cpu_throw(oldtd, newtd) + * + * Remove current thread state, then select the next thread to run + * and load its state. + * r0 = oldtd + * r1 = newtd + */ +ENTRY(cpu_throw) + mov r5, r1 + + /* + * r0 = oldtd + * r5 = newtd + */ + +#ifdef VFP /* This thread is dying, disable */ + bl _C_LABEL(vfp_discard) /* VFP without preserving state. */ +#endif + + GET_PCPU(r7, r9) + ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */ + + /* Switch to lwp0 context */ + + ldr r9, .Lcpufuncs + mov lr, pc + ldr pc, [r9, #CF_IDCACHE_WBINV_ALL] + ldr r0, [r7, #(PCB_PL1VEC)] + ldr r1, [r7, #(PCB_DACR)] + /* + * r0 = Pointer to L1 slot for vector_page (or NULL) + * r1 = lwp0's DACR + * r5 = lwp0 + * r7 = lwp0's PCB + * r9 = cpufuncs + */ + + /* + * Ensure the vector table is accessible by fixing up lwp0's L1 + */ + cmp r0, #0 /* No need to fixup vector table? */ + ldrne r3, [r0] /* But if yes, fetch current value */ + ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */ + mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */ + cmpne r3, r2 /* Stuffing the same value? */ + strne r2, [r0] /* Store if not. */ + +#ifdef PMAP_INCLUDE_PTE_SYNC + /* + * Need to sync the cache to make sure that last store is + * visible to the MMU. + */ + movne r1, #4 + movne lr, pc + ldrne pc, [r9, #CF_DCACHE_WB_RANGE] +#endif /* PMAP_INCLUDE_PTE_SYNC */ + + /* + * Note: We don't do the same optimisation as cpu_switch() with + * respect to avoiding flushing the TLB if we're switching to + * the same L1 since this process' VM space may be about to go + * away, so we don't want *any* turds left in the TLB. + */ + + /* Switch the memory to the new process */ + ldr r0, [r7, #(PCB_PAGEDIR)] + mov lr, pc + ldr pc, [r9, #CF_CONTEXT_SWITCH] + + GET_PCPU(r6, r4) + /* Hook in a new pcb */ + str r7, [r6, #PC_CURPCB] + /* We have a new curthread now so make a note it */ + str r5, [r6, #PC_CURTHREAD] + + /* Set the new tp */ + ldr r6, [r5, #(TD_MD + MD_TP)] + ldr r4, =ARM_TP_ADDRESS + str r6, [r4] + ldr r6, [r5, #(TD_MD + MD_RAS_START)] + str r6, [r4, #4] /* ARM_RAS_START */ + ldr r6, [r5, #(TD_MD + MD_RAS_END)] + str r6, [r4, #8] /* ARM_RAS_END */ + + /* Restore all the saved registers and exit */ + add r3, r7, #PCB_R4 + ldmia r3, {r4-r12, sp, pc} +END(cpu_throw) + +/* + * cpu_switch(oldtd, newtd, lock) + * + * Save the current thread state, then select the next thread to run + * and load its state. + * r0 = oldtd + * r1 = newtd + * r2 = lock (new lock for old thread) + */ +ENTRY(cpu_switch) + /* Interrupts are disabled. */ + /* Save all the registers in the old thread's pcb. */ + ldr r3, [r0, #(TD_PCB)] + + /* Restore all the saved registers and exit */ + add r3, #(PCB_R4) + stmia r3, {r4-r12, sp, lr, pc} + + mov r6, r2 /* Save the mutex */ + + /* rem: r0 = old lwp */ + /* rem: interrupts are disabled */ + + /* Process is now on a processor. */ + /* We have a new curthread now so make a note it */ + GET_PCPU(r7, r2) + str r1, [r7, #PC_CURTHREAD] + + /* Hook in a new pcb */ + ldr r2, [r1, #TD_PCB] + str r2, [r7, #PC_CURPCB] + + /* Stage two : Save old context */ + + /* Get the user structure for the old thread. */ + ldr r2, [r0, #(TD_PCB)] + mov r4, r0 /* Save the old thread. */ + + /* Store the old tp; userland can change it on armv4. */ + ldr r3, =ARM_TP_ADDRESS + ldr r9, [r3] + str r9, [r0, #(TD_MD + MD_TP)] + ldr r9, [r3, #4] + str r9, [r0, #(TD_MD + MD_RAS_START)] + ldr r9, [r3, #8] + str r9, [r0, #(TD_MD + MD_RAS_END)] + + /* Set the new tp */ + ldr r9, [r1, #(TD_MD + MD_TP)] + str r9, [r3] + ldr r9, [r1, #(TD_MD + MD_RAS_START)] + str r9, [r3, #4] + ldr r9, [r1, #(TD_MD + MD_RAS_END)] + str r9, [r3, #8] + + /* Get the user structure for the new process in r9 */ + ldr r9, [r1, #(TD_PCB)] + + /* rem: r2 = old PCB */ + /* rem: r9 = new PCB */ + /* rem: interrupts are enabled */ + +#ifdef VFP + fmrx r0, fpexc /* If the VFP is enabled */ + tst r0, #(VFPEXC_EN) /* the current thread has */ + movne r1, #1 /* used it, so go save */ + addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */ + blne _C_LABEL(vfp_store) /* and disable the VFP. */ +#endif + + /* r0-r3 now free! */ + + /* Third phase : restore saved context */ + + /* rem: r2 = old PCB */ + /* rem: r9 = new PCB */ + + ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */ + mov r2, #DOMAIN_CLIENT + cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */ + beq .Lcs_context_switched /* Yup. Don't flush cache */ + mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */ + /* + * Get the new L1 table pointer into r11. If we're switching to + * an LWP with the same address space as the outgoing one, we can + * skip the cache purge and the TTB load. + * + * To avoid data dep stalls that would happen anyway, we try + * and get some useful work done in the mean time. + */ + mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */ + ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */ + + teq r10, r11 /* Same L1? */ + cmpeq r0, r5 /* Same DACR? */ + beq .Lcs_context_switched /* yes! */ + + /* + * Definately need to flush the cache. + */ + + ldr r1, .Lcpufuncs + mov lr, pc + ldr pc, [r1, #CF_IDCACHE_WBINV_ALL] + +.Lcs_cache_purge_skipped: + /* rem: r6 = lock */ + /* rem: r9 = new PCB */ + /* rem: r10 = old L1 */ + /* rem: r11 = new L1 */ + + mov r2, #0x00000000 + ldr r7, [r9, #(PCB_PL1VEC)] + + /* + * Ensure the vector table is accessible by fixing up the L1 + */ + cmp r7, #0 /* No need to fixup vector table? */ + ldrne r2, [r7] /* But if yes, fetch current value */ + ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */ + mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */ + cmpne r2, r0 /* Stuffing the same value? */ +#ifndef PMAP_INCLUDE_PTE_SYNC + strne r0, [r7] /* Nope, update it */ +#else + beq .Lcs_same_vector + str r0, [r7] /* Otherwise, update it */ + + /* + * Need to sync the cache to make sure that last store is + * visible to the MMU. + */ + ldr r2, .Lcpufuncs + mov r0, r7 + mov r1, #4 + mov lr, pc + ldr pc, [r2, #CF_DCACHE_WB_RANGE] + +.Lcs_same_vector: +#endif /* PMAP_INCLUDE_PTE_SYNC */ + + cmp r10, r11 /* Switching to the same L1? */ + ldr r10, .Lcpufuncs + beq .Lcs_same_l1 /* Yup. */ + /* + * Do a full context switch, including full TLB flush. + */ + mov r0, r11 + mov lr, pc + ldr pc, [r10, #CF_CONTEXT_SWITCH] + + b .Lcs_context_switched + + /* + * We're switching to a different process in the same L1. + * In this situation, we only need to flush the TLB for the + * vector_page mapping, and even then only if r7 is non-NULL. + */ +.Lcs_same_l1: + cmp r7, #0 + movne r0, #0 /* We *know* vector_page's VA is 0x0 */ + movne lr, pc + ldrne pc, [r10, #CF_TLB_FLUSHID_SE] + +.Lcs_context_switched: + + /* Release the old thread */ + str r6, [r4, #TD_LOCK] + + /* XXXSCW: Safe to re-enable FIQs here */ + + /* rem: r9 = new PCB */ + + /* Restore all the saved registers and exit */ + add r3, r9, #PCB_R4 + ldmia r3, {r4-r12, sp, pc} +END(cpu_switch) + + + diff --git a/sys/arm/arm/swtch-v6.S b/sys/arm/arm/swtch-v6.S new file mode 100644 index 000000000000..34788eb001a2 --- /dev/null +++ b/sys/arm/arm/swtch-v6.S @@ -0,0 +1,484 @@ +/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */ + +/*- + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/*- + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * cpuswitch.S + * + * cpu switching functions + * + * Created : 15/10/94 + * + */ + +#include "assym.s" +#include "opt_sched.h" + +#include +#include +#include +#include +#include + +__FBSDID("$FreeBSD$"); + +#if __ARM_ARCH >= 6 && defined(SMP) +#define GET_PCPU(tmp, tmp2) \ + mrc p15, 0, tmp, c0, c0, 5; \ + and tmp, tmp, #0xf; \ + ldr tmp2, .Lcurpcpu+4; \ + mul tmp, tmp, tmp2; \ + ldr tmp2, .Lcurpcpu; \ + add tmp, tmp, tmp2; +#else + +#define GET_PCPU(tmp, tmp2) \ + ldr tmp, .Lcurpcpu +#endif + +#ifdef VFP + .fpu vfp /* allow VFP instructions */ +#endif + +.Lcurpcpu: + .word _C_LABEL(__pcpu) + .word PCPU_SIZE +.Lblocked_lock: + .word _C_LABEL(blocked_lock) + + +#include + +ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */ + DSB + mcr CP15_TTBR0(r0) /* set the new TTB */ + ISB + mov r0, #(CPU_ASID_KERNEL) + mcr CP15_TLBIASID(r0) /* flush not global TLBs */ + /* + * Flush entire Branch Target Cache because of the branch predictor + * is not architecturally invisible. See ARM Architecture Reference + * Manual ARMv7-A and ARMv7-R edition, page B2-1264(65), Branch + * predictors and Requirements for branch predictor maintenance + * operations sections. + * + * QQQ: The predictor is virtually addressed and holds virtual target + * addresses. Therefore, if mapping is changed, the predictor cache + * must be flushed.The flush is part of entire i-cache invalidation + * what is always called when code mapping is changed. So herein, + * it's the only place where standalone predictor flush must be + * executed in kernel (except self modifying code case). + */ + mcr CP15_BPIALL /* and flush entire Branch Target Cache */ + DSB + mov pc, lr +END(cpu_context_switch) + +/* + * cpu_throw(oldtd, newtd) + * + * Remove current thread state, then select the next thread to run + * and load its state. + * r0 = oldtd + * r1 = newtd + */ +ENTRY(cpu_throw) + mov r10, r0 /* r10 = oldtd */ + mov r11, r1 /* r11 = newtd */ + +#ifdef VFP /* This thread is dying, disable */ + bl _C_LABEL(vfp_discard) /* VFP without preserving state. */ +#endif + GET_PCPU(r8, r9) /* r8 = current pcpu */ + ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */ + + cmp r10, #0 /* old thread? */ + beq 2f /* no, skip */ + + /* Remove this CPU from the active list. */ + ldr r5, [r8, #PC_CURPMAP] + mov r0, #(PM_ACTIVE) + add r5, r0 /* r5 = old pm_active */ + + /* Compute position and mask. */ +#if _NCPUWORDS > 1 + lsr r0, r4, #3 + bic r0, #3 + add r5, r0 /* r5 = position in old pm_active */ + mov r2, #1 + and r0, r4, #31 + lsl r2, r0 /* r2 = mask */ +#else + mov r2, #1 + lsl r2, r4 /* r2 = mask */ +#endif + /* Clear cpu from old active list. */ +#ifdef SMP +1: ldrex r0, [r5] + bic r0, r2 + strex r1, r0, [r5] + teq r1, #0 + bne 1b +#else + ldr r0, [r5] + bic r0, r2 + str r0, [r5] +#endif + +2: +#ifdef INVARIANTS + cmp r11, #0 /* new thread? */ + beq badsw1 /* no, panic */ +#endif + ldr r7, [r11, #(TD_PCB)] /* r7 = new PCB */ + + /* + * Registers at this point + * r4 = current cpu id + * r7 = new PCB + * r8 = current pcpu + * r11 = newtd + */ + + /* MMU switch to new thread. */ + ldr r0, [r7, #(PCB_PAGEDIR)] +#ifdef INVARIANTS + cmp r0, #0 /* new thread? */ + beq badsw4 /* no, panic */ +#endif + bl _C_LABEL(cpu_context_switch) + + /* + * Set new PMAP as current one. + * Insert cpu to new active list. + */ + + ldr r6, [r11, #(TD_PROC)] /* newtd->proc */ + ldr r6, [r6, #(P_VMSPACE)] /* newtd->proc->vmspace */ + add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */ + str r6, [r8, #PC_CURPMAP] /* store to curpmap */ + + mov r0, #PM_ACTIVE + add r6, r0 /* r6 = new pm_active */ + + /* compute position and mask */ +#if _NCPUWORDS > 1 + lsr r0, r4, #3 + bic r0, #3 + add r6, r0 /* r6 = position in new pm_active */ + mov r2, #1 + and r0, r4, #31 + lsl r2, r0 /* r2 = mask */ +#else + mov r2, #1 + lsl r2, r4 /* r2 = mask */ +#endif + /* Set cpu to new active list. */ +#ifdef SMP +1: ldrex r0, [r6] + orr r0, r2 + strex r1, r0, [r6] + teq r1, #0 + bne 1b +#else + ldr r0, [r6] + orr r0, r2 + str r0, [r6] +#endif + /* + * Registers at this point. + * r7 = new PCB + * r8 = current pcpu + * r11 = newtd + * They must match the ones in sw1 position !!! + */ + DMB + b sw1 /* share new thread init with cpu_switch() */ +END(cpu_throw) + +/* + * cpu_switch(oldtd, newtd, lock) + * + * Save the current thread state, then select the next thread to run + * and load its state. + * r0 = oldtd + * r1 = newtd + * r2 = lock (new lock for old thread) + */ +ENTRY(cpu_switch) + /* Interrupts are disabled. */ +#ifdef INVARIANTS + cmp r0, #0 /* old thread? */ + beq badsw2 /* no, panic */ +#endif + /* Save all the registers in the old thread's pcb. */ + ldr r3, [r0, #(TD_PCB)] + add r3, #(PCB_R4) + stmia r3, {r4-r12, sp, lr, pc} + +#ifdef INVARIANTS + cmp r1, #0 /* new thread? */ + beq badsw3 /* no, panic */ +#endif + /* + * Save arguments. Note that we can now use r0-r14 until + * it is time to restore them for the new thread. However, + * some registers are not safe over function call. + */ + mov r9, r2 /* r9 = lock */ + mov r10, r0 /* r10 = oldtd */ + mov r11, r1 /* r11 = newtd */ + + GET_PCPU(r8, r3) /* r8 = current PCPU */ + ldr r7, [r11, #(TD_PCB)] /* r7 = newtd->td_pcb */ + + + +#ifdef VFP + ldr r3, [r10, #(TD_PCB)] + fmrx r0, fpexc /* If the VFP is enabled */ + tst r0, #(VFPEXC_EN) /* the current thread has */ + movne r1, #1 /* used it, so go save */ + addne r0, r3, #(PCB_VFPSTATE) /* the state into the PCB */ + blne _C_LABEL(vfp_store) /* and disable the VFP. */ +#endif + + /* + * MMU switch. If we're switching to a thread with the same + * address space as the outgoing one, we can skip the MMU switch. + */ + mrc CP15_TTBR0(r1) /* r1 = old TTB */ + ldr r0, [r7, #(PCB_PAGEDIR)] /* r0 = new TTB */ + cmp r0, r1 /* Switching to the TTB? */ + beq sw0 /* same TTB, skip */ + +#ifdef INVARIANTS + cmp r0, #0 /* new thread? */ + beq badsw4 /* no, panic */ +#endif + + bl cpu_context_switch /* new TTB as argument */ + + /* + * Registers at this point + * r7 = new PCB + * r8 = current pcpu + * r9 = lock + * r10 = oldtd + * r11 = newtd + */ + + /* + * Set new PMAP as current one. + * Update active list on PMAPs. + */ + ldr r6, [r11, #TD_PROC] /* newtd->proc */ + ldr r6, [r6, #P_VMSPACE] /* newtd->proc->vmspace */ + add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */ + + ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */ + str r6, [r8, #PC_CURPMAP] /* and save new one */ + + mov r0, #PM_ACTIVE + add r5, r0 /* r5 = old pm_active */ + add r6, r0 /* r6 = new pm_active */ + + /* Compute position and mask. */ + ldr r4, [r8, #PC_CPUID] +#if _NCPUWORDS > 1 + lsr r0, r4, #3 + bic r0, #3 + add r5, r0 /* r5 = position in old pm_active */ + add r6, r0 /* r6 = position in new pm_active */ + mov r2, #1 + and r0, r4, #31 + lsl r2, r0 /* r2 = mask */ +#else + mov r2, #1 + lsl r2, r4 /* r2 = mask */ +#endif + /* Clear cpu from old active list. */ +#ifdef SMP +1: ldrex r0, [r5] + bic r0, r2 + strex r1, r0, [r5] + teq r1, #0 + bne 1b +#else + ldr r0, [r5] + bic r0, r2 + str r0, [r5] +#endif + /* Set cpu to new active list. */ +#ifdef SMP +1: ldrex r0, [r6] + orr r0, r2 + strex r1, r0, [r6] + teq r1, #0 + bne 1b +#else + ldr r0, [r6] + orr r0, r2 + str r0, [r6] +#endif + +sw0: + /* + * Registers at this point + * r7 = new PCB + * r8 = current pcpu + * r9 = lock + * r10 = oldtd + * r11 = newtd + */ + + /* Change the old thread lock. */ + add r5, r10, #TD_LOCK + DMB +1: ldrex r0, [r5] + strex r1, r9, [r5] + teq r1, #0 + bne 1b + DMB + +sw1: + clrex + /* + * Registers at this point + * r7 = new PCB + * r8 = current pcpu + * r11 = newtd + */ + +#if defined(SMP) && defined(SCHED_ULE) + /* + * 386 and amd64 do the blocked lock test only for SMP and SCHED_ULE + * QQQ: What does it mean in reality and why is it done? + */ + ldr r6, =blocked_lock +1: + ldr r3, [r11, #TD_LOCK] /* atomic write regular read */ + cmp r3, r6 + beq 1b +#endif + /* Set the new tls */ + ldr r0, [r11, #(TD_MD + MD_TP)] + mcr CP15_TPIDRURO(r0) /* write tls thread reg 2 */ + + /* We have a new curthread now so make a note it */ + str r11, [r8, #PC_CURTHREAD] + mcr CP15_TPIDRPRW(r11) + + /* store pcb in per cpu structure */ + str r7, [r8, #PC_CURPCB] + + /* + * Restore all saved registers and return. Note that some saved + * registers can be changed when either cpu_fork(), cpu_set_upcall(), + * cpu_set_fork_handler(), or makectx() was called. + */ + add r3, r7, #PCB_R4 + ldmia r3, {r4-r12, sp, pc} + +#ifdef INVARIANTS +badsw1: + ldr r0, =sw1_panic_str + bl _C_LABEL(panic) +1: nop + b 1b + +badsw2: + ldr r0, =sw2_panic_str + bl _C_LABEL(panic) +1: nop + b 1b + +badsw3: + ldr r0, =sw3_panic_str + bl _C_LABEL(panic) +1: nop + b 1b + +badsw4: + ldr r0, =sw4_panic_str + bl _C_LABEL(panic) +1: nop + b 1b + +sw1_panic_str: + .asciz "cpu_throw: no newthread supplied.\n" +sw2_panic_str: + .asciz "cpu_switch: no curthread supplied.\n" +sw3_panic_str: + .asciz "cpu_switch: no newthread supplied.\n" +sw4_panic_str: + .asciz "cpu_switch: new pagedir is NULL.\n" +#endif +END(cpu_switch) diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S index d7571ec37071..e70532a447e2 100644 --- a/sys/arm/arm/swtch.S +++ b/sys/arm/arm/swtch.S @@ -79,9 +79,7 @@ */ #include "assym.s" -#include "opt_sched.h" -#include #include #include #include @@ -89,708 +87,10 @@ __FBSDID("$FreeBSD$"); -#if __ARM_ARCH >= 6 && defined(SMP) -#define GET_PCPU(tmp, tmp2) \ - mrc p15, 0, tmp, c0, c0, 5; \ - and tmp, tmp, #0xf; \ - ldr tmp2, .Lcurpcpu+4; \ - mul tmp, tmp, tmp2; \ - ldr tmp2, .Lcurpcpu; \ - add tmp, tmp, tmp2; -#else - -#define GET_PCPU(tmp, tmp2) \ - ldr tmp, .Lcurpcpu -#endif - #ifdef VFP .fpu vfp /* allow VFP instructions */ #endif -.Lcurpcpu: - .word _C_LABEL(__pcpu) - .word PCPU_SIZE -.Lblocked_lock: - .word _C_LABEL(blocked_lock) - - -#if __ARM_ARCH < 6 - -#define DOMAIN_CLIENT 0x01 - -.Lcpufuncs: - .word _C_LABEL(cpufuncs) - -/* - * cpu_throw(oldtd, newtd) - * - * Remove current thread state, then select the next thread to run - * and load its state. - * r0 = oldtd - * r1 = newtd - */ -ENTRY(cpu_throw) - mov r5, r1 - - /* - * r0 = oldtd - * r5 = newtd - */ - -#ifdef VFP /* This thread is dying, disable */ - bl _C_LABEL(vfp_discard) /* VFP without preserving state. */ -#endif - - GET_PCPU(r7, r9) - ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */ - - /* Switch to lwp0 context */ - - ldr r9, .Lcpufuncs -#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT) - mov lr, pc - ldr pc, [r9, #CF_IDCACHE_WBINV_ALL] -#endif - ldr r0, [r7, #(PCB_PL1VEC)] - ldr r1, [r7, #(PCB_DACR)] - /* - * r0 = Pointer to L1 slot for vector_page (or NULL) - * r1 = lwp0's DACR - * r5 = lwp0 - * r7 = lwp0's PCB - * r9 = cpufuncs - */ - - /* - * Ensure the vector table is accessible by fixing up lwp0's L1 - */ - cmp r0, #0 /* No need to fixup vector table? */ - ldrne r3, [r0] /* But if yes, fetch current value */ - ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */ - mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */ - cmpne r3, r2 /* Stuffing the same value? */ - strne r2, [r0] /* Store if not. */ - -#ifdef PMAP_INCLUDE_PTE_SYNC - /* - * Need to sync the cache to make sure that last store is - * visible to the MMU. - */ - movne r1, #4 - movne lr, pc - ldrne pc, [r9, #CF_DCACHE_WB_RANGE] -#endif /* PMAP_INCLUDE_PTE_SYNC */ - - /* - * Note: We don't do the same optimisation as cpu_switch() with - * respect to avoiding flushing the TLB if we're switching to - * the same L1 since this process' VM space may be about to go - * away, so we don't want *any* turds left in the TLB. - */ - - /* Switch the memory to the new process */ - ldr r0, [r7, #(PCB_PAGEDIR)] - mov lr, pc - ldr pc, [r9, #CF_CONTEXT_SWITCH] - - GET_PCPU(r6, r4) - /* Hook in a new pcb */ - str r7, [r6, #PC_CURPCB] - /* We have a new curthread now so make a note it */ - str r5, [r6, #PC_CURTHREAD] -#if __ARM_ARCH >= 6 - mcr p15, 0, r5, c13, c0, 4 -#endif - /* Set the new tp */ - ldr r6, [r5, #(TD_MD + MD_TP)] -#if __ARM_ARCH >= 6 - mcr p15, 0, r6, c13, c0, 3 -#else - ldr r4, =ARM_TP_ADDRESS - str r6, [r4] - ldr r6, [r5, #(TD_MD + MD_RAS_START)] - str r6, [r4, #4] /* ARM_RAS_START */ - ldr r6, [r5, #(TD_MD + MD_RAS_END)] - str r6, [r4, #8] /* ARM_RAS_END */ -#endif - /* Restore all the saved registers and exit */ - add r3, r7, #PCB_R4 - ldmia r3, {r4-r12, sp, pc} -END(cpu_throw) - -/* - * cpu_switch(oldtd, newtd, lock) - * - * Save the current thread state, then select the next thread to run - * and load its state. - * r0 = oldtd - * r1 = newtd - * r2 = lock (new lock for old thread) - */ -ENTRY(cpu_switch) - /* Interrupts are disabled. */ - /* Save all the registers in the old thread's pcb. */ - ldr r3, [r0, #(TD_PCB)] - - /* Restore all the saved registers and exit */ - add r3, #(PCB_R4) - stmia r3, {r4-r12, sp, lr, pc} - - mov r6, r2 /* Save the mutex */ - - /* rem: r0 = old lwp */ - /* rem: interrupts are disabled */ - - /* Process is now on a processor. */ - /* We have a new curthread now so make a note it */ - GET_PCPU(r7, r2) - str r1, [r7, #PC_CURTHREAD] -#if __ARM_ARCH >= 6 - mcr p15, 0, r1, c13, c0, 4 -#endif - - /* Hook in a new pcb */ - ldr r2, [r1, #TD_PCB] - str r2, [r7, #PC_CURPCB] - - /* Stage two : Save old context */ - - /* Get the user structure for the old thread. */ - ldr r2, [r0, #(TD_PCB)] - mov r4, r0 /* Save the old thread. */ - -#if __ARM_ARCH >= 6 - /* - * Set new tp. No need to store the old one first, userland can't - * change it directly on armv6. - */ - ldr r9, [r1, #(TD_MD + MD_TP)] - mcr p15, 0, r9, c13, c0, 3 -#else - /* Store the old tp; userland can change it on armv4. */ - ldr r3, =ARM_TP_ADDRESS - ldr r9, [r3] - str r9, [r0, #(TD_MD + MD_TP)] - ldr r9, [r3, #4] - str r9, [r0, #(TD_MD + MD_RAS_START)] - ldr r9, [r3, #8] - str r9, [r0, #(TD_MD + MD_RAS_END)] - - /* Set the new tp */ - ldr r9, [r1, #(TD_MD + MD_TP)] - str r9, [r3] - ldr r9, [r1, #(TD_MD + MD_RAS_START)] - str r9, [r3, #4] - ldr r9, [r1, #(TD_MD + MD_RAS_END)] - str r9, [r3, #8] -#endif - - /* Get the user structure for the new process in r9 */ - ldr r9, [r1, #(TD_PCB)] - - /* rem: r2 = old PCB */ - /* rem: r9 = new PCB */ - /* rem: interrupts are enabled */ - -#ifdef VFP - fmrx r0, fpexc /* If the VFP is enabled */ - tst r0, #(VFPEXC_EN) /* the current thread has */ - movne r1, #1 /* used it, so go save */ - addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */ - blne _C_LABEL(vfp_store) /* and disable the VFP. */ -#endif - - /* r0-r3 now free! */ - - /* Third phase : restore saved context */ - - /* rem: r2 = old PCB */ - /* rem: r9 = new PCB */ - - ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */ - mov r2, #DOMAIN_CLIENT - cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */ - beq .Lcs_context_switched /* Yup. Don't flush cache */ - mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */ - /* - * Get the new L1 table pointer into r11. If we're switching to - * an LWP with the same address space as the outgoing one, we can - * skip the cache purge and the TTB load. - * - * To avoid data dep stalls that would happen anyway, we try - * and get some useful work done in the mean time. - */ - mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */ - ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */ - - teq r10, r11 /* Same L1? */ - cmpeq r0, r5 /* Same DACR? */ - beq .Lcs_context_switched /* yes! */ - -#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT) - /* - * Definately need to flush the cache. - */ - - ldr r1, .Lcpufuncs - mov lr, pc - ldr pc, [r1, #CF_IDCACHE_WBINV_ALL] -#endif -.Lcs_cache_purge_skipped: - /* rem: r6 = lock */ - /* rem: r9 = new PCB */ - /* rem: r10 = old L1 */ - /* rem: r11 = new L1 */ - - mov r2, #0x00000000 - ldr r7, [r9, #(PCB_PL1VEC)] - - /* - * Ensure the vector table is accessible by fixing up the L1 - */ - cmp r7, #0 /* No need to fixup vector table? */ - ldrne r2, [r7] /* But if yes, fetch current value */ - ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */ - mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */ - cmpne r2, r0 /* Stuffing the same value? */ -#ifndef PMAP_INCLUDE_PTE_SYNC - strne r0, [r7] /* Nope, update it */ -#else - beq .Lcs_same_vector - str r0, [r7] /* Otherwise, update it */ - - /* - * Need to sync the cache to make sure that last store is - * visible to the MMU. - */ - ldr r2, .Lcpufuncs - mov r0, r7 - mov r1, #4 - mov lr, pc - ldr pc, [r2, #CF_DCACHE_WB_RANGE] - -.Lcs_same_vector: -#endif /* PMAP_INCLUDE_PTE_SYNC */ - - cmp r10, r11 /* Switching to the same L1? */ - ldr r10, .Lcpufuncs - beq .Lcs_same_l1 /* Yup. */ - /* - * Do a full context switch, including full TLB flush. - */ - mov r0, r11 - mov lr, pc - ldr pc, [r10, #CF_CONTEXT_SWITCH] - - b .Lcs_context_switched - - /* - * We're switching to a different process in the same L1. - * In this situation, we only need to flush the TLB for the - * vector_page mapping, and even then only if r7 is non-NULL. - */ -.Lcs_same_l1: - cmp r7, #0 - movne r0, #0 /* We *know* vector_page's VA is 0x0 */ - movne lr, pc - ldrne pc, [r10, #CF_TLB_FLUSHID_SE] - -.Lcs_context_switched: - - /* Release the old thread */ - str r6, [r4, #TD_LOCK] -#if defined(SCHED_ULE) && defined(SMP) - ldr r6, .Lblocked_lock - GET_CURTHREAD_PTR(r3) -1: - ldr r4, [r3, #TD_LOCK] - cmp r4, r6 - beq 1b -#endif - - /* XXXSCW: Safe to re-enable FIQs here */ - - /* rem: r9 = new PCB */ - - /* Restore all the saved registers and exit */ - add r3, r9, #PCB_R4 - ldmia r3, {r4-r12, sp, pc} -END(cpu_switch) - - -#else /* __ARM_ARCH < 6 */ -#include - -ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */ - DSB - mcr CP15_TTBR0(r0) /* set the new TTB */ - ISB - mov r0, #(CPU_ASID_KERNEL) - mcr CP15_TLBIASID(r0) /* flush not global TLBs */ - /* - * Flush entire Branch Target Cache because of the branch predictor - * is not architecturally invisible. See ARM Architecture Reference - * Manual ARMv7-A and ARMv7-R edition, page B2-1264(65), Branch - * predictors and Requirements for branch predictor maintenance - * operations sections. - * - * QQQ: The predictor is virtually addressed and holds virtual target - * addresses. Therefore, if mapping is changed, the predictor cache - * must be flushed.The flush is part of entire i-cache invalidation - * what is always called when code mapping is changed. So herein, - * it's the only place where standalone predictor flush must be - * executed in kernel (except self modifying code case). - */ - mcr CP15_BPIALL /* and flush entire Branch Target Cache */ - DSB - mov pc, lr -END(cpu_context_switch) - -/* - * cpu_throw(oldtd, newtd) - * - * Remove current thread state, then select the next thread to run - * and load its state. - * r0 = oldtd - * r1 = newtd - */ -ENTRY(cpu_throw) - mov r10, r0 /* r10 = oldtd */ - mov r11, r1 /* r11 = newtd */ - -#ifdef VFP /* This thread is dying, disable */ - bl _C_LABEL(vfp_discard) /* VFP without preserving state. */ -#endif - GET_PCPU(r8, r9) /* r8 = current pcpu */ - ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */ - - cmp r10, #0 /* old thread? */ - beq 2f /* no, skip */ - - /* Remove this CPU from the active list. */ - ldr r5, [r8, #PC_CURPMAP] - mov r0, #(PM_ACTIVE) - add r5, r0 /* r5 = old pm_active */ - - /* Compute position and mask. */ -#if _NCPUWORDS > 1 - lsr r0, r4, #3 - bic r0, #3 - add r5, r0 /* r5 = position in old pm_active */ - mov r2, #1 - and r0, r4, #31 - lsl r2, r0 /* r2 = mask */ -#else - mov r2, #1 - lsl r2, r4 /* r2 = mask */ -#endif - /* Clear cpu from old active list. */ -#ifdef SMP -1: ldrex r0, [r5] - bic r0, r2 - strex r1, r0, [r5] - teq r1, #0 - bne 1b -#else - ldr r0, [r5] - bic r0, r2 - str r0, [r5] -#endif - -2: -#ifdef INVARIANTS - cmp r11, #0 /* new thread? */ - beq badsw1 /* no, panic */ -#endif - ldr r7, [r11, #(TD_PCB)] /* r7 = new PCB */ - - /* - * Registers at this point - * r4 = current cpu id - * r7 = new PCB - * r8 = current pcpu - * r11 = newtd - */ - - /* MMU switch to new thread. */ - ldr r0, [r7, #(PCB_PAGEDIR)] -#ifdef INVARIANTS - cmp r0, #0 /* new thread? */ - beq badsw4 /* no, panic */ -#endif - bl _C_LABEL(cpu_context_switch) - - /* - * Set new PMAP as current one. - * Insert cpu to new active list. - */ - - ldr r6, [r11, #(TD_PROC)] /* newtd->proc */ - ldr r6, [r6, #(P_VMSPACE)] /* newtd->proc->vmspace */ - add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */ - str r6, [r8, #PC_CURPMAP] /* store to curpmap */ - - mov r0, #PM_ACTIVE - add r6, r0 /* r6 = new pm_active */ - - /* compute position and mask */ -#if _NCPUWORDS > 1 - lsr r0, r4, #3 - bic r0, #3 - add r6, r0 /* r6 = position in new pm_active */ - mov r2, #1 - and r0, r4, #31 - lsl r2, r0 /* r2 = mask */ -#else - mov r2, #1 - lsl r2, r4 /* r2 = mask */ -#endif - /* Set cpu to new active list. */ -#ifdef SMP -1: ldrex r0, [r6] - orr r0, r2 - strex r1, r0, [r6] - teq r1, #0 - bne 1b -#else - ldr r0, [r6] - orr r0, r2 - str r0, [r6] -#endif - /* - * Registers at this point. - * r7 = new PCB - * r8 = current pcpu - * r11 = newtd - * They must match the ones in sw1 position !!! - */ - DMB - b sw1 /* share new thread init with cpu_switch() */ -END(cpu_throw) - -/* - * cpu_switch(oldtd, newtd, lock) - * - * Save the current thread state, then select the next thread to run - * and load its state. - * r0 = oldtd - * r1 = newtd - * r2 = lock (new lock for old thread) - */ -ENTRY(cpu_switch) - /* Interrupts are disabled. */ -#ifdef INVARIANTS - cmp r0, #0 /* old thread? */ - beq badsw2 /* no, panic */ -#endif - /* Save all the registers in the old thread's pcb. */ - ldr r3, [r0, #(TD_PCB)] - add r3, #(PCB_R4) - stmia r3, {r4-r12, sp, lr, pc} - -#ifdef INVARIANTS - cmp r1, #0 /* new thread? */ - beq badsw3 /* no, panic */ -#endif - /* - * Save arguments. Note that we can now use r0-r14 until - * it is time to restore them for the new thread. However, - * some registers are not safe over function call. - */ - mov r9, r2 /* r9 = lock */ - mov r10, r0 /* r10 = oldtd */ - mov r11, r1 /* r11 = newtd */ - - GET_PCPU(r8, r3) /* r8 = current PCPU */ - ldr r7, [r11, #(TD_PCB)] /* r7 = newtd->td_pcb */ - - - -#ifdef VFP - ldr r3, [r10, #(TD_PCB)] - fmrx r0, fpexc /* If the VFP is enabled */ - tst r0, #(VFPEXC_EN) /* the current thread has */ - movne r1, #1 /* used it, so go save */ - addne r0, r3, #(PCB_VFPSTATE) /* the state into the PCB */ - blne _C_LABEL(vfp_store) /* and disable the VFP. */ -#endif - - /* - * MMU switch. If we're switching to a thread with the same - * address space as the outgoing one, we can skip the MMU switch. - */ - mrc CP15_TTBR0(r1) /* r1 = old TTB */ - ldr r0, [r7, #(PCB_PAGEDIR)] /* r0 = new TTB */ - cmp r0, r1 /* Switching to the TTB? */ - beq sw0 /* same TTB, skip */ - -#ifdef INVARIANTS - cmp r0, #0 /* new thread? */ - beq badsw4 /* no, panic */ -#endif - - bl cpu_context_switch /* new TTB as argument */ - - /* - * Registers at this point - * r7 = new PCB - * r8 = current pcpu - * r9 = lock - * r10 = oldtd - * r11 = newtd - */ - - /* - * Set new PMAP as current one. - * Update active list on PMAPs. - */ - ldr r6, [r11, #TD_PROC] /* newtd->proc */ - ldr r6, [r6, #P_VMSPACE] /* newtd->proc->vmspace */ - add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */ - - ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */ - str r6, [r8, #PC_CURPMAP] /* and save new one */ - - mov r0, #PM_ACTIVE - add r5, r0 /* r5 = old pm_active */ - add r6, r0 /* r6 = new pm_active */ - - /* Compute position and mask. */ - ldr r4, [r8, #PC_CPUID] -#if _NCPUWORDS > 1 - lsr r0, r4, #3 - bic r0, #3 - add r5, r0 /* r5 = position in old pm_active */ - add r6, r0 /* r6 = position in new pm_active */ - mov r2, #1 - and r0, r4, #31 - lsl r2, r0 /* r2 = mask */ -#else - mov r2, #1 - lsl r2, r4 /* r2 = mask */ -#endif - /* Clear cpu from old active list. */ -#ifdef SMP -1: ldrex r0, [r5] - bic r0, r2 - strex r1, r0, [r5] - teq r1, #0 - bne 1b -#else - ldr r0, [r5] - bic r0, r2 - str r0, [r5] -#endif - /* Set cpu to new active list. */ -#ifdef SMP -1: ldrex r0, [r6] - orr r0, r2 - strex r1, r0, [r6] - teq r1, #0 - bne 1b -#else - ldr r0, [r6] - orr r0, r2 - str r0, [r6] -#endif - -sw0: - /* - * Registers at this point - * r7 = new PCB - * r8 = current pcpu - * r9 = lock - * r10 = oldtd - * r11 = newtd - */ - - /* Change the old thread lock. */ - add r5, r10, #TD_LOCK - DMB -1: ldrex r0, [r5] - strex r1, r9, [r5] - teq r1, #0 - bne 1b - DMB - -sw1: - clrex - /* - * Registers at this point - * r7 = new PCB - * r8 = current pcpu - * r11 = newtd - */ - -#if defined(SMP) && defined(SCHED_ULE) - /* - * 386 and amd64 do the blocked lock test only for SMP and SCHED_ULE - * QQQ: What does it mean in reality and why is it done? - */ - ldr r6, =blocked_lock -1: - ldr r3, [r11, #TD_LOCK] /* atomic write regular read */ - cmp r3, r6 - beq 1b -#endif - /* Set the new tls */ - ldr r0, [r11, #(TD_MD + MD_TP)] - mcr CP15_TPIDRURO(r0) /* write tls thread reg 2 */ - - /* We have a new curthread now so make a note it */ - str r11, [r8, #PC_CURTHREAD] - mcr CP15_TPIDRPRW(r11) - - /* store pcb in per cpu structure */ - str r7, [r8, #PC_CURPCB] - - /* - * Restore all saved registers and return. Note that some saved - * registers can be changed when either cpu_fork(), cpu_set_upcall(), - * cpu_set_fork_handler(), or makectx() was called. - */ - add r3, r7, #PCB_R4 - ldmia r3, {r4-r12, sp, pc} - -#ifdef INVARIANTS -badsw1: - ldr r0, =sw1_panic_str - bl _C_LABEL(panic) -1: nop - b 1b - -badsw2: - ldr r0, =sw2_panic_str - bl _C_LABEL(panic) -1: nop - b 1b - -badsw3: - ldr r0, =sw3_panic_str - bl _C_LABEL(panic) -1: nop - b 1b - -badsw4: - ldr r0, =sw4_panic_str - bl _C_LABEL(panic) -1: nop - b 1b - -sw1_panic_str: - .asciz "cpu_throw: no newthread supplied.\n" -sw2_panic_str: - .asciz "cpu_switch: no curthread supplied.\n" -sw3_panic_str: - .asciz "cpu_switch: no newthread supplied.\n" -sw4_panic_str: - .asciz "cpu_switch: new pagedir is NULL.\n" -#endif -END(cpu_switch) - - -#endif /* __ARM_ARCH < 6 */ - ENTRY(savectx) stmfd sp!, {lr} sub sp, sp, #4 diff --git a/sys/conf/files.arm b/sys/conf/files.arm index e6b89a197be6..bf0e26268075 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -74,6 +74,8 @@ arm/arm/stdatomic.c standard \ compile-with "${NORMAL_C:N-Wmissing-prototypes}" arm/arm/support.S standard arm/arm/swtch.S standard +arm/arm/swtch-v4.S optional !armv6 +arm/arm/swtch-v6.S optional armv6 arm/arm/sys_machdep.c standard arm/arm/syscall.c standard arm/arm/trap.c optional !armv6 From 6cb9984dc34009f750e4664d2f30ec554261b666 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 30 Jan 2016 08:27:09 +0000 Subject: [PATCH 049/236] EHCI: Correct address of EHCI_USBMODE_LPM register is 0xC8, not 0xA8. --- sys/dev/usb/controller/ehcireg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/controller/ehcireg.h b/sys/dev/usb/controller/ehcireg.h index 1bfda909cdd0..2394b2c17c9a 100644 --- a/sys/dev/usb/controller/ehcireg.h +++ b/sys/dev/usb/controller/ehcireg.h @@ -167,7 +167,7 @@ * bits are equal */ #define EHCI_USBMODE_NOLPM 0x68 /* RW USB Device mode reg (no LPM) */ -#define EHCI_USBMODE_LPM 0xA8 /* RW USB Device mode reg (LPM) */ +#define EHCI_USBMODE_LPM 0xC8 /* RW USB Device mode reg (LPM) */ #define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */ #define EHCI_UM_CM_IDLE 0x0 /* Idle */ #define EHCI_UM_CM_HOST 0x3 /* Host Controller */ From 0b2832301dc16b79f3bed52d7f9ececa54f230f9 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 30 Jan 2016 10:10:29 +0000 Subject: [PATCH 050/236] ARM: Don't misuse ARM_TP_ADDRESS as ARMv4 / ARMv6 selector. --- sys/arm/arm/machdep.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index c39d7d2b5508..8d7c39c4d0b9 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -427,10 +427,8 @@ cpu_startup(void *dummy) { struct pcb *pcb = thread0.td_pcb; const unsigned int mbyte = 1024 * 1024; -#ifdef ARM_TP_ADDRESS -#ifndef ARM_CACHE_LOCK_ENABLE +#if __ARM_ARCH < 6 && !defined(ARM_CACHE_LOCK_ENABLE) vm_page_t m; -#endif #endif identify_arm_cpu(); @@ -456,11 +454,9 @@ cpu_startup(void *dummy) pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack + USPACE_SVC_STACK_TOP; pmap_set_pcb_pagedir(kernel_pmap, pcb); -#if __ARM_ARCH < 6 +#if __ARM_ARCH < 6 vector_page_setprot(VM_PROT_READ); pmap_postinit(); -#endif -#ifdef ARM_TP_ADDRESS #ifdef ARM_CACHE_LOCK_ENABLE pmap_kenter_user(ARM_TP_ADDRESS, ARM_TP_ADDRESS); arm_lock_cache_line(ARM_TP_ADDRESS); From e13af8890119de2f10170bd143a071b9dc7ace5c Mon Sep 17 00:00:00 2001 From: tuexen Date: Sat, 30 Jan 2016 10:39:05 +0000 Subject: [PATCH 051/236] Ignore peer addresses in a consistent way also when checking for new addresses during restart. If this is not done, restart doesn't work when the local socket is IPv4 only and the peer uses IPv4 and IPv6 addresses. MFC after: 3 days. --- sys/netinet/sctp_output.c | 97 +++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 95ac97c903dd..21e45deb0d7f 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5307,6 +5307,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, uint16_t ptype, plen; uint8_t fnd; struct sctp_nets *net; + int check_src; #ifdef INET struct sockaddr_in sin4, *sa4; @@ -5328,39 +5329,61 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, sin6.sin6_len = sizeof(sin6); #endif /* First what about the src address of the pkt ? */ - fnd = 0; - TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - sa = (struct sockaddr *)&net->ro._l_addr; - if (sa->sa_family == src->sa_family) { + check_src = 0; + switch (src->sa_family) { #ifdef INET - if (sa->sa_family == AF_INET) { - struct sockaddr_in *src4; - - sa4 = (struct sockaddr_in *)sa; - src4 = (struct sockaddr_in *)src; - if (sa4->sin_addr.s_addr == src4->sin_addr.s_addr) { - fnd = 1; - break; - } - } + case AF_INET: + if (asoc->scope.ipv4_addr_legal) { + check_src = 1; + } + break; #endif #ifdef INET6 - if (sa->sa_family == AF_INET6) { - struct sockaddr_in6 *src6; - - sa6 = (struct sockaddr_in6 *)sa; - src6 = (struct sockaddr_in6 *)src; - if (SCTP6_ARE_ADDR_EQUAL(sa6, src6)) { - fnd = 1; - break; - } - } -#endif + case AF_INET6: + if (asoc->scope.ipv6_addr_legal) { + check_src = 1; } + break; +#endif + default: + /* TSNH */ + break; } - if (fnd == 0) { - /* New address added! no need to look futher. */ - return (1); + if (check_src) { + fnd = 0; + TAILQ_FOREACH(net, &asoc->nets, sctp_next) { + sa = (struct sockaddr *)&net->ro._l_addr; + if (sa->sa_family == src->sa_family) { +#ifdef INET + if (sa->sa_family == AF_INET) { + struct sockaddr_in *src4; + + sa4 = (struct sockaddr_in *)sa; + src4 = (struct sockaddr_in *)src; + if (sa4->sin_addr.s_addr == src4->sin_addr.s_addr) { + fnd = 1; + break; + } + } +#endif +#ifdef INET6 + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *src6; + + sa6 = (struct sockaddr_in6 *)sa; + src6 = (struct sockaddr_in6 *)src; + if (SCTP6_ARE_ADDR_EQUAL(sa6, src6)) { + fnd = 1; + break; + } + } +#endif + } + } + if (fnd == 0) { + /* New address added! no need to look futher. */ + return (1); + } } /* Ok so far lets munge through the rest of the packet */ offset += sizeof(struct sctp_init_chunk); @@ -5381,9 +5404,11 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, phdr == NULL) { return (1); } - p4 = (struct sctp_ipv4addr_param *)phdr; - sin4.sin_addr.s_addr = p4->addr; - sa_touse = (struct sockaddr *)&sin4; + if (asoc->scope.ipv4_addr_legal) { + p4 = (struct sctp_ipv4addr_param *)phdr; + sin4.sin_addr.s_addr = p4->addr; + sa_touse = (struct sockaddr *)&sin4; + } break; } #endif @@ -5398,10 +5423,12 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, phdr == NULL) { return (1); } - p6 = (struct sctp_ipv6addr_param *)phdr; - memcpy((caddr_t)&sin6.sin6_addr, p6->addr, - sizeof(p6->addr)); - sa_touse = (struct sockaddr *)&sin6; + if (asoc->scope.ipv6_addr_legal) { + p6 = (struct sctp_ipv6addr_param *)phdr; + memcpy((caddr_t)&sin6.sin6_addr, p6->addr, + sizeof(p6->addr)); + sa_touse = (struct sockaddr *)&sin6; + } break; } #endif From 8a9d3a9d9f89f3731ef2821665265c9fd250bbff Mon Sep 17 00:00:00 2001 From: tuexen Date: Sat, 30 Jan 2016 11:10:22 +0000 Subject: [PATCH 052/236] Don't change the remote UDP encapsulation port for SCTP packets containing an INIT chunk. MFC after: 3 days --- sys/netinet/sctp_input.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 9edfcf67808a..1dbb6cf3f0c9 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5684,7 +5684,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); #if defined(INET) || defined(INET6) - if ((net != NULL) && (port != 0)) { + if ((net != NULL) && + (ch->chunk_type != SCTP_INITIATION) && + (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } @@ -5715,7 +5717,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); #if defined(INET) || defined(INET6) - if ((net != NULL) && (port != 0)) { + if ((net != NULL) && + (ch->chunk_type != SCTP_INITIATION) && + (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } @@ -5827,7 +5831,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ inp = stcb->sctp_ep; #if defined(INET) || defined(INET6) - if ((net != NULL) && (port != 0)) { + if ((net != NULL) && + (ch->chunk_type != SCTP_INITIATION) && + (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } From 2b5e197c218584bbca74465ecdce077370e4b687 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 30 Jan 2016 12:23:28 +0000 Subject: [PATCH 053/236] ARM: Cleanup mp_machdep.c. SMP is supported only on ARMv6 and later. --- sys/arm/arm/mp_machdep.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 36618669ac61..a80c5aaeb422 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -156,7 +156,6 @@ init_secondary(int cpu) #ifndef ARM_INTRNG int start = 0, end = 0; #endif -#if __ARM_ARCH >= 6 uint32_t actlr_mask, actlr_set; pmap_set_tex(); @@ -168,11 +167,6 @@ init_secondary(int cpu) set_stackptrs(cpu); enable_interrupts(PSR_A); -#else /* __ARM_ARCH >= 6 */ - cpu_setup(); - setttb(pmap_pa); - cpu_tlb_flushID(); -#endif /* __ARM_ARCH >= 6 */ pc = &__pcpu[cpu]; /* @@ -184,10 +178,6 @@ init_secondary(int cpu) pcpu_init(pc, cpu, sizeof(struct pcpu)); dpcpu_init(dpcpu[cpu - 1], cpu); -#if __ARM_ARCH < 6 - /* Provide stack pointers for other processor modes. */ - set_stackptrs(cpu); -#endif /* Signal our startup to BSP */ atomic_add_rel_32(&mp_naps, 1); From 9aecdeee5e3f9ced484d9481c0f053d9ff59986e Mon Sep 17 00:00:00 2001 From: tuexen Date: Sat, 30 Jan 2016 12:58:38 +0000 Subject: [PATCH 054/236] Don't allow a remote encapsulation port change during the SCTP restart procedure. MFC after: 3 days --- sys/netinet/sctp_input.c | 8 +++---- sys/netinet/sctp_output.c | 50 +++++++++++++++++++++++++++------------ sys/netinet/sctp_output.h | 3 ++- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 1dbb6cf3f0c9..a1e79e41c1bf 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -85,7 +85,7 @@ static void sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_init_chunk *cp, struct sctp_inpcb *inp, - struct sctp_tcb *stcb, int *abort_no_unlock, + struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_no_unlock, uint8_t mflowtype, uint32_t mflowid, uint32_t vrf_id, uint16_t port) { @@ -198,8 +198,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); } else { SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); - sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst, - sh, cp, + sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset, + src, dst, sh, cp, mflowtype, mflowid, vrf_id, port, ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); @@ -4840,7 +4840,7 @@ __attribute__((noinline)) } sctp_handle_init(m, iphlen, *offset, src, dst, sh, (struct sctp_init_chunk *)ch, inp, - stcb, &abort_no_unlock, + stcb, *netp, &abort_no_unlock, mflowtype, mflowid, vrf_id, port); *offset = length; diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 21e45deb0d7f..017261000189 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5484,7 +5484,8 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, */ void sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, - struct mbuf *init_pkt, int iphlen, int offset, + struct sctp_nets *src_net, struct mbuf *init_pkt, + int iphlen, int offset, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_init_chunk *init_chk, uint8_t mflowtype, uint32_t mflowid, @@ -5528,20 +5529,39 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc = NULL; } if ((asoc != NULL) && - (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) && - (sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) { - /* new addresses, out of here in non-cookie-wait states */ - /* - * Send a ABORT, we don't add the new address error clause - * though we even set the T bit and copy in the 0 tag.. this - * looks no different than if no listener was present. - */ - op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), - "Address added"); - sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, - mflowtype, mflowid, inp->fibnum, - vrf_id, port); - return; + (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT)) { + if (sctp_are_there_new_addresses(asoc, init_pkt, offset, src)) { + /* + * new addresses, out of here in non-cookie-wait + * states + * + * Send an ABORT, without the new address error cause. + * This looks no different than if no listener was + * present. + */ + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Address added"); + sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, + mflowtype, mflowid, inp->fibnum, + vrf_id, port); + return; + } + if (src_net != NULL && (src_net->port != port)) { + /* + * change of remote encapsulation port, out of here + * in non-cookie-wait states + * + * Send an ABORT, without an specific error cause. This + * looks no different than if no listener was + * present. + */ + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Remote encapsulation port changed"); + sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, + mflowtype, mflowid, inp->fibnum, + vrf_id, port); + return; + } } abort_flag = 0; op_err = sctp_arethere_unrecognized_parameters(init_pkt, diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index d7222c44bf51..b2441a6fe0b6 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -80,7 +80,8 @@ sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int ); void -sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *, struct mbuf *, +sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *, + struct sctp_nets *, struct mbuf *, int, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, struct sctp_init_chunk *, From 0b42c3f61a8157d90034b93c97e5f2eb58e84550 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 30 Jan 2016 13:11:13 +0000 Subject: [PATCH 055/236] ARM: Remove TLB IPI. We don't support SMP on ARMv6. All ARMv7 multicore cpus already uses hardware broadcast for TLB and cache operations. --- sys/arm/arm/mp_machdep.c | 19 ---------------- sys/arm/include/cpufunc.h | 47 --------------------------------------- sys/arm/include/smp.h | 8 +++---- 3 files changed, 4 insertions(+), 70 deletions(-) diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index a80c5aaeb422..0106c7af347c 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -341,13 +341,6 @@ ipi_hardclock(void *arg) critical_exit(); } -static void -ipi_tlb(void *dummy __unused) -{ - - CTR1(KTR_SMP, "%s: IPI_TLB", __func__); - cpufuncs.cf_tlb_flushID(); -} #else static int ipi_handler(void *arg) @@ -413,10 +406,6 @@ ipi_handler(void *arg) CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__); hardclockintr(); break; - case IPI_TLB: - CTR1(KTR_SMP, "%s: IPI_TLB", __func__); - cpufuncs.cf_tlb_flushID(); - break; default: panic("Unknown IPI 0x%0x on cpu %d", ipi, curcpu); } @@ -446,7 +435,6 @@ release_aps(void *dummy __unused) intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0); intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0); intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0); - intr_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0); #else #ifdef IPI_IRQ_START @@ -538,10 +526,3 @@ ipi_selected(cpuset_t cpus, u_int ipi) platform_ipi_send(cpus, ipi); } -void -tlb_broadcast(int ipi) -{ - - if (smp_started) - ipi_all_but_self(ipi); -} diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 8bbb1dd7491c..f842e0f6f375 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -184,8 +184,6 @@ extern u_int cputype; #define cpu_faultstatus() cpufuncs.cf_faultstatus() #define cpu_faultaddress() cpufuncs.cf_faultaddress() -#ifndef SMP - #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() #define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e) #define cpu_tlb_flushI() cpufuncs.cf_tlb_flushI() @@ -193,51 +191,6 @@ extern u_int cputype; #define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD() #define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e) -#else -void tlb_broadcast(int); - -#if defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) -#define TLB_BROADCAST /* No need to explicitely send an IPI */ -#else -#define TLB_BROADCAST tlb_broadcast(7) -#endif - -#define cpu_tlb_flushID() do { \ - cpufuncs.cf_tlb_flushID(); \ - TLB_BROADCAST; \ -} while(0) - -#define cpu_tlb_flushID_SE(e) do { \ - cpufuncs.cf_tlb_flushID_SE(e); \ - TLB_BROADCAST; \ -} while(0) - - -#define cpu_tlb_flushI() do { \ - cpufuncs.cf_tlb_flushI(); \ - TLB_BROADCAST; \ -} while(0) - - -#define cpu_tlb_flushI_SE(e) do { \ - cpufuncs.cf_tlb_flushI_SE(e); \ - TLB_BROADCAST; \ -} while(0) - - -#define cpu_tlb_flushD() do { \ - cpufuncs.cf_tlb_flushD(); \ - TLB_BROADCAST; \ -} while(0) - - -#define cpu_tlb_flushD_SE(e) do { \ - cpufuncs.cf_tlb_flushD_SE(e); \ - TLB_BROADCAST; \ -} while(0) - -#endif - #define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all() #define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s)) diff --git a/sys/arm/include/smp.h b/sys/arm/include/smp.h index c50b99db1236..a993cc0579c2 100644 --- a/sys/arm/include/smp.h +++ b/sys/arm/include/smp.h @@ -14,8 +14,8 @@ enum { IPI_STOP, IPI_STOP_HARD = IPI_STOP, /* These are synonyms on arm. */ IPI_HARDCLOCK, - IPI_TLB, - IPI_CACHE, + IPI_TLB, /* Not used now, but keep it reserved. */ + IPI_CACHE, /* Not used now, but keep it reserved. */ INTR_IPI_COUNT }; #else @@ -25,8 +25,8 @@ enum { #define IPI_STOP 4 #define IPI_STOP_HARD 4 #define IPI_HARDCLOCK 6 -#define IPI_TLB 7 -#define IPI_CACHE 8 +#define IPI_TLB 7 /* Not used now, but keep it reserved. */ +#define IPI_CACHE 8 /* Not used now, but keep it reserved. */ #endif /* INTRNG */ void init_secondary(int cpu); From 564dfaad22d8372dc013f627f70fd3cc45aee989 Mon Sep 17 00:00:00 2001 From: allanjude Date: Sat, 30 Jan 2016 15:53:28 +0000 Subject: [PATCH 056/236] The zfsboot automated part of bsdinstall now supports UEFI MFC after: 3 days Sponsored by: ScaleEngine Inc. Differential Revision: https://reviews.freebsd.org/D4960 --- usr.sbin/bsdinstall/scripts/zfsboot | 115 ++++++++++++---------------- 1 file changed, 47 insertions(+), 68 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 5c3fc8011aa5..ed93c370bf2b 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -109,7 +109,12 @@ f_include $BSDCFG_SHARE/variable.subr # # Default partitioning scheme to use on disks # -: ${ZFSBOOT_PARTITION_SCHEME:=GPT} +: ${ZFSBOOT_PARTITION_SCHEME:=} + +# +# Default partitioning scheme to use on disks +# +: ${ZFSBOOT_BOOT_TYPE:=} # # How much swap to put on each block device in the boot zpool @@ -193,6 +198,7 @@ GPART_ADD_ALIGN_LABEL='gpart add %s -l %s -t %s "%s"' GPART_ADD_ALIGN_LABEL_WITH_SIZE='gpart add %s -l %s -t %s -s %s "%s"' GPART_BOOTCODE='gpart bootcode -b "%s" "%s"' GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"' +GPART_BOOTCODE_PARTONLY='gpart bootcode -p "%s" -i %s "%s"' GPART_CREATE='gpart create -s %s "%s"' GPART_DESTROY_F='gpart destroy -F "%s"' GPART_SET_ACTIVE='gpart set -a active -i %s "%s"' @@ -297,7 +303,6 @@ msg_swap_size="Swap Size" msg_swap_size_help="Customize how much swap space is allocated to each selected disk" msg_swap_toosmall="The selected swap size (%s) is to small. Please enter a value greater than 100MB or enter 0 for no swap" msg_these_disks_are_too_small="These disks are too small given the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 50%% or more of each of the following selected disk\ndevices (not recommended):\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices." -msg_uefi_not_supported="The FreeBSD UEFI loader does not currently support booting root-on-ZFS. Your system will need to boot in legacy (CSM) mode.\nDo you want to continue?" msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'" msg_unsupported_partition_scheme="%s is an unsupported partition scheme" msg_user_cancelled="User Cancelled." @@ -345,7 +350,7 @@ dialog_menu_main() 'E $msg_encrypt_disks' '$usegeli' '$msg_encrypt_disks_help' 'P $msg_partition_scheme' - '$ZFSBOOT_PARTITION_SCHEME' + '$ZFSBOOT_PARTITION_SCHEME ($ZFSBOOT_BOOT_TYPE)' '$msg_partition_scheme_help' 'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE' '$msg_swap_size_help' @@ -695,48 +700,6 @@ dialog_menu_layout() return $DIALOG_OK } -# dialog_uefi_prompt -# -# Confirm that the user wants to continue with the installation on a BIOS -# system when they have booted with UEFI -# -dialog_uefi_prompt() -{ - local title="$DIALOG_TITLE" - local btitle="$DIALOG_BACKTITLE" - local prompt # Calculated below - local hline="$hline_arrows_tab_enter" - - local height=8 width=50 prefix=" " - local plen=${#prefix} list= line= - local max_width=$(( $width - 3 - $plen )) - - local yes no defaultno extra_args format - if [ "$USE_XDIALOG" ]; then - yes=ok no=cancel defaultno=default-no - extra_args="--wrap --left" - format="$msg_uefi_not_supported" - else - yes=yes no=no defaultno=defaultno - extra_args="--cr-wrap" - format="$msg_uefi_not_supported" - fi - - # Add height for Xdialog(1) - [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 )) - - prompt=$( printf "$format" ) - f_dprintf "%s: UEFI prompt" "$0" - $DIALOG \ - --title "$title" \ - --backtitle "$btitle" \ - --hline "$hline" \ - --$yes-label "$msg_yes" \ - --$no-label "$msg_no" \ - $extra_args \ - --yesno "$prompt" $height $width -} - # zfs_create_diskpart $disk $index # # For each block device to be used in the zpool, rather than just create the @@ -848,14 +811,25 @@ zfs_create_diskpart() fi # - # 2. Add small freebsd-boot partition labeled `boot#' + # 2. Add small freebsd-boot or efi partition # - f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \ - "$align_small" gptboot$index freebsd-boot 512k $disk || - return $FAILURE - f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \ - /boot/pmbr /boot/gptzfsboot 1 $disk || - return $FAILURE + if [ "$ZFSBOOT_BOOT_TYPE" = "UEFI" ]; then + f_eval_catch $funcname gpart \ + "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \ + "$align_small" efiboot$index efi 800k $disk || + return $FAILURE + f_eval_catch $funcname gpart "$GPART_BOOTCODE_PARTONLY" \ + /boot/boot1.efifat 1 $disk || + return $FAILURE + else + f_eval_catch $funcname gpart \ + "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \ + "$align_small" gptboot$index freebsd-boot \ + 512k $disk || return $FAILURE + f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \ + /boot/pmbr /boot/gptzfsboot 1 $disk || + return $FAILURE + fi # NB: zpool will use the `zfs#' GPT labels bootpart=p2 swappart=p2 targetpart=p2 @@ -1463,18 +1437,16 @@ f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC" f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT" # -# If the system was booted with UEFI, warn the user that FreeBSD can't do -# ZFS with UEFI yet +# If the system was booted with UEFI, set the default boot type to UEFI # -if f_interactive; then - bootmethod=$( sysctl -n machdep.bootmethod ) - f_dprintf "machdep.bootmethod=[%s]" "$bootmethod" - if [ "$bootmethod" != "BIOS" ]; then - dialog_uefi_prompt - retval=$? - f_dprintf "uefi_prompt=[%s]" "$retval" - [ $retval -eq $DIALOG_OK ] || f_die - fi +bootmethod=$( sysctl -n machdep.bootmethod ) +f_dprintf "machdep.bootmethod=[%s]" "$bootmethod" +if [ "$bootmethod" = "UEFI" ]; then + : ${ZFSBOOT_BOOT_TYPE:=UEFI} + : ${ZFSBOOT_PARTITION_SCHEME:=GPT} +else + : ${ZFSBOOT_BOOT_TYPE:=BIOS} + : ${ZFSBOOT_PARTITION_SCHEME:=GPT} fi # @@ -1596,15 +1568,22 @@ while :; do fi ;; ?" $msg_partition_scheme") - # Toggle between GPT and MBR - if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then - ZFSBOOT_PARTITION_SCHEME=MBR - elif [ "$ZFSBOOT_PARTITION_SCHEME" = MBR ]; then + # Toggle between GPT (BIOS), GPT (UEFI) and MBR + if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" -a "$ZFSBOOT_BOOT_TYPE" = "BIOS" ]; then + ZFSBOOT_PARTITION_SCHEME="GPT" + ZFSBOOT_BOOT_TYPE="UEFI" + elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" ]; then + ZFSBOOT_PARTITION_SCHEME="MBR" + ZFSBOOT_BOOT_TYPE="BIOS" + elif [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then ZFSBOOT_PARTITION_SCHEME="GPT + Active" + ZFSBOOT_BOOT_TYPE="BIOS" elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix" + ZFSBOOT_BOOT_TYPE="BIOS" else - ZFSBOOT_PARTITION_SCHEME=GPT + ZFSBOOT_PARTITION_SCHEME="GPT" + ZFSBOOT_BOOT_TYPE="BIOS" fi ;; ?" $msg_swap_size") From 5827747532eb462b34220c84db9bee3609e6fdae Mon Sep 17 00:00:00 2001 From: tuexen Date: Sat, 30 Jan 2016 16:56:39 +0000 Subject: [PATCH 057/236] Update the path mtu when turning on/off UDP encapsulation for SCTP. MFC after: 3 days --- sys/netinet/sctp_input.c | 45 +++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index a1e79e41c1bf..a6f625d13a11 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5684,11 +5684,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); #if defined(INET) || defined(INET6) - if ((net != NULL) && - (ch->chunk_type != SCTP_INITIATION) && - (port != 0)) { + if ((ch->chunk_type != SCTP_INITIATION) && + (net != NULL) && (net->port != port)) { if (net->port == 0) { - sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); + /* UDP encapsulation turned on. */ + net->mtu -= sizeof(struct udphdr); + if (stcb->asoc.smallest_mtu > net->mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); + } + } else if (port == 0) { + /* UDP encapsulation turned off. */ + net->mtu += sizeof(struct udphdr); + /* XXX Update smallest_mtu */ } net->port = port; } @@ -5717,11 +5724,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); #if defined(INET) || defined(INET6) - if ((net != NULL) && - (ch->chunk_type != SCTP_INITIATION) && - (port != 0)) { + if ((ch->chunk_type != SCTP_INITIATION) && + (net != NULL) && (net->port != port)) { if (net->port == 0) { - sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); + /* UDP encapsulation turned on. */ + net->mtu -= sizeof(struct udphdr); + if (stcb->asoc.smallest_mtu > net->mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); + } + } else if (port == 0) { + /* UDP encapsulation turned off. */ + net->mtu += sizeof(struct udphdr); + /* XXX Update smallest_mtu */ } net->port = port; } @@ -5831,11 +5845,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ inp = stcb->sctp_ep; #if defined(INET) || defined(INET6) - if ((net != NULL) && - (ch->chunk_type != SCTP_INITIATION) && - (port != 0)) { + if ((ch->chunk_type != SCTP_INITIATION) && + (net != NULL) && (net->port != port)) { if (net->port == 0) { - sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); + /* UDP encapsulation turned on. */ + net->mtu -= sizeof(struct udphdr); + if (stcb->asoc.smallest_mtu > net->mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); + } + } else if (port == 0) { + /* UDP encapsulation turned off. */ + net->mtu += sizeof(struct udphdr); + /* XXX Update smallest_mtu */ } net->port = port; } From bdc2db735b716a3db57871143a45b138b25f57c5 Mon Sep 17 00:00:00 2001 From: ngie Date: Sat, 30 Jan 2016 17:10:14 +0000 Subject: [PATCH 058/236] Revert r295062 to unbreak buildworld Some of the structures referenced in power.c (in particular struct nvme_power_state) are missing from sbin/nvmecontrol/ Pointyhat to: imp Reported by: Jenkins [*], O. Hartmann , Outback Dingo --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/nvmecontrol.8 | 17 --- sbin/nvmecontrol/nvmecontrol.c | 1 - sbin/nvmecontrol/nvmecontrol.h | 4 - sbin/nvmecontrol/power.c | 185 --------------------------------- 5 files changed, 1 insertion(+), 208 deletions(-) delete mode 100644 sbin/nvmecontrol/power.c diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index e8a23719a2a7..ea60da3c2941 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -2,7 +2,7 @@ PROG= nvmecontrol SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \ - perftest.c reset.c nvme_util.c power.c + perftest.c reset.c nvme_util.c MAN= nvmecontrol.8 .PATH: ${.CURDIR}/../../sys/dev/nvme diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index ae8132ec5cbc..3b4b5c23aef3 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -70,11 +70,6 @@ .Op Fl f Ar path_to_firmware .Op Fl a .Aq device id -.Nm -.Ic power -.Op Fl l -.Op Fl p power_state -.Op fl w workload_hint .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. @@ -125,18 +120,6 @@ Activate the firmware in slot 4 of the nvme0 controller on the next reset. .Pp Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the nvme0 controller and activate it on the next reset. -.Pp -.Dl nvmecontrol power -l nvme0 -.Pp -List all the current power modes. -.Pp -.Dl nvmecontrol power -p 3 nvme0 -.Pp -Set the current power mode. -.Pp -.Dl nvmecontrol power nvme0 -.Pp -Get the current power mode. .Sh AUTHORS .An -nosplit .Nm diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index cd7c19d0165d..4dee1909280a 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -58,7 +58,6 @@ static struct nvme_function { {"reset", reset, RESET_USAGE}, {"logpage", logpage, LOGPAGE_USAGE}, {"firmware", firmware, FIRMWARE_USAGE}, - {"power", power, POWER_USAGE}, {NULL, NULL, NULL}, }; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index b3cecd26dcea..8401dd7ccda3 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -55,16 +55,12 @@ #define FIRMWARE_USAGE \ " nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" -#define POWER_USAGE \ -" nvmecontrol power [-l] [-p new-state [-w workload-hint]] \n" - void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); void logpage(int argc, char *argv[]); void firmware(int argc, char *argv[]); -void power(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid); diff --git a/sbin/nvmecontrol/power.c b/sbin/nvmecontrol/power.c deleted file mode 100644 index e681ccd14dcc..000000000000 --- a/sbin/nvmecontrol/power.c +++ /dev/null @@ -1,185 +0,0 @@ -/*- - * Copyright (c) 2016 Netflix, 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 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nvmecontrol.h" - -_Static_assert(sizeof(struct nvme_power_state) == 256 / NBBY, - "nvme_power_state size wrong"); - -static void -power_usage(void) -{ - fprintf(stderr, "usage:\n"); - fprintf(stderr, POWER_USAGE); - exit(1); -} - -static void -power_list_one(int i, struct nvme_power_state *nps) -{ - int mpower, apower, ipower; - - mpower = nps->mp; - if (nps->mps == 0) - mpower *= 100; - ipower = nps->idlp; - if (nps->ips == 1) - ipower *= 100; - apower = nps->actp; - if (nps->aps == 1) - apower *= 100; - printf("%2d: %2d.%04dW%c %3d.%03dms %3d.%03dms %2d %2d %2d %2d %2d.%04dW %2d.%04dW %d\n", - i, mpower / 10000, mpower % 10000, - nps->nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000, - nps->exlat / 1000, nps->exlat % 1000, nps->rrt, nps->rrl, - nps->rwt, nps->rwl, ipower / 10000, ipower % 10000, - apower / 10000, apower % 10000, nps->apw); -} - -static void -power_list(struct nvme_controller_data *cdata) -{ - int i; - - printf("\nPower States Supported: %d\n\n", cdata->npss + 1); - printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workloadd\n"); - printf("-- -------- --------- --------- -- -- -- -- -------- -------- --\n"); - for (i = 0; i <= cdata->npss; i++) - power_list_one(i, &cdata->power_state[i]); -} - -static void -power_set(int fd, int power, int workload, int perm) -{ - struct nvme_pt_command pt; - uint32_t p; - - p = perm ? (1u << 31) : 0; - memset(&pt, 0, sizeof(pt)); - pt.cmd.opc = NVME_OPC_SET_FEATURES; - pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT | p; - pt.cmd.cdw11 = power | (workload << 5); - - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) - err(1, "set feature power mgmt request failed"); - - if (nvme_completion_is_error(&pt.cpl)) - errx(1, "set feature power mgmt request returned error"); -} - -static void -power_show(int fd) -{ - struct nvme_pt_command pt; - - memset(&pt, 0, sizeof(pt)); - pt.cmd.opc = NVME_OPC_GET_FEATURES; - pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT; - - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) - err(1, "set feature power mgmt request failed"); - - if (nvme_completion_is_error(&pt.cpl)) - errx(1, "set feature power mgmt request returned error"); - - printf("Current Power Mode is %d\n", pt.cpl.cdw0); -} - -void -power(int argc, char *argv[]) -{ - struct nvme_controller_data cdata; - int ch, listflag = 0, powerflag = 0, power = 0, fd; - int workload = 0; - char *end; - - while ((ch = getopt(argc, argv, "lp:w:")) != -1) { - switch ((char)ch) { - case 'l': - listflag = 1; - break; - case 'p': - powerflag = 1; - power = strtol(optarg, &end, 0); - if (*end != '\0') { - fprintf(stderr, "Invalid power state number: %s\n", optarg); - power_usage(); - } - break; - case 'w': - workload = strtol(optarg, &end, 0); - if (*end != '\0') { - fprintf(stderr, "Invalid workload hint: %s\n", optarg); - power_usage(); - } - break; - default: - power_usage(); - } - } - - /* Check that a controller was specified. */ - if (optind >= argc) - power_usage(); - - if (listflag && powerflag) { - fprintf(stderr, "Can't set power and list power states\n"); - power_usage(); - } - - open_dev(argv[optind], &fd, 1, 1); - read_controller_data(fd, &cdata); - - if (listflag) { - power_list(&cdata); - goto out; - } - - if (powerflag) { - power_set(fd, power, workload, 0); - goto out; - } - power_show(fd); - -out: - close(fd); - exit(0); -} From 9103969d651c52b3b37e9a3ce7455d2ba458668c Mon Sep 17 00:00:00 2001 From: tuexen Date: Sat, 30 Jan 2016 17:32:46 +0000 Subject: [PATCH 059/236] Add missing parentheses. This was reported by ccaughie via GitHub for the userland stack. MFC after: 3 days --- sys/netinet/sctp_var.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index ae1b3eb3089d..7213b97684bd 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -86,7 +86,7 @@ extern struct pr_usrreqs sctp_usrreqs; #define sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_cc) ? (sctp_maxspace(sb) - (sb)->sb_cc) : 0)) -#define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0) +#define sctp_sbspace_sub(a,b) (((a) > (b)) ? ((a) - (b)) : 0) /* * I tried to cache the readq entries at one point. But the reality From 24165ad0083e4bb622a2b2531d300ba45983f0bd Mon Sep 17 00:00:00 2001 From: ngie Date: Sat, 30 Jan 2016 17:54:18 +0000 Subject: [PATCH 060/236] Fix the type for hw.ncpu, so sysctlbyname doesn't consistently fail on 64-bit architectures where sizeof(int) != sizeof(size_t). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MFC after: 1 week PR: 206758 Reported by: Christoph Schönweiler Submitted by: kib Sponsored by: EMC / Isilon Storage Division --- libexec/atrun/atrun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libexec/atrun/atrun.c b/libexec/atrun/atrun.c index 1e25766c41b1..7b11e7bb1997 100644 --- a/libexec/atrun/atrun.c +++ b/libexec/atrun/atrun.c @@ -459,8 +459,9 @@ main(int argc, char *argv[]) int c; int run_batch; #ifdef __FreeBSD__ - size_t ncpu, ncpusz; + size_t ncpusz; double load_avg = -1; + int ncpu; #else double load_avg = LOADAVG_MX; #endif From d653644a7f54e4567d3f346fcc021be55affc87a Mon Sep 17 00:00:00 2001 From: ngie Date: Sat, 30 Jan 2016 18:33:23 +0000 Subject: [PATCH 061/236] Use the correct type for i when iterating over `buf` to avoid unlikely negative array indexing in iicrdwr(..) Differential Revision: https://reviews.freebsd.org/D5132 Obtained from: HardenedBSD PR: 206754 Reported by: CTurt Submitted by: Madhi Moktari Sponsored by: EMC / Isilon Storage Division --- sys/dev/iicbus/iic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/iicbus/iic.c b/sys/dev/iicbus/iic.c index 84e1314a8d19..c6dd53d610b5 100644 --- a/sys/dev/iicbus/iic.c +++ b/sys/dev/iicbus/iic.c @@ -293,7 +293,8 @@ iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags) struct iic_msg *buf, *m; void **usrbufs; device_t iicdev, parent; - int error, i; + int error; + uint32_t i; iicdev = priv->sc->sc_dev; parent = device_get_parent(iicdev); From 9302898500113c6f03e1967407d1b0d5699f3789 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 30 Jan 2016 19:59:58 +0000 Subject: [PATCH 062/236] test: Optimize operator lookup. The linear search using strcmp() shows up in pmcstat for several percent. Split the operators into lengths and whether they start with '-' and compare bytes using == instead of strcmp(). A simple test sh -c 'i=0; w=$(printf %0100d 7); while [ "$i" -lt 1000000 ]; do v=$(printf %sx%s "$w" "$w"); i=$((i+1)); done' is over 4% faster on an amd64 bhyve VM. --- bin/test/test.c | 166 ++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 68 deletions(-) diff --git a/bin/test/test.c b/bin/test/test.c index 46e9999eb0bb..48b718e6412d 100644 --- a/bin/test/test.c +++ b/bin/test/test.c @@ -120,51 +120,53 @@ enum token { #define TOKEN_TYPE(token) ((token) & 0xff00) -static struct t_op { - char op_text[4]; +static const struct t_op { + char op_text[2]; short op_num; -} const ops [] = { - {"-r", FILRD}, - {"-w", FILWR}, - {"-x", FILEX}, - {"-e", FILEXIST}, - {"-f", FILREG}, - {"-d", FILDIR}, - {"-c", FILCDEV}, - {"-b", FILBDEV}, - {"-p", FILFIFO}, - {"-u", FILSUID}, - {"-g", FILSGID}, - {"-k", FILSTCK}, - {"-s", FILGZ}, - {"-t", FILTT}, - {"-z", STREZ}, - {"-n", STRNZ}, - {"-h", FILSYM}, /* for backwards compat */ - {"-O", FILUID}, - {"-G", FILGID}, - {"-L", FILSYM}, - {"-S", FILSOCK}, +} ops1[] = { {"=", STREQ}, - {"==", STREQ}, - {"!=", STRNE}, {"<", STRLT}, {">", STRGT}, - {"-eq", INTEQ}, - {"-ne", INTNE}, - {"-ge", INTGE}, - {"-gt", INTGT}, - {"-le", INTLE}, - {"-lt", INTLT}, - {"-nt", FILNT}, - {"-ot", FILOT}, - {"-ef", FILEQ}, {"!", UNOT}, - {"-a", BAND}, - {"-o", BOR}, {"(", LPAREN}, {")", RPAREN}, - {"", 0} +}, opsm1[] = { + {"r", FILRD}, + {"w", FILWR}, + {"x", FILEX}, + {"e", FILEXIST}, + {"f", FILREG}, + {"d", FILDIR}, + {"c", FILCDEV}, + {"b", FILBDEV}, + {"p", FILFIFO}, + {"u", FILSUID}, + {"g", FILSGID}, + {"k", FILSTCK}, + {"s", FILGZ}, + {"t", FILTT}, + {"z", STREZ}, + {"n", STRNZ}, + {"h", FILSYM}, /* for backwards compat */ + {"O", FILUID}, + {"G", FILGID}, + {"L", FILSYM}, + {"S", FILSOCK}, + {"a", BAND}, + {"o", BOR}, +}, ops2[] = { + {"==", STREQ}, + {"!=", STRNE}, +}, opsm2[] = { + {"eq", INTEQ}, + {"ne", INTNE}, + {"ge", INTGE}, + {"gt", INTGT}, + {"le", INTLE}, + {"lt", INTLT}, + {"nt", FILNT}, + {"ot", FILOT}, + {"ef", FILEQ}, }; static int nargc; @@ -416,35 +418,71 @@ filstat(char *nm, enum token mode) } } -static enum token -t_lex(char *s) +static int +find_op_1char(const struct t_op *op, const struct t_op *end, const char *s) { - struct t_op const *op = ops; + char c; - if (s == 0) { - return EOI; - } - while (*op->op_text) { - if (strcmp(s, op->op_text) == 0) { - if (((TOKEN_TYPE(op->op_num) == UNOP || - TOKEN_TYPE(op->op_num) == BUNOP) - && isunopoperand()) || - (op->op_num == LPAREN && islparenoperand()) || - (op->op_num == RPAREN && isrparenoperand())) - break; + c = s[0]; + while (op != end) { + if (c == *op->op_text) return op->op_num; - } op++; } return OPERAND; } +static int +find_op_2char(const struct t_op *op, const struct t_op *end, const char *s) +{ + while (op != end) { + if (s[0] == op->op_text[0] && s[1] == op->op_text[1]) + return op->op_num; + op++; + } + return OPERAND; +} + +static int +find_op(const char *s) +{ + if (s[0] == '\0') + return OPERAND; + else if (s[1] == '\0') + return find_op_1char(ops1, (&ops1)[1], s); + else if (s[2] == '\0') + return s[0] == '-' ? find_op_1char(opsm1, (&opsm1)[1], s + 1) : + find_op_2char(ops2, (&ops2)[1], s); + else if (s[3] == '\0') + return s[0] == '-' ? find_op_2char(opsm2, (&opsm2)[1], s + 1) : + OPERAND; + else + return OPERAND; +} + +static enum token +t_lex(char *s) +{ + int num; + + if (s == 0) { + return EOI; + } + num = find_op(s); + if (((TOKEN_TYPE(num) == UNOP || TOKEN_TYPE(num) == BUNOP) + && isunopoperand()) || + (num == LPAREN && islparenoperand()) || + (num == RPAREN && isrparenoperand())) + return OPERAND; + return num; +} + static int isunopoperand(void) { - struct t_op const *op = ops; char *s; char *t; + int num; if (nargc == 1) return 1; @@ -452,20 +490,16 @@ isunopoperand(void) if (nargc == 2) return parenlevel == 1 && strcmp(s, ")") == 0; t = *(t_wp + 2); - while (*op->op_text) { - if (strcmp(s, op->op_text) == 0) - return TOKEN_TYPE(op->op_num) == BINOP && - (parenlevel == 0 || t[0] != ')' || t[1] != '\0'); - op++; - } - return 0; + num = find_op(s); + return TOKEN_TYPE(num) == BINOP && + (parenlevel == 0 || t[0] != ')' || t[1] != '\0'); } static int islparenoperand(void) { - struct t_op const *op = ops; char *s; + int num; if (nargc == 1) return 1; @@ -474,12 +508,8 @@ islparenoperand(void) return parenlevel == 1 && strcmp(s, ")") == 0; if (nargc != 3) return 0; - while (*op->op_text) { - if (strcmp(s, op->op_text) == 0) - return TOKEN_TYPE(op->op_num) == BINOP; - op++; - } - return 0; + num = find_op(s); + return TOKEN_TYPE(num) == BINOP; } static int From 365b605737d46eaff10439e6236e87a2d102cdb8 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 30 Jan 2016 20:10:20 +0000 Subject: [PATCH 063/236] sh(1): Document 'cd -'. This reflects the changes in r294649 and can therefore not be MFCed by itself. --- bin/sh/sh.1 | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 14ae89833c8a..94067792e40e 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd August 29, 2015 +.Dd January 30, 2016 .Dt SH 1 .Os .Sh NAME @@ -1952,13 +1952,20 @@ Execute the specified built-in command, This is useful when the user wishes to override a shell function with the same name as a built-in command. .It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory +.It Ic cd Fl Switch to the specified .Ar directory , -or to the directory specified in the +to the directory specified in the .Va HOME environment variable if no .Ar directory -is specified. +is specified or +to the directory specified in the +.Va OLDPWD +environment variable if +.Ar directory +is +.Fl . If .Ar directory does not begin with @@ -1982,10 +1989,12 @@ the .Ic cd command will print out the name of the directory that it actually switched to -if this is different from the name that the user gave. -These may be different either because the +if the .Va CDPATH -mechanism was used or because a symbolic link was crossed. +mechanism was used or if +.Ar directory +was +.Fl . .Pp If the .Fl P @@ -2774,6 +2783,10 @@ Initialization file for interactive shells. Locale settings. These are inherited by children of the shell, and is used in a limited manner by the shell itself. +.It Ev OLDPWD +The previous current directory. +This is used and updated by +.Ic cd . .It Ev PWD An absolute pathname for the current directory, possibly containing symbolic links. From 8705203e12c893788c5411aecab0a0c7b1500713 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 30 Jan 2016 21:21:25 +0000 Subject: [PATCH 064/236] sh: Don't allocate a redirtab if there are no redirections. Builtins (including variable assignments without command word), function calls and redirected compound commands need to restore file descriptors to their original state after execution. This is handled by allocating a redirtab structure. These mallocs and frees show up heavily in pmcstat. Only allocate a redirtab if there are actually redirections and maintain a count of how many levels of REDIR_PUSH there are without redirtabs. A simple loop without external programs like sh -c 'i=0; w=$(printf %0100d 7); while [ "$i" -lt 1000000 ]; do i=$((i+1)); done' is over 25% faster on an amd64 bhyve VM. --- bin/sh/redir.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/bin/sh/redir.c b/bin/sh/redir.c index 95d3238daf1b..0a7aa96fb601 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -70,6 +70,7 @@ struct redirtab { struct redirtab *next; int renamed[10]; int fd0_redirected; + unsigned int empty_redirs; }; @@ -82,6 +83,9 @@ static struct redirtab *redirlist; */ static int fd0_redirected = 0; +/* Number of redirtabs that have not been allocated. */ +static unsigned int empty_redirs = 0; + static void openredirect(union node *, char[10 ]); static int openhere(union node *); @@ -115,12 +119,17 @@ redirect(union node *redir, int flags) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { - sv = ckmalloc(sizeof (struct redirtab)); - for (i = 0 ; i < 10 ; i++) - sv->renamed[i] = EMPTY; - sv->fd0_redirected = fd0_redirected; - sv->next = redirlist; - redirlist = sv; + empty_redirs++; + if (redir != NULL) { + sv = ckmalloc(sizeof (struct redirtab)); + for (i = 0 ; i < 10 ; i++) + sv->renamed[i] = EMPTY; + sv->fd0_redirected = fd0_redirected; + sv->empty_redirs = empty_redirs - 1; + sv->next = redirlist; + redirlist = sv; + empty_redirs = 0; + } } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; @@ -303,6 +312,12 @@ popredir(void) struct redirtab *rp = redirlist; int i; + INTOFF; + if (empty_redirs > 0) { + empty_redirs--; + INTON; + return; + } for (i = 0 ; i < 10 ; i++) { if (rp->renamed[i] != EMPTY) { if (rp->renamed[i] >= 0) { @@ -313,8 +328,8 @@ popredir(void) } } } - INTOFF; fd0_redirected = rp->fd0_redirected; + empty_redirs = rp->empty_redirs; redirlist = rp->next; ckfree(rp); INTON; From aaa09f3f95ea590fcb532f5209ce37a04b52eb43 Mon Sep 17 00:00:00 2001 From: ian Date: Sat, 30 Jan 2016 22:03:14 +0000 Subject: [PATCH 065/236] Make pfctl(8) work on strict-alignment platforms, by copying a pair of embedded structures out of a packed, unaligned struct into local copies on the stack which are aligned. The original patch to do this was submitted by Guy Yur , and this is conceptually the same change, but restructured with the #ifndef __NO_STRICT_ALIGNMENT wrapper, similar to how the same issue is handled in the kernel pf code. PR: 185617 PR: 206658 --- sbin/pfctl/pf_print_state.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c index 46d4523373d5..346e6236f320 100644 --- a/sbin/pfctl/pf_print_state.c +++ b/sbin/pfctl/pf_print_state.c @@ -208,22 +208,30 @@ void print_state(struct pfsync_state *s, int opts) { struct pfsync_state_peer *src, *dst; - struct pfsync_state_key *sk, *nk; + struct pfsync_state_key *key, *sk, *nk; struct protoent *p; int min, sec; +#ifndef __NO_STRICT_ALIGNMENT + struct pfsync_state_key aligned_key[2]; + + bcopy(&s->key, aligned_key, sizeof(aligned_key)); + key = aligned_key; +#else + key = s->key; +#endif if (s->direction == PF_OUT) { src = &s->src; dst = &s->dst; - sk = &s->key[PF_SK_STACK]; - nk = &s->key[PF_SK_WIRE]; + sk = &key[PF_SK_STACK]; + nk = &key[PF_SK_WIRE]; if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) sk->port[0] = nk->port[0]; } else { src = &s->dst; dst = &s->src; - sk = &s->key[PF_SK_WIRE]; - nk = &s->key[PF_SK_STACK]; + sk = &key[PF_SK_WIRE]; + nk = &key[PF_SK_STACK]; if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) sk->port[1] = nk->port[1]; } From b58cf84475d50faf34154d618b960890cefdb6ba Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Jan 2016 22:48:06 +0000 Subject: [PATCH 066/236] Implement power command to list all power modes, find out the power mode we're in and to set the power mode. --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/nvmecontrol.8 | 17 +++ sbin/nvmecontrol/nvmecontrol.c | 1 + sbin/nvmecontrol/nvmecontrol.h | 4 + sbin/nvmecontrol/power.c | 185 +++++++++++++++++++++++++++++++++ sys/dev/nvme/nvme.h | 30 +++++- 6 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 sbin/nvmecontrol/power.c diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index ea60da3c2941..e8a23719a2a7 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -2,7 +2,7 @@ PROG= nvmecontrol SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \ - perftest.c reset.c nvme_util.c + perftest.c reset.c nvme_util.c power.c MAN= nvmecontrol.8 .PATH: ${.CURDIR}/../../sys/dev/nvme diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index 3b4b5c23aef3..ae8132ec5cbc 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -70,6 +70,11 @@ .Op Fl f Ar path_to_firmware .Op Fl a .Aq device id +.Nm +.Ic power +.Op Fl l +.Op Fl p power_state +.Op fl w workload_hint .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. @@ -120,6 +125,18 @@ Activate the firmware in slot 4 of the nvme0 controller on the next reset. .Pp Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the nvme0 controller and activate it on the next reset. +.Pp +.Dl nvmecontrol power -l nvme0 +.Pp +List all the current power modes. +.Pp +.Dl nvmecontrol power -p 3 nvme0 +.Pp +Set the current power mode. +.Pp +.Dl nvmecontrol power nvme0 +.Pp +Get the current power mode. .Sh AUTHORS .An -nosplit .Nm diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 4dee1909280a..cd7c19d0165d 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -58,6 +58,7 @@ static struct nvme_function { {"reset", reset, RESET_USAGE}, {"logpage", logpage, LOGPAGE_USAGE}, {"firmware", firmware, FIRMWARE_USAGE}, + {"power", power, POWER_USAGE}, {NULL, NULL, NULL}, }; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 8401dd7ccda3..b3cecd26dcea 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -55,12 +55,16 @@ #define FIRMWARE_USAGE \ " nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" +#define POWER_USAGE \ +" nvmecontrol power [-l] [-p new-state [-w workload-hint]] \n" + void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); void logpage(int argc, char *argv[]); void firmware(int argc, char *argv[]); +void power(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid); diff --git a/sbin/nvmecontrol/power.c b/sbin/nvmecontrol/power.c new file mode 100644 index 000000000000..e681ccd14dcc --- /dev/null +++ b/sbin/nvmecontrol/power.c @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2016 Netflix, 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 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +_Static_assert(sizeof(struct nvme_power_state) == 256 / NBBY, + "nvme_power_state size wrong"); + +static void +power_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, POWER_USAGE); + exit(1); +} + +static void +power_list_one(int i, struct nvme_power_state *nps) +{ + int mpower, apower, ipower; + + mpower = nps->mp; + if (nps->mps == 0) + mpower *= 100; + ipower = nps->idlp; + if (nps->ips == 1) + ipower *= 100; + apower = nps->actp; + if (nps->aps == 1) + apower *= 100; + printf("%2d: %2d.%04dW%c %3d.%03dms %3d.%03dms %2d %2d %2d %2d %2d.%04dW %2d.%04dW %d\n", + i, mpower / 10000, mpower % 10000, + nps->nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000, + nps->exlat / 1000, nps->exlat % 1000, nps->rrt, nps->rrl, + nps->rwt, nps->rwl, ipower / 10000, ipower % 10000, + apower / 10000, apower % 10000, nps->apw); +} + +static void +power_list(struct nvme_controller_data *cdata) +{ + int i; + + printf("\nPower States Supported: %d\n\n", cdata->npss + 1); + printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workloadd\n"); + printf("-- -------- --------- --------- -- -- -- -- -------- -------- --\n"); + for (i = 0; i <= cdata->npss; i++) + power_list_one(i, &cdata->power_state[i]); +} + +static void +power_set(int fd, int power, int workload, int perm) +{ + struct nvme_pt_command pt; + uint32_t p; + + p = perm ? (1u << 31) : 0; + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_SET_FEATURES; + pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT | p; + pt.cmd.cdw11 = power | (workload << 5); + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "set feature power mgmt request failed"); + + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "set feature power mgmt request returned error"); +} + +static void +power_show(int fd) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_GET_FEATURES; + pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "set feature power mgmt request failed"); + + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "set feature power mgmt request returned error"); + + printf("Current Power Mode is %d\n", pt.cpl.cdw0); +} + +void +power(int argc, char *argv[]) +{ + struct nvme_controller_data cdata; + int ch, listflag = 0, powerflag = 0, power = 0, fd; + int workload = 0; + char *end; + + while ((ch = getopt(argc, argv, "lp:w:")) != -1) { + switch ((char)ch) { + case 'l': + listflag = 1; + break; + case 'p': + powerflag = 1; + power = strtol(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "Invalid power state number: %s\n", optarg); + power_usage(); + } + break; + case 'w': + workload = strtol(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "Invalid workload hint: %s\n", optarg); + power_usage(); + } + break; + default: + power_usage(); + } + } + + /* Check that a controller was specified. */ + if (optind >= argc) + power_usage(); + + if (listflag && powerflag) { + fprintf(stderr, "Can't set power and list power states\n"); + power_usage(); + } + + open_dev(argv[optind], &fd, 1, 1); + read_controller_data(fd, &cdata); + + if (listflag) { + power_list(&cdata); + goto out; + } + + if (powerflag) { + power_set(fd, power, workload, 0); + goto out; + } + power_show(fd); + +out: + close(fd); + exit(0); +} diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h index 227a89ef0daf..19a63e8d5d7d 100644 --- a/sys/dev/nvme/nvme.h +++ b/sys/dev/nvme/nvme.h @@ -392,6 +392,34 @@ enum nvme_activate_action { NVME_AA_ACTIVATE = 0x2, }; +struct nvme_power_state { + /** Maximum Power */ + uint16_t mp; /* Maximum Power */ + uint8_t ps_rsvd1; + uint8_t mps : 1; /* Max Power Scale */ + uint8_t nops : 1; /* Non-Operational State */ + uint8_t ps_rsvd2 : 6; + uint32_t enlat; /* Entry Latency */ + uint32_t exlat; /* Exit Latency */ + uint8_t rrt : 5; /* Relative Read Throughput */ + uint8_t ps_rsvd3 : 3; + uint8_t rrl : 5; /* Relative Read Latency */ + uint8_t ps_rsvd4 : 3; + uint8_t rwt : 5; /* Relative Write Throughput */ + uint8_t ps_rsvd5 : 3; + uint8_t rwl : 5; /* Relative Write Latency */ + uint8_t ps_rsvd6 : 3; + uint16_t idlp; /* Idle Power */ + uint8_t ps_rsvd7 : 6; + uint8_t ips : 2; /* Idle Power Scale */ + uint8_t ps_rsvd8; + uint16_t actp; /* Active Power */ + uint8_t apw : 3; /* Active Power Workload */ + uint8_t ps_rsvd9 : 3; + uint8_t aps : 2; /* Active Power Scale */ + uint8_t ps_rsvd10[9]; +} __packed; + #define NVME_SERIAL_NUMBER_LENGTH 20 #define NVME_MODEL_NUMBER_LENGTH 40 #define NVME_FIRMWARE_REVISION_LENGTH 8 @@ -532,7 +560,7 @@ struct nvme_controller_data { uint8_t reserved5[1344]; /* bytes 2048-3071: power state descriptors */ - uint8_t reserved6[1024]; + struct nvme_power_state power_state[32]; /* bytes 3072-4095: vendor specific */ uint8_t vs[1024]; From 1d2b72fed204d35ae1b155efeb6423d0a9dded13 Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 08:06:22 +0000 Subject: [PATCH 067/236] ARM: Next round of cleanup in swtch-v*.S. - remove now useless #if __ARM_ARCH conditional - use macro for accessing CP15 registers - remove unused PCPU_SIZE Pointed by: kib --- sys/arm/arm/swtch-v4.S | 1 - sys/arm/arm/swtch-v6.S | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sys/arm/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S index 19933e1345be..52dc88c8f85e 100644 --- a/sys/arm/arm/swtch-v4.S +++ b/sys/arm/arm/swtch-v4.S @@ -99,7 +99,6 @@ __FBSDID("$FreeBSD$"); .Lcurpcpu: .word _C_LABEL(__pcpu) - .word PCPU_SIZE .Lblocked_lock: .word _C_LABEL(blocked_lock) diff --git a/sys/arm/arm/swtch-v6.S b/sys/arm/arm/swtch-v6.S index 34788eb001a2..3822cdbfe16a 100644 --- a/sys/arm/arm/swtch-v6.S +++ b/sys/arm/arm/swtch-v6.S @@ -85,13 +85,14 @@ #include #include #include +#include #include __FBSDID("$FreeBSD$"); -#if __ARM_ARCH >= 6 && defined(SMP) +#if defined(SMP) #define GET_PCPU(tmp, tmp2) \ - mrc p15, 0, tmp, c0, c0, 5; \ + mrc CP15_MPIDR(tmp); \ and tmp, tmp, #0xf; \ ldr tmp2, .Lcurpcpu+4; \ mul tmp, tmp, tmp2; \ @@ -113,9 +114,6 @@ __FBSDID("$FreeBSD$"); .Lblocked_lock: .word _C_LABEL(blocked_lock) - -#include - ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */ DSB mcr CP15_TTBR0(r0) /* set the new TTB */ From ef3ac0819b2bfbc97ffbb0135d436614d3020c55 Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 08:53:53 +0000 Subject: [PATCH 068/236] ARM: Convert spaces to tabs, fix formatting. Not a functional change. --- sys/arm/arm/swtch-v4.S | 27 ++++++++++++--------------- sys/arm/arm/swtch-v6.S | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/sys/arm/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S index 52dc88c8f85e..6fdbeed197c2 100644 --- a/sys/arm/arm/swtch-v4.S +++ b/sys/arm/arm/swtch-v4.S @@ -98,7 +98,7 @@ __FBSDID("$FreeBSD$"); #endif .Lcurpcpu: - .word _C_LABEL(__pcpu) + .word _C_LABEL(__pcpu) .Lblocked_lock: .word _C_LABEL(blocked_lock) @@ -129,7 +129,7 @@ ENTRY(cpu_throw) #endif GET_PCPU(r7, r9) - ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */ + ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */ /* Switch to lwp0 context */ @@ -275,25 +275,25 @@ ENTRY(cpu_switch) /* rem: r2 = old PCB */ /* rem: r9 = new PCB */ - ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */ + ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */ mov r2, #DOMAIN_CLIENT - cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */ - beq .Lcs_context_switched /* Yup. Don't flush cache */ - mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */ + cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */ + beq .Lcs_context_switched /* Yup. Don't flush cache */ + mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */ /* - * Get the new L1 table pointer into r11. If we're switching to + * Get the new L1 table pointer into r11. If we're switching to * an LWP with the same address space as the outgoing one, we can * skip the cache purge and the TTB load. * * To avoid data dep stalls that would happen anyway, we try * and get some useful work done in the mean time. */ - mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */ - ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */ + mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */ + ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */ - teq r10, r11 /* Same L1? */ - cmpeq r0, r5 /* Same DACR? */ - beq .Lcs_context_switched /* yes! */ + teq r10, r11 /* Same L1? */ + cmpeq r0, r5 /* Same DACR? */ + beq .Lcs_context_switched /* yes! */ /* * Definately need to flush the cache. @@ -375,6 +375,3 @@ ENTRY(cpu_switch) add r3, r9, #PCB_R4 ldmia r3, {r4-r12, sp, pc} END(cpu_switch) - - - diff --git a/sys/arm/arm/swtch-v6.S b/sys/arm/arm/swtch-v6.S index 3822cdbfe16a..ef2156a4f121 100644 --- a/sys/arm/arm/swtch-v6.S +++ b/sys/arm/arm/swtch-v6.S @@ -109,7 +109,7 @@ __FBSDID("$FreeBSD$"); #endif .Lcurpcpu: - .word _C_LABEL(__pcpu) + .word _C_LABEL(__pcpu) .word PCPU_SIZE .Lblocked_lock: .word _C_LABEL(blocked_lock) @@ -134,7 +134,7 @@ ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */ * it's the only place where standalone predictor flush must be * executed in kernel (except self modifying code case). */ - mcr CP15_BPIALL /* and flush entire Branch Target Cache */ + mcr CP15_BPIALL /* flush entire Branch Target Cache */ DSB mov pc, lr END(cpu_context_switch) @@ -155,9 +155,9 @@ ENTRY(cpu_throw) bl _C_LABEL(vfp_discard) /* VFP without preserving state. */ #endif GET_PCPU(r8, r9) /* r8 = current pcpu */ - ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */ + ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */ - cmp r10, #0 /* old thread? */ + cmp r10, #0 /* old thread? */ beq 2f /* no, skip */ /* Remove this CPU from the active list. */ @@ -206,7 +206,7 @@ ENTRY(cpu_throw) */ /* MMU switch to new thread. */ - ldr r0, [r7, #(PCB_PAGEDIR)] + ldr r0, [r7, #(PCB_PAGEDIR)] #ifdef INVARIANTS cmp r0, #0 /* new thread? */ beq badsw4 /* no, panic */ @@ -290,11 +290,11 @@ ENTRY(cpu_switch) * it is time to restore them for the new thread. However, * some registers are not safe over function call. */ - mov r9, r2 /* r9 = lock */ + mov r9, r2 /* r9 = lock */ mov r10, r0 /* r10 = oldtd */ mov r11, r1 /* r11 = newtd */ - GET_PCPU(r8, r3) /* r8 = current PCPU */ + GET_PCPU(r8, r3) /* r8 = current PCPU */ ldr r7, [r11, #(TD_PCB)] /* r7 = newtd->td_pcb */ @@ -341,8 +341,8 @@ ENTRY(cpu_switch) ldr r6, [r6, #P_VMSPACE] /* newtd->proc->vmspace */ add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */ - ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */ - str r6, [r8, #PC_CURPMAP] /* and save new one */ + ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */ + str r6, [r8, #PC_CURPMAP] /* and save new one */ mov r0, #PM_ACTIVE add r5, r0 /* r5 = old pm_active */ @@ -376,7 +376,7 @@ ENTRY(cpu_switch) #endif /* Set cpu to new active list. */ #ifdef SMP -1: ldrex r0, [r6] +1: ldrex r0, [r6] orr r0, r2 strex r1, r0, [r6] teq r1, #0 @@ -427,7 +427,7 @@ sw1: beq 1b #endif /* Set the new tls */ - ldr r0, [r11, #(TD_MD + MD_TP)] + ldr r0, [r11, #(TD_MD + MD_TP)] mcr CP15_TPIDRURO(r0) /* write tls thread reg 2 */ /* We have a new curthread now so make a note it */ @@ -450,7 +450,7 @@ badsw1: ldr r0, =sw1_panic_str bl _C_LABEL(panic) 1: nop - b 1b + b 1b badsw2: ldr r0, =sw2_panic_str From bce584a511ad0b0656d9f8efe013509e06a276ae Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 09:16:20 +0000 Subject: [PATCH 069/236] ARM: Rename ARM specific VM_MEMATTR_WT memory attribute to standard one. --- sys/arm/include/vm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 70a4ab9700bc..552460e9f9a9 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -38,13 +38,13 @@ #define VM_MEMATTR_NOCACHE ((vm_memattr_t)PTE2_ATTR_NOCACHE) #define VM_MEMATTR_DEVICE ((vm_memattr_t)PTE2_ATTR_DEVICE) #define VM_MEMATTR_SO ((vm_memattr_t)PTE2_ATTR_SO) -#define VM_MEMATTR_WT ((vm_memattr_t)PTE2_ATTR_WT) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PTE2_ATTR_WT) #define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA #define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */ #ifdef _KERNEL /* Don't export aliased VM_MEMATTR to userland */ -#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WT /* for DRM */ +#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WRITE_THROUGH /* for DRM */ #define VM_MEMATTR_WRITE_BACK VM_MEMATTR_WB_WA /* for DRM */ #endif #else From 7a376205b60afd75b2bea3e2699893aa9b366099 Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 13:59:16 +0000 Subject: [PATCH 070/236] ARM: First round of cpufunc.* cleaning. All abort_fixup functions are not currently used or defined. Delete them. --- sys/arm/arm/cpufunc.c | 48 --------------------------------------- sys/arm/include/cpufunc.h | 12 ---------- 2 files changed, 60 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index e479803006f7..a08008365542 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -155,9 +155,6 @@ struct cpu_functions arm9_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm9_context_switch, /* context_switch */ arm9_setup /* cpu setup */ @@ -220,9 +217,6 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm10_context_switch, /* context_switch */ arm10_setup /* cpu setup */ @@ -283,9 +277,6 @@ struct cpu_functions sheeva_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm10_context_switch, /* context_switch */ arm10_setup /* cpu setup */ @@ -345,10 +336,6 @@ struct cpu_functions pj4bv7_cpufuncs = { (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ - - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - armv7_context_switch, /* context_switch */ pj4bv7_setup /* cpu setup */ @@ -412,9 +399,6 @@ struct cpu_functions xscale_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - xscale_context_switch, /* context_switch */ xscale_setup /* cpu setup */ @@ -477,9 +461,6 @@ struct cpu_functions xscalec3_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - xscalec3_context_switch, /* context_switch */ xscale_setup /* cpu setup */ @@ -541,8 +522,6 @@ struct cpu_functions fa526_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ fa526_context_switch, /* context_switch */ @@ -605,9 +584,6 @@ struct cpu_functions arm1176_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm11_context_switch, /* context_switch */ arm11x6_setup /* cpu setup */ @@ -677,9 +653,6 @@ struct cpu_functions cortexa_cpufuncs = { /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - armv7_context_switch, /* context_switch */ cortexa_setup /* cpu setup */ @@ -994,27 +967,6 @@ set_cpufuncs() return (0); } -/* - * Fixup routines for data and prefetch aborts. - * - * Several compile time symbols are used - * - * DEBUG_FAULT_CORRECTION - Print debugging information during the - * correction of registers after a fault. - */ - - -/* - * Null abort fixup routine. - * For use when no fixup is required. - */ -int -cpufunc_null_fixup(arg) - void *arg; -{ - return(ABORT_FIXUP_OK); -} - /* * CPU Setup code */ diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index f842e0f6f375..1fecc4efa7b8 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -164,9 +164,6 @@ struct cpu_functions { /* Soft functions */ - int (*cf_dataabt_fixup) (void *arg); - int (*cf_prefetchabt_fixup) (void *arg); - void (*cf_context_switch) (void); void (*cf_setup) (void); @@ -215,12 +212,6 @@ extern u_int cputype; #define cpu_sleep(m) cpufuncs.cf_sleep(m) -#define cpu_dataabt_fixup(a) cpufuncs.cf_dataabt_fixup(a) -#define cpu_prefetchabt_fixup(a) cpufuncs.cf_prefetchabt_fixup(a) -#define ABORT_FIXUP_OK 0 /* fixup succeeded */ -#define ABORT_FIXUP_FAILED 1 /* fixup failed */ -#define ABORT_FIXUP_RETURN 2 /* abort handler should return */ - #define cpu_setup() cpufuncs.cf_setup() int set_cpufuncs (void); @@ -228,9 +219,6 @@ int set_cpufuncs (void); #define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */ void cpufunc_nullop (void); -int cpufunc_null_fixup (void *); -int early_abort_fixup (void *); -int late_abort_fixup (void *); u_int cpufunc_id (void); u_int cpufunc_cpuid (void); u_int cpufunc_control (u_int clear, u_int bic); From 8887150af48686df7b5c2f7317a20a9d5320ab5f Mon Sep 17 00:00:00 2001 From: smh Date: Sun, 31 Jan 2016 15:14:23 +0000 Subject: [PATCH 071/236] Configure ixgbe phy & gbic power Setup phy and gbic power as per Linux 4.3.13 driver. This fixes link not detected on X540-AT2 after booting to Linux which turns the phy power off on detach. Reviewed by: sbruno MFC after: 2 days Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D5107 --- sys/dev/ixgbe/if_ix.c | 12 ++++++++++++ sys/dev/ixgbe/ixgbe_phy.c | 3 +++ sys/dev/ixgbe/ixgbe_type.h | 3 +++ sys/dev/ixgbe/ixgbe_x540.c | 3 +-- sys/dev/ixgbe/ixgbe_x550.c | 19 +++++++++++++++++-- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 168fa1310f74..c6a50840d207 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -592,6 +592,12 @@ ixgbe_attach(device_t dev) if (error) goto err_late; + /* Enable the optics for 82599 SFP+ fiber */ + ixgbe_enable_tx_laser(hw); + + /* Enable power to the phy. */ + ixgbe_set_phy_power(hw, TRUE); + /* Setup OS specific network interface */ if (ixgbe_setup_interface(dev, adapter) != 0) goto err_late; @@ -1260,6 +1266,9 @@ ixgbe_init_locked(struct adapter *adapter) device_printf(dev, "Error setting up EEE: %d\n", err); } + /* Enable power to the phy. */ + ixgbe_set_phy_power(hw, TRUE); + /* Config/Enable Link */ ixgbe_config_link(adapter); @@ -3980,6 +3989,9 @@ ixgbe_setup_low_power_mode(struct adapter *adapter) mtx_assert(&adapter->core_mtx, MA_OWNED); + if (!hw->wol_enabled) + ixgbe_set_phy_power(hw, FALSE); + /* Limit power management flow to X550EM baseT */ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && hw->phy.ops.enter_lplu) { diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 6bff17291f1f..f5d22b252e3c 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -2734,6 +2734,9 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) u32 status; u16 reg; + if (!on && ixgbe_mng_present(hw)) + return 0; + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index d76cde26cddf..da03f79e5fc1 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -1479,7 +1479,10 @@ struct ixgbe_dmac_config { #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK 0xFF01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG 0xFC01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_ALARM_1 0xCC00 /* Global alarm 1 */ +#define IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT 0x0010 /* device fault */ #define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL 0x4000 /* high temp failure */ +#define IXGBE_MDIO_GLOBAL_FAULT_MSG 0xC850 /* Global Fault Message */ +#define IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP 0x8007 /* high temp failure */ #define IXGBE_MDIO_GLOBAL_INT_MASK 0xD400 /* Global int mask */ #define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN 0x1000 /* autoneg vendor alarm int enable */ #define IXGBE_MDIO_GLOBAL_ALARM_1_INT 0x4 /* int in Global alarm 1 */ diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c index 96478eaf6a7b..fd52ebeb8c52 100644 --- a/sys/dev/ixgbe/ixgbe_x540.c +++ b/sys/dev/ixgbe/ixgbe_x540.c @@ -82,8 +82,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw) /* PHY */ phy->ops.init = ixgbe_init_phy_ops_generic; phy->ops.reset = NULL; - if (!ixgbe_mng_present(hw)) - phy->ops.set_phy_power = ixgbe_set_copper_phy_power; + phy->ops.set_phy_power = ixgbe_set_copper_phy_power; /* MAC */ mac->ops.reset_hw = ixgbe_reset_hw_X540; diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c index d62035d44f9f..1199d38f9158 100644 --- a/sys/dev/ixgbe/ixgbe_x550.c +++ b/sys/dev/ixgbe/ixgbe_x550.c @@ -965,7 +965,7 @@ void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf) num_qs = 4; /* 32 VFs / pools */ bitmask = 0x0000000F; break; - default: /* 64 VFs / pools */ + default: /* 64 VFs / pools */ num_qs = 2; bitmask = 0x00000003; break; @@ -1264,7 +1264,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) IXGBE_MDIO_GLOBAL_ALARM_1_INT))) return status; - /* High temperature failure alarm triggered */ + /* Global alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); @@ -1277,6 +1277,21 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) /* power down the PHY in case the PHY FW didn't already */ ixgbe_set_copper_phy_power(hw, FALSE); return IXGBE_ERR_OVERTEMP; + } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { + /* device fault alarm triggered */ + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + ®); + + if (status != IXGBE_SUCCESS) + return status; + + /* if device fault was due to high temp alarm handle and exit */ + if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { + /* power down the PHY in case the PHY FW didn't */ + ixgbe_set_copper_phy_power(hw, FALSE); + return IXGBE_ERR_OVERTEMP; + } } /* Vendor alarm 2 triggered */ From acf1ac2c927e0b011984dfeb36d171e8307f06a9 Mon Sep 17 00:00:00 2001 From: smh Date: Sun, 31 Jan 2016 15:18:03 +0000 Subject: [PATCH 072/236] Fix ixgbe flow control autoneg reporting Fix ixgbe reporting of flow control autoneg when running under DBG 1 Reviewed by: erj MFC after: 2 days Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D5089 --- sys/dev/ixgbe/ixgbe_common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index d67e6802b184..feb74f6f8b34 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -199,9 +199,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) break; } - ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, + if (!supported) { + ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Device %x does not support flow control autoneg", hw->device_id); + } + return supported; } From 29094706e8c7e781bc4a022eaeab960349037d16 Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 15:36:13 +0000 Subject: [PATCH 073/236] ARM: Next round of cpufunc.* cleaning. Nobody uses flush_brnchtgt* functions, delete them. --- sys/arm/arm/cpufunc.c | 18 ------------------ sys/arm/arm/cpufunc_asm_fa526.S | 6 ------ sys/arm/include/cpufunc.h | 6 ------ 3 files changed, 30 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index a08008365542..aaf6040beefa 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -148,8 +148,6 @@ struct cpu_functions arm9_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ @@ -210,8 +208,6 @@ struct cpu_functions armv5_ec_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ @@ -270,8 +266,6 @@ struct cpu_functions sheeva_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ sheeva_cpu_sleep, /* sleep */ @@ -330,8 +324,6 @@ struct cpu_functions pj4bv7_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ @@ -392,8 +384,6 @@ struct cpu_functions xscale_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ @@ -454,8 +444,6 @@ struct cpu_functions xscalec3_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ @@ -515,8 +503,6 @@ struct cpu_functions fa526_cpufuncs = { fa526_flush_prefetchbuf, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */ fa526_cpu_sleep, /* sleep */ @@ -577,8 +563,6 @@ struct cpu_functions arm1176_cpufuncs = { arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */ arm11_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ arm11x6_sleep, /* sleep */ @@ -646,8 +630,6 @@ struct cpu_functions cortexa_cpufuncs = { cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ armv7_cpu_sleep, /* sleep */ diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index 55c2f376f738..7b524707e6f8 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -200,12 +200,6 @@ ENTRY(fa526_icache_sync_range) mov pc, lr END(fa526_icache_sync_range) -ENTRY(fa526_flush_brnchtgt_E) - mov r0, #0 - mcr p15, 0, r0, c7, c5, 6 /* invalidate BTB cache */ - mov pc, lr -END(fa526_flush_brnchtgt_E) - ENTRY(fa526_context_switch) /* * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 1fecc4efa7b8..c997a8ee4255 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -157,8 +157,6 @@ struct cpu_functions { void (*cf_flush_prefetchbuf) (void); void (*cf_drain_writebuf) (void); - void (*cf_flush_brnchtgt_C) (void); - void (*cf_flush_brnchtgt_E) (u_int va); void (*cf_sleep) (int mode); @@ -207,9 +205,6 @@ extern u_int cputype; #define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf() #define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() -#define cpu_flush_brnchtgt_C() cpufuncs.cf_flush_brnchtgt_C() -#define cpu_flush_brnchtgt_E(e) cpufuncs.cf_flush_brnchtgt_E(e) - #define cpu_sleep(m) cpufuncs.cf_sleep(m) #define cpu_setup() cpufuncs.cf_setup() @@ -235,7 +230,6 @@ void fa526_cpu_sleep (int); void fa526_tlb_flushI_SE (u_int); void fa526_tlb_flushID_SE (u_int); void fa526_flush_prefetchbuf (void); -void fa526_flush_brnchtgt_E (u_int); void fa526_icache_sync_all (void); void fa526_icache_sync_range(vm_offset_t start, vm_size_t end); From 0ea74690b74f680896dfb426353ecb703a5de558 Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 16:34:06 +0000 Subject: [PATCH 074/236] ARM: cpufunc_domains, cpufunc_faultstatus and cpufunc_faultaddress functions are equal for all ARM variants. Remove them from cpu_functions table. --- sys/arm/arm/cpufunc.c | 42 +++------------------------------------ sys/arm/arm/cpufunc_asm.S | 19 +++++++----------- sys/arm/include/cpufunc.h | 17 ++++------------ 3 files changed, 14 insertions(+), 64 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index aaf6040beefa..6ac516fa9b1a 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -105,16 +105,12 @@ int ctrl; struct cpu_functions arm9_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ arm9_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ @@ -164,16 +160,12 @@ struct cpu_functions arm9_cpufuncs = { struct cpu_functions armv5_ec_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ armv5_ec_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ @@ -222,16 +214,12 @@ struct cpu_functions armv5_ec_cpufuncs = { struct cpu_functions sheeva_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ sheeva_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ @@ -281,16 +269,12 @@ struct cpu_functions sheeva_cpufuncs = { struct cpu_functions pj4bv7_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ armv7_drain_writebuf, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ armv7_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ @@ -341,16 +325,12 @@ struct cpu_functions pj4bv7_cpufuncs = { struct cpu_functions xscale_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ xscale_cpwait, /* cpwait */ /* MMU functions */ xscale_control, /* control */ - cpufunc_domains, /* domain */ xscale_setttb, /* setttb */ - cpufunc_faultstatus, /* faultstatus */ - cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ @@ -401,16 +381,12 @@ struct cpu_functions xscale_cpufuncs = { struct cpu_functions xscalec3_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ xscale_cpwait, /* cpwait */ /* MMU functions */ xscale_control, /* control */ - cpufunc_domains, /* domain */ xscalec3_setttb, /* setttb */ - cpufunc_faultstatus, /* faultstatus */ - cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ @@ -460,16 +436,12 @@ struct cpu_functions xscalec3_cpufuncs = { struct cpu_functions fa526_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* domain */ fa526_setttb, /* setttb */ - cpufunc_faultstatus, /* faultstatus */ - cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ @@ -519,16 +491,12 @@ struct cpu_functions fa526_cpufuncs = { struct cpu_functions arm1176_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ arm11x6_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ @@ -578,16 +546,12 @@ struct cpu_functions arm1176_cpufuncs = { struct cpu_functions cortexa_cpufuncs = { /* CPU functions */ - cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ - cpufunc_domains, /* Domain */ armv7_setttb, /* Setttb */ - cpufunc_faultstatus, /* Faultstatus */ - cpufunc_faultaddress, /* Faultaddress */ /* * TLB functions. ARMv7 does all TLB ops based on a unified TLB model @@ -681,7 +645,7 @@ get_cachetype_cp15() __asm __volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctype)); - cpuid = cpufunc_id(); + cpuid = cpu_ident(); /* * ...and thus spake the ARM ARM: * @@ -788,7 +752,7 @@ get_cachetype_cp15() int set_cpufuncs() { - cputype = cpufunc_id(); + cputype = cpu_ident(); cputype &= CPU_ID_CPU_MASK; #ifdef CPU_ARM9 @@ -1074,7 +1038,7 @@ arm11x6_setup(void) uint32_t sbz=0; uint32_t cpuid; - cpuid = cpufunc_id(); + cpuid = cpu_ident(); cpuctrl = CPU_CONTROL_MMU_ENABLE | diff --git a/sys/arm/arm/cpufunc_asm.S b/sys/arm/arm/cpufunc_asm.S index 12f5840365d1..ea3a721e45aa 100644 --- a/sys/arm/arm/cpufunc_asm.S +++ b/sys/arm/arm/cpufunc_asm.S @@ -62,16 +62,11 @@ END(cpufunc_nullop) * */ -ENTRY(cpufunc_id) +ENTRY(cpu_ident) mrc p15, 0, r0, c0, c0, 0 RET END(cpufunc_id) -ENTRY(cpufunc_cpuid) - mrc p15, 0, r0, c0, c0, 0 - RET -END(cpufunc_cpuid) - ENTRY(cpu_get_control) mrc p15, 0, r0, c1, c0, 0 RET @@ -82,15 +77,15 @@ ENTRY(cpu_read_cache_config) RET END(cpu_read_cache_config) -ENTRY(cpufunc_faultstatus) +ENTRY(cpu_faultstatus) mrc p15, 0, r0, c5, c0, 0 RET -END(cpufunc_faultstatus) +END(cpu_faultstatus) -ENTRY(cpufunc_faultaddress) +ENTRY(cpu_faultaddress) mrc p15, 0, r0, c6, c0, 0 RET -END(cpufunc_faultaddress) +END(cpu_faultaddress) /* * Generic functions to write the internal coprocessor registers @@ -110,10 +105,10 @@ ENTRY(cpufunc_control) END(cpufunc_control) #endif -ENTRY(cpufunc_domains) +ENTRY(cpu_domains) mcr p15, 0, r0, c3, c0, 0 RET -END(cpufunc_domains) +END(cpu_domains) /* * Generic functions to read/modify/write the internal coprocessor registers diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index c997a8ee4255..55fa13fe4b65 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -60,16 +60,12 @@ struct cpu_functions { /* CPU functions */ - u_int (*cf_id) (void); void (*cf_cpwait) (void); /* MMU functions */ u_int (*cf_control) (u_int bic, u_int eor); - void (*cf_domains) (u_int domains); void (*cf_setttb) (u_int ttb); - u_int (*cf_faultstatus) (void); - u_int (*cf_faultaddress) (void); /* TLB functions */ @@ -170,14 +166,10 @@ struct cpu_functions { extern struct cpu_functions cpufuncs; extern u_int cputype; -#define cpu_ident() cpufuncs.cf_id() #define cpu_cpwait() cpufuncs.cf_cpwait() #define cpu_control(c, e) cpufuncs.cf_control(c, e) -#define cpu_domains(d) cpufuncs.cf_domains(d) #define cpu_setttb(t) cpufuncs.cf_setttb(t) -#define cpu_faultstatus() cpufuncs.cf_faultstatus() -#define cpu_faultaddress() cpufuncs.cf_faultaddress() #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() #define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e) @@ -214,12 +206,11 @@ int set_cpufuncs (void); #define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */ void cpufunc_nullop (void); -u_int cpufunc_id (void); -u_int cpufunc_cpuid (void); +u_int cpu_ident (void); u_int cpufunc_control (u_int clear, u_int bic); -void cpufunc_domains (u_int domains); -u_int cpufunc_faultstatus (void); -u_int cpufunc_faultaddress (void); +void cpu_domains (u_int domains); +u_int cpu_faultstatus (void); +u_int cpu_faultaddress (void); u_int cpu_pfr (int); #if defined(CPU_FA526) From f3fd5fb6506e47f14a0398218b03da192cc6a6fb Mon Sep 17 00:00:00 2001 From: mmel Date: Sun, 31 Jan 2016 16:55:52 +0000 Subject: [PATCH 075/236] ARM: Fix END() symbol for cpu_ident function. I forgot to rename it in r295096. --- sys/arm/arm/cpufunc_asm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm/arm/cpufunc_asm.S b/sys/arm/arm/cpufunc_asm.S index ea3a721e45aa..2f733f564cbf 100644 --- a/sys/arm/arm/cpufunc_asm.S +++ b/sys/arm/arm/cpufunc_asm.S @@ -65,7 +65,7 @@ END(cpufunc_nullop) ENTRY(cpu_ident) mrc p15, 0, r0, c0, c0, 0 RET -END(cpufunc_id) +END(cpu_ident) ENTRY(cpu_get_control) mrc p15, 0, r0, c1, c0, 0 From aac959f2803afefc82f457e5b8b61a12c89b1396 Mon Sep 17 00:00:00 2001 From: andrew Date: Sun, 31 Jan 2016 17:32:20 +0000 Subject: [PATCH 076/236] Fix the logic in the ddb command 'show ktr /a'. Prior to r118269 it would print until cncheckc returned a non -1, i.e. a character had been entered. After this change it would print only if cncheckc returned a character. As this was before each call to db_mach_vtrace the normal outcome was nothing was printed. With this change 'show ktr /a' will now keep printing until the user stops the command with a key press, or there is no more entries to print. --- sys/kern/kern_ktr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c index 6885706e4c06..1af3b94f55d4 100644 --- a/sys/kern/kern_ktr.c +++ b/sys/kern/kern_ktr.c @@ -419,7 +419,7 @@ DB_SHOW_COMMAND(ktr, db_ktr_all) db_ktr_verbose |= (strchr(modif, 'V') != NULL) ? 1 : 0; /* just timestap please */ if (strchr(modif, 'a') != NULL) { db_disable_pager(); - while (cncheckc() != -1) + while (cncheckc() == -1) if (db_mach_vtrace() == 0) break; } else { From 9813c740a6fa121e9da1a79356aa50992f82aaa2 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 31 Jan 2016 17:32:58 +0000 Subject: [PATCH 077/236] Add make universe targets "kernels" and "worlds". "make kernels" is now shorthand for "make universe -DMAKE_JUST_KERNELS" "make worlds" is now shorthand for "make universe -DMAKE_JUST_WORLDS" The kernels target includes modules (unless you add -DNO_MODULES). And of course you can still add all the other universe options, such as "make kernels TARGETS=arm" to build kernels for all arm arches, or TARGET_ARCH=armv6 to build all armv6 kernels, etc. Reviewed by: imp --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index acb061bf8a74..7467cd2b1687 100644 --- a/Makefile +++ b/Makefile @@ -328,7 +328,7 @@ bmake: .PHONY ${MMAKE} all; \ ${MMAKE} install DESTDIR=${MYMAKE:H} BINDIR= -tinderbox toolchains kernel-toolchains: upgrade_checks +tinderbox toolchains kernel-toolchains kernels worlds: upgrade_checks tinderbox: @cd ${.CURDIR}; ${SUB_MAKE} DOING_TINDERBOX=YES universe @@ -339,6 +339,12 @@ toolchains: kernel-toolchains: @cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=kernel-toolchain universe +kernels: + @cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=buildkernel universe + +worlds: + @cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=buildworld universe + # # universe # From 37617f7cb005082f23a6727fb7fdf8740ea668d9 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:14:31 +0000 Subject: [PATCH 078/236] Reset OPTIND to 1 in f_device_find() --- usr.sbin/bsdconfig/share/device.subr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr index d95684dc702e..97c3ecd99586 100644 --- a/usr.sbin/bsdconfig/share/device.subr +++ b/usr.sbin/bsdconfig/share/device.subr @@ -1,6 +1,6 @@ if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1 # -# Copyright (c) 2012-2014 Devin Teske +# Copyright (c) 2012-2016 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1032,7 +1032,7 @@ f_device_is_active() # f_device_find() { - local OPTIND OPTARG flag only_one= + local OPTIND=1 OPTARG flag only_one= while getopts 1 flag; do case "$flag" in 1) only_one=1 ;; From 089e1927c5f216d8771aed2b3c7cd3fb97a84663 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:22:10 +0000 Subject: [PATCH 079/236] Optimize f_sprintf() for bash bash lacks the ksh93 optimization that makes sub-shells fast if they do not alter io. bash 3.1-alpha1 introduced printf -v var_to_set which is not as fast but is still significantly faster than var_to_set=$( printf ) when using any version of bash. If we find our interpreter to somehow be bash by invocation or inclusion, use the feature that provides fastest results. --- usr.sbin/bsdconfig/share/strings.subr | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index e0cd7e0a1d5a..aafa8915c0ed 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -138,7 +138,15 @@ f_sprintf() { local __var_to_set="$1" shift 1 # var_to_set - eval "$__var_to_set"=\$\( printf -- \"\$@\" \) + + case "$BASH_VERSION" in + 3.1*|4.*) + local __tmp + printf -v __tmp "$@" + eval "$__var_to_set"=\"\${__tmp%\$NL}\" + ;; + *) eval "$__var_to_set"=\$\( printf -- \"\$@\" \) + esac } # f_vsnprintf $var_to_set $size $format $format_args From 1240a0f4ee67c9e42e747c5c2896f09ec87b5378 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:28:41 +0000 Subject: [PATCH 080/236] Optimize f_substr() to use built-ins only Change f_snprintf() to use optimzed f_substr() --- usr.sbin/bsdconfig/share/strings.subr | 89 +++++++++++++++++---------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index aafa8915c0ed..bb2e95d15579 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -1,6 +1,6 @@ if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1 # -# Copyright (c) 2006-2013 Devin Teske +# Copyright (c) 2006-2016 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -52,44 +52,53 @@ VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" ############################################################ FUNCTIONS -# f_substr "$string" $start [$length] +# f_substr [-v $var_to_set] $string $start [$length] # -# Simple wrapper to awk(1)'s `substr' function. +# Similar to awk(1)'s substr(), return length substring of string that begins +# at start position counted from 1. # f_substr() { - local string="$1" start="${2:-0}" len="${3:-0}" - echo "$string" | awk "{ print substr(\$0, $start, $len) }" -} + local OPTIND=1 OPTARG __flag __var_to_set= + while getopts v: __flag; do + case "$__flag" in + v) __var_to_set="$OPTARG" ;; + esac + done + shift $(( $OPTIND - 1 )) + + local __tmp="$1" __start="${2:-1}" __size="$3" + local __tbuf __tbuf_len __trim __trimq -# f_snprintf $var_to_set $size $format [$arguments ...] -# -# Similar to snprintf(3), write at most $size number of bytes into $var_to_set -# using printf(1) syntax (`$format [$arguments ...]'). The value of $var_to_set -# is NULL unless at-least one byte is stored from the output. -# -f_snprintf() -{ - local __funcname=f_snprintf - local __var_to_set="$1" __size="$2" - shift 2 # var_to_set size - - if [ "$__size" -eq 0 ] 2> /dev/null; then - setvar "$__var_to_set" "" + if [ ! "$__tmp" ]; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" return ${SUCCESS:-0} - elif [ $? -ge 2 ] || [ $__size -lt 0 ]; then - setvar "$__var_to_set" "" - echo "$__funcname: invalid size argument \`__size'" >&2 + fi + [ "$__start" -ge 1 ] 2> /dev/null || __start=1 + if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" return ${FAILURE:-1} fi - local __f_snprintf_tmp - f_sprintf __f_snprintf_tmp "$@" + __trim=$(( $__start - 1 )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 + while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]; do + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + done + __trimq=$(( $__trim / $__tbuf_len )) + __trim=$(( $__trim - $__tbuf_len * $__trimq )) + while [ $__trimq -gt 0 ]; do + __tmp="${__tmp#$__tbuf}" + __trimq=$(( $__trimq - 1 )) + done + done - local __tmp_size=${#__f_snprintf_tmp} - local __trim=$(( $__tmp_size - $__size )) __trimq - local __tbuf __tbuf_len + local __tmp_size=${#__tmp} local __mask __mask_len + __trim=$(( $__tmp_size - ${__size:-$__tmp_size} )) while [ $__trim -gt 0 ]; do __tbuf="?" __tbuf_len=1 @@ -102,11 +111,11 @@ f_snprintf() __trimq=$(( $__trim / $__tbuf_len )) __trim=$(( $__trim - $__tbuf_len * $__trimq )) while [ $__trimq -gt 0 ]; do - __f_snprintf_tmp="${__f_snprintf_tmp%$__tbuf}" + __tmp="${__tmp%$__tbuf}" __trimq=$(( $__trimq - 1 )) done else - __mask="$__f_snprintf_tmp" + __mask="$__tmp" while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ] do __tbuf="$__tbuf?" @@ -123,10 +132,26 @@ f_snprintf() __mask="${__mask#$__tbuf}" __trimq=$(( $__trimq - 1 )) done - __f_snprintf_tmp="${__f_snprintf_tmp%"$__mask"}" + __tmp="${__tmp%"$__mask"}" fi done - setvar "$__var_to_set" "$__f_snprintf_tmp" + + setvar "$__var_to_set" "$__tmp" +} + +# f_snprintf $var_to_set $size $format [$arguments ...] +# +# Similar to snprintf(3), write at most $size number of bytes into $var_to_set +# using printf(1) syntax (`$format [$arguments ...]'). +# +f_snprintf() +{ + local __var_to_set="$1" __size="$2" + shift 2 # var_to_set size + + local __f_snprintf_tmp + f_sprintf __f_snprintf_tmp "$@" + f_substr "$__var_to_set" "$__f_snprintf_tmp" 1 "$__size" } # f_sprintf $var_to_set $format [$arguments ...] From d869ee600b2d80c3f0e212b40018f765aaa17390 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:30:02 +0000 Subject: [PATCH 081/236] Move f_sprintf() above f_snprintf() Ordering functions by appearance of use --- usr.sbin/bsdconfig/share/strings.subr | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index bb2e95d15579..4237f42aee0f 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -139,21 +139,6 @@ f_substr() setvar "$__var_to_set" "$__tmp" } -# f_snprintf $var_to_set $size $format [$arguments ...] -# -# Similar to snprintf(3), write at most $size number of bytes into $var_to_set -# using printf(1) syntax (`$format [$arguments ...]'). -# -f_snprintf() -{ - local __var_to_set="$1" __size="$2" - shift 2 # var_to_set size - - local __f_snprintf_tmp - f_sprintf __f_snprintf_tmp "$@" - f_substr "$__var_to_set" "$__f_snprintf_tmp" 1 "$__size" -} - # f_sprintf $var_to_set $format [$arguments ...] # # Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax @@ -174,6 +159,21 @@ f_sprintf() esac } +# f_snprintf $var_to_set $size $format [$arguments ...] +# +# Similar to snprintf(3), write at most $size number of bytes into $var_to_set +# using printf(1) syntax (`$format [$arguments ...]'). +# +f_snprintf() +{ + local __var_to_set="$1" __size="$2" + shift 2 # var_to_set size + + local __f_snprintf_tmp + f_sprintf __f_snprintf_tmp "$@" + f_substr "$__var_to_set" "$__f_snprintf_tmp" 1 "$__size" +} + # f_vsnprintf $var_to_set $size $format $format_args # # Similar to vsnprintf(3), write at most $size number of bytes into $var_to_set From 787316176728e376efcc9bfaee26d2d429e11a14 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:31:24 +0000 Subject: [PATCH 082/236] Move f_vsprintf() below f_sprintf() Variable argument versions grouped with standard versions --- usr.sbin/bsdconfig/share/strings.subr | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 4237f42aee0f..1e78b755e3a6 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -159,6 +159,16 @@ f_sprintf() esac } +# f_vsprintf $var_to_set $format $format_args +# +# Similar to vsprintf(3), write a string into $var_to_set using printf(1) +# syntax (`$format $format_args'). +# +f_vsprintf() +{ + eval f_sprintf \"\$1\" \"\$2\" $3 +} + # f_snprintf $var_to_set $size $format [$arguments ...] # # Similar to snprintf(3), write at most $size number of bytes into $var_to_set @@ -209,16 +219,6 @@ f_vsnprintf() eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4 } -# f_vsprintf $var_to_set $format $format_args -# -# Similar to vsprintf(3), write a string into $var_to_set using printf(1) -# syntax (`$format $format_args'). -# -f_vsprintf() -{ - eval f_sprintf \"\$1\" \"\$2\" $3 -} - # f_longest_line_length # # Simple wrapper to an awk(1) script to print the length of the longest line of From 5a5c0e7cfee968bb2f62f27d5de3671f2c170845 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:33:24 +0000 Subject: [PATCH 083/236] Move f_isinteger() to the top Grouping builtins-only algos together --- usr.sbin/bsdconfig/share/strings.subr | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 1e78b755e3a6..093084514558 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -52,6 +52,16 @@ VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" ############################################################ FUNCTIONS +# f_isinteger $arg +# +# Returns true if argument is a positive/negative whole integer. +# +f_isinteger() +{ + local arg="${1#-}" + [ "${arg:-x}" = "${arg%[!0-9]*}" ] +} + # f_substr [-v $var_to_set] $string $start [$length] # # Similar to awk(1)'s substr(), return length substring of string that begins @@ -267,16 +277,6 @@ f_number_of_lines() awk "$f_number_of_lines_awk" } -# f_isinteger $arg -# -# Returns true if argument is a positive/negative whole integer. -# -f_isinteger() -{ - local arg="${1#-}" - [ "${arg:-x}" = "${arg%[!0-9]*}" ] -} - # f_uriencode [$text] # # Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric From 279666ea90b23a114d8b7018e1c4a49ddaf4f45a Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 31 Jan 2016 21:34:25 +0000 Subject: [PATCH 084/236] Move awk(1)-dependent recipes to the bottom --- usr.sbin/bsdconfig/share/strings.subr | 228 +++++++++++++------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 093084514558..1a4fe6ef081c 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -229,120 +229,6 @@ f_vsnprintf() eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4 } -# f_longest_line_length -# -# Simple wrapper to an awk(1) script to print the length of the longest line of -# input (read from stdin). Supports the newline escape-sequence `\n' for -# splitting a single line into multiple lines. -# -f_longest_line_length_awk=' -BEGIN { longest = 0 } -{ - if (split($0, lines, /\\n/) > 1) - { - for (n in lines) - { - len = length(lines[n]) - longest = ( len > longest ? len : longest ) - } - } - else - { - len = length($0) - longest = ( len > longest ? len : longest ) - } -} -END { print longest } -' -f_longest_line_length() -{ - awk "$f_longest_line_length_awk" -} - -# f_number_of_lines -# -# Simple wrapper to an awk(1) script to print the number of lines read from -# stdin. Supports newline escape-sequence `\n' for splitting a single line into -# multiple lines. -# -f_number_of_lines_awk=' -BEGIN { num_lines = 0 } -{ - num_lines += split(" "$0, unused, /\\n/) -} -END { print num_lines } -' -f_number_of_lines() -{ - awk "$f_number_of_lines_awk" -} - -# f_uriencode [$text] -# -# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric -# characters are converted to `%XX' sequence where XX represents the hexa- -# decimal ordinal of the non-alphanumeric character. If $text is missing, data -# is instead read from standard input. -# -f_uriencode_awk=' -BEGIN { - output = "" - for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n) -} -{ - sline = "" - slen = length($0) - for (n = 1; n <= slen; n++) { - char = substr($0, n, 1) - if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char] - sline = sline char - } - output = output ( output ? "%0a" : "" ) sline -} -END { print output } -' -f_uriencode() -{ - if [ $# -gt 0 ]; then - echo "$1" | awk "$f_uriencode_awk" - else - awk "$f_uriencode_awk" - fi -} - -# f_uridecode [$text] -# -# Decode $text from a URI. Encoded characters are converted from their `%XX' -# sequence into original unencoded ASCII sequences. If $text is missing, data -# is instead read from standard input. -# -f_uridecode_awk=' -BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) } -{ - sline = "" - slen = length($0) - for (n = 1; n <= slen; n++) - { - seq = substr($0, n, 3) - if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) { - hex = substr(seq, 2, 2) - sline = sline chr[sprintf("%u", "0x"hex)] - n += 2 - } else - sline = sline substr(seq, 1, 1) - } - print sline -} -' -f_uridecode() -{ - if [ $# -gt 0 ]; then - echo "$1" | awk "$f_uridecode_awk" - else - awk "$f_uridecode_awk" - fi -} - # f_replaceall $string $find $replace [$var_to_set] # # Replace all occurrences of $find in $string with $replace. If $var_to_set is @@ -526,6 +412,120 @@ f_expand_number() fi } +# f_longest_line_length +# +# Simple wrapper to an awk(1) script to print the length of the longest line of +# input (read from stdin). Supports the newline escape-sequence `\n' for +# splitting a single line into multiple lines. +# +f_longest_line_length_awk=' +BEGIN { longest = 0 } +{ + if (split($0, lines, /\\n/) > 1) + { + for (n in lines) + { + len = length(lines[n]) + longest = ( len > longest ? len : longest ) + } + } + else + { + len = length($0) + longest = ( len > longest ? len : longest ) + } +} +END { print longest } +' +f_longest_line_length() +{ + awk "$f_longest_line_length_awk" +} + +# f_number_of_lines +# +# Simple wrapper to an awk(1) script to print the number of lines read from +# stdin. Supports newline escape-sequence `\n' for splitting a single line into +# multiple lines. +# +f_number_of_lines_awk=' +BEGIN { num_lines = 0 } +{ + num_lines += split(" "$0, unused, /\\n/) +} +END { print num_lines } +' +f_number_of_lines() +{ + awk "$f_number_of_lines_awk" +} + +# f_uriencode [$text] +# +# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric +# characters are converted to `%XX' sequence where XX represents the hexa- +# decimal ordinal of the non-alphanumeric character. If $text is missing, data +# is instead read from standard input. +# +f_uriencode_awk=' +BEGIN { + output = "" + for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n) +} +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) { + char = substr($0, n, 1) + if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char] + sline = sline char + } + output = output ( output ? "%0a" : "" ) sline +} +END { print output } +' +f_uriencode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uriencode_awk" + else + awk "$f_uriencode_awk" + fi +} + +# f_uridecode [$text] +# +# Decode $text from a URI. Encoded characters are converted from their `%XX' +# sequence into original unencoded ASCII sequences. If $text is missing, data +# is instead read from standard input. +# +f_uridecode_awk=' +BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) } +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) + { + seq = substr($0, n, 3) + if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) { + hex = substr(seq, 2, 2) + sline = sline chr[sprintf("%u", "0x"hex)] + n += 2 + } else + sline = sline substr(seq, 1, 1) + } + print sline +} +' +f_uridecode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uridecode_awk" + else + awk "$f_uridecode_awk" + fi +} + ############################################################ MAIN f_dprintf "%s: Successfully loaded." strings.subr From b1110bdf93dbca4d5481aa6649af2ae11eddf475 Mon Sep 17 00:00:00 2001 From: dteske Date: Mon, 1 Feb 2016 00:54:26 +0000 Subject: [PATCH 085/236] Utilize new `-v var_to_set' of f_snprintf() --- usr.sbin/bsdconfig/bsdconfig | 4 ++-- usr.sbin/bsdconfig/networking/share/media.subr | 12 ++++++------ usr.sbin/bsdconfig/networking/share/resolv.subr | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig index 993865cacc8c..2ecdb30bc5a9 100755 --- a/usr.sbin/bsdconfig/bsdconfig +++ b/usr.sbin/bsdconfig/bsdconfig @@ -212,7 +212,7 @@ dialog_menu_main() *) menu_program="$menuitem/$menu_program" esac - tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) + f_substr -v tag "$DIALOG_MENU_TAGS" $index 1 setvar "menu_program$tag" "$menu_program" f_shell_escape "$menu_title" menu_title @@ -256,7 +256,7 @@ dialog_menu_main() *) menu_program="$BSDCFG_LOCAL_LIBE/$menuitem/$menu_program" esac - tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) + f_substr -v tag "$DIALOG_MENU_TAGS" $index 1 setvar "menu_program$tag" "$menu_program" f_shell_escape "$menu_title" menu_title diff --git a/usr.sbin/bsdconfig/networking/share/media.subr b/usr.sbin/bsdconfig/networking/share/media.subr index 1cb77f802948..028944b5eb6b 100644 --- a/usr.sbin/bsdconfig/networking/share/media.subr +++ b/usr.sbin/bsdconfig/networking/share/media.subr @@ -180,18 +180,18 @@ f_dialog_menu_media_options() f_ifconfig_media $interface | \ ( index=1 - echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" - echo "'$opt_none'" + f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1 + echo "'$tagn' '$opt_none'" index=$(( $index + 1 )) - echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" - echo "'$opt_cust'" + f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1 + echo "'$tagn' '$opt_cust'" index=$(( $index + 1 )) while read media_options; do [ $index -lt ${#DIALOG_MENU_TAGS} ] || break - echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" - echo "'$media_options'" + f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1 + echo "'$tagn' '$media_options'" index=$(( $index + 1 )) done ) diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr index fc42e1265c9c..779863c9981d 100644 --- a/usr.sbin/bsdconfig/networking/share/resolv.subr +++ b/usr.sbin/bsdconfig/networking/share/resolv.subr @@ -441,7 +441,7 @@ f_dialog_menu_nameservers() for ns in $nameservers; do [ $index -lt ${#DIALOG_MENU_TAGS} ] || break - tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) + f_substr -v tag "$DIALOG_MENU_TAGS" $index 1 echo "'$tag nameserver' '$ns'" index=$(( $index + 1 )) done From d1bdb4dcfedb4b60c32f6ac621c6f3fae9c846e2 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Mon, 1 Feb 2016 02:04:40 +0000 Subject: [PATCH 086/236] Use the correct type to pmap_mapdev() in nexus_activate_resource(). pmap_mapdev() takes vm_paddr_t, which may be sized differently from vm_offset_t, as it is in book-e. Sponsored by: Alex Perez/Inertial Computing --- sys/powerpc/powerpc/nexus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c index 8a4d81583f67..dff21f804146 100644 --- a/sys/powerpc/powerpc/nexus.c +++ b/sys/powerpc/powerpc/nexus.c @@ -189,13 +189,13 @@ nexus_activate_resource(device_t bus __unused, device_t child __unused, { if (type == SYS_RES_MEMORY) { - vm_offset_t start; + vm_paddr_t start; void *p; - start = (vm_offset_t) rman_get_start(r); + start = (vm_paddr_t) rman_get_start(r); if (bootverbose) - printf("nexus mapdev: start %zx, len %ld\n", start, - rman_get_size(r)); + printf("nexus mapdev: start %jx, len %ld\n", + (uintmax_t)start, rman_get_size(r)); p = pmap_mapdev(start, (vm_size_t) rman_get_size(r)); if (p == NULL) From e230f0c486d60c9fb0ed0f2f8a528e6be2cf7d91 Mon Sep 17 00:00:00 2001 From: araujo Date: Mon, 1 Feb 2016 02:31:59 +0000 Subject: [PATCH 087/236] Clean up unused-but-set-variable spotted by gcc-4.9. Reviewed by: mav, slm Approved by: rodrigc (mentor) MFC after: 2 weeks Sponsored by: gandi.net --- sys/dev/mps/mps_mapping.c | 4 +--- sys/dev/mps/mps_sas.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c index d0819efc26e9..d96f33cdd919 100644 --- a/sys/dev/mps/mps_mapping.c +++ b/sys/dev/mps/mps_mapping.c @@ -890,7 +890,7 @@ _mapping_get_dev_info(struct mps_softc *sc, u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - u8 entry, enc_idx, phy_idx, sata_end_device; + u8 entry, enc_idx, phy_idx; u32 map_idx, index, device_info; struct _map_phy_change *phy_change, *tmp_phy_change; uint64_t sas_address; @@ -920,10 +920,8 @@ _mapping_get_dev_info(struct mps_softc *sc, sas_address = sas_device_pg0.SASAddress.High; sas_address = (sas_address << 32) | sas_device_pg0.SASAddress.Low; - sata_end_device = 0; if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { - sata_end_device = 1; rc = mpssas_get_sas_address_for_sata_disk(sc, &sas_address, phy_change->dev_handle, device_info, &phy_change->is_SATA_SSD); diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index 4fbdbb2d20c0..8cba1d72286c 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -2797,11 +2797,9 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr) uint8_t *request, *response; MPI2_SMP_PASSTHROUGH_REQUEST *req; struct mps_softc *sc; - struct sglist *sg; int error; sc = sassc->sc; - sg = NULL; error = 0; /* From bf546063c06c3709a08ff56f1ef56cff22865853 Mon Sep 17 00:00:00 2001 From: araujo Date: Mon, 1 Feb 2016 02:33:58 +0000 Subject: [PATCH 088/236] Clean up unused-but-set-variable spotted by gcc-4.9. Reviewed by: mav Approved by: rodrigc (mentor) MFC after: 2 weeks Sponsored by: gandi.net Differential Revision: https://reviews.freebsd.org/D5109 --- sys/cam/scsi/scsi_pass.c | 3 --- sys/cam/scsi/scsi_sa.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c index c0c313e82bd8..b9612851d2a7 100644 --- a/sys/cam/scsi/scsi_pass.c +++ b/sys/cam/scsi/scsi_pass.c @@ -773,9 +773,6 @@ passclose(struct cdev *dev, int flag, int fmt, struct thread *td) if (softc->open_count == 0) { struct pass_io_req *io_req, *io_req2; - int need_unlock; - - need_unlock = 0; TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) { TAILQ_REMOVE(&softc->done_queue, io_req, links); diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c index 149d06228455..78d43d81c92f 100644 --- a/sys/cam/scsi/scsi_sa.c +++ b/sys/cam/scsi/scsi_sa.c @@ -4961,10 +4961,6 @@ sasetpos(struct cam_periph *periph, int hard, struct mtlocate *locate_info) /*sense_len*/ SSD_FULL_SIZE, /*timeout*/ SPACE_TIMEOUT); } else { - uint32_t blk_pointer; - - blk_pointer = locate_info->logical_id; - scsi_locate_10(&ccb->csio, /*retries*/ 1, /*cbfcnp*/ sadone, From 45e2a376b1471c34b1b1cf6baca356b4d8018588 Mon Sep 17 00:00:00 2001 From: ngie Date: Mon, 1 Feb 2016 06:25:16 +0000 Subject: [PATCH 089/236] Add an additional 1 second sleep to after calling ggatec before calling dd to defeat a race when writing out to the geom_gate(4) device This will quell the Jenkins failure emails until I come up with a better solution MFC after: 1 month Reported by: Jenkins Sponsored by: EMC / Isilon Storage Division --- tests/sys/geom/class/gate/1_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sys/geom/class/gate/1_test.sh b/tests/sys/geom/class/gate/1_test.sh index 3e277349631f..9b2cf698924c 100644 --- a/tests/sys/geom/class/gate/1_test.sh +++ b/tests/sys/geom/class/gate/1_test.sh @@ -41,6 +41,7 @@ if ! ggatec create -p $port -u $us 127.0.0.1 /dev/$work; then echo 'Bail out!' exit 1 fi +sleep 1 dd if=/dev/${src} of=/dev/ggate${us} bs=1m count=1 sleep 1 From 6bfd44302722ea2bb067ec956966c4ae3a6fb615 Mon Sep 17 00:00:00 2001 From: ngie Date: Mon, 1 Feb 2016 06:27:59 +0000 Subject: [PATCH 090/236] Use the pidfile support added to ggated(8) in r294973 to ensure that the ggated(8) daemon used by the tests is the instance specifically invoked by the tests instead of one or more daemon instances running on the system MFC after: 1 month Sponsored by: EMC / Isilon Storage Division --- tests/sys/geom/class/gate/1_test.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/sys/geom/class/gate/1_test.sh b/tests/sys/geom/class/gate/1_test.sh index 9b2cf698924c..ba573bb6e122 100644 --- a/tests/sys/geom/class/gate/1_test.sh +++ b/tests/sys/geom/class/gate/1_test.sh @@ -10,6 +10,7 @@ us=0 while [ -c /dev/ggate${us} ]; do : $(( us += 1 )) done +pidfile=ggated.$$.pid conf=`mktemp $base.XXXXXX` || exit 1 port=33080 @@ -19,7 +20,7 @@ src=$(attach_md -t malloc -s 1M) test_cleanup() { ggatec destroy -f -u $us - killall ggated + pkill -F $pidfile geom_test_cleanup } trap test_cleanup ABRT EXIT INT TERM @@ -30,7 +31,7 @@ src_checksum=$(md5 -q /dev/$src) echo "127.0.0.1 RW /dev/$work" > $conf -if ! ggated -p $port $conf; then +if ! ggated -p $port -F $pidfile $conf; then echo 'ggated failed to start' echo 'Bail out!' exit 1 From d6e7c68d6ae5bb607a3fb1bba6f71b9bedf384cb Mon Sep 17 00:00:00 2001 From: ngie Date: Mon, 1 Feb 2016 07:09:08 +0000 Subject: [PATCH 091/236] Add #include to mute warning from clang/gcc about implicitly declaring strcmp(3) MFC after: 1 month Reported by: Jenkins Sponsored by: EMC / Isilon Storage Division --- contrib/smbfs/smbutil/print.c | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/smbfs/smbutil/print.c b/contrib/smbfs/smbutil/print.c index d87ec78587c6..5e4538f7d1cb 100644 --- a/contrib/smbfs/smbutil/print.c +++ b/contrib/smbfs/smbutil/print.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include From b1ee4ad409df5a3440c668cf19bec883afa7310c Mon Sep 17 00:00:00 2001 From: ngie Date: Mon, 1 Feb 2016 07:15:31 +0000 Subject: [PATCH 092/236] Remove `r_tmp` to fix a -Wunused-but-set-variable warning with gcc 4.9 MFC after: 1 month Sponsored by: EMC / Isilon Storage Division --- sbin/rcorder/rcorder.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sbin/rcorder/rcorder.c b/sbin/rcorder/rcorder.c index 1d10a40d961a..37faa2470e55 100644 --- a/sbin/rcorder/rcorder.c +++ b/sbin/rcorder/rcorder.c @@ -701,7 +701,7 @@ keep_ok(filenode *fnode) static void do_file(filenode *fnode) { - f_reqnode *r, *r_tmp; + f_reqnode *r; f_provnode *p, *p_tmp; provnode *pnode; int was_set; @@ -728,13 +728,8 @@ do_file(filenode *fnode) */ r = fnode->req_list; while (r != NULL) { - r_tmp = r; satisfy_req(r, fnode->filename); r = r->next; -#if 0 - if (was_set == 0) - free(r_tmp); -#endif } fnode->req_list = NULL; From 5ca894a86d88814ef41a76421f3a6a35456436d6 Mon Sep 17 00:00:00 2001 From: ngie Date: Mon, 1 Feb 2016 08:06:17 +0000 Subject: [PATCH 093/236] Delete argsize to fix a -Wunused-but-set-variable warning with gcc 4.9 The variable isn't actually checked -- just the end result which gets returned from the function Differential Revision: https://reviews.freebsd.org/D5156 Reviewed by: araujo, delphij MFC after: 1 month Sponsored by: EMC / Isilon Storage Division --- sbin/swapon/swapon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index f58143179c2f..03b2b09bf742 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -315,7 +315,7 @@ swap_on_geli_args(const char *mntops) const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; const char *aflag, *eflag, *lflag, *Tflag, *sflag; char *p, *args, *token, *string, *ops; - int argsize, pagesize; + int pagesize; size_t pagesize_len; u_long ul; @@ -389,7 +389,7 @@ swap_on_geli_args(const char *mntops) sectorsize_str = p; } - argsize = asprintf(&args, "%s%s%s%s%s%s%s%s%s -d", + (void)asprintf(&args, "%s%s%s%s%s%s%s%s%s -d", aflag, aalgo, eflag, ealgo, lflag, keylen_str, Tflag, sflag, sectorsize_str); From 6e83480ac9d23ef93d924fed9b905567ce9086d5 Mon Sep 17 00:00:00 2001 From: mmel Date: Mon, 1 Feb 2016 13:13:53 +0000 Subject: [PATCH 094/236] ARM: Remove never used cpu_tlb_flushI and cpu_tlb_flushI_SE() functions and their implementations. --- sys/arm/arm/cpufunc.c | 16 ---------------- sys/arm/arm/cpufunc_asm_arm10.S | 5 ----- sys/arm/arm/cpufunc_asm_arm11.S | 12 ------------ sys/arm/arm/cpufunc_asm_armv4.S | 5 ----- sys/arm/arm/cpufunc_asm_fa526.S | 8 -------- sys/arm/include/cpufunc.h | 9 --------- 6 files changed, 55 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 6ac516fa9b1a..dc5167e803c9 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -116,8 +116,6 @@ struct cpu_functions arm9_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ arm9_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -171,8 +169,6 @@ struct cpu_functions armv5_ec_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ arm10_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - arm10_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -280,8 +276,6 @@ struct cpu_functions pj4bv7_cpufuncs = { armv7_tlb_flushID, /* tlb_flushID */ armv7_tlb_flushID_SE, /* tlb_flushID_SE */ - armv7_tlb_flushID, /* tlb_flushI */ - armv7_tlb_flushID_SE, /* tlb_flushI_SE */ armv7_tlb_flushID, /* tlb_flushD */ armv7_tlb_flushID_SE, /* tlb_flushD_SE */ @@ -336,8 +330,6 @@ struct cpu_functions xscale_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ xscale_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -392,8 +384,6 @@ struct cpu_functions xscalec3_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ xscale_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -447,8 +437,6 @@ struct cpu_functions fa526_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ fa526_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - fa526_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -502,8 +490,6 @@ struct cpu_functions arm1176_cpufuncs = { arm11_tlb_flushID, /* tlb_flushID */ arm11_tlb_flushID_SE, /* tlb_flushID_SE */ - arm11_tlb_flushI, /* tlb_flushI */ - arm11_tlb_flushI_SE, /* tlb_flushI_SE */ arm11_tlb_flushD, /* tlb_flushD */ arm11_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -561,8 +547,6 @@ struct cpu_functions cortexa_cpufuncs = { armv7_tlb_flushID, /* tlb_flushID */ armv7_tlb_flushID_SE, /* tlb_flushID_SE */ - armv7_tlb_flushID, /* tlb_flushI */ - armv7_tlb_flushID_SE, /* tlb_flushI_SE */ armv7_tlb_flushID, /* tlb_flushD */ armv7_tlb_flushID_SE, /* tlb_flushD_SE */ diff --git a/sys/arm/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S index ab5f791976aa..21bc59786a86 100644 --- a/sys/arm/arm/cpufunc_asm_arm10.S +++ b/sys/arm/arm/cpufunc_asm_arm10.S @@ -44,11 +44,6 @@ ENTRY(arm10_tlb_flushID_SE) bx lr END(arm10_tlb_flushID_SE) -ENTRY(arm10_tlb_flushI_SE) - mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */ - bx lr -END(arm10_tlb_flushI_SE) - /* * Context switch. diff --git a/sys/arm/arm/cpufunc_asm_arm11.S b/sys/arm/arm/cpufunc_asm_arm11.S index a25decbf0fb1..f83f819d963d 100644 --- a/sys/arm/arm/cpufunc_asm_arm11.S +++ b/sys/arm/arm/cpufunc_asm_arm11.S @@ -47,12 +47,6 @@ ENTRY(arm11_tlb_flushID_SE) RET END(arm11_tlb_flushID_SE) -ENTRY(arm11_tlb_flushI_SE) - mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */ - mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ - RET -END(arm11_tlb_flushI_SE) - /* * Context switch. * @@ -87,12 +81,6 @@ ENTRY(arm11_tlb_flushID) mov pc, lr END(arm11_tlb_flushID) -ENTRY(arm11_tlb_flushI) - mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */ - mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ - mov pc, lr -END(arm11_tlb_flushI) - ENTRY(arm11_tlb_flushD) mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ diff --git a/sys/arm/arm/cpufunc_asm_armv4.S b/sys/arm/arm/cpufunc_asm_armv4.S index a61a3dc2a306..6d665acf512e 100644 --- a/sys/arm/arm/cpufunc_asm_armv4.S +++ b/sys/arm/arm/cpufunc_asm_armv4.S @@ -48,11 +48,6 @@ ENTRY(armv4_tlb_flushID) RET END(armv4_tlb_flushID) -ENTRY(armv4_tlb_flushI) - mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */ - RET -END(armv4_tlb_flushI) - ENTRY(armv4_tlb_flushD) mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */ RET diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index 7b524707e6f8..1fcca217617d 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -64,14 +64,6 @@ ENTRY(fa526_tlb_flushID_SE) mov pc, lr END(fa526_tlb_flushID_SE) -/* - * TLB functions - */ -ENTRY(fa526_tlb_flushI_SE) - mcr p15, 0, r0, c8, c5, 1 /* flush Itlb single entry */ - mov pc, lr -END(fa526_tlb_flushI_SE) - ENTRY(fa526_cpu_sleep) mov r0, #0 /* nop diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 55fa13fe4b65..48d1c00b5e13 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -71,8 +71,6 @@ struct cpu_functions { void (*cf_tlb_flushID) (void); void (*cf_tlb_flushID_SE) (u_int va); - void (*cf_tlb_flushI) (void); - void (*cf_tlb_flushI_SE) (u_int va); void (*cf_tlb_flushD) (void); void (*cf_tlb_flushD_SE) (u_int va); @@ -173,8 +171,6 @@ extern u_int cputype; #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() #define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e) -#define cpu_tlb_flushI() cpufuncs.cf_tlb_flushI() -#define cpu_tlb_flushI_SE(e) cpufuncs.cf_tlb_flushI_SE(e) #define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD() #define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e) @@ -218,7 +214,6 @@ void fa526_setup (void); void fa526_setttb (u_int ttb); void fa526_context_switch (void); void fa526_cpu_sleep (int); -void fa526_tlb_flushI_SE (u_int); void fa526_tlb_flushID_SE (u_int); void fa526_flush_prefetchbuf (void); @@ -261,7 +256,6 @@ extern unsigned arm9_dcache_index_inc; #if defined(CPU_ARM9E) void arm10_tlb_flushID_SE (u_int); -void arm10_tlb_flushI_SE (u_int); void arm10_context_switch (void); @@ -316,8 +310,6 @@ void pj4bv7_setup (void); #if defined(CPU_ARM1176) void arm11_tlb_flushID (void); void arm11_tlb_flushID_SE (u_int); -void arm11_tlb_flushI (void); -void arm11_tlb_flushI_SE (u_int); void arm11_tlb_flushD (void); void arm11_tlb_flushD_SE (u_int va); @@ -364,7 +356,6 @@ void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t); defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) void armv4_tlb_flushID (void); -void armv4_tlb_flushI (void); void armv4_tlb_flushD (void); void armv4_tlb_flushD_SE (u_int va); From ed12f5f7269f2674e075a66911d9a99a18149063 Mon Sep 17 00:00:00 2001 From: mmel Date: Mon, 1 Feb 2016 14:28:58 +0000 Subject: [PATCH 095/236] ARM: Rename remaining instances of cpufunc_id() to cpu_ident(), forgotten in r295096. Remove tlb_flushI/tlb_flushI_SE functions forgotten in r295122. --- sys/arm/arm/cpufunc.c | 2 -- sys/arm/arm/elf_trampoline.c | 8 ++++---- sys/arm/arm/pmap.c | 2 +- sys/arm/mv/armadaxp/armadaxp.c | 2 +- sys/arm/mv/armadaxp/armadaxp_mp.c | 2 +- sys/arm/ti/ti_cpuid.c | 2 +- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index dc5167e803c9..2ffef6bdee37 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -221,8 +221,6 @@ struct cpu_functions sheeva_cpufuncs = { armv4_tlb_flushID, /* tlb_flushID */ arm10_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - arm10_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index c3a7eeddfc93..6c086ea6192c 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -49,7 +49,7 @@ void _start(void); void __start(void); void __startC(void); -extern unsigned int cpufunc_id(void); +extern unsigned int cpu_ident(void); extern void armv6_idcache_wbinv_all(void); extern void armv7_idcache_wbinv_all(void); extern void do_call(void *, void *, void *, int); @@ -248,7 +248,7 @@ _startC(void) #ifndef KZIP #ifdef CPU_ARM9 /* So that idcache_wbinv works; */ - if ((cpufunc_id() & 0x0000f000) == 0x00009000) + if ((cpu_ident() & 0x0000f000) == 0x00009000) arm9_setup(); #endif #endif @@ -266,7 +266,7 @@ get_cachetype_cp15() __asm __volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctype)); - cpuid = cpufunc_id(); + cpuid = cpu_ident(); /* * ...and thus spake the ARM ARM: * @@ -683,7 +683,7 @@ __start(void) #ifdef CPU_ARM9 /* So that idcache_wbinv works; */ - if ((cpufunc_id() & 0x0000f000) == 0x00009000) + if ((cpu_ident() & 0x0000f000) == 0x00009000) arm9_setup(); #endif setup_pagetables(pt_addr, (vm_paddr_t)curaddr, diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index 688fe7bf906b..99a39a0ee522 100644 --- a/sys/arm/arm/pmap.c +++ b/sys/arm/arm/pmap.c @@ -561,7 +561,7 @@ pmap_pte_init_xscale(void) { uint32_t id, type; - id = cpufunc_id(); + id = cpu_ident(); type = id & ~(CPU_ID_XSCALE_COREREV_MASK|CPU_ID_REVISION_MASK); if (type == CPU_ID_PXA250 || type == CPU_ID_PXA210) { diff --git a/sys/arm/mv/armadaxp/armadaxp.c b/sys/arm/mv/armadaxp/armadaxp.c index 693ae6a93e65..3cb03faeae62 100644 --- a/sys/arm/mv/armadaxp/armadaxp.c +++ b/sys/arm/mv/armadaxp/armadaxp.c @@ -128,7 +128,7 @@ get_tclk(void) { uint32_t cputype; - cputype = cpufunc_id(); + cputype = cpu_ident(); cputype &= CPU_ID_CPU_MASK; if (cputype == CPU_ID_MV88SV584X_V7) diff --git a/sys/arm/mv/armadaxp/armadaxp_mp.c b/sys/arm/mv/armadaxp/armadaxp_mp.c index 6685204b59ed..4ccf7e3ef360 100644 --- a/sys/arm/mv/armadaxp/armadaxp_mp.c +++ b/sys/arm/mv/armadaxp/armadaxp_mp.c @@ -111,7 +111,7 @@ platform_mp_start_ap(void) * Initialization procedure depends on core revision, * in this step CHIP ID is checked to choose proper procedure */ - cputype = cpufunc_id(); + cputype = cpu_ident(); cputype &= CPU_ID_CPU_MASK; /* diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c index 38af285c1abd..b2f0f65ab9b6 100644 --- a/sys/arm/ti/ti_cpuid.c +++ b/sys/arm/ti/ti_cpuid.c @@ -120,7 +120,7 @@ omap4_get_revision(void) * the ARM cpuid to get the correct revision. */ if (revision == 0) { - id_code = cpufunc_id(); + id_code = cpu_ident(); revision = (id_code & 0xf) - 1; } From 2cf7257fdf54821c78e5a20f1923df89ac1870b8 Mon Sep 17 00:00:00 2001 From: avg Date: Mon, 1 Feb 2016 15:40:40 +0000 Subject: [PATCH 096/236] MFV r294821: 6529 Properly handle updates of variably-sized SA entries. Reviewed by: Brian Behlendorf Reviewed by: Matthew Ahrens Reviewed by: Ned Bass Reviewed by: Tim Chase Approved by: Gordon Ross Author: Andriy Gapon illumos/illumos-gate@e7e978b1f75353cb29673af9b35453c20c2827bf During the update process in sa_modify_attrs(), the sizes of existing variably-sized SA entries are obtained from sa_lengths[]. The case where a variably-sized SA was being replaced neglected to increment the index into sa_lengths[], so subsequent variable-length SAs would be rewritten with the wrong length. This patch adds the missing increment operation so all variably-sized SA entries are stored with their correct lengths. Another problem was that index into attr_desc[] was increased even when an attribute was removed. If that attribute was not the last attribute, then the last attribute was lost. --- .../opensolaris/uts/common/fs/zfs/sa.c | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c index 9293e9a97e27..200369216947 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c @@ -1652,7 +1652,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr, int spill_data_size = 0; int spill_attr_count = 0; int error; - uint16_t length; + uint16_t length, reg_length; int i, j, k, length_idx; sa_hdr_phys_t *hdr; sa_idx_tab_t *idx_tab; @@ -1712,34 +1712,50 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr, hdr = SA_GET_HDR(hdl, SA_BONUS); idx_tab = SA_IDX_TAB_GET(hdl, SA_BONUS); for (; k != 2; k++) { - /* iterate over each attribute in layout */ + /* + * Iterate over each attribute in layout. Fetch the + * size of variable-length attributes needing rewrite + * from sa_lengths[]. + */ for (i = 0, length_idx = 0; i != count; i++) { sa_attr_type_t attr; attr = idx_tab->sa_layout->lot_attrs[i]; - if (attr == newattr) { - /* duplicate attributes are not allowed */ - ASSERT(action == SA_REPLACE || - action == SA_REMOVE); - /* must be variable-sized to be replaced here */ - if (action == SA_REPLACE) { - ASSERT(SA_REGISTERED_LEN(sa, attr) == 0); - SA_ADD_BULK_ATTR(attr_desc, j, attr, - locator, datastart, buflen); - } + reg_length = SA_REGISTERED_LEN(sa, attr); + if (reg_length == 0) { + length = hdr->sa_lengths[length_idx]; + length_idx++; } else { - length = SA_REGISTERED_LEN(sa, attr); - if (length == 0) { - length = hdr->sa_lengths[length_idx]; - } + length = reg_length; + } + if (attr == newattr) { + /* + * There is nothing to do for SA_REMOVE, + * so it is just skipped. + */ + if (action == SA_REMOVE) + continue; + /* + * Duplicate attributes are not allowed, so the + * action can not be SA_ADD here. + */ + ASSERT3S(action, ==, SA_REPLACE); + + /* + * Only a variable-sized attribute can be + * replaced here, and its size must be changing. + */ + ASSERT3U(reg_length, ==, 0); + ASSERT3U(length, !=, buflen); + SA_ADD_BULK_ATTR(attr_desc, j, attr, + locator, datastart, buflen); + } else { SA_ADD_BULK_ATTR(attr_desc, j, attr, NULL, (void *) (TOC_OFF(idx_tab->sa_idx_tab[attr]) + (uintptr_t)old_data[k]), length); } - if (SA_REGISTERED_LEN(sa, attr) == 0) - length_idx++; } if (k == 0 && hdl->sa_spill) { hdr = SA_GET_HDR(hdl, SA_SPILL); @@ -1750,10 +1766,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr, } } if (action == SA_ADD) { - length = SA_REGISTERED_LEN(sa, newattr); - if (length == 0) { - length = buflen; - } + reg_length = SA_REGISTERED_LEN(sa, newattr); + IMPLY(reg_length != 0, reg_length == buflen); SA_ADD_BULK_ATTR(attr_desc, j, newattr, locator, datastart, buflen); } From 306a6faf84555a480968ca79e8c67749c0aeffc6 Mon Sep 17 00:00:00 2001 From: glebius Date: Mon, 1 Feb 2016 17:41:21 +0000 Subject: [PATCH 097/236] These files were getting sys/malloc.h and vm/uma.h with header pollution via sys/mbuf.h --- sys/contrib/ipfilter/netinet/ip_compat.h | 1 + sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 1 + sys/dev/bwn/if_bwn.c | 3 ++- sys/dev/ed/if_ed.c | 3 ++- sys/dev/ep/if_ep.c | 1 + sys/dev/fe/if_fe.c | 1 + sys/dev/fxp/if_fxp.c | 1 + sys/dev/iscsi_initiator/isc_cam.c | 1 + sys/dev/iscsi_initiator/isc_sm.c | 1 + sys/dev/iscsi_initiator/isc_soc.c | 1 + sys/dev/iscsi_initiator/isc_subr.c | 1 + sys/dev/iscsi_initiator/iscsi_subr.c | 1 + sys/dev/le/lance.c | 1 + sys/dev/malo/if_malo.c | 1 + sys/dev/netmap/netmap_offloadings.c | 1 + sys/dev/oce/oce_if.h | 1 + sys/dev/otus/if_otus.c | 1 + sys/dev/sfxge/sfxge_rx.c | 3 ++- sys/dev/sfxge/sfxge_tx.c | 3 ++- sys/dev/sn/if_sn.c | 1 + sys/dev/tx/if_tx.c | 1 + sys/dev/usb/wlan/if_rsu.c | 1 + sys/dev/wi/if_wi.c | 1 + sys/dev/wi/if_wi_pci.c | 1 + sys/dev/xe/if_xe.c | 1 + sys/dev/xl/if_xl.c | 3 ++- sys/kern/subr_mchain.c | 1 + sys/kern/uipc_sockbuf.c | 1 + sys/net/bridgestp.c | 1 + sys/net/if_epair.c | 1 + sys/net/if_mib.c | 1 + sys/net/netisr.c | 1 + sys/net/pfvar.h | 2 ++ sys/net80211/ieee80211.c | 1 + sys/net80211/ieee80211_acl.c | 1 + sys/net80211/ieee80211_action.c | 1 + sys/net80211/ieee80211_ageq.c | 1 + sys/net80211/ieee80211_amrr.c | 1 + sys/net80211/ieee80211_crypto_none.c | 1 + sys/net80211/ieee80211_ddb.c | 1 + sys/net80211/ieee80211_freebsd.c | 3 ++- sys/net80211/ieee80211_ht.c | 1 + sys/net80211/ieee80211_ioctl.c | 1 + sys/net80211/ieee80211_output.c | 3 ++- sys/net80211/ieee80211_power.c | 1 + sys/net80211/ieee80211_proto.c | 3 ++- sys/net80211/ieee80211_scan.c | 1 + sys/net80211/ieee80211_scan_sta.c | 1 + sys/net80211/ieee80211_scan_sw.c | 1 + sys/net80211/ieee80211_xauth.c | 1 + sys/netgraph/netflow/netflow.c | 1 + sys/netgraph/netflow/netflow_v9.c | 2 ++ sys/netgraph/netflow/ng_netflow.c | 2 ++ sys/netgraph/ng_base.c | 1 + sys/netinet/in_proto.c | 1 + sys/netinet/tcp_lro.c | 3 ++- sys/netinet/toecore.c | 1 + sys/netinet6/in6_proto.c | 1 + sys/netinet6/send.c | 1 + sys/netipsec/ipsec_mbuf.c | 1 + sys/netipsec/key_debug.c | 2 +- sys/netpfil/ipfw/ip_fw_log.c | 3 ++- sys/rpc/replay.c | 1 + 63 files changed, 76 insertions(+), 11 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 8aece74b53cc..bcb47e93464d 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -147,6 +147,7 @@ struct ether_addr { # include # include +# include # include # define KRWLOCK_FILL_SZ 56 # define KMUTEX_FILL_SZ 56 diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 30ec46c11b9d..8a5a90d74073 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -36,6 +36,7 @@ static const char rcsid[] = "@(#)$Id$"; #if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000) #include #endif +# include # include # include #if !defined(__hpux) diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 93996e27beb8..e2228e6e3c59 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -36,8 +36,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include +#include #include #include #include diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index 00e785d91c35..95d80f690643 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -43,8 +43,9 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include +#include +#include #include #include #include diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c index cd7afb530a46..9f6848a1de58 100644 --- a/sys/dev/ep/if_ep.c +++ b/sys/dev/ep/if_ep.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/fe/if_fe.c b/sys/dev/fe/if_fe.c index 4598b59fcb97..1be74f9d2c8b 100644 --- a/sys/dev/fe/if_fe.c +++ b/sys/dev/fe/if_fe.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index cf0e6a249ff9..dc9181758a30 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/iscsi_initiator/isc_cam.c b/sys/dev/iscsi_initiator/isc_cam.c index 6089694364c6..e53a0fb66ced 100644 --- a/sys/dev/iscsi_initiator/isc_cam.c +++ b/sys/dev/iscsi_initiator/isc_cam.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/iscsi_initiator/isc_sm.c b/sys/dev/iscsi_initiator/isc_sm.c index 6810047b77ac..097cdcca2153 100644 --- a/sys/dev/iscsi_initiator/isc_sm.c +++ b/sys/dev/iscsi_initiator/isc_sm.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/iscsi_initiator/isc_soc.c b/sys/dev/iscsi_initiator/isc_soc.c index e77f0700c69e..adb9914c00f7 100644 --- a/sys/dev/iscsi_initiator/isc_soc.c +++ b/sys/dev/iscsi_initiator/isc_soc.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/iscsi_initiator/isc_subr.c b/sys/dev/iscsi_initiator/isc_subr.c index 677c5f1674c8..d553cd1c3326 100644 --- a/sys/dev/iscsi_initiator/isc_subr.c +++ b/sys/dev/iscsi_initiator/isc_subr.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/iscsi_initiator/iscsi_subr.c b/sys/dev/iscsi_initiator/iscsi_subr.c index b22ed831207b..cf746cda65f7 100644 --- a/sys/dev/iscsi_initiator/iscsi_subr.c +++ b/sys/dev/iscsi_initiator/iscsi_subr.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c index 2b4202be2cdd..f8a333b9fd5c 100644 --- a/sys/dev/le/lance.c +++ b/sys/dev/le/lance.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c index ff487082e708..6cd0f2969472 100644 --- a/sys/dev/malo/if_malo.c +++ b/sys/dev/malo/if_malo.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/netmap/netmap_offloadings.c b/sys/dev/netmap/netmap_offloadings.c index 34eafab7c87e..4055c427cb56 100644 --- a/sys/dev/netmap/netmap_offloadings.c +++ b/sys/dev/netmap/netmap_offloadings.c @@ -31,6 +31,7 @@ #include #include #include /* defines used in kernel.h */ +#include /* types used in module initialization */ #include /* types used in module initialization */ #include #include /* struct socket */ diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h index bb788413faa0..99707e496783 100644 --- a/sys/dev/oce/oce_if.h +++ b/sys/dev/oce/oce_if.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c index daa96266353a..03bfa73d1f52 100644 --- a/sys/dev/otus/if_otus.c +++ b/sys/dev/otus/if_otus.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/sfxge/sfxge_rx.c b/sys/dev/sfxge/sfxge_rx.c index 5ee946872867..d4e4fd431c1b 100644 --- a/sys/dev/sfxge/sfxge_rx.c +++ b/sys/dev/sfxge/sfxge_rx.c @@ -34,7 +34,8 @@ #include __FBSDID("$FreeBSD$"); -#include +#include +#include #include #include #include diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c index 9cf5c79a8213..e729360c6b63 100644 --- a/sys/dev/sfxge/sfxge_tx.c +++ b/sys/dev/sfxge/sfxge_tx.c @@ -49,7 +49,8 @@ #include __FBSDID("$FreeBSD$"); -#include +#include +#include #include #include #include diff --git a/sys/dev/sn/if_sn.c b/sys/dev/sn/if_sn.c index 26e60bc0445a..c1fbc9ad8ac7 100644 --- a/sys/dev/sn/if_sn.c +++ b/sys/dev/sn/if_sn.c @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/tx/if_tx.c b/sys/dev/tx/if_tx.c index 7a12aee288d1..42b327fbdf26 100644 --- a/sys/dev/tx/if_tx.c +++ b/sys/dev/tx/if_tx.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index 0dcde19add44..5aa460ba82c1 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 832e6aa37c04..8f9d1a0e7525 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c index b218c2479a69..a0e872af9c88 100644 --- a/sys/dev/wi/if_wi_pci.c +++ b/sys/dev/wi/if_wi_pci.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c index 4a7aa6e8eb69..4975fd53726b 100644 --- a/sys/dev/xe/if_xe.c +++ b/sys/dev/xe/if_xe.c @@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c index f7bd599a04ed..9568967d609b 100644 --- a/sys/dev/xl/if_xl.c +++ b/sys/dev/xl/if_xl.c @@ -106,8 +106,9 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include +#include +#include #include #include #include diff --git a/sys/kern/subr_mchain.c b/sys/kern/subr_mchain.c index e9d7d22129b4..233a78aac706 100644 --- a/sys/kern/subr_mchain.c +++ b/sys/kern/subr_mchain.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index ba77fcaca92a..edf03a3b51fc 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include /* for aio_swake proto */ #include #include +#include #include #include #include diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c index bd5ef9f906e6..d6e118cb5891 100644 --- a/sys/net/bridgestp.c +++ b/sys/net/bridgestp.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index fd7a757c9f86..6c14037f3d02 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/net/if_mib.c b/sys/net/if_mib.c index a9840caa68c2..590664268667 100644 --- a/sys/net/if_mib.c +++ b/sys/net/if_mib.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/sys/net/netisr.c b/sys/net/netisr.c index 4b3576ded2ae..64efbd772b6e 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 2a7182e78b9f..ed23eb5b20a7 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -36,8 +36,10 @@ #include #include #include +#include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index ca27cb13f249..a1c70401748d 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_acl.c b/sys/net80211/ieee80211_acl.c index eeb7f0bc68da..58679b0b1765 100644 --- a/sys/net80211/ieee80211_acl.c +++ b/sys/net80211/ieee80211_acl.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c index e37863ee12fb..9c7598932970 100644 --- a/sys/net80211/ieee80211_action.c +++ b/sys/net80211/ieee80211_action.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_ageq.c b/sys/net80211/ieee80211_ageq.c index b650136c05be..d282fccf9bb4 100644 --- a/sys/net80211/ieee80211_ageq.c +++ b/sys/net80211/ieee80211_ageq.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index b7c11fd2417b..f50334e9af1b 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/net80211/ieee80211_crypto_none.c b/sys/net80211/ieee80211_crypto_none.c index 30f2fc38882a..fef4c0946b20 100644 --- a/sys/net80211/ieee80211_crypto_none.c +++ b/sys/net80211/ieee80211_crypto_none.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index ae4910c6ee0d..de7a243098de 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 0ccf378fff6d..57cbbf57056e 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -32,10 +32,11 @@ __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include -#include #include #include +#include #include +#include #include #include #include diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index e6fe16e58fa5..1a217346f811 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index e78b86221121..bdaac4810df0 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 322491d25a2c..42046807abaf 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -33,8 +33,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include +#include #include #include diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index 73c1382b1218..587e48f07d3f 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 408bf935b92c..1b8b5249946a 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -35,8 +35,9 @@ __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include -#include #include +#include +#include #include #include diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c index f28a9829d60d..8bc5d2eed0d1 100644 --- a/sys/net80211/ieee80211_scan.c +++ b/sys/net80211/ieee80211_scan.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index ea922d7e82a3..accf6c8cd299 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c index 53e45203f10c..52f6ea7210b8 100644 --- a/sys/net80211/ieee80211_scan_sw.c +++ b/sys/net80211/ieee80211_scan_sw.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/net80211/ieee80211_xauth.c b/sys/net80211/ieee80211_xauth.c index 2341ffb162e9..1e57e16af646 100644 --- a/sys/net80211/ieee80211_xauth.c +++ b/sys/net80211/ieee80211_xauth.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c index 6adffc9e6072..84dee4767240 100644 --- a/sys/netgraph/netflow/netflow.c +++ b/sys/netgraph/netflow/netflow.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/netgraph/netflow/netflow_v9.c b/sys/netgraph/netflow/netflow_v9.c index 2fc700d5d4f7..5124bbd48075 100644 --- a/sys/netgraph/netflow/netflow_v9.c +++ b/sys/netgraph/netflow/netflow_v9.c @@ -37,9 +37,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c index b524ca51fcbd..4f9f953c6f91 100644 --- a/sys/netgraph/netflow/ng_netflow.c +++ b/sys/netgraph/netflow/ng_netflow.c @@ -40,10 +40,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include +#include #include #include diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 673dc25045f6..0f48e12a8759 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 0ac91c72bb88..e7569c45f740 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index 566334348810..d49071c50d28 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -38,8 +38,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include +#include #include #include diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c index cfa77e76a128..4bca16c09120 100644 --- a/sys/netinet/toecore.c +++ b/sys/netinet/toecore.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 4d328d282ec3..cad09316cf94 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c index b946ded155d1..66b36db7827b 100644 --- a/sys/netinet6/send.c +++ b/sys/netinet6/send.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/netipsec/ipsec_mbuf.c b/sys/netipsec/ipsec_mbuf.c index 8e68ffb41c6f..b3df0e01cc50 100644 --- a/sys/netipsec/ipsec_mbuf.c +++ b/sys/netipsec/ipsec_mbuf.c @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/sys/netipsec/key_debug.c b/sys/netipsec/key_debug.c index b5bdb0ed42ca..4aad7433ee7a 100644 --- a/sys/netipsec/key_debug.c +++ b/sys/netipsec/key_debug.c @@ -36,10 +36,10 @@ #include "opt_ipsec.h" #endif -#include #include #ifdef _KERNEL #include +#include #include #include #endif diff --git a/sys/netpfil/ipfw/ip_fw_log.c b/sys/netpfil/ipfw/ip_fw_log.c index 29374f949015..236c4f1f19d7 100644 --- a/sys/netpfil/ipfw/ip_fw_log.c +++ b/sys/netpfil/ipfw/ip_fw_log.c @@ -39,8 +39,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include +#include #include #include #include diff --git a/sys/rpc/replay.c b/sys/rpc/replay.c index 1bd5378d9fbe..3900a84d0f14 100644 --- a/sys/rpc/replay.c +++ b/sys/rpc/replay.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include From 8714daf02392c2c257877445ed56217220c3401e Mon Sep 17 00:00:00 2001 From: skra Date: Mon, 1 Feb 2016 19:36:33 +0000 Subject: [PATCH 098/236] Remove not needed includes. --- sys/arm/arm/genassym.c | 1 - sys/arm/arm/mp_machdep.c | 1 - sys/arm/mv/orion/db88f5xxx.c | 1 - sys/arm/ti/omap4/pandaboard/pandaboard.c | 1 - 4 files changed, 4 deletions(-) diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index a5d2f6b9645f..eb4e51b81bba 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 0106c7af347c..6cedd46e2bb5 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/arm/mv/orion/db88f5xxx.c b/sys/arm/mv/orion/db88f5xxx.c index f59d511f4d09..bfac68a6ac24 100644 --- a/sys/arm/mv/orion/db88f5xxx.c +++ b/sys/arm/mv/orion/db88f5xxx.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.c b/sys/arm/ti/omap4/pandaboard/pandaboard.c index 20e5e8a6da87..f557f736c56d 100644 --- a/sys/arm/ti/omap4/pandaboard/pandaboard.c +++ b/sys/arm/ti/omap4/pandaboard/pandaboard.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include From 0924d1687c5bc1e7e372986f9ec31e50ccd21c7b Mon Sep 17 00:00:00 2001 From: skra Date: Mon, 1 Feb 2016 19:43:04 +0000 Subject: [PATCH 099/236] Remove all stuff related to __ARM_ARCH >= 6 from pmap.h header except for include. It was used by old pmap-v6 code. --- sys/arm/include/pmap.h | 166 +---------------------------------------- 1 file changed, 4 insertions(+), 162 deletions(-) diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 009c61faf3a9..8222652084b4 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -60,21 +60,10 @@ /* * Pte related macros */ -#if ARM_ARCH_6 || ARM_ARCH_7A -#ifdef SMP -#define PTE_NOCACHE 2 -#else -#define PTE_NOCACHE 1 -#endif -#define PTE_CACHE 6 -#define PTE_DEVICE 2 -#define PTE_PAGETABLE 6 -#else #define PTE_NOCACHE 1 #define PTE_CACHE 2 #define PTE_DEVICE PTE_NOCACHE #define PTE_PAGETABLE 3 -#endif enum mem_type { STRONG_ORD = 0, @@ -104,11 +93,7 @@ enum mem_type { #define pmap_page_get_memattr(m) ((m)->md.pv_memattr) #define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0) -#if (ARM_MMU_V6 + ARM_MMU_V7) > 0 -boolean_t pmap_page_is_mapped(vm_page_t); -#else #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) -#endif void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); /* @@ -131,9 +116,7 @@ struct pv_chunk; struct md_page { int pvh_attrs; vm_memattr_t pv_memattr; -#if (ARM_MMU_V6 + ARM_MMU_V7) == 0 vm_offset_t pv_kva; /* first kernel VA mapping */ -#endif TAILQ_HEAD(,pv_entry) pv_list; }; @@ -164,11 +147,7 @@ struct pmap { struct l2_dtable *pm_l2[L2_SIZE]; cpuset_t pm_active; /* active on cpus */ struct pmap_statistics pm_stats; /* pmap statictics */ -#if (ARM_MMU_V6 + ARM_MMU_V7) != 0 - TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ -#else TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ -#endif }; typedef struct pmap *pmap_t; @@ -198,10 +177,8 @@ typedef struct pv_entry { vm_offset_t pv_va; /* virtual address for mapping */ TAILQ_ENTRY(pv_entry) pv_list; int pv_flags; /* flags (wired, etc...) */ -#if (ARM_MMU_V6 + ARM_MMU_V7) == 0 pmap_t pv_pmap; /* pmap where mapping lies */ TAILQ_ENTRY(pv_entry) pv_plist; -#endif } *pv_entry_t; /* @@ -270,9 +247,7 @@ void *pmap_mapdev(vm_offset_t, vm_size_t); void pmap_unmapdev(vm_offset_t, vm_size_t); vm_page_t pmap_use_pt(pmap_t, vm_offset_t); void pmap_debug(int); -#if (ARM_MMU_V6 + ARM_MMU_V7) == 0 void pmap_map_section(vm_offset_t, vm_offset_t, vm_offset_t, int, int); -#endif void pmap_link_l2pt(vm_offset_t, vm_offset_t, struct pv_addr *); vm_size_t pmap_map_chunk(vm_offset_t, vm_offset_t, vm_offset_t, vm_size_t, int, int); void @@ -340,119 +315,9 @@ extern int pmap_needs_pte_sync; /* * User-visible names for the ones that vary with MMU class. */ -#if (ARM_MMU_V6 + ARM_MMU_V7) != 0 -#define L2_AP(x) (L2_AP0(x)) -#else #define L2_AP(x) (L2_AP0(x) | L2_AP1(x) | L2_AP2(x) | L2_AP3(x)) -#endif -#if (ARM_MMU_V6 + ARM_MMU_V7) != 0 -/* - * AP[2:1] access permissions model: - * - * AP[2](APX) - Write Disable - * AP[1] - User Enable - * AP[0] - Reference Flag - * - * AP[2] AP[1] Kernel User - * 0 0 R/W N - * 0 1 R/W R/W - * 1 0 R N - * 1 1 R R - * - */ -#define L2_S_PROT_R (0) /* kernel read */ -#define L2_S_PROT_U (L2_AP0(2)) /* user read */ -#define L2_S_REF (L2_AP0(1)) /* reference flag */ - -#define L2_S_PROT_MASK (L2_S_PROT_U|L2_S_PROT_R|L2_APX) -#define L2_S_EXECUTABLE(pte) (!(pte & L2_XN)) -#define L2_S_WRITABLE(pte) (!(pte & L2_APX)) -#define L2_S_REFERENCED(pte) (!!(pte & L2_S_REF)) - -#ifndef SMP -#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C) -#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C) -#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C) -#else -#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C|L1_SHARED) -#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C|L2_SHARED) -#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C|L2_SHARED) -#endif /* SMP */ - -#define L1_S_PROTO (L1_TYPE_S) -#define L1_C_PROTO (L1_TYPE_C) -#define L2_S_PROTO (L2_TYPE_S) - -/* - * Promotion to a 1MB (SECTION) mapping requires that the corresponding - * 4KB (SMALL) page mappings have identical settings for the following fields: - */ -#define L2_S_PROMOTE (L2_S_REF | L2_SHARED | L2_S_PROT_MASK | \ - L2_XN | L2_S_PROTO) - -/* - * In order to compare 1MB (SECTION) entry settings with the 4KB (SMALL) - * page mapping it is necessary to read and shift appropriate bits from - * L1 entry to positions of the corresponding bits in the L2 entry. - */ -#define L1_S_DEMOTE(l1pd) ((((l1pd) & L1_S_PROTO) >> 0) | \ - (((l1pd) & L1_SHARED) >> 6) | \ - (((l1pd) & L1_S_REF) >> 6) | \ - (((l1pd) & L1_S_PROT_MASK) >> 6) | \ - (((l1pd) & L1_S_XN) >> 4)) - -#ifndef SMP -#define ARM_L1S_STRONG_ORD (0) -#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2)) -#define ARM_L1S_DEVICE_SHARE (L1_S_B) -#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1)) -#define ARM_L1S_NRML_IWT_OWT (L1_S_C) -#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B) -#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B) - -#define ARM_L2L_STRONG_ORD (0) -#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2)) -#define ARM_L2L_DEVICE_SHARE (L2_B) -#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1)) -#define ARM_L2L_NRML_IWT_OWT (L2_C) -#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B) -#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B) - -#define ARM_L2S_STRONG_ORD (0) -#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2)) -#define ARM_L2S_DEVICE_SHARE (L2_B) -#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1)) -#define ARM_L2S_NRML_IWT_OWT (L2_C) -#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B) -#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B) -#else -#define ARM_L1S_STRONG_ORD (0) -#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2)) -#define ARM_L1S_DEVICE_SHARE (L1_S_B) -#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1)|L1_SHARED) -#define ARM_L1S_NRML_IWT_OWT (L1_S_C|L1_SHARED) -#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B|L1_SHARED) -#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B|L1_SHARED) - -#define ARM_L2L_STRONG_ORD (0) -#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2)) -#define ARM_L2L_DEVICE_SHARE (L2_B) -#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1)|L2_SHARED) -#define ARM_L2L_NRML_IWT_OWT (L2_C|L2_SHARED) -#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED) -#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B|L2_SHARED) - -#define ARM_L2S_STRONG_ORD (0) -#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2)) -#define ARM_L2S_DEVICE_SHARE (L2_B) -#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1)|L2_SHARED) -#define ARM_L2S_NRML_IWT_OWT (L2_C|L2_SHARED) -#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED) -#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B|L2_SHARED) -#endif /* SMP */ - -#elif ARM_NMMUS > 1 +#if ARM_NMMUS > 1 /* More than one MMU class configured; use variables. */ #define L2_S_PROT_U pte_l2_s_prot_u #define L2_S_PROT_W pte_l2_s_prot_w @@ -494,7 +359,7 @@ extern int pmap_needs_pte_sync; #endif /* ARM_NMMUS > 1 */ -#if defined(CPU_XSCALE_81342) || ARM_ARCH_6 || ARM_ARCH_7A +#if defined(CPU_XSCALE_81342) #define PMAP_NEEDS_PTE_SYNC 1 #define PMAP_INCLUDE_PTE_SYNC #else @@ -505,8 +370,6 @@ extern int pmap_needs_pte_sync; * These macros return various bits based on kernel/user and protection. * Note that the compiler will usually fold these at compile time. */ -#if (ARM_MMU_V6 + ARM_MMU_V7) == 0 - #define L1_S_PROT_U (L1_S_AP(AP_U)) #define L1_S_PROT_W (L1_S_AP(AP_W)) #define L1_S_PROT_MASK (L1_S_PROT_U|L1_S_PROT_W) @@ -524,27 +387,6 @@ extern int pmap_needs_pte_sync; #define L2_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_S_PROT_U : 0) | \ (((pr) & VM_PROT_WRITE) ? L2_S_PROT_W : 0)) -#else -#define L1_S_PROT_U (L1_S_AP(AP_U)) -#define L1_S_PROT_W (L1_S_APX) /* Write disable */ -#define L1_S_PROT_MASK (L1_S_PROT_W|L1_S_PROT_U) -#define L1_S_REF (L1_S_AP(AP_REF)) /* Reference flag */ -#define L1_S_WRITABLE(pd) (!((pd) & L1_S_PROT_W)) -#define L1_S_EXECUTABLE(pd) (!((pd) & L1_S_XN)) -#define L1_S_REFERENCED(pd) ((pd) & L1_S_REF) - -#define L1_S_PROT(ku, pr) (((((ku) == PTE_KERNEL) ? 0 : L1_S_PROT_U) | \ - (((pr) & VM_PROT_WRITE) ? 0 : L1_S_PROT_W) | \ - (((pr) & VM_PROT_EXECUTE) ? 0 : L1_S_XN))) - -#define L2_L_PROT_MASK (L2_APX|L2_AP0(0x3)) -#define L2_L_PROT(ku, pr) (L2_L_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \ - (((pr) & VM_PROT_WRITE) ? L2_APX : 0))) - -#define L2_S_PROT(ku, pr) (L2_S_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \ - (((pr) & VM_PROT_WRITE) ? L2_APX : 0))) - -#endif /* * Macros to test if a mapping is mappable with an L1 Section mapping @@ -619,12 +461,12 @@ extern void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys, vm_offset_t a_offs, vm_paddr_t b_phys, vm_offset_t b_offs, int cnt); extern void (*pmap_zero_page_func)(vm_paddr_t, int, int); -#if (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 || defined(CPU_XSCALE_81342) +#if ARM_MMU_GENERIC != 0 || defined(CPU_XSCALE_81342) void pmap_copy_page_generic(vm_paddr_t, vm_paddr_t); void pmap_zero_page_generic(vm_paddr_t, int, int); void pmap_pte_init_generic(void); -#endif /* (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 */ +#endif /* ARM_MMU_GENERIC != 0 */ #if ARM_MMU_XSCALE == 1 void pmap_copy_page_xscale(vm_paddr_t, vm_paddr_t); From 0e26efe2d7cf6ba3520c373445f73eca41063634 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 1 Feb 2016 23:12:04 +0000 Subject: [PATCH 100/236] Restore the ABI of 'struct fpreg' on powerpc. The PT_{GET,SET}FPREGS requests use 'struct fpreg' and the NT_FPREGSET core note stores a copy of 'struct fpreg'. As with x86 and the floating point state there compared to the extended state in XSAVE, struct fpreg on powerpc now only holds the 'base' FP state, and setting it via PT_SETFPREGS leaves the extended vector state in a thread unchanged. Reviewed by: jhibbits Differential Revision: https://reviews.freebsd.org/D5004 --- sys/powerpc/fpu/fpu_emu.c | 2 +- sys/powerpc/fpu/fpu_emu.h | 2 +- sys/powerpc/fpu/fpu_extern.h | 4 ++-- sys/powerpc/include/reg.h | 6 +----- sys/powerpc/powerpc/exec_machdep.c | 18 ++++++++++++++---- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c index 82074aab868f..9056dca8aa23 100644 --- a/sys/powerpc/fpu/fpu_emu.c +++ b/sys/powerpc/fpu/fpu_emu.c @@ -183,7 +183,7 @@ fpu_dumpfpn(struct fpn *fp) * (Typically: zero, SIGFPE, SIGILL, SIGSEGV) */ int -fpu_emulate(struct trapframe *frame, struct fpreg *fpf) +fpu_emulate(struct trapframe *frame, struct fpu *fpf) { static union instr insn; static struct fpemu fe; diff --git a/sys/powerpc/fpu/fpu_emu.h b/sys/powerpc/fpu/fpu_emu.h index 89ccc3611528..30e617e474ec 100644 --- a/sys/powerpc/fpu/fpu_emu.h +++ b/sys/powerpc/fpu/fpu_emu.h @@ -138,7 +138,7 @@ struct fpn { * Emulator state. */ struct fpemu { - struct fpreg *fe_fpstate; /* registers, etc */ + struct fpu *fe_fpstate; /* registers, etc */ int fe_fpscr; /* fpscr copy (modified during op) */ int fe_cx; /* keep track of exceptions */ struct fpn fe_f1; /* operand 1 */ diff --git a/sys/powerpc/fpu/fpu_extern.h b/sys/powerpc/fpu/fpu_extern.h index 9c24f1dab038..9f4b0132dc18 100644 --- a/sys/powerpc/fpu/fpu_extern.h +++ b/sys/powerpc/fpu/fpu_extern.h @@ -31,14 +31,14 @@ */ struct proc; -struct fpreg; +struct fpu; struct trapframe; union instr; struct fpemu; struct fpn; /* fpu.c */ -int fpu_emulate(struct trapframe *, struct fpreg *); +int fpu_emulate(struct trapframe *, struct fpu *); int fpu_execute(struct trapframe *, struct fpemu *, union instr *); /* fpu_explode.c */ diff --git a/sys/powerpc/include/reg.h b/sys/powerpc/include/reg.h index e77625ab8ddf..0eff51e5451e 100644 --- a/sys/powerpc/include/reg.h +++ b/sys/powerpc/include/reg.h @@ -18,12 +18,8 @@ struct reg { register_t pc; }; -/* Must match pcb.pcb_fpu */ struct fpreg { - union { - double fpr; - uint64_t vsr[2]; - } fpreg[32]; + double fpreg[32]; double fpscr; }; diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index d657244ffe56..d8238a1b58f1 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -608,13 +608,18 @@ int fill_fpregs(struct thread *td, struct fpreg *fpregs) { struct pcb *pcb; + int i; pcb = td->td_pcb; if ((pcb->pcb_flags & PCB_FPREGS) == 0) memset(fpregs, 0, sizeof(struct fpreg)); - else - memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); + else { + memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); + for (i = 0; i < 32; i++) + memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, + sizeof(double)); + } return (0); } @@ -641,10 +646,15 @@ int set_fpregs(struct thread *td, struct fpreg *fpregs) { struct pcb *pcb; + int i; pcb = td->td_pcb; pcb->pcb_flags |= PCB_FPREGS; - memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); + memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double)); + for (i = 0; i < 32; i++) { + memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i], + sizeof(double)); + } return (0); } @@ -1060,7 +1070,7 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); pcb->pcb_flags |= PCB_FPREGS; } - sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu); + sig = fpu_emulate(frame, &pcb->pcb_fpu); #endif return (sig); From f701a1108437f8cbc6937ddffc0431a1b9df1cb0 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 1 Feb 2016 23:51:30 +0000 Subject: [PATCH 101/236] As it turns out, one of the more or less recent changes to em(4) causes watchdog timeouts when using TSO4 at link speeds below Gigabit, at least with 82573E. So disable the assist automatically when at lower speeds. Submitted by: jfv Approved by: erj Obtained from: D3162 MFC after: 3 days --- sys/dev/e1000/if_em.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index c1a9ce8717df..b6c98b160e25 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1371,8 +1371,15 @@ em_init_locked(struct adapter *adapter) if_clearhwassist(ifp); if (if_getcapenable(ifp) & IFCAP_TXCSUM) if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0); - if (if_getcapenable(ifp) & IFCAP_TSO4) - if_sethwassistbits(ifp, CSUM_TSO, 0); + /* + ** There have proven to be problems with TSO when not + ** at full gigabit speed, so disable the assist automatically + ** when at lower speeds. -jfv + */ + if (if_getcapenable(ifp) & IFCAP_TSO4) { + if (adapter->link_speed == SPEED_1000) + if_sethwassistbits(ifp, CSUM_TSO, 0); + } /* Configure for OS presence */ em_init_manageability(adapter); From 578b3baef33491b548d2f0443135e50d55f2b2c2 Mon Sep 17 00:00:00 2001 From: cem Date: Tue, 2 Feb 2016 00:14:51 +0000 Subject: [PATCH 102/236] kcrypto_aes: Use separate sessions for AES and SHA1 Some hardware supports AES acceleration but not SHA1, e.g., AES-NI extensions. It is useful to have accelerated AES even if SHA1 must be software. Suggested by: asomers Reviewed by: asomers, dfr Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D5146 --- sys/kgssapi/krb5/kcrypto_aes.c | 56 +++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/sys/kgssapi/krb5/kcrypto_aes.c b/sys/kgssapi/krb5/kcrypto_aes.c index d2dac2158f0a..fca963c5f1c6 100644 --- a/sys/kgssapi/krb5/kcrypto_aes.c +++ b/sys/kgssapi/krb5/kcrypto_aes.c @@ -43,7 +43,8 @@ __FBSDID("$FreeBSD$"); struct aes_state { struct mtx as_lock; - uint64_t as_session; + uint64_t as_session_aes; + uint64_t as_session_sha1; }; static void @@ -61,8 +62,10 @@ aes_destroy(struct krb5_key_state *ks) { struct aes_state *as = ks->ks_priv; - if (as->as_session) - crypto_freesession(as->as_session); + if (as->as_session_aes != 0) + crypto_freesession(as->as_session_aes); + if (as->as_session_sha1 != 0) + crypto_freesession(as->as_session_sha1); mtx_destroy(&as->as_lock); free(ks->ks_priv, M_GSSAPI); } @@ -72,32 +75,35 @@ aes_set_key(struct krb5_key_state *ks, const void *in) { void *kp = ks->ks_key; struct aes_state *as = ks->ks_priv; - struct cryptoini cri[2]; + struct cryptoini cri; if (kp != in) bcopy(in, kp, ks->ks_class->ec_keylen); - if (as->as_session) - crypto_freesession(as->as_session); - - bzero(cri, sizeof(cri)); + if (as->as_session_aes != 0) + crypto_freesession(as->as_session_aes); + if (as->as_session_sha1 != 0) + crypto_freesession(as->as_session_sha1); /* * We only want the first 96 bits of the HMAC. */ - cri[0].cri_alg = CRYPTO_SHA1_HMAC; - cri[0].cri_klen = ks->ks_class->ec_keybits; - cri[0].cri_mlen = 12; - cri[0].cri_key = ks->ks_key; - cri[0].cri_next = &cri[1]; + bzero(&cri, sizeof(cri)); + cri.cri_alg = CRYPTO_SHA1_HMAC; + cri.cri_klen = ks->ks_class->ec_keybits; + cri.cri_mlen = 12; + cri.cri_key = ks->ks_key; + cri.cri_next = NULL; + crypto_newsession(&as->as_session_sha1, &cri, + CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE); - cri[1].cri_alg = CRYPTO_AES_CBC; - cri[1].cri_klen = ks->ks_class->ec_keybits; - cri[1].cri_mlen = 0; - cri[1].cri_key = ks->ks_key; - cri[1].cri_next = NULL; - - crypto_newsession(&as->as_session, cri, + bzero(&cri, sizeof(cri)); + cri.cri_alg = CRYPTO_AES_CBC; + cri.cri_klen = ks->ks_class->ec_keybits; + cri.cri_mlen = 0; + cri.cri_key = ks->ks_key; + cri.cri_next = NULL; + crypto_newsession(&as->as_session_aes, &cri, CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE); } @@ -114,7 +120,7 @@ aes_crypto_cb(struct cryptop *crp) int error; struct aes_state *as = (struct aes_state *) crp->crp_opaque; - if (CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC) + if (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC) return (0); error = crp->crp_etype; @@ -151,7 +157,7 @@ aes_encrypt_1(const struct krb5_key_state *ks, int buftype, void *buf, crd->crd_next = NULL; crd->crd_alg = CRYPTO_AES_CBC; - crp->crp_sid = as->as_session; + crp->crp_sid = as->as_session_aes; crp->crp_flags = buftype | CRYPTO_F_CBIFSYNC; crp->crp_buf = buf; crp->crp_opaque = (void *) as; @@ -159,7 +165,7 @@ aes_encrypt_1(const struct krb5_key_state *ks, int buftype, void *buf, error = crypto_dispatch(crp); - if ((CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC) == 0) { + if ((CRYPTO_SESID2CAPS(as->as_session_aes) & CRYPTOCAP_F_SYNC) == 0) { mtx_lock(&as->as_lock); if (!error && !(crp->crp_flags & CRYPTO_F_DONE)) error = msleep(crp, &as->as_lock, 0, "gssaes", 0); @@ -326,7 +332,7 @@ aes_checksum(const struct krb5_key_state *ks, int usage, crd->crd_next = NULL; crd->crd_alg = CRYPTO_SHA1_HMAC; - crp->crp_sid = as->as_session; + crp->crp_sid = as->as_session_sha1; crp->crp_ilen = inlen; crp->crp_olen = 12; crp->crp_etype = 0; @@ -337,7 +343,7 @@ aes_checksum(const struct krb5_key_state *ks, int usage, error = crypto_dispatch(crp); - if ((CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC) == 0) { + if ((CRYPTO_SESID2CAPS(as->as_session_sha1) & CRYPTOCAP_F_SYNC) == 0) { mtx_lock(&as->as_lock); if (!error && !(crp->crp_flags & CRYPTO_F_DONE)) error = msleep(crp, &as->as_lock, 0, "gssaes", 0); From b04e8a547e7e868f83d0fab68feb768770323303 Mon Sep 17 00:00:00 2001 From: alfred Date: Tue, 2 Feb 2016 05:57:59 +0000 Subject: [PATCH 103/236] Increase max allowed backlog for listen sockets from short to int. PR: 203922 Submitted by: White Knight MFC After: 4 weeks --- sys/kern/uipc_debug.c | 6 +++--- sys/kern/uipc_socket.c | 10 ++++++++-- sys/netinet/sctp_sysctl.c | 4 ++++ sys/netinet/sctp_uio.h | 10 ++++++---- sys/sys/socketvar.h | 12 ++++++------ usr.bin/netstat/inet.c | 6 +++--- usr.bin/netstat/sctp.c | 5 +++-- usr.bin/netstat/unix.c | 8 ++++---- 8 files changed, 37 insertions(+), 24 deletions(-) diff --git a/sys/kern/uipc_debug.c b/sys/kern/uipc_debug.c index caecad9bac84..7c8b93cdbd92 100644 --- a/sys/kern/uipc_debug.c +++ b/sys/kern/uipc_debug.c @@ -461,9 +461,9 @@ db_print_socket(struct socket *so, const char *socketname, int indent) db_print_indent(indent); /* so_list skipped */ - db_printf("so_qlen: %d ", so->so_qlen); - db_printf("so_incqlen: %d ", so->so_incqlen); - db_printf("so_qlimit: %d ", so->so_qlimit); + db_printf("so_qlen: %u ", so->so_qlen); + db_printf("so_incqlen: %u ", so->so_incqlen); + db_printf("so_qlimit: %u ", so->so_qlimit); db_printf("so_timeo: %d ", so->so_timeo); db_printf("so_error: %d\n", so->so_error); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 350ca3cdd0b0..5d2247fddb1d 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -196,7 +196,7 @@ VNET_DEFINE(struct hhook_head *, socket_hhh[HHOOK_SOCKET_LAST + 1]); * NB: The orginal sysctl somaxconn is still available but hidden * to prevent confusion about the actual purpose of this number. */ -static int somaxconn = SOMAXCONN; +static u_int somaxconn = SOMAXCONN; static int sysctl_somaxconn(SYSCTL_HANDLER_ARGS) @@ -209,7 +209,13 @@ sysctl_somaxconn(SYSCTL_HANDLER_ARGS) if (error || !req->newptr ) return (error); - if (val < 1 || val > USHRT_MAX) + /* + * The purpose of the UINT_MAX / 3 limit, is so that the formula + * 3 * so_qlimit / 2 + * below, will not overflow. + */ + + if (val < 1 || val > UINT_MAX / 3) return (EINVAL); somaxconn = val; diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index b72e896cd223..e19793679984 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -426,7 +426,11 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.maxqlen = 0; } else { xinpcb.qlen = so->so_qlen; + xinpcb.qlen_old = so->so_qlen > USHRT_MAX ? + USHRT_MAX : (uint16_t) so->so_qlen; xinpcb.maxqlen = so->so_qlimit; + xinpcb.maxqlen_old = so->so_qlimit > USHRT_MAX ? + USHRT_MAX : (uint16_t) so->so_qlimit; } SCTP_INP_INCR_REF(inp); SCTP_INP_RUNLOCK(inp); diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index cfc79788adda..2299f66fa51d 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -1170,13 +1170,15 @@ struct xsctp_inpcb { uint32_t total_nospaces; uint32_t fragmentation_point; uint16_t local_port; - uint16_t qlen; - uint16_t maxqlen; + uint16_t qlen_old; + uint16_t maxqlen_old; void *socket; + uint32_t qlen; + uint32_t maxqlen; #if defined(__LP64__) - uint32_t extra_padding[29]; /* future */ + uint32_t extra_padding[27]; /* future */ #else - uint32_t extra_padding[30]; /* future */ + uint32_t extra_padding[28]; /* future */ #endif }; diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 26cf9a6721ed..55a7950cebb7 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -95,10 +95,10 @@ struct socket { TAILQ_HEAD(, socket) so_incomp; /* (e) queue of partial unaccepted connections */ TAILQ_HEAD(, socket) so_comp; /* (e) queue of complete unaccepted connections */ TAILQ_ENTRY(socket) so_list; /* (e) list of unaccepted connections */ - u_short so_qlen; /* (e) number of unaccepted connections */ - u_short so_incqlen; /* (e) number of unaccepted incomplete + u_int so_qlen; /* (e) number of unaccepted connections */ + u_int so_incqlen; /* (e) number of unaccepted incomplete connections */ - u_short so_qlimit; /* (e) max number queued connections */ + u_int so_qlimit; /* (e) max number queued connections */ short so_timeo; /* (g) connection timeout */ u_short so_error; /* (f) error affecting connection */ struct sigio *so_sigio; /* [sg] information for async I/O or @@ -172,9 +172,9 @@ struct xsocket { caddr_t so_pcb; /* another convenient handle */ int xso_protocol; int xso_family; - u_short so_qlen; - u_short so_incqlen; - u_short so_qlimit; + u_int so_qlen; + u_int so_incqlen; + u_int so_qlimit; short so_timeo; u_short so_error; pid_t so_pgid; diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 6a933145e7e8..b0a0a7fca050 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -486,11 +486,11 @@ protopr(u_long off, const char *name, int af1, int proto) else xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", name, vchar); if (Lflag) { - char buf1[15]; + char buf1[33]; - snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, + snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen, so->so_incqlen, so->so_qlimit); - xo_emit("{:listen-queue-sizes/%-14.14s} ", buf1); + xo_emit("{:listen-queue-sizes/%-32.32s} ", buf1); } else if (Tflag) { if (istcp) xo_emit("{:sent-retransmit-packets/%6u} " diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c index 5f609a077d24..6c766b2ad082 100644 --- a/usr.bin/netstat/sctp.c +++ b/usr.bin/netstat/sctp.c @@ -467,9 +467,10 @@ sctp_process_inpcb(struct xsctp_inpcb *xinpcb, tname = "????"; if (Lflag) { - char buf1[9]; + char buf1[22]; - snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen); + snprintf(buf1, sizeof buf1, "%u/%u", + xinpcb->qlen, xinpcb->maxqlen); xo_emit("{:protocol/%-6.6s/%s} {:type/%-5.5s/%s} ", pname, tname); xo_emit("{d:queues/%-8.8s}{e:queue-len/%hu}" diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c index a7503f5f4725..04e4ae5e0aa7 100644 --- a/usr.bin/netstat/unix.c +++ b/usr.bin/netstat/unix.c @@ -271,7 +271,7 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so) struct unpcb *unp; struct sockaddr_un *sa; static int first = 1; - char buf1[15]; + char buf1[33]; static const char *titles[2] = { "{T:/%-8.8s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%8.8s} " "{T:/%8.8s} {T:/%8.8s} {T:/%8.8s} {T:Addr}\n", @@ -310,10 +310,10 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so) return; if (Lflag) { - snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, + snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen, so->so_incqlen, so->so_qlimit); - xo_emit("unix {d:socket/%-14.14s}{e:queue-length/%d}" - "{e:incomplete-queue-length/%d}{e:queue-limit/%d}", + xo_emit("unix {d:socket/%-32.32s}{e:queue-length/%u}" + "{e:incomplete-queue-length/%u}{e:queue-limit/%u}", buf1, so->so_qlen, so->so_incqlen, so->so_qlimit); } else { xo_emit(format[fmt], From ee0ad14f04253e3dbd765ebf9e131f4839a1df88 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 2 Feb 2016 07:02:51 +0000 Subject: [PATCH 104/236] Fix MFS builds when both MD_ROOT_SIZE and MFS_IMAGE are specified MD_ROOT_SIZE and embed_mfs.sh were basically retired as part of https://reviews.freebsd.org/D2903 . However, when building a kernel with 'options MD_ROOT_SIZE' specified, this results in a non-working MFS, as within sys/dev/md/md.c we fall within the wrong # ifdef. This patch implements the following: * Allow kernels to be built without the MD_ROOT_SIZE option, which results in a kernel built as per D2903. * Allow kernels to be built with the MD_ROOT_SIZE option, which results in a kernel built similarly to the pre-D2903 way, with the following differences: * The MFS is now put in a separate section within the kernel (oldmfs, so it differs from the mfs section introduced by D2903). * embed_mfs.sh is changed, so it looks up the oldmfs section within the kernel, gets its size and offset, sees if the MFS will fit within the allocated oldmfs section and only if all is well does a dd of the MFS image into the kernel. Submitted by: Stanislav Galabov Reviewed by: brooks, imp Differential Revision: https://reviews.freebsd.org/D5093 --- sys/conf/NOTES | 8 ++++++++ sys/conf/kern.post.mk | 5 +++++ sys/conf/kern.pre.mk | 8 +++++++- sys/dev/md/md.c | 14 ++++---------- sys/tools/embed_mfs.sh | 20 ++++++++++++++++---- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 7d06fe321703..67a1bb4e6866 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1078,6 +1078,14 @@ options UFS_GJOURNAL # Make space in the kernel for a root filesystem on a md device. # Define to the number of kilobytes to reserve for the filesystem. +# This is now optional. +# If not defined, the root filesystem passed in as the MFS_IMAGE makeoption +# will be automatically embedded in the kernel during linking. Its exact size +# will be consumed within the kernel. +# If defined, the old way of embedding the filesystem in the kernel will be +# used. That is to say MD_ROOT_SIZE KB will be allocated in the kernel and +# later, the filesystem image passed in as the MFS_IMAGE makeoption will be +# dd'd into the reserved space if it fits. options MD_ROOT_SIZE=10 # Make the md device a potential root device, either with preloaded diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index 56f7c507f1fb..5bcc56eba733 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -130,6 +130,9 @@ ${FULLKERNEL}: ${SYSTEM_DEP} vers.o @rm -f ${.TARGET} @echo linking ${.TARGET} ${SYSTEM_LD} +.if !empty(MD_ROOT_SIZE_CONFIGURED) && defined(MFS_IMAGE) + @sh ${S}/tools/embed_mfs.sh ${.TARGET} ${MFS_IMAGE} +.endif .if ${MK_CTF} != "no" @echo ${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ... @${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${SYSTEM_OBJS} vers.o @@ -353,6 +356,7 @@ vnode_if_typedef.h: ${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -q .if ${MFS_IMAGE:Uno} != "no" +.if empty(MD_ROOT_SIZE_CONFIGURED) # Generate an object file from the file system image to embed in the kernel # via linking. Make sure the contents are in the mfs section and rename the # start/end/size variables to __start_mfs, __stop_mfs, and mfs_size, @@ -372,6 +376,7 @@ embedfs_${MFS_IMAGE:T:R}.o: ${MFS_IMAGE} _binary_${MFS_IMAGE:C,[^[:alnum:]],_,g}_end=mfs_root_end \ ${.TARGET} .endif +.endif # XXX strictly, everything depends on Makefile because changes to ${PROF} # only appear there, but we don't handle that. diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index c9623cbfc512..cf6ec1066f53 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -195,9 +195,13 @@ SYSTEM_DEP= Makefile ${SYSTEM_OBJS} SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS} SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o} SYSTEM_OBJS+= hack.So + +MD_ROOT_SIZE_CONFIGURED!= grep MD_ROOT_SIZE opt_md.h || true ; echo .if ${MFS_IMAGE:Uno} != "no" +.if empty(MD_ROOT_SIZE_CONFIGURED) SYSTEM_OBJS+= embedfs_${MFS_IMAGE:T:R}.o .endif +.endif SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} --no-warn-mismatch \ --warn-common --export-dynamic --dynamic-linker /red/herring \ -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o @@ -230,8 +234,9 @@ MKMODULESENV+= __MPATH="${__MPATH}" # Architecture and output format arguments for objdump to convert image to # object file -.if ${MFS_IMAGE:Uno} != "no" +.if ${MFS_IMAGE:Uno} != "no" +.if empty(MD_ROOT_SIZE_CONFIGURED) .if !defined(EMBEDFS_FORMAT.${MACHINE_ARCH}) EMBEDFS_FORMAT.${MACHINE_ARCH}!= awk -F'"' '/OUTPUT_FORMAT/ {print $$2}' ${LDSCRIPT} .if empty(EMBEDFS_FORMAT.${MACHINE_ARCH}) @@ -254,6 +259,7 @@ EMBEDFS_FORMAT.mips64?= elf64-tradbigmips EMBEDFS_FORMAT.mips64el?= elf64-tradlittlemips EMBEDFS_FORMAT.riscv?= elf64-littleriscv .endif +.endif # Detect kernel config options that force stack frames to be turned on. DDB_ENABLED!= grep DDB opt_ddb.h || true ; echo diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 2fa9f460edd9..222bc403e67d 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -130,18 +130,12 @@ SYSCTL_INT(_vm, OID_AUTO, md_malloc_wait, CTLFLAG_RW, &md_malloc_wait, 0, */ #if defined(MD_ROOT_SIZE) /* + * We put the mfs_root symbol into the oldmfs section of the kernel object file. * Applications that patch the object with the image can determine - * the size looking at the start and end markers (strings), - * so we want them contiguous. + * the size looking at the oldmfs section size within the kernel. */ -static struct { - u_char start[MD_ROOT_SIZE*1024]; - u_char end[128]; -} mfs_root = { - .start = "MFS Filesystem goes here", - .end = "MFS Filesystem had better STOP here", -}; -const int mfs_root_size = sizeof(mfs_root.start); +u_char mfs_root[MD_ROOT_SIZE*1024] __attribute__ ((section ("oldmfs"))); +const int mfs_root_size = sizeof(mfs_root); #else extern volatile u_char __weak_symbol mfs_root; extern volatile u_char __weak_symbol mfs_root_end; diff --git a/sys/tools/embed_mfs.sh b/sys/tools/embed_mfs.sh index 785cf3f81bc0..3f20257b7a58 100644 --- a/sys/tools/embed_mfs.sh +++ b/sys/tools/embed_mfs.sh @@ -32,8 +32,20 @@ # $2: MFS image filename # -obs=`strings -at d $1 | grep "MFS Filesystem goes here" | awk '{print $1}'` -dd if=$2 ibs=8192 of=$1 obs=${obs} oseek=1 conv=notrunc 2> /dev/null +mfs_size=`stat -f '%z' $2 2> /dev/null` +# If we can't determine MFS image size - bail. +[ -z ${mfs_size} ] && echo "Can't determine MFS image size" && exit 1 -strings $1 | grep 'MFS Filesystem had better STOP here' > /dev/null || \ - (rm $1 && echo "MFS image too large" && false) +sec_info=`objdump -h $1 2> /dev/null | grep " oldmfs "` +# If we can't find the mfs section within the given kernel - bail. +[ -z "${sec_info}" ] && echo "Can't locate mfs section within kernel" && exit 1 + +sec_size=`echo ${sec_info} | awk '{printf("%d", "0x" $3)}' 2> /dev/null` +sec_start=`echo ${sec_info} | awk '{printf("%d", "0x" $6)}' 2> /dev/null` + +# If the mfs section size is smaller than the mfs image - bail. +[ ${sec_size} -lt ${mfs_size} ] && echo "MFS image too large" && exit 1 + +# Dump the mfs image into the mfs section +dd if=$2 ibs=8192 of=$1 obs=${sec_start} oseek=1 conv=notrunc 2> /dev/null && \ + echo "MFS image embedded into kernel" && exit 0 From 4fbe101595e65ea3b679a3d18bf897d5ac7038a7 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 2 Feb 2016 07:47:38 +0000 Subject: [PATCH 105/236] Rename some CPU_MIPSxxx options and add new CPU_MIPSxxx options This revision does the following renames: CPU_MIPS24KC -> CPU_MIPS24K CPU_MIPS74KC -> CPU_MIPS74K CPU_MIPS1004KC -> CPU_MIPS1004K It also adds the following new CPU_MIPSxxx options: CPU_MIPS24KE, CPU_MIPS34K, CPU_MIPS1074K, CPU_INTERAPTIV, CPU_PROAPTIV CPU_MIPSxxxxKC is limiting and possibly misleading as it implies the MIPSxxxxK CPU has no FPU. It would be better if the CPUs are named after their standard functionalities only and the presence or absence of FPU can then be controlled via the CPU_HAVEFPU option. I will send out another dependent revision that moves MIPS 32 r2 and r3 CPUs to use the EHB instruction for clearing hazards instead of NOP/SSNOP. Submitted by: Stanislav Galabov Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D5077 --- sys/conf/options.mips | 10 +++++++--- sys/mips/conf/AR934X_BASE | 2 +- sys/mips/conf/QCA955X_BASE | 2 +- sys/mips/include/asm.h | 2 +- sys/mips/include/cpufunc.h | 2 +- sys/mips/include/cpuregs.h | 6 +++--- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/sys/conf/options.mips b/sys/conf/options.mips index 47cff06ff7c2..e85f5b1327e2 100644 --- a/sys/conf/options.mips +++ b/sys/conf/options.mips @@ -29,9 +29,13 @@ # $FreeBSD$ CPU_MIPS4KC opt_global.h -CPU_MIPS24KC opt_global.h -CPU_MIPS74KC opt_global.h -CPU_MIPS1004KC opt_global.h +CPU_MIPS24K opt_global.h +CPU_MIPS34K opt_global.h +CPU_MIPS74K opt_global.h +CPU_MIPS1004K opt_global.h +CPU_MIPS1074K opt_global.h +CPU_INTERAPTIV opt_global.h +CPU_PROAPTIV opt_global.h CPU_MIPS32 opt_global.h CPU_MIPS64 opt_global.h CPU_SENTRY5 opt_global.h diff --git a/sys/mips/conf/AR934X_BASE b/sys/mips/conf/AR934X_BASE index 4faaf9e6be61..87bea17beac8 100644 --- a/sys/mips/conf/AR934X_BASE +++ b/sys/mips/conf/AR934X_BASE @@ -12,7 +12,7 @@ machine mips mips ident AR934X_BASE -cpu CPU_MIPS74KC +cpu CPU_MIPS74K makeoptions KERNLOADADDR=0x80050000 options HZ=1000 diff --git a/sys/mips/conf/QCA955X_BASE b/sys/mips/conf/QCA955X_BASE index 45dcbb7aa837..a7b5df73dc05 100644 --- a/sys/mips/conf/QCA955X_BASE +++ b/sys/mips/conf/QCA955X_BASE @@ -13,7 +13,7 @@ machine mips mips ident QCA955X_BASE -cpu CPU_MIPS74KC +cpu CPU_MIPS74K makeoptions KERNLOADADDR=0x80050000 options HZ=1000 diff --git a/sys/mips/include/asm.h b/sys/mips/include/asm.h index 9e7e7719076a..8a7d640f9e12 100644 --- a/sys/mips/include/asm.h +++ b/sys/mips/include/asm.h @@ -700,7 +700,7 @@ _C_LABEL(x): #elif defined(CPU_RMI) #define HAZARD_DELAY #define ITLBNOPFIX -#elif defined(CPU_MIPS74KC) +#elif defined(CPU_MIPS74K) #define HAZARD_DELAY sll $0,$0,3 #define ITLBNOPFIX sll $0,$0,3 #else diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h index 6ffb0ba1c099..3ebb8c14b448 100644 --- a/sys/mips/include/cpufunc.h +++ b/sys/mips/include/cpufunc.h @@ -248,7 +248,7 @@ MIPS_RW32_COP0_SEL(config5, MIPS_COP_0_CONFIG, 5); #if defined(CPU_NLM) || defined(BERI_LARGE_TLB) MIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6); #endif -#if defined(CPU_NLM) || defined(CPU_MIPS1004KC) +#if defined(CPU_NLM) || defined(CPU_MIPS1004K) MIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7); #endif MIPS_RW32_COP0(count, MIPS_COP_0_COUNT); diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h index 976321ab318b..a782c59bd0df 100644 --- a/sys/mips/include/cpuregs.h +++ b/sys/mips/include/cpuregs.h @@ -149,12 +149,12 @@ #define MIPS_CCA_CC 0x05 /* Cacheable Coherent. */ #endif -#if defined(CPU_MIPS74KC) +#if defined(CPU_MIPS74K) #define MIPS_CCA_UNCACHED 0x02 #define MIPS_CCA_CACHED 0x03 #endif -#if defined(CPU_MIPS1004KC) +#if defined(CPU_MIPS1004K) #define MIPS_CCA_UNCACHED 0x02 #define MIPS_CCA_CACHED 0x05 #endif @@ -214,7 +214,7 @@ #define COP0_SYNC .word 0xc0 /* ehb */ #elif defined(CPU_SB1) #define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop -#elif defined(CPU_MIPS74KC) || defined(CPU_MIPS1004KC) +#elif defined(CPU_MIPS74K) || defined(CPU_MIPS1004K) #define COP0_SYNC .word 0xc0 /* ehb */ #else /* From d381a76dda3865495a367b4103581a44fb6ec986 Mon Sep 17 00:00:00 2001 From: des Date: Tue, 2 Feb 2016 10:02:38 +0000 Subject: [PATCH 106/236] Document our modified default value for PermitRootLogin. --- crypto/openssh/sshd_config | 2 +- crypto/openssh/sshd_config.5 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config index 6ab7900bc544..5cf3d4f6ea97 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -45,7 +45,7 @@ # Authentication: #LoginGraceTime 2m -#PermitRootLogin prohibit-password +#PermitRootLogin no #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index 9945fc93cab0..e9e460b5e297 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -1217,7 +1217,7 @@ The argument must be or .Dq no . The default is -.Dq prohibit-password . +.Dq no . Note that if .Cm ChallengeResponseAuthentication is From 86ce64705e75081226b33569e8335f94947a0514 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 10:11:56 +0000 Subject: [PATCH 107/236] Correctly handle the case where copystr(9) is given a string longer than the passed in length. In this case we need to return ENAMETOOLONG. --- sys/arm64/arm64/copystr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm64/arm64/copystr.c b/sys/arm64/arm64/copystr.c index 008fdd1b5645..ebb4acddfbaf 100644 --- a/sys/arm64/arm64/copystr.c +++ b/sys/arm64/arm64/copystr.c @@ -56,6 +56,6 @@ copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len, if (lencopied != NULL) *lencopied = pos; - return (0); + return (error); } From 8c057ed9b1f5a02e407eb5641f65c5ff2cc977e6 Mon Sep 17 00:00:00 2001 From: skra Date: Tue, 2 Feb 2016 10:17:51 +0000 Subject: [PATCH 108/236] Fix setting of protection bits for page table entries in pmap_map(). This function is only called from vm_page_startup() and vm_reserv_startup(). I.e. during vm subsystem initialization. As VM_PROT_WRITE is always used in these calls, the typo did not have any effect. Likely, it's the reason why it wasn't discovered so long. --- sys/arm/arm/pmap-v6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 4f774c487f76..23167d6e053b 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -1325,7 +1325,7 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x)," " prot = %d\n", __func__, *virt, start, end, end - start, prot)); - l2prot = (prot & VM_PROT_WRITE) ? PTE2_AP_KRW : PTE1_AP_KR; + l2prot = (prot & VM_PROT_WRITE) ? PTE2_AP_KRW : PTE2_AP_KR; l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX; l1prot = ATTR_TO_L1(l2prot); From f0c954c605dca38f4db001f41011e1ae332e2408 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 10:28:56 +0000 Subject: [PATCH 109/236] Implement single stepping on arm64. We need to set the single step bits in the processor and debug state registers. A flag has been added to the pcb to tell us when to enable single stepping for a given thread. Reviewed by: kib Sponsored by: ABT Systems Ltd Differential Revision: https://reviews.freebsd.org/D4730 --- sys/arm64/arm64/genassym.c | 2 ++ sys/arm64/arm64/machdep.c | 6 ++++-- sys/arm64/arm64/mp_machdep.c | 3 +++ sys/arm64/arm64/swtch.S | 39 ++++++++++++++++++++++++++++++++++++ sys/arm64/arm64/trap.c | 15 +++++++++++--- sys/arm64/include/armreg.h | 1 + sys/arm64/include/pcb.h | 4 ++++ 7 files changed, 65 insertions(+), 5 deletions(-) diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c index 214b99d727d6..67c295f2ed9a 100644 --- a/sys/arm64/arm64/genassym.c +++ b/sys/arm64/arm64/genassym.c @@ -49,10 +49,12 @@ ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); /* Size of pcb, rounded to keep stack alignment */ ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1)); +ASSYM(PCB_SINGLE_STEP_SHIFT, PCB_SINGLE_STEP_SHIFT); ASSYM(PCB_REGS, offsetof(struct pcb, pcb_x)); ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp)); ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr)); ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); +ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(SF_UC, offsetof(struct sigframe, sf_uc)); diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 409ecd316b27..f7552c46adae 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -233,7 +233,8 @@ int ptrace_single_step(struct thread *td) { - /* TODO; */ + td->td_frame->tf_spsr |= PSR_SS; + td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; return (0); } @@ -241,7 +242,8 @@ int ptrace_clear_single_step(struct thread *td) { - /* TODO; */ + td->td_frame->tf_spsr &= ~PSR_SS; + td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; return (0); } diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c index 19cee7788c3f..b89982d32e9c 100644 --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #ifdef VFP @@ -247,6 +248,8 @@ init_secondary(uint64_t cpu) vfp_init(); #endif + dbg_monitor_init(); + /* Enable interrupts */ intr_enable(); diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S index 1f20b3d63c9c..3175e879114d 100644 --- a/sys/arm64/arm64/swtch.S +++ b/sys/arm64/arm64/swtch.S @@ -37,10 +37,37 @@ __FBSDID("$FreeBSD$"); +.macro clear_step_flag pcbflags, tmp + tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f + mrs \tmp, mdscr_el1 + bic \tmp, \tmp, #1 + msr mdscr_el1, \tmp + isb +999: +.endm + +.macro set_step_flag pcbflags, tmp + tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f + mrs \tmp, mdscr_el1 + orr \tmp, \tmp, #1 + msr mdscr_el1, \tmp + isb +999: +.endm + /* * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) + /* Of old == NULL skip disabling stepping */ + cbz x0, 1f + + /* If we were single stepping, disable it */ + ldr x4, [x0, #TD_PCB] + ldr w5, [x4, #PCB_FLAGS] + clear_step_flag w5, x6 +1: + #ifdef VFP /* Backup the new thread pointer around a call to C code */ mov x19, x1 @@ -69,6 +96,10 @@ ENTRY(cpu_throw) dsb sy isb + /* If we are single stepping, enable it */ + ldr w5, [x4, #PCB_FLAGS] + set_step_flag w5, x6 + /* Restore the registers */ ldp x5, x6, [x4, #PCB_SP] mov sp, x5 @@ -127,6 +158,10 @@ ENTRY(cpu_switch) mrs x6, tpidr_el0 stp x5, x6, [x4, #PCB_SP] + /* If we were single stepping, disable it */ + ldr w5, [x4, #PCB_FLAGS] + clear_step_flag w5, x6 + #ifdef VFP mov x19, x0 mov x20, x1 @@ -174,6 +209,10 @@ ENTRY(cpu_switch) b.eq 1b #endif + /* If we are single stepping, enable it */ + ldr w5, [x4, #PCB_FLAGS] + set_step_flag w5, x6 + /* Restore the registers */ ldp x5, x6, [x4, #PCB_SP] mov sp, x5 diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index ac810adad27c..89d6d0c89f84 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -138,7 +138,6 @@ svc_handler(struct trapframe *frame) int error; td = curthread; - td->td_frame = frame; error = syscallenter(td, &sa); syscallret(td, error, &sa); @@ -338,6 +337,9 @@ do_el0_sync(struct trapframe *frame) ("Invalid pcpu address from userland: %p (tpidr %lx)", get_pcpu(), READ_SPECIALREG(tpidr_el1))); + td = curthread; + td->td_frame = frame; + esr = READ_SPECIALREG(esr_el1); exception = ESR_ELx_EXCEPTION(esr); switch (exception) { @@ -373,15 +375,22 @@ do_el0_sync(struct trapframe *frame) el0_excp_unknown(frame); break; case EXCP_PC_ALIGN: - td = curthread; call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr); userret(td, frame); break; case EXCP_BRK: - td = curthread; call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr); userret(td, frame); break; + case EXCP_SOFTSTP_EL0: + td->td_frame->tf_spsr &= ~PSR_SS; + td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; + WRITE_SPECIALREG(MDSCR_EL1, + READ_SPECIALREG(MDSCR_EL1) & ~DBG_MDSCR_SS); + call_trapsignal(td, SIGTRAP, TRAP_TRACE, + (void *)frame->tf_elr); + userret(td, frame); + break; default: print_registers(frame); panic("Unknown userland exception %x esr_el1 %lx\n", exception, diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index ffcf98982187..0c86462376fc 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -101,6 +101,7 @@ #define EXCP_SP_ALIGN 0x26 /* SP slignment fault */ #define EXCP_TRAP_FP 0x2c /* Trapped FP exception */ #define EXCP_SERROR 0x2f /* SError interrupt */ +#define EXCP_SOFTSTP_EL0 0x32 /* Software Step, from lower EL */ #define EXCP_SOFTSTP_EL1 0x33 /* Software Step, from same EL */ #define EXCP_WATCHPT_EL1 0x35 /* Watchpoint, from same EL */ #define EXCP_BRK 0x3c /* Breakpoint */ diff --git a/sys/arm64/include/pcb.h b/sys/arm64/include/pcb.h index 027b60544c38..55dd6e92eb3d 100644 --- a/sys/arm64/include/pcb.h +++ b/sys/arm64/include/pcb.h @@ -45,6 +45,10 @@ struct pcb { /* Fault handler, the error value is passed in x0 */ vm_offset_t pcb_onfault; + u_int pcb_flags; +#define PCB_SINGLE_STEP_SHIFT 0 +#define PCB_SINGLE_STEP (1 << PCB_SINGLE_STEP_SHIFT) + /* Place last to simplify the asm to access the rest if the struct */ __uint128_t pcb_vfp[32]; uint32_t pcb_fpcr; From c240461c44197da4a3bd10c1e092e39bfb00d128 Mon Sep 17 00:00:00 2001 From: skra Date: Tue, 2 Feb 2016 10:32:45 +0000 Subject: [PATCH 110/236] Remove all remaining references to old and not more used struct pmap_devmap, pmap_devmap_bootstrap() and pmap_devmap[]. It was replaced in r257660. --- sys/arm/annapurna/alpine/alpine_machdep.c | 2 +- sys/arm/include/pmap-v6.h | 14 -------------- sys/arm/mv/mv_common.c | 2 +- sys/arm/mv/mv_machdep.c | 2 +- sys/arm/mv/orion/db88f5xxx.c | 2 +- sys/arm/versatile/versatile_machdep.c | 2 +- 6 files changed, 5 insertions(+), 19 deletions(-) diff --git a/sys/arm/annapurna/alpine/alpine_machdep.c b/sys/arm/annapurna/alpine/alpine_machdep.c index 959b30faa12b..dc6d3a4245db 100644 --- a/sys/arm/annapurna/alpine/alpine_machdep.c +++ b/sys/arm/annapurna/alpine/alpine_machdep.c @@ -123,7 +123,7 @@ platform_late_init(void) } /* - * Construct pmap_devmap[] with DT-derived config data. + * Construct devmap table with DT-derived config data. */ int platform_devmap_init(void) diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index 5ca8f1767248..c22b937d537a 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -225,20 +225,6 @@ pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, pmap_preboot_map_attr(pa, va, size, prot, cache); } -/* - * This structure is used by machine-dependent code to describe - * static mappings of devices, created at bootstrap time. - */ -struct pmap_devmap { - vm_offset_t pd_va; /* virtual address */ - vm_paddr_t pd_pa; /* physical address */ - vm_size_t pd_size; /* size of region */ - vm_prot_t pd_prot; /* protection code */ - int pd_cache; /* cache attributes */ -}; - -void pmap_devmap_bootstrap(const struct pmap_devmap *); - #endif /* _KERNEL */ // ----------------- TO BE DELETED --------------------------------------------- diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c index 8e9465512853..afefc7f28600 100644 --- a/sys/arm/mv/mv_common.c +++ b/sys/arm/mv/mv_common.c @@ -377,7 +377,7 @@ soc_id(uint32_t *dev, uint32_t *rev) * Notice: system identifiers are available in the registers range of * PCIE controller, so using this function is only allowed (and * possible) after the internal registers range has been mapped in via - * pmap_devmap_bootstrap(). + * arm_devmap_bootstrap(). */ *dev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 0) >> 16; *rev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 8) & 0xff; diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c index 9b307730b387..8f0375bc1b05 100644 --- a/sys/arm/mv/mv_machdep.c +++ b/sys/arm/mv/mv_machdep.c @@ -337,7 +337,7 @@ __weak_reference(mv_default_fdt_pci_devmap, mv_pci_devmap); */ /* - * Construct pmap_devmap[] with DT-derived config data. + * Construct devmap table with DT-derived config data. */ int platform_devmap_init(void) diff --git a/sys/arm/mv/orion/db88f5xxx.c b/sys/arm/mv/orion/db88f5xxx.c index bfac68a6ac24..15751cc990b7 100644 --- a/sys/arm/mv/orion/db88f5xxx.c +++ b/sys/arm/mv/orion/db88f5xxx.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin); /* Static device mappings. */ -const struct pmap_devmap pmap_devmap[] = { +const struct arm_devmap_entry db88f5xxx_devmap[] = { /* * Map the on-board devices VA == PA so that we can access them * with the MMU on or off. diff --git a/sys/arm/versatile/versatile_machdep.c b/sys/arm/versatile/versatile_machdep.c index 2869f1b5d668..ac3ebd22ed40 100644 --- a/sys/arm/versatile/versatile_machdep.c +++ b/sys/arm/versatile/versatile_machdep.c @@ -88,7 +88,7 @@ static struct arm_devmap_entry fdt_devmap[FDT_DEVMAP_MAX] = { /* - * Construct pmap_devmap[] with DT-derived config data. + * Construct devmap table with DT-derived config data. */ int platform_devmap_init(void) From c2491870ac4a7747285b738c2ae6d9f6d6cba437 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 10:39:18 +0000 Subject: [PATCH 111/236] Add suppor to loader.efi to load files off hte network. For this we need to open the device in exclusive mode as, without this, the firmware may also be reading packets off the interface leading to a race. Reviewed by: emaste Sponsored by: ABT Systems Ltd Differential Revision: https://reviews.freebsd.org/D4132 --- sys/boot/efi/libefi/efinet.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index f1e614331999..d9ecdcc45f1c 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -184,11 +184,16 @@ efinet_init(struct iodesc *desc, void *machdep_hint) EFI_HANDLE h; EFI_STATUS status; + if (nif->nif_driver->netif_ifs[nif->nif_unit].dif_unit < 0) { + printf("Invalid network interface %d\n", nif->nif_unit); + return; + } + h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata); if (status != EFI_SUCCESS) { - printf("net%d: cannot start interface (status=%ld)\n", - nif->nif_unit, (long)status); + printf("net%d: cannot start interface (status=%lu)\n", + nif->nif_unit, EFI_ERROR_CODE(status)); return; } @@ -288,11 +293,30 @@ efinet_dev_init() stats = calloc(nifs, sizeof(struct netif_stats)); for (i = 0; i < nifs; i++) { + EFI_SIMPLE_NETWORK *net; + EFI_HANDLE h; + dif = &efinetif.netif_ifs[i]; + dif->dif_unit = -1; + + h = efi_find_handle(&efinet_dev, i); + + /* + * Open the network device in exclusive mode. Without this + * we will be racing with the UEFI network stack. It will + * pull packets off the network leading to lost packets. + */ + status = BS->OpenProtocol(h, &sn_guid, (void **)&net, + IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE); + if (status != EFI_SUCCESS) { + printf("Unable to open network interface %d\n", i); + continue; + } + dif->dif_unit = i; dif->dif_nsel = 1; dif->dif_stats = &stats[i]; - dif->dif_private = efi_find_handle(&efinet_dev, i); + dif->dif_private = h; } return (0); From 7e1c03eb21e331df8f1351de93f84e377f7a6435 Mon Sep 17 00:00:00 2001 From: mmel Date: Tue, 2 Feb 2016 10:50:32 +0000 Subject: [PATCH 112/236] ARM: Remove last unused function, cpu_flush_prefetchbuf(), from cpu_functions table. --- sys/arm/arm/cpufunc.c | 9 --------- sys/arm/arm/cpufunc_asm_arm11x6.S | 5 ----- sys/arm/arm/cpufunc_asm_fa526.S | 6 ------ sys/arm/include/cpufunc.h | 4 ---- 4 files changed, 24 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 2ffef6bdee37..422a1a5d3afe 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -140,7 +140,6 @@ struct cpu_functions arm9_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ (void *)cpufunc_nullop, /* sleep */ @@ -194,7 +193,6 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ (void *)cpufunc_nullop, /* sleep */ @@ -246,7 +244,6 @@ struct cpu_functions sheeva_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ sheeva_cpu_sleep, /* sleep */ @@ -298,7 +295,6 @@ struct cpu_functions pj4bv7_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ (void *)cpufunc_nullop, /* sleep */ @@ -352,7 +348,6 @@ struct cpu_functions xscale_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ xscale_cpu_sleep, /* sleep */ @@ -406,7 +401,6 @@ struct cpu_functions xscalec3_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ xscale_cpu_sleep, /* sleep */ @@ -459,7 +453,6 @@ struct cpu_functions fa526_cpufuncs = { /* Other functions */ - fa526_flush_prefetchbuf, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ fa526_cpu_sleep, /* sleep */ @@ -513,7 +506,6 @@ struct cpu_functions arm1176_cpufuncs = { /* Other functions */ - arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */ arm11_drain_writebuf, /* drain_writebuf */ arm11x6_sleep, /* sleep */ @@ -574,7 +566,6 @@ struct cpu_functions cortexa_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ armv7_cpu_sleep, /* sleep */ diff --git a/sys/arm/arm/cpufunc_asm_arm11x6.S b/sys/arm/arm/cpufunc_asm_arm11x6.S index b88c0fd67ee2..be6d5309d935 100644 --- a/sys/arm/arm/cpufunc_asm_arm11x6.S +++ b/sys/arm/arm/cpufunc_asm_arm11x6.S @@ -138,11 +138,6 @@ ENTRY_NP(arm11x6_icache_sync_all) RET END(arm11x6_icache_sync_all) -ENTRY_NP(arm11x6_flush_prefetchbuf) - mcr p15, 0, r0, c7, c5, 4 /* Flush Prefetch Buffer */ - RET -END(arm11x6_flush_prefetchbuf) - ENTRY_NP(arm11x6_icache_sync_range) add r1, r1, r0 sub r1, r1, #1 diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index 1fcca217617d..38cb11ad5323 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -72,12 +72,6 @@ ENTRY(fa526_cpu_sleep) mov pc, lr END(fa526_cpu_sleep) -ENTRY(fa526_flush_prefetchbuf) - mov r0, #0 - mcr p15, 0, r0, c7, c5, 4 /* Pre-fetch flush */ - mov pc, lr -END(fa526_flush_prefetchbuf) - /* * Cache functions */ diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 48d1c00b5e13..b56d1c20c9bc 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -149,7 +149,6 @@ struct cpu_functions { /* Other functions */ - void (*cf_flush_prefetchbuf) (void); void (*cf_drain_writebuf) (void); void (*cf_sleep) (int mode); @@ -191,7 +190,6 @@ extern u_int cputype; #define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s)) #define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf() -#define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf() #define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() #define cpu_sleep(m) cpufuncs.cf_sleep(m) @@ -215,7 +213,6 @@ void fa526_setttb (u_int ttb); void fa526_context_switch (void); void fa526_cpu_sleep (int); void fa526_tlb_flushID_SE (u_int); -void fa526_flush_prefetchbuf (void); void fa526_icache_sync_all (void); void fa526_icache_sync_range(vm_offset_t start, vm_size_t end); @@ -327,7 +324,6 @@ void arm11x6_setttb (u_int); void arm11x6_idcache_wbinv_all (void); void arm11x6_dcache_wbinv_all (void); void arm11x6_icache_sync_all (void); -void arm11x6_flush_prefetchbuf (void); void arm11x6_icache_sync_range (vm_offset_t, vm_size_t); void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t); void arm11x6_setup (void); From 2dd3f93a4bbeb8931ca56f139ef169319ae075c2 Mon Sep 17 00:00:00 2001 From: hselasky Date: Tue, 2 Feb 2016 11:36:58 +0000 Subject: [PATCH 113/236] Use LIBADD instead of LDADD. Sponsored by: Mellanox Technologies --- contrib/ofed/librdmacm/examples/build/cmatose/Makefile | 3 +-- contrib/ofed/librdmacm/examples/build/mckey/Makefile | 3 +-- contrib/ofed/librdmacm/examples/build/udaddy/Makefile | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/contrib/ofed/librdmacm/examples/build/cmatose/Makefile b/contrib/ofed/librdmacm/examples/build/cmatose/Makefile index 31d2ae7f7f6b..e2baf40bcf2c 100644 --- a/contrib/ofed/librdmacm/examples/build/cmatose/Makefile +++ b/contrib/ofed/librdmacm/examples/build/cmatose/Makefile @@ -5,7 +5,6 @@ PROG= cmatose MAN= SRCS= cmatose.c -LDADD+= -libverbs -lrdmacm -lpthread -LDADD+= -lmlx4 +LIBADD= ibverbs rdmacm pthread mlx4 .include diff --git a/contrib/ofed/librdmacm/examples/build/mckey/Makefile b/contrib/ofed/librdmacm/examples/build/mckey/Makefile index 4abaf2786d56..6ef498fb905b 100644 --- a/contrib/ofed/librdmacm/examples/build/mckey/Makefile +++ b/contrib/ofed/librdmacm/examples/build/mckey/Makefile @@ -5,7 +5,6 @@ PROG= mckey MAN= SRCS= mckey.c -LDADD+= -libverbs -lrdmacm -lpthread -LDADD+= -lmlx4 +LIBADD= ibverbs rdmacm pthread mlx4 .include diff --git a/contrib/ofed/librdmacm/examples/build/udaddy/Makefile b/contrib/ofed/librdmacm/examples/build/udaddy/Makefile index 1e325505bc86..fc76534fbed1 100644 --- a/contrib/ofed/librdmacm/examples/build/udaddy/Makefile +++ b/contrib/ofed/librdmacm/examples/build/udaddy/Makefile @@ -5,7 +5,6 @@ PROG= udaddy MAN= SRCS= udaddy.c -LDADD+= -libverbs -lrdmacm -lpthread -LDADD+= -lmlx4 +LIBADD= ibverbs rdmacm pthread mlx4 .include From 08d60f77fad33862cdb65c438131e126658af325 Mon Sep 17 00:00:00 2001 From: ume Date: Tue, 2 Feb 2016 11:51:18 +0000 Subject: [PATCH 114/236] Make dynamic link of libiconv from ports work again. The symbols of libiconv from ports were changed to have prefixed. Since we have iconv in our libc these days, we don't need it on 10.X and later. However, 9.X still need this. Spotted by: Yoshihiko Sarumaru MFC after: 1 days --- bin/csh/iconv_stub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/csh/iconv_stub.c b/bin/csh/iconv_stub.c index d1a9e475d87e..e20608c60616 100644 --- a/bin/csh/iconv_stub.c +++ b/bin/csh/iconv_stub.c @@ -36,9 +36,9 @@ #undef iconv_close #define ICONVLIB "libiconv.so" -#define ICONV_ENGINE "iconv" -#define ICONV_OPEN "iconv_open" -#define ICONV_CLOSE "iconv_close" +#define ICONV_ENGINE "libiconv" +#define ICONV_OPEN "libiconv_open" +#define ICONV_CLOSE "libiconv_close" typedef iconv_t iconv_open_t(const char *, const char *); From f6859814fe79dccdcede33e2a31616ec07fa1f28 Mon Sep 17 00:00:00 2001 From: mmel Date: Tue, 2 Feb 2016 14:53:34 +0000 Subject: [PATCH 115/236] ARM: All remaining functions in cpufunc_asm_arm10.S are identical with functions in cpufunc_asm_arm9.S. Use arm9 variants and remove cpufunc_asm_arm10.S completly. --- sys/arm/arm/cpufunc.c | 8 ++-- sys/arm/arm/cpufunc_asm_arm10.S | 71 --------------------------------- sys/arm/include/cpufunc.h | 12 ++---- sys/conf/Makefile.arm | 1 - sys/conf/files.arm | 3 +- 5 files changed, 9 insertions(+), 86 deletions(-) delete mode 100644 sys/arm/arm/cpufunc_asm_arm10.S diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 422a1a5d3afe..514a6b1a4059 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -167,7 +167,7 @@ struct cpu_functions armv5_ec_cpufuncs = { /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ - arm10_tlb_flushID_SE, /* tlb_flushID_SE */ + arm9_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -199,7 +199,7 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Soft functions */ - arm10_context_switch, /* context_switch */ + arm9_context_switch, /* context_switch */ arm10_setup /* cpu setup */ @@ -218,7 +218,7 @@ struct cpu_functions sheeva_cpufuncs = { /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ - arm10_tlb_flushID_SE, /* tlb_flushID_SE */ + arm9_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ @@ -250,7 +250,7 @@ struct cpu_functions sheeva_cpufuncs = { /* Soft functions */ - arm10_context_switch, /* context_switch */ + arm9_context_switch, /* context_switch */ arm10_setup /* cpu setup */ }; diff --git a/sys/arm/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S deleted file mode 100644 index 21bc59786a86..000000000000 --- a/sys/arm/arm/cpufunc_asm_arm10.S +++ /dev/null @@ -1,71 +0,0 @@ -/* $NetBSD: cpufunc_asm_arm10.S,v 1.1 2003/09/06 09:12:29 rearnsha Exp $ */ - -/*- - * Copyright (c) 2002 ARM Limited - * 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. - * 3. The name of the company may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ARM10 assembly functions for CPU / MMU / TLB specific operations - * - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * TLB functions - */ -ENTRY(arm10_tlb_flushID_SE) - mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */ - mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */ - bx lr -END(arm10_tlb_flushID_SE) - - -/* - * Context switch. - * - * These is the CPU-specific parts of the context switcher cpu_switch() - * These functions actually perform the TTB reload. - * - * NOTE: Special calling convention - * r1, r4-r13 must be preserved - */ -ENTRY(arm10_context_switch) - /* - * We can assume that the caches will only contain kernel addresses - * at this point. So no need to flush them again. - */ - mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ - mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */ - mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */ - - /* Paranoia -- make sure the pipeline is empty. */ - nop - nop - nop - bx lr -END(arm10_context_switch) diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index b56d1c20c9bc..aad0febfa470 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -225,11 +225,13 @@ void fa526_idcache_wbinv_range(vm_offset_t start, vm_size_t end); #endif -#ifdef CPU_ARM9 +#if defined(CPU_ARM9) || defined(CPU_ARM9E) void arm9_setttb (u_int); - void arm9_tlb_flushID_SE (u_int va); +void arm9_context_switch (void); +#endif +#if defined(CPU_ARM9) void arm9_icache_sync_all (void); void arm9_icache_sync_range (vm_offset_t, vm_size_t); @@ -241,8 +243,6 @@ void arm9_dcache_wb_range (vm_offset_t, vm_size_t); void arm9_idcache_wbinv_all (void); void arm9_idcache_wbinv_range (vm_offset_t, vm_size_t); -void arm9_context_switch (void); - void arm9_setup (void); extern unsigned arm9_dcache_sets_max; @@ -252,10 +252,6 @@ extern unsigned arm9_dcache_index_inc; #endif #if defined(CPU_ARM9E) -void arm10_tlb_flushID_SE (u_int); - -void arm10_context_switch (void); - void arm10_setup (void); u_int sheeva_control_ext (u_int, u_int); diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm index af5f7da3ec76..a7df55b5fe3b 100644 --- a/sys/conf/Makefile.arm +++ b/sys/conf/Makefile.arm @@ -68,7 +68,6 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M\ FILES_CPU_FUNC = \ $S/$M/$M/cpufunc_asm_arm9.S \ - $S/$M/$M/cpufunc_asm_arm10.S \ $S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S \ $S/$M/$M/cpufunc_asm_xscale_c3.S $S/$M/$M/cpufunc_asm_armv5_ec.S \ $S/$M/$M/cpufunc_asm_fa526.S $S/$M/$M/cpufunc_asm_sheeva.S \ diff --git a/sys/conf/files.arm b/sys/conf/files.arm index bf0e26268075..9f3a6bffedc0 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -11,8 +11,7 @@ arm/arm/busdma_machdep-v6.c optional armv6 arm/arm/copystr.S standard arm/arm/cpufunc.c standard arm/arm/cpufunc_asm.S standard -arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 -arm/arm/cpufunc_asm_arm10.S optional cpu_arm9e +arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 | cpu_arm9e arm/arm/cpufunc_asm_arm11.S optional cpu_arm1176 arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176 arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 From 469d12176a57ab0d99110aa56ce2633fb4daf3d7 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 2 Feb 2016 16:00:42 +0000 Subject: [PATCH 116/236] Move MIPS32 Release 2 and Release 3 CPUs to use the EHB instruction for clearing hazards. This revision makes currently known MIPS32 Release 2 and Release 3 CPUs use the EHB instruction when clearing hazards. So far the MIPS 74K and MIPS1004K (somewhat) were already using the EHB. Now we add more r2 and r3 CPUs to this list. Also, for the cases of MIPS coherent processing systems (currently 1004K, 1074K, interAptiv and proAptiv) - define proper CCA attributes. Submitted by: Stanislav Galabov Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D5078 --- sys/mips/include/cpuregs.h | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h index a782c59bd0df..a1d9bc0195da 100644 --- a/sys/mips/include/cpuregs.h +++ b/sys/mips/include/cpuregs.h @@ -110,6 +110,7 @@ * C: Cacheable, coherency unspecified. * CNC: Cacheable non-coherent. * CC: Cacheable coherent. + * CCS: Cacheable coherent, shared read. * CCE: Cacheable coherent, exclusive read. * CCEW: Cacheable coherent, exclusive write. * CCUOW: Cacheable coherent, update on write. @@ -154,9 +155,20 @@ #define MIPS_CCA_CACHED 0x03 #endif -#if defined(CPU_MIPS1004K) -#define MIPS_CCA_UNCACHED 0x02 -#define MIPS_CCA_CACHED 0x05 +/* + * 1004K and 1074K cores, as well as interAptiv and proAptiv cores, support + * Cacheable Coherent CCAs 0x04 and 0x05, as well as Cacheable non-Coherent + * CCA 0x03 and Uncached Accelerated CCA 0x07 + */ +#if defined(CPU_MIPS1004K) || defined(CPU_MIPS1074K) || \ + defined(CPU_INTERAPTIV) || defined(CPU_PROAPTIV) +#define MIPS_CCA_CNC 0x03 +#define MIPS_CCA_CCE 0x04 +#define MIPS_CCA_CCS 0x05 +#define MIPS_CCA_UA 0x07 + +/* We use shared read CCA for CACHED CCA */ +#define MIPS_CCA_CACHED MIPS_CCA_CCS #endif #ifndef MIPS_CCA_UNCACHED @@ -214,8 +226,18 @@ #define COP0_SYNC .word 0xc0 /* ehb */ #elif defined(CPU_SB1) #define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop -#elif defined(CPU_MIPS74K) || defined(CPU_MIPS1004K) -#define COP0_SYNC .word 0xc0 /* ehb */ +#elif defined(CPU_MIPS24K) || defined(CPU_MIPS34K) || \ + defined(CPU_MIPS74K) || defined(CPU_MIPS1004K) || \ + defined(CPU_MIPS1074K) || defined(CPU_INTERAPTIV) || \ + defined(CPU_PROAPTIV) +/* + * According to MIPS32tm Architecture for Programmers, Vol.II, rev. 2.00: + * "As EHB becomes standard in MIPS implementations, the previous SSNOPs can be + * removed, leaving only the EHB". + * Also, all MIPS32 Release 2 implementations have the EHB instruction, which + * resolves all execution hazards. The same goes for MIPS32 Release 3. + */ +#define COP0_SYNC .word 0xc0 /* ehb */ #else /* * Pick a reasonable default based on the "typical" spacing described in the From 16015b3babb3371b475313662b909976dd9a40b4 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 2 Feb 2016 16:22:35 +0000 Subject: [PATCH 117/236] Use CPU_MIPS24K now in AR933x based boards. I'll flip on other boards as i test them. Tested: * AR9331, Carambola 2 --- sys/mips/conf/AR933X_BASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/mips/conf/AR933X_BASE b/sys/mips/conf/AR933X_BASE index 38f847db12eb..c5619fe4ff4a 100644 --- a/sys/mips/conf/AR933X_BASE +++ b/sys/mips/conf/AR933X_BASE @@ -12,7 +12,7 @@ machine mips mips ident AR933X_BASE -cpu CPU_MIPS4KC +cpu CPU_MIPS24K makeoptions KERNLOADADDR=0x80050000 options HZ=1000 From 9de256aba3ba3d52b2a60731d976ad88ae302fe7 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 2 Feb 2016 16:25:53 +0000 Subject: [PATCH 118/236] Use MIPS24K now. Submitted by: Stanislav Galabov Differential Revision: https://reviews.freebsd.org/D5079 --- sys/mips/rt305x/std.rt305x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/mips/rt305x/std.rt305x b/sys/mips/rt305x/std.rt305x index c7212a2c6d3e..d0e09b3b6b07 100644 --- a/sys/mips/rt305x/std.rt305x +++ b/sys/mips/rt305x/std.rt305x @@ -3,5 +3,5 @@ files "../rt305x/files.rt305x" -cpu CPU_MIPS4KC +cpu CPU_MIPS24K From 80defbca6b1280bd85e38b31455b6e3af0158dd0 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 16:32:44 +0000 Subject: [PATCH 119/236] Only look for the ranges property when we have children. This fixes booting on systems with a gicv2, but no PCIe so no gicv2m. Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/gic_fdt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/arm64/arm64/gic_fdt.c b/sys/arm64/arm64/gic_fdt.c index 924a08b1cf66..075f1d6b8523 100644 --- a/sys/arm64/arm64/gic_fdt.c +++ b/sys/arm64/arm64/gic_fdt.c @@ -158,12 +158,17 @@ arm_gic_fdt_attach(device_t dev) OF_getencprop(root, "#size-cells", &sc->sc_size_cells, sizeof(sc->sc_size_cells)); + /* If we have no children don't probe for them */ + child = OF_child(root); + if (child == 0) + return (0); + if (gic_fill_ranges(root, sc) < 0) { device_printf(dev, "could not get ranges\n"); return (ENXIO); } - for (child = OF_child(root); child != 0; child = OF_peer(child)) { + for (; child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) { From 7c81e8b6526c1c0b426d113b839b2f72ef058929 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 16:35:37 +0000 Subject: [PATCH 120/236] Increase the space we use after the kernel to 8MiB. On 2GiB HiKey board we would try to access data past this point stopping the boot. Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/locore.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 5a61c4a1f7cf..9909a42472d9 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -369,8 +369,8 @@ create_pagetables: sub x8, x7, x6 /* Get the number of l2 pages to allocate, rounded down */ lsr x10, x8, #(L2_SHIFT) - /* Add 4 MiB for any rounding above and the module data */ - add x10, x10, #2 + /* Add 8 MiB for any rounding above and the module data */ + add x10, x10, #4 /* Create the kernel space L2 table */ mov x6, x26 From 700dcbc1a2bc36e3a116192b615faf238f4e6e72 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 17:57:15 +0000 Subject: [PATCH 121/236] Ensure we don't overflow the phys_avail array. Some firmware may provide more memory locations than we have space to record. Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/pmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index dcd6e5dc8021..37b9480b620c 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -596,7 +596,8 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) * up to the physical address KERNBASE points at. */ map_slot = avail_slot = 0; - for (; map_slot < (physmap_idx * 2); map_slot += 2) { + for (; map_slot < (physmap_idx * 2) && + avail_slot < (PHYS_AVAIL_SIZE - 2); map_slot += 2) { if (physmap[map_slot] == physmap[map_slot + 1]) continue; @@ -612,7 +613,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) } /* Add the memory before the kernel */ - if (physmap[avail_slot] < pa) { + if (physmap[avail_slot] < pa && avail_slot < (PHYS_AVAIL_SIZE - 2)) { phys_avail[avail_slot] = physmap[map_slot]; phys_avail[avail_slot + 1] = pa; physmem += (phys_avail[avail_slot + 1] - From 5b58d7a3f84952d4d0e45ed7d2501aa4c1a28f2e Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 2 Feb 2016 17:59:43 +0000 Subject: [PATCH 122/236] Increase the size of PHYS_AVAIL_SIZE to allow firmware to provide a large number of physical memory locations we can access. This is the case on some HiKey boards that may have UEFI reserved memory dispersed through the physical space. Sponsored by: ABT Systems Ltd --- sys/arm64/include/pmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h index e109de2816d8..0faf2e8fc9d9 100644 --- a/sys/arm64/include/pmap.h +++ b/sys/arm64/include/pmap.h @@ -121,7 +121,7 @@ extern struct pmap kernel_pmap_store; #define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) #define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) -#define PHYS_AVAIL_SIZE 10 +#define PHYS_AVAIL_SIZE 32 extern vm_paddr_t phys_avail[]; extern vm_paddr_t dump_avail[]; extern vm_offset_t virtual_avail; From fbaeae62942b44dadfb17071b979c3f3a8af3b5e Mon Sep 17 00:00:00 2001 From: sobomax Date: Tue, 2 Feb 2016 19:04:40 +0000 Subject: [PATCH 123/236] Root out files that don't really belong here and could in fact screw you over if you happen to use git for FreeBSD development, as it is the case with the unbound/.gitignore, which lits files that are actually required for the buildworld. MFC after: 1 day --- contrib/libucl/tests/.gitignore | 8 ------ contrib/libxo/.gitignore | 46 --------------------------------- contrib/unbound/.gitignore | 38 --------------------------- 3 files changed, 92 deletions(-) delete mode 100644 contrib/libucl/tests/.gitignore delete mode 100644 contrib/libxo/.gitignore delete mode 100644 contrib/unbound/.gitignore diff --git a/contrib/libucl/tests/.gitignore b/contrib/libucl/tests/.gitignore deleted file mode 100644 index 5a48681d39b2..000000000000 --- a/contrib/libucl/tests/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.log -*.trs -*.plist - -test_basic -test_generate -test_schema -test_speed diff --git a/contrib/libxo/.gitignore b/contrib/libxo/.gitignore deleted file mode 100644 index 8d70b6cc1550..000000000000 --- a/contrib/libxo/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Object files -*.o - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.app - -*~ -*.orig - -aclocal.m4 -ar-lib -autom4te.cache -build -compile -config.guess -config.h.in -config.sub -depcomp -install-sh -ltmain.sh -missing -m4 - -Makefile.in -configure -.DS_Store - -xoconfig.h.in -xo_config.h.in - -.gdbinit -.gdbinit.local -xtest -xtest.dSYM -tests/w diff --git a/contrib/unbound/.gitignore b/contrib/unbound/.gitignore deleted file mode 100644 index 7fed8d74d386..000000000000 --- a/contrib/unbound/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -*.lo -*.o -/.libs/ -/Makefile -/autom4te.cache/ -/config.h -/config.log -/config.status -/dnstap/dnstap_config.h -/doc/example.conf -/doc/libunbound.3 -/doc/unbound-anchor.8 -/doc/unbound-checkconf.8 -/doc/unbound-control.8 -/doc/unbound-host.1 -/doc/unbound.8 -/doc/unbound.conf.5 -/libtool -/libunbound.la -/smallapp/unbound-control-setup.sh -/unbound -/unbound-anchor -/unbound-checkconf -/unbound-control -/unbound-control-setup -/unbound-host -/unbound.h -/asynclook -/delayer -/lock-verify -/memstats -/perf -/petal -/pktview -/streamtcp -/testbound -/unittest - From 8668ce861294a71b908fb9a02f65e92283e3dbf0 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Tue, 2 Feb 2016 20:50:06 +0000 Subject: [PATCH 124/236] Add order for installworld/distribution. Sponsored by: EMC / Isilon Storage Division --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 7467cd2b1687..988d9cc683d8 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,7 @@ TGTS+= ${BITGTS} .ORDER: buildworld installworld .ORDER: buildworld distributeworld .ORDER: buildworld buildkernel +.ORDER: installworld distribution .ORDER: buildkernel installkernel .ORDER: buildkernel installkernel.debug .ORDER: buildkernel reinstallkernel From d11470578c3ef9061bf7a0aceadd61b81315ec27 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Tue, 2 Feb 2016 20:50:09 +0000 Subject: [PATCH 125/236] Adjust install .WAITs for lib/ and etc/ to allow parallelization more. Only 'installworld' needs to be protected and only when not using -DNO_ROOT, which implies not installing to / and not needing the lib dependency protections. Sponsored by: EMC / Isilon Storage Division --- Makefile.inc1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 6ee07b1d19c0..222d7ec2b74f 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -72,7 +72,7 @@ SRCDIR?= ${.CURDIR} SUBDIR= ${SUBDIR_OVERRIDE} .else SUBDIR= lib libexec -.if make(install*) +.if !defined(NO_ROOT) && (make(installworld) || make(install)) # Ensure libraries are installed before progressing. SUBDIR+=.WAIT .endif @@ -127,7 +127,7 @@ SUBDIR+= ${_DIR} # by calling 'makedb' in share/man. This is only relevant for # install/distribute so they build the whatis file after every manpage is # installed. -.if make(install*) +.if make(installworld) || make(install) SUBDIR+=.WAIT .endif SUBDIR+=etc From 3e85ebe5f5e7719e9b0c364faa475505a06c1405 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 2 Feb 2016 21:10:43 +0000 Subject: [PATCH 126/236] MFV r295109: Update openresolve to version 3.7.2 Relnotes: yes --- contrib/openresolv/Makefile | 8 ++++---- contrib/openresolv/resolvconf.8.in | 2 +- contrib/openresolv/resolvconf.conf.5.in | 11 ++++++++--- contrib/openresolv/resolvconf.in | 1 - contrib/openresolv/unbound.in | 3 ++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/contrib/openresolv/Makefile b/contrib/openresolv/Makefile index aca2cb531769..a898b95e6b51 100644 --- a/contrib/openresolv/Makefile +++ b/contrib/openresolv/Makefile @@ -1,5 +1,5 @@ PKG= openresolv -VERSION= 3.7.0 +VERSION= 3.7.1 # Nasty hack so that make clean works without configure being run _CONFIG_MK!= test -e config.mk && echo config.mk || echo config-null.mk @@ -37,7 +37,7 @@ SED_RESTARTCMD= -e 's:@RESTARTCMD \(.*\)@:${RESTARTCMD}:g' DISTPREFIX?= ${PKG}-${VERSION} DISTFILEGZ?= ${DISTPREFIX}.tar.gz -DISTFILE?= ${DISTPREFIX}.tar.bz2 +DISTFILE?= ${DISTPREFIX}.tar.xz FOSSILID?= current .SUFFIXES: .in @@ -77,9 +77,9 @@ install: proginstall maninstall import: rm -rf /tmp/${DISTPREFIX} ${INSTALL} -d /tmp/${DISTPREFIX} - cp README ${SRCS} /tmp/${DISPREFIX} + cp README ${SRCS} /tmp/${DISTPREFIX} dist: fossil tarball --name ${DISTPREFIX} ${FOSSILID} ${DISTFILEGZ} - gunzip -c ${DISTFILEGZ} | bzip2 >${DISTFILE} + gunzip -c ${DISTFILEGZ} | xz >${DISTFILE} rm ${DISTFILEGZ} diff --git a/contrib/openresolv/resolvconf.8.in b/contrib/openresolv/resolvconf.8.in index 10dcf5dd7399..bfbfc7f4726a 100644 --- a/contrib/openresolv/resolvconf.8.in +++ b/contrib/openresolv/resolvconf.8.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 27, 2014 +.Dd April 27, 2015 .Dt RESOLVCONF 8 .Os .Sh NAME diff --git a/contrib/openresolv/resolvconf.conf.5.in b/contrib/openresolv/resolvconf.conf.5.in index d4f654308e9e..7aa14507f4e8 100644 --- a/contrib/openresolv/resolvconf.conf.5.in +++ b/contrib/openresolv/resolvconf.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 20, 2015 +.Dd May 14, 2015 .Dt RESOLVCONF.CONF 5 .Os .Sh NAME @@ -91,6 +91,11 @@ To remove a block, you can use 192.168.* These interfaces name servers will only be queried for the domains listed in their resolv.conf. Useful for VPN domains. +Setting +.Sy private_interfaces Ns ="*" +will stop the forwarding of the root zone and allows the local resolver to +recursively query the root servers directly. +Requires a local nameserver other than libc. This is equivalent to the .Nm resolvconf -p option. @@ -149,7 +154,7 @@ When set to /dev/null or NULL, .Sy resolv_conf_local_only is defaulted to NO, .Sy local_nameservers -is unset unless overriden and only the information set in +is unset unless overridden and only the information set in .Nm is written to .Sy resolv_conf . @@ -271,7 +276,7 @@ Each subscriber attempts to automatically configure itself, but not every distribution has been catered for. Also, users could equally want to use a different version from the one installed by default, such as bind8 and bind9. -To accomodate this, the subscribers have these files in configurable +To accommodate this, the subscribers have these files in configurable variables, documented below. .Pp .Bl -tag -width indent diff --git a/contrib/openresolv/resolvconf.in b/contrib/openresolv/resolvconf.in index 3b2b0f53fd83..a946ed8c44b5 100644 --- a/contrib/openresolv/resolvconf.in +++ b/contrib/openresolv/resolvconf.in @@ -50,7 +50,6 @@ elif [ -d "$SYSCONFDIR/resolvconf" ]; then interface_order="$(cat "$SYSCONFDIR"/interface-order)" fi fi -TMPDIR="$VARDIR/tmp" IFACEDIR="$VARDIR/interfaces" METRICDIR="$VARDIR/metrics" PRIVATEDIR="$VARDIR/private" diff --git a/contrib/openresolv/unbound.in b/contrib/openresolv/unbound.in index 5752e6f2c412..a803615783fc 100644 --- a/contrib/openresolv/unbound.in +++ b/contrib/openresolv/unbound.in @@ -45,7 +45,8 @@ for d in $DOMAINS; do ns="${d#*:}" case "$unbound_insecure" in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) - newconf="$newconf${NL}domain-insecure: \"$dn\"" + newconf="$newconf${NL}server:$NL" + newconf="$newconf domain-insecure: \"$dn\"$NL" ;; esac newconf="$newconf${NL}forward-zone:$NL name: \"$dn\"$NL" From a6cb20ae14309c434280be518b3b8e4786b749b6 Mon Sep 17 00:00:00 2001 From: skra Date: Tue, 2 Feb 2016 21:10:55 +0000 Subject: [PATCH 127/236] Make pmap_preboot_map_attr() vm subsystem compliant, so its arguments do not depend on pmap internals. This is a preparation for hiding internal pmap definitions as much as possible from the rest of system. Simultaneously, the protection argument evaluation is fixed. Happily, it did not effect the mappings. And it's the reason why it was not fixed earlier. --- sys/arm/arm/pmap-v6.c | 14 +++++++------- sys/arm/include/pmap-v6.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 23167d6e053b..d4ab9305b39d 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -645,7 +645,7 @@ pt2map_pt2pg(vm_offset_t va) * vm_offset_t pmap_preboot_reserve_pages(u_int num); * vm_offset_t pmap_preboot_get_vpages(u_int num); * void pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, - * int prot, int attr); + * vm_prot_t prot, vm_memattr_t attr); * * (2) for all stages: * @@ -984,15 +984,16 @@ pmap_preboot_get_vpages(u_int num) * Pre-bootstrap epoch page mapping(s) with attributes. */ void -pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, int prot, - int attr) +pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, + vm_prot_t prot, vm_memattr_t attr) { u_int num; - u_int l1_attr, l1_prot; + u_int l1_attr, l1_prot, l2_prot; pt1_entry_t *pte1p; pt2_entry_t *pte2p; - l1_prot = ATTR_TO_L1(prot); + l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR; + l1_prot = ATTR_TO_L1(l2_prot); l1_attr = ATTR_TO_L1(attr); /* Map all the pages. */ @@ -1006,13 +1007,12 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, int prot, num -= PTE1_SIZE; } else { pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, PTE2_KERN(pa, prot, attr)); + pte2_store(pte2p, PTE2_KERN(pa, l2_prot, attr)); va += PAGE_SIZE; pa += PAGE_SIZE; num -= PAGE_SIZE; } } - } /* diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index c22b937d537a..3c46d9d8dfa5 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -216,8 +216,8 @@ vm_paddr_t pmap_preboot_get_pages(u_int ); void pmap_preboot_map_pages(vm_paddr_t , vm_offset_t , u_int ); vm_offset_t pmap_preboot_reserve_pages(u_int ); vm_offset_t pmap_preboot_get_vpages(u_int ); -void pmap_preboot_map_attr(vm_paddr_t , vm_offset_t , vm_size_t , - int , int ); +void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t, + vm_memattr_t); static __inline void pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, vm_size_t size, int prot, int cache) From 0e3e47574bf5acf679d49201fac275e29e11322f Mon Sep 17 00:00:00 2001 From: bdrewery Date: Tue, 2 Feb 2016 21:11:23 +0000 Subject: [PATCH 128/236] Deduplicate distrib-dirs logic from r289086 in distribution. Sponsored by: EMC / Isilon Storage Division --- Makefile.inc1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 222d7ec2b74f..001df800a4bf 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1087,9 +1087,7 @@ distrib-dirs: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} -distribution: .MAKE .PHONY - ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ - ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} +distribution: distrib-dirs .MAKE .PHONY ${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \ METALOG=${METALOG} installconfig From 625b10fd273c586f5eebc4ec3ac15ea40e6e56f0 Mon Sep 17 00:00:00 2001 From: skra Date: Tue, 2 Feb 2016 21:17:25 +0000 Subject: [PATCH 129/236] Use pmap_preboot_map_attr() directly in arm_devmap_bootstrap() instead of hiding behind pmap_map_chunk(). It's not longer needed after old pmap-v6 code was removed. For compatibility with __ARM_ARCH < 6, define PTE_DEVICE in devmap.c file. Certainly, it would be nice if VM_MEMATTR_DEVICE could be used even for __ARM_ARCH < 6. --- sys/arm/arm/devmap.c | 11 ++++++++++- sys/arm/include/pmap-v6.h | 29 ----------------------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/sys/arm/arm/devmap.c b/sys/arm/arm/devmap.c index 823210f90604..380e12941dc2 100644 --- a/sys/arm/arm/devmap.c +++ b/sys/arm/arm/devmap.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -52,6 +53,9 @@ static boolean_t devmap_bootstrap_done = false; #define PTE_DEVICE VM_MEMATTR_DEVICE #elif defined(__arm__) #define MAX_VADDR ARM_VECTORS_HIGH +#if __ARM_ARCH >= 6 +#define PTE_DEVICE VM_MEMATTR_DEVICE +#endif #endif /* @@ -204,8 +208,13 @@ arm_devmap_bootstrap(vm_offset_t l1pt, const struct arm_devmap_entry *table) for (pd = devmap_table; pd->pd_size != 0; ++pd) { #if defined(__arm__) +#if __ARM_ARCH >= 6 + pmap_preboot_map_attr(pd->pd_pa, pd->pd_va, pd->pd_size, + pd->pd_prot, pd->pd_cache); +#else pmap_map_chunk(l1pt, pd->pd_va, pd->pd_pa, pd->pd_size, - pd->pd_prot,pd->pd_cache); + pd->pd_prot, pd->pd_cache); +#endif #elif defined(__aarch64__) pmap_kenter_device(pd->pd_va, pd->pd_size, pd->pd_pa); #endif diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index 3c46d9d8dfa5..d5223845fb02 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -218,12 +218,6 @@ vm_offset_t pmap_preboot_reserve_pages(u_int ); vm_offset_t pmap_preboot_get_vpages(u_int ); void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t, vm_memattr_t); -static __inline void -pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, - vm_size_t size, int prot, int cache) -{ - pmap_preboot_map_attr(pa, va, size, prot, cache); -} #endif /* _KERNEL */ @@ -256,29 +250,6 @@ pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, */ void vector_page_setprot(int); -/* - * sys/arm/arm/bus_space_generic.c (just comment) - * sys/arm/arm/devmap.c - * sys/arm/arm/pmap.c (just comment) - * sys/arm/at91/at91_machdep.c - * sys/arm/cavium/cns11xx/econa_machdep.c - * sys/arm/freescale/imx/imx6_machdep.c (just comment) - * sys/arm/mv/orion/db88f5xxx.c - * sys/arm/mv/mv_localbus.c - * sys/arm/mv/mv_machdep.c - * sys/arm/mv/mv_pci.c - * sys/arm/s3c2xx0/s3c24x0_machdep.c - * sys/arm/versatile/versatile_machdep.c - * sys/arm/xscale/ixp425/avila_machdep.c - * sys/arm/xscale/i8134x/crb_machdep.c - * sys/arm/xscale/i80321/ep80219_machdep.c - * sys/arm/xscale/i80321/iq31244_machdep.c - * sys/arm/xscale/pxa/pxa_machdep.c - */ -#define PTE_DEVICE PTE2_ATTR_DEVICE - - - #endif /* _KERNEL */ // ----------------------------------------------------------------------------- From 34fbc07d367c7631e872f66e3b53df4956e8c89f Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 2 Feb 2016 21:58:17 +0000 Subject: [PATCH 130/236] Replace (Qo \ Qc) with (Qo (space) Qc) When using col(1) piped to vim(1) as pager for man(1), the former sequence of (Qo \ Qc) renders as "" without the space. Replace with (Qo (space) Qc) which renders properly in more (all?) pagers. --- usr.sbin/sysrc/sysrc.8 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8 index dbd0e4b3c326..c331156f1180 100644 --- a/usr.sbin/sysrc/sysrc.8 +++ b/usr.sbin/sysrc/sysrc.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2011-2015 Devin Teske +.\" Copyright (c) 2011-2016 Devin Teske .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 12, 2015 +.Dd February 2, 2016 .Dt SYSRC 8 .Os .Sh NAME @@ -255,7 +255,7 @@ When using the .Ql key+=value syntax to add items to existing values, the first character of the value is taken as the delimiter separating items -.Pq usually Qo \ Qc or Qo , Qc . +.Pq usually Qo (space) Qc or Qo , Qc . For example, in the following statement: .Bl -item -offset indent .It From 6d511d769313fd1dae574a1d395369df219e86b6 Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 2 Feb 2016 22:18:43 +0000 Subject: [PATCH 131/236] For +=/-=, add . and / to convenience characters sysrc(8) supports key+=value and key-=value, but can be told what the delimiter is by being passed as char1 (e.g., "sysrc key+=",value" to use a comma as the delimiter instead of space). For convenience, if the first char is alpha-numeric, it is assumed you wanted whitespace as the delimiter. However, if you naively (as I just did) execute: sysrc rc_conf_files+=/etc/rc.conf.other the result is unexpected. This commit makes `.' and `/' in-addition to alpha-numeric first-characters to cause the default of whitespace to be used as the delimiter. This also means that you can no longer use these as a delimiter. --- usr.sbin/sysrc/sysrc | 4 ++-- usr.sbin/sysrc/sysrc.8 | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc index e384dff93f6c..aa57f1beb7f2 100644 --- a/usr.sbin/sysrc/sysrc +++ b/usr.sbin/sysrc/sysrc @@ -790,7 +790,7 @@ while [ $# -gt 0 ]; do delim="${add%"${add#?}"}" # first character oldIFS="$IFS" case "$delim" in - ""|[$IFS]|[a-zA-Z0-9]) delim=" " ;; + ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; *) IFS="$delim" esac new="$before" @@ -812,7 +812,7 @@ while [ $# -gt 0 ]; do delim="${remove%"${remove#?}"}" # first character oldIFS="$IFS" case "$delim" in - ""|[$IFS]|[a-zA-Z0-9]) delim=" " ;; + ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; *) IFS="$delim" esac new= diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8 index c331156f1180..3996b1f9482c 100644 --- a/usr.sbin/sysrc/sysrc.8 +++ b/usr.sbin/sysrc/sysrc.8 @@ -275,6 +275,10 @@ it is added .Pp For convenience, if the first character is alpha-numeric .Pq letters A-Z, a-z, or numbers 0-9 , +dot +.Pq Li . , +or slash +.Pq Li / , .Nm uses the default setting of whitespace as separator. For example, the above and below statements are equivalent since @@ -329,6 +333,10 @@ it is removed .Pp For convenience, if the first character is alpha-numeric .Pq letters A-Z, a-z, or numbers 0-9 , +dot +.Pq Li . , +or slash +.Pq Li / , .Nm uses the default setting of whitespace as separator. For example, the above and below statements are equivalent since From 633e1868c3d57650c964455860f7fc1fc0726aa4 Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 2 Feb 2016 22:34:48 +0000 Subject: [PATCH 132/236] Bump version to 7.1 for +=/-= fix MFC after: 3 days X-MFC-to: stable/10 X-MFC-with: r295169, r295170 --- usr.sbin/sysrc/sysrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc index aa57f1beb7f2..065b7ae49ee2 100644 --- a/usr.sbin/sysrc/sysrc +++ b/usr.sbin/sysrc/sysrc @@ -1,6 +1,6 @@ #!/bin/sh #- -# Copyright (c) 2010-2015 Devin Teske +# Copyright (c) 2010-2016 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" # # Version information # -SYSRC_VERSION="7.0 Sep-13,2015" +SYSRC_VERSION="7.1 Feb-2,2016" # # Options From 8d851d4e740abae7b12ae8a5ff7e3dc1daa32a29 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 2 Feb 2016 22:55:03 +0000 Subject: [PATCH 133/236] - Note that devctl(8) will appear in 10.3 first. - Add missing devctl_set_driver entry to namelist in devlist(3). - Fix sorting of function prototypes in devlist(3). MFC after: 3 days --- lib/libdevctl/devctl.3 | 9 +++++---- usr.sbin/devctl/devctl.8 | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3 index be869f9d9868..b2734cf4aa30 100644 --- a/lib/libdevctl/devctl.3 +++ b/lib/libdevctl/devctl.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 26, 2014 +.Dd February 2, 2016 .Dt DEVCTL 3 .Os .Sh NAME @@ -35,6 +35,7 @@ .Nm devctl_disable , .Nm devctl_enable , .Nm devctl_resume , +.Nm devctl_set_driver , .Nm devctl_suspend .Nd device control library .Sh LIBRARY @@ -52,9 +53,9 @@ .Ft int .Fn devctl_resume "const char *device" .Ft int -.Fn devctl_suspend "const char *device" -.Ft int .Fn devctl_set_driver "const char *device" "const char *driver" "bool force" +.Ft int +.Fn devctl_suspend "const char *device" .Sh DESCRIPTION The .Nm @@ -287,7 +288,7 @@ The new device driver failed to attach. The .Nm library first appeared in -.Fx 11.0 . +.Fx 10.3 . .Sh BUGS If a device is suspended individually via .Fn devctl_suspend diff --git a/usr.sbin/devctl/devctl.8 b/usr.sbin/devctl/devctl.8 index fef42be13073..2257cb63cc3d 100644 --- a/usr.sbin/devctl/devctl.8 +++ b/usr.sbin/devctl/devctl.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 5, 2015 +.Dd February 2, 2016 .Dt DEVCTL 8 .Os .Sh NAME @@ -134,4 +134,4 @@ the device will not be changed. The .Nm utility first appeared in -.Fx 11.0 . +.Fx 10.3 . From 27e083b53bbc58462060f9d7e7a041bf72ccd3a7 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Tue, 2 Feb 2016 23:33:58 +0000 Subject: [PATCH 134/236] Move logic to destroy a struct catentry to its own function. This will be used later for memory leak handling. Obtained from: OneFS Sponsored by: EMC / Isilon Storage Division --- lib/libc/nls/msgcat.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c index 0cba460403b3..3df76b60b4bd 100644 --- a/lib/libc/nls/msgcat.c +++ b/lib/libc/nls/msgcat.c @@ -325,6 +325,21 @@ catgets(nl_catd catd, int set_id, int msg_id, const char *s) return ((char *)s); } +static void +catfree(struct catentry *np) +{ + + if (np->catd != NULL && np->catd != NLERR) { + munmap(np->catd->__data, (size_t)np->catd->__size); + free(np->catd); + } + SLIST_REMOVE(&cache, np, catentry, list); + free(np->name); + free(np->path); + free(np->lang); + free(np); +} + int catclose(nl_catd catd) { @@ -341,15 +356,8 @@ catclose(nl_catd catd) SLIST_FOREACH(np, &cache, list) { if (catd == np->catd) { np->refcount--; - if (np->refcount == 0) { - munmap(catd->__data, (size_t)catd->__size); - free(catd); - SLIST_REMOVE(&cache, np, catentry, list); - free(np->name); - free(np->path); - free(np->lang); - free(np); - } + if (np->refcount == 0) + catfree(np); break; } } From 98d4913b4094d9b5522bdf1acdce47999e74ac7d Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 2 Feb 2016 23:51:39 +0000 Subject: [PATCH 135/236] Fix a typo in a comment --- usr.sbin/sysrc/sysrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc index 065b7ae49ee2..1da537fd5992 100644 --- a/usr.sbin/sysrc/sysrc +++ b/usr.sbin/sysrc/sysrc @@ -595,7 +595,7 @@ fi if [ "$SHOW_ALL" ]; then # # Get a list of variables that are currently set in the rc.conf(5) - # files (included `/etc/defaults/rc.conf') by performing a call to + # files (including `/etc/defaults/rc.conf') by performing a call to # source_rc_confs() in a clean environment. # ( # Operate in a sub-shell to protect the parent environment From e5ae512d17e6046ae62a9952cb51217771139be4 Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 2 Feb 2016 23:54:07 +0000 Subject: [PATCH 136/236] Revert r295169 and switch `\ ' to `" "' MFC after: 3 days X-MFC-to: stable/10 X-MFC-with: r295169, r295170, r295173, r295177 --- usr.sbin/sysrc/sysrc.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8 index 3996b1f9482c..075fc3bd8a1e 100644 --- a/usr.sbin/sysrc/sysrc.8 +++ b/usr.sbin/sysrc/sysrc.8 @@ -255,7 +255,7 @@ When using the .Ql key+=value syntax to add items to existing values, the first character of the value is taken as the delimiter separating items -.Pq usually Qo (space) Qc or Qo , Qc . +.Pq usually Qo " " Qc or Qo , Qc . For example, in the following statement: .Bl -item -offset indent .It @@ -316,7 +316,7 @@ When using the .Ql key-=value syntax to remove items from existing values, the first character of the value is taken as the delimiter separating items -.Pq usually Qo \ Qc or Qo , Qc . +.Pq usually Qo " " Qc or Qo , Qc . For example, in the following statement: .Pp .Dl Nm cloned_interfaces-=" gif0" From 5f95bf68114f2eb19fc30a8fb38352f8e0135f2a Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 3 Feb 2016 00:51:38 +0000 Subject: [PATCH 137/236] Define f_sprintf() dynamically at inclusion time No need to check/re-check capabilities that won't change at runtime. --- usr.sbin/bsdconfig/share/strings.subr | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 1a4fe6ef081c..f1dbbd76a5e6 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -154,20 +154,25 @@ f_substr() # Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax # (`$format [$arguments ...]'). # -f_sprintf() -{ - local __var_to_set="$1" - shift 1 # var_to_set - - case "$BASH_VERSION" in - 3.1*|4.*) - local __tmp +case "$BASH_VERSION" in +3.1*|4.*) + f_sprintf() + { + local __var_to_set="$1" __tmp + shift 1 # var_to_set printf -v __tmp "$@" eval "$__var_to_set"=\"\${__tmp%\$NL}\" - ;; - *) eval "$__var_to_set"=\$\( printf -- \"\$@\" \) - esac -} + } + ;; +*) + # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above + f_sprintf() + { + local __var_to_set="$1" + shift 1 # var_to_set + eval "$__var_to_set"=\$\( printf -- \"\$@\" \) + } +esac # f_vsprintf $var_to_set $format $format_args # From d6406df83942d9fa08b4b2cf53ee2c5527172039 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Wed, 3 Feb 2016 01:29:06 +0000 Subject: [PATCH 138/236] Make lbc(4) the same driver pass as simplebus. Device trees mark lbc as compatible with simplebus. Since simplebus is passed first, it attaches first. When lbc's pass (default pass) comes, the bus is already attached to simplebus, so is skipped. Sponsored by: Alex Perez/Inertial Computing --- sys/powerpc/mpc85xx/lbc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c index f9a1718635a0..7dfaa06ed966 100644 --- a/sys/powerpc/mpc85xx/lbc.c +++ b/sys/powerpc/mpc85xx/lbc.c @@ -113,7 +113,8 @@ static driver_t lbc_driver = { devclass_t lbc_devclass; -DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass, 0, 0); +EARLY_DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass, + 0, 0, BUS_PASS_BUS); /* * Calculate address mask used by OR(n) registers. Use memory region size to From d8a6a1cf148b47a295850717ae031f12d55b5741 Mon Sep 17 00:00:00 2001 From: cem Date: Wed, 3 Feb 2016 01:40:07 +0000 Subject: [PATCH 139/236] Revert r295167 at bdrewery's request $ svn merge -c -295167 . JHB reports Navdeep reports that it breaks distribution and etcupdate. Approved by: bdrewery --- Makefile.inc1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 001df800a4bf..222d7ec2b74f 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1087,7 +1087,9 @@ distrib-dirs: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} -distribution: distrib-dirs .MAKE .PHONY +distribution: .MAKE .PHONY + ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ + ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} ${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \ METALOG=${METALOG} installconfig From 86be85e87ea583d6b89dc395f00ae6b6ba8ec606 Mon Sep 17 00:00:00 2001 From: jhibbits Date: Wed, 3 Feb 2016 01:50:27 +0000 Subject: [PATCH 140/236] Align signal stack pointer to 16 bytes. The stack must be aligned to 16 bytes at all times. Clang 3.8 is especially adamant about this, and causes strange behavior and segmentation faults if it is not the case. PR: kern/206810 --- sys/powerpc/powerpc/exec_machdep.c | 6 +++--- sys/powerpc/powerpc/sigcode32.S | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index d8238a1b58f1..4e56429ea0bb 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -219,10 +219,10 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) */ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { - usfp = (void *)((uintptr_t)td->td_sigstk.ss_sp + - td->td_sigstk.ss_size - rndfsize); + usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp + + td->td_sigstk.ss_size - rndfsize) & ~0xFul); } else { - usfp = (void *)(tf->fixreg[1] - rndfsize); + usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul); } /* diff --git a/sys/powerpc/powerpc/sigcode32.S b/sys/powerpc/powerpc/sigcode32.S index 023618215d32..cd4c3cf72f9e 100644 --- a/sys/powerpc/powerpc/sigcode32.S +++ b/sys/powerpc/powerpc/sigcode32.S @@ -45,9 +45,9 @@ */ .globl CNAME(sigcode32),CNAME(szsigcode32) CNAME(sigcode32): - addi 1,1,-20 /* reserved space for callee */ + addi 1,1,-32 /* reserved space for callee */ blrl - addi 3,1,20+SF_UC /* restore sp, and get &frame->sf_uc */ + addi 3,1,32+SF_UC /* restore sp, and get &frame->sf_uc */ li 0,SYS_sigreturn sc /* sigreturn(scp) */ li 0,SYS_exit From 075f458553f88ba29dc4d130e77dd6321f595b21 Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 3 Feb 2016 02:46:00 +0000 Subject: [PATCH 141/236] Remove trailing whitespace --- usr.sbin/bsdconfig/share/strings.subr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index f1dbbd76a5e6..bf0604aa8142 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -65,7 +65,7 @@ f_isinteger() # f_substr [-v $var_to_set] $string $start [$length] # # Similar to awk(1)'s substr(), return length substring of string that begins -# at start position counted from 1. +# at start position counted from 1. # f_substr() { @@ -76,7 +76,7 @@ f_substr() esac done shift $(( $OPTIND - 1 )) - + local __tmp="$1" __start="${2:-1}" __size="$3" local __tbuf __tbuf_len __trim __trimq From 65c2ff7ea86f0742ea35f9bca64c13656af2f529 Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 3 Feb 2016 03:03:04 +0000 Subject: [PATCH 142/236] f_substr: Write to stdout when no `-v var_to_set' Fixes ``setvar: : bad variable name'' --- usr.sbin/bsdconfig/share/strings.subr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index bf0604aa8142..f9e33c75d835 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -146,7 +146,11 @@ f_substr() fi done - setvar "$__var_to_set" "$__tmp" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__tmp" + else + echo "$__tmp" + fi } # f_sprintf $var_to_set $format [$arguments ...] From b2bf30d1a948ddce18a8a4178be88dde5ec18c69 Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 3 Feb 2016 03:55:08 +0000 Subject: [PATCH 143/236] Remove SIG prefix from trapped signals Makes traps functional if running under shells/dash --- usr.sbin/bsdconfig/share/common.subr | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr index 599644637922..2b911fcec668 100644 --- a/usr.sbin/bsdconfig/share/common.subr +++ b/usr.sbin/bsdconfig/share/common.subr @@ -1,7 +1,7 @@ if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 # # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012-2015 Devin Teske +# Copyright (c) 2012-2016 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1015,10 +1015,9 @@ f_count_ifs() # # Trap signals so we can recover gracefully # -trap 'f_interrupt' SIGINT -trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \ - SIGFPE SIGTRAP SIGABRT SIGSEGV -trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM +trap 'f_interrupt' INT +trap 'f_die' TERM PIPE XCPU XFSZ FPE TRAP ABRT SEGV +trap '' ALRM PROF USR1 USR2 HUP VTALRM # # Clone terminal stdout/stderr so we can redirect to it from within sub-shells From 0129d4cd2c7ad3bc5d278e7ac95f23ffbe04166f Mon Sep 17 00:00:00 2001 From: dteske Date: Wed, 3 Feb 2016 04:02:50 +0000 Subject: [PATCH 144/236] f_substr(): Optimized recipe if running under bash This makes runnig f_substr() faster than it was when running under bash, but both sh and dash are still faster when using the non-bash recipe which features dynamically unrolled loops. --- usr.sbin/bsdconfig/share/strings.subr | 177 +++++++++++++++----------- 1 file changed, 106 insertions(+), 71 deletions(-) diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index f9e33c75d835..f33f4df566ad 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -67,52 +67,58 @@ f_isinteger() # Similar to awk(1)'s substr(), return length substring of string that begins # at start position counted from 1. # -f_substr() -{ - local OPTIND=1 OPTARG __flag __var_to_set= - while getopts v: __flag; do - case "$__flag" in - v) __var_to_set="$OPTARG" ;; +case "$BASH_VERSION" in +*?*) + f_substr() + { + local __var_to_set= + case "$1" in + -v) __var_to_set="$2"; shift 2 ;; + -v?*) __var_to_set="${2#-v}"; shift 1 ;; esac - done - shift $(( $OPTIND - 1 )) - - local __tmp="$1" __start="${2:-1}" __size="$3" - local __tbuf __tbuf_len __trim __trimq - - if [ ! "$__tmp" ]; then - [ "$__var_to_set" ] && setvar "$__var_to_set" "" - return ${SUCCESS:-0} - fi - [ "$__start" -ge 1 ] 2> /dev/null || __start=1 - if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then - [ "$__var_to_set" ] && setvar "$__var_to_set" "" - return ${FAILURE:-1} - fi - - __trim=$(( $__start - 1 )) - while [ $__trim -gt 0 ]; do - __tbuf="?" - __tbuf_len=1 - while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]; do - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) + local __tmp="$1" __start="${2:-1}" __len="$3" + [ "$__start" -gt 0 ] 2> /dev/null && + __start=$(( $__start - 1 )) + if [ ! "$__var_to_set" ]; then + eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\" + return $? + fi + if [ "$__len" ]; then + eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\" + else + eval $__var_to_set=\"\${__tmp:\$__start}\" + fi + } + ;; +*) + # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above + f_substr() + { + local OPTIND=1 OPTARG __flag __var_to_set= + while getopts v: __flag; do + case "$__flag" in + v) __var_to_set="$OPTARG" ;; + esac done - __trimq=$(( $__trim / $__tbuf_len )) - __trim=$(( $__trim - $__tbuf_len * $__trimq )) - while [ $__trimq -gt 0 ]; do - __tmp="${__tmp#$__tbuf}" - __trimq=$(( $__trimq - 1 )) - done - done + shift $(( $OPTIND - 1 )) - local __tmp_size=${#__tmp} - local __mask __mask_len - __trim=$(( $__tmp_size - ${__size:-$__tmp_size} )) - while [ $__trim -gt 0 ]; do - __tbuf="?" - __tbuf_len=1 - if [ $__trim -le $__size ]; then + local __tmp="$1" __start="${2:-1}" __size="$3" + local __tbuf __tbuf_len __trim __trimq + + if [ ! "$__tmp" ]; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" + return ${SUCCESS:-0} + fi + [ "$__start" -ge 1 ] 2> /dev/null || __start=1 + if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" + return ${FAILURE:-1} + fi + + __trim=$(( $__start - 1 )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ] do __tbuf="$__tbuf?" @@ -121,37 +127,66 @@ f_substr() __trimq=$(( $__trim / $__tbuf_len )) __trim=$(( $__trim - $__tbuf_len * $__trimq )) while [ $__trimq -gt 0 ]; do - __tmp="${__tmp%$__tbuf}" + __tmp="${__tmp#$__tbuf}" __trimq=$(( $__trimq - 1 )) done - else - __mask="$__tmp" - while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ] - do - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) - done - __trimq=$(( $__size / $__tbuf_len )) - if [ $(( $__trimq * $__tbuf_len )) -ne $__size ]; then - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) - fi - __mask_len=$(( $__tmp_size - $__tbuf_len * $__trimq )) - __trim=$(( $__tmp_size - $__mask_len - $__size )) - while [ $__trimq -gt 0 ]; do - __mask="${__mask#$__tbuf}" - __trimq=$(( $__trimq - 1 )) - done - __tmp="${__tmp%"$__mask"}" - fi - done + done - if [ "$__var_to_set" ]; then - setvar "$__var_to_set" "$__tmp" - else - echo "$__tmp" - fi -} + local __tmp_size=${#__tmp} + local __mask __mask_len + __trim=$(( $__tmp_size - ${__size:-$__tmp_size} )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 + if [ $__trim -le $__size ]; then + while [ $__tbuf_len -lt $(( + $__trim / $__tbuf_len + )) ]; do + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + done + __trimq=$(( $__trim / $__tbuf_len )) + __trim=$(( $__trim - $__tbuf_len * $__trimq )) + while [ $__trimq -gt 0 ]; do + __tmp="${__tmp%$__tbuf}" + __trimq=$(( $__trimq - 1 )) + done + else + __mask="$__tmp" + while [ $__tbuf_len -lt $(( + $__size / $__tbuf_len + )) ]; do + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + done + __trimq=$(( $__size / $__tbuf_len )) + if [ $__size -ne $(( + $__trimq * $__tbuf_len + )) ]; then + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + fi + __mask_len=$(( + $__tmp_size - $__tbuf_len * $__trimq + )) + __trim=$(( + $__tmp_size - $__mask_len - $__size + )) + while [ $__trimq -gt 0 ]; do + __mask="${__mask#$__tbuf}" + __trimq=$(( $__trimq - 1 )) + done + __tmp="${__tmp%"$__mask"}" + fi + done + + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__tmp" + else + echo "$__tmp" + fi + } +esac # f_sprintf $var_to_set $format [$arguments ...] # From 4de365e69c81fbfd2f2d24281ad241f229e9ef02 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 08:12:21 +0000 Subject: [PATCH 145/236] ARM: acle-compat.h is arm specific header, don't include it for aarch64. This fixes aarch64 buildkernel. --- sys/arm/arm/devmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/arm/arm/devmap.c b/sys/arm/arm/devmap.c index 380e12941dc2..4dffa8cc7a2b 100644 --- a/sys/arm/arm/devmap.c +++ b/sys/arm/arm/devmap.c @@ -40,7 +40,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef __arm__ #include +#endif #include #include #include From d10f7c8df15f0065949470152e01d5f035d49f26 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 08:59:12 +0000 Subject: [PATCH 146/236] ARM: The arm/xscale/i80321 directory is now orphaned, but two drivers are shared with i8134x. In preparation for removal of i80321, copy these drivers to i8134x. --- sys/arm/xscale/i8134x/crb_machdep.c | 2 +- sys/arm/xscale/i8134x/files.i81342 | 4 +- sys/arm/xscale/i8134x/i80321_timer.c | 485 ++++++++++++++++++++++++ sys/arm/xscale/i8134x/i80321_wdog.c | 154 ++++++++ sys/arm/xscale/i8134x/i80321reg.h | 547 +++++++++++++++++++++++++++ sys/arm/xscale/i8134x/i80321var.h | 137 +++++++ 6 files changed, 1326 insertions(+), 3 deletions(-) create mode 100644 sys/arm/xscale/i8134x/i80321_timer.c create mode 100644 sys/arm/xscale/i8134x/i80321_wdog.c create mode 100644 sys/arm/xscale/i8134x/i80321reg.h create mode 100644 sys/arm/xscale/i8134x/i80321var.h diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 2bd77a5f30a7..e306a75a5b12 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$"); #include -#include /* For i80321_calibrate_delay() */ +#include /* For i80321_calibrate_delay() */ #include #include diff --git a/sys/arm/xscale/i8134x/files.i81342 b/sys/arm/xscale/i8134x/files.i81342 index ed93e6bf855a..63c715cb4be7 100644 --- a/sys/arm/xscale/i8134x/files.i81342 +++ b/sys/arm/xscale/i8134x/files.i81342 @@ -1,7 +1,7 @@ # $FreeBSD$ arm/arm/bus_space_base.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog +arm/xscale/i8134x/i80321_timer.c standard +arm/xscale/i8134x/i80321_wdog.c optional iopwdog arm/xscale/i8134x/i81342.c standard arm/xscale/i8134x/i81342_mcu.c standard arm/xscale/i8134x/i81342_pci.c optional pci diff --git a/sys/arm/xscale/i8134x/i80321_timer.c b/sys/arm/xscale/i8134x/i80321_timer.c new file mode 100644 index 000000000000..ea15d920bf01 --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321_timer.c @@ -0,0 +1,485 @@ +/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */ + +/*- + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * Timer/clock support for the Intel i80321 I/O processor. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CPU_XSCALE_81342 +#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because + definitions overrides the ones from i80321reg.h + */ +#endif +#include "opt_timer.h" + +void (*i80321_hardclock_hook)(void) = NULL; +struct i80321_timer_softc { + device_t dev; +} timer_softc; + + +static unsigned i80321_timer_get_timecount(struct timecounter *tc); + + +static uint32_t counts_per_hz; + +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) +static uint32_t offset; +static uint32_t last = -1; +#endif + +static int ticked = 0; + +#ifndef COUNTS_PER_SEC +#define COUNTS_PER_SEC 200000000 /* 200MHz */ +#endif + +#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000) + +static struct timecounter i80321_timer_timecounter = { + i80321_timer_get_timecount, /* get_timecount */ + NULL, /* no poll_pps */ + ~0u, /* counter_mask */ +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) + COUNTS_PER_SEC, +#else + COUNTS_PER_SEC * 3, /* frequency */ +#endif + "i80321 timer", /* name */ + 1000 /* quality */ +}; + +static int +i80321_timer_probe(device_t dev) +{ + + device_set_desc(dev, "i80321 timer"); + return (0); +} + +static int +i80321_timer_attach(device_t dev) +{ + timer_softc.dev = dev; + + return (0); +} + +static device_method_t i80321_timer_methods[] = { + DEVMETHOD(device_probe, i80321_timer_probe), + DEVMETHOD(device_attach, i80321_timer_attach), + {0, 0}, +}; + +static driver_t i80321_timer_driver = { + "itimer", + i80321_timer_methods, + sizeof(struct i80321_timer_softc), +}; +static devclass_t i80321_timer_devclass; + +DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0); + +int clockhandler(void *); + + +static __inline uint32_t +tmr1_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c1, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c1, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} + +static __inline void +tmr1_write(uint32_t val) +{ + + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c1, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c1, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tcr1_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c3, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c3, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} +static __inline void +tcr1_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c3, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c3, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +trr1_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c5, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c5, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tmr0_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c0, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c0, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} + +static __inline void +tmr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c0, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c0, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tcr0_read(void) +{ + uint32_t rv; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c2, c9, 0" +#else + __asm __volatile("mrc p6, 0, %0, c2, c1, 0" +#endif + : "=r" (rv)); + return (rv); +} +static __inline void +tcr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c2, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c2, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +trr0_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c4, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c4, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline void +tisr_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c6, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c6, c1, 0" +#endif + : + : "r" (val)); +} + +static __inline uint32_t +tisr_read(void) +{ + int ret; + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mrc p6, 0, %0, c6, c9, 0" : "=r" (ret)); +#else + __asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret)); +#endif + return (ret); +} + +static unsigned +i80321_timer_get_timecount(struct timecounter *tc) +{ +#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) + uint32_t cur = tcr0_read(); + + if (cur > last && last != -1) { + offset += counts_per_hz; + if (ticked > 0) + ticked--; + } + if (ticked) { + offset += ticked * counts_per_hz; + ticked = 0; + } + return (counts_per_hz - cur + offset); +#else + uint32_t ret; + + __asm __volatile("mrc p14, 0, %0, c1, c0, 0\n" + : "=r" (ret)); + return (ret); +#endif +} + +/* + * i80321_calibrate_delay: + * + * Calibrate the delay loop. + */ +void +i80321_calibrate_delay(void) +{ + + /* + * Just use hz=100 for now -- we'll adjust it, if necessary, + * in cpu_initclocks(). + */ + counts_per_hz = COUNTS_PER_SEC / 100; + + tmr0_write(0); /* stop timer */ + tisr_write(TISR_TMR0); /* clear interrupt */ + trr0_write(counts_per_hz); /* reload value */ + tcr0_write(counts_per_hz); /* current value */ + + tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); +} + +/* + * cpu_initclocks: + * + * Initialize the clock and get them going. + */ +void +cpu_initclocks(void) +{ + u_int oldirqstate; + struct resource *irq; + int rid = 0; + void *ihl; + device_t dev = timer_softc.dev; + + if (hz < 50 || COUNTS_PER_SEC % hz) { + printf("Cannot get %d Hz clock; using 100 Hz\n", hz); + hz = 100; + } + tick = 1000000 / hz; /* number of microseconds between interrupts */ + + /* + * We only have one timer available; stathz and profhz are + * always left as 0 (the upper-layer clock code deals with + * this situation). + */ + if (stathz != 0) + printf("Cannot get %d Hz statclock\n", stathz); + stathz = 0; + + if (profhz != 0) + printf("Cannot get %d Hz profclock\n", profhz); + profhz = 0; + + /* Report the clock frequency. */ + + oldirqstate = disable_interrupts(PSR_I); + + irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, +#ifdef CPU_XSCALE_81342 + ICU_INT_TIMER0, ICU_INT_TIMER0, +#else + ICU_INT_TMR0, ICU_INT_TMR0, +#endif + 1, RF_ACTIVE); + if (!irq) + panic("Unable to setup the clock irq handler.\n"); + else + bus_setup_intr(dev, irq, INTR_TYPE_CLK, clockhandler, NULL, + NULL, &ihl); + tmr0_write(0); /* stop timer */ + tisr_write(TISR_TMR0); /* clear interrupt */ + + counts_per_hz = COUNTS_PER_SEC / hz; + + trr0_write(counts_per_hz); /* reload value */ + tcr0_write(counts_per_hz); /* current value */ + tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); + + tc_init(&i80321_timer_timecounter); + restore_interrupts(oldirqstate); + rid = 0; +#if !defined(XSCALE_DISABLE_CCNT) && !defined(CPU_XSCALE_81342) + /* Enable the clock count register. */ + __asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid)); + rid &= ~(1 << 3); + rid |= (1 << 2) | 1; + __asm __volatile("mcr p14, 0, %0, c0, c0, 0\n" + : : "r" (rid)); +#endif +} + + +/* + * DELAY: + * + * Delay for at least N microseconds. + */ +void +DELAY(int n) +{ + uint32_t cur, last, delta, usecs; + + /* + * This works by polling the timer and counting the + * number of microseconds that go by. + */ + last = tcr0_read(); + delta = usecs = 0; + + while (n > usecs) { + cur = tcr0_read(); + + /* Check to see if the timer has wrapped around. */ + if (last < cur) + delta += (last + (counts_per_hz - cur)); + else + delta += (last - cur); + + last = cur; + + if (delta >= COUNTS_PER_USEC) { + usecs += delta / COUNTS_PER_USEC; + delta %= COUNTS_PER_USEC; + } + } +} + +/* + * clockhandler: + * + * Handle the hardclock interrupt. + */ +int +clockhandler(void *arg) +{ + struct trapframe *frame = arg; + + ticked++; + tisr_write(TISR_TMR0); + hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); + + if (i80321_hardclock_hook != NULL) + (*i80321_hardclock_hook)(); + return (FILTER_HANDLED); +} + +void +cpu_startprofclock(void) +{ +} + +void +cpu_stopprofclock(void) +{ + +} diff --git a/sys/arm/xscale/i8134x/i80321_wdog.c b/sys/arm/xscale/i8134x/i80321_wdog.c new file mode 100644 index 000000000000..c11c78a48e33 --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321_wdog.c @@ -0,0 +1,154 @@ +/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */ + +/*- + * Copyright (c) 2005 Olivier Houchard + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * Watchdog timer support for the Intel i80321 I/O processor. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +struct iopwdog_softc { + device_t dev; + int armed; + int wdog_period; +}; + +static __inline void +wdtcr_write(uint32_t val) +{ + +#ifdef CPU_XSCALE_81342 + __asm __volatile("mcr p6, 0, %0, c7, c9, 0" +#else + __asm __volatile("mcr p6, 0, %0, c7, c1, 0" +#endif + : + : "r" (val)); +} + +static void +iopwdog_tickle(void *arg) +{ + struct iopwdog_softc *sc = arg; + + if (!sc->armed) + return; + wdtcr_write(WDTCR_ENABLE1); + wdtcr_write(WDTCR_ENABLE2); +} + +static int +iopwdog_probe(device_t dev) +{ + struct iopwdog_softc *sc = device_get_softc(dev); + char buf[128]; + + /* + * XXX Should compute the period based on processor speed. + * For a 600MHz XScale core, the wdog must be tickled approx. + * every 7 seconds. + */ + + sc->wdog_period = 7; + sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds", + sc->wdog_period); + device_set_desc_copy(dev, buf); + + return (0); +} + +static void +iopwdog_watchdog_fn(void *private, u_int cmd, int *error) +{ + struct iopwdog_softc *sc = private; + + cmd &= WD_INTERVAL; + if (cmd > 0 && cmd <= 63 + && (uint64_t)1<wdog_period * 1000000000) { + /* Valid value -> Enable watchdog */ + iopwdog_tickle(sc); + sc->armed = 1; + *error = 0; + } else { + /* Can't disable this watchdog! */ + if (sc->armed) + *error = EOPNOTSUPP; + } +} + +static int +iopwdog_attach(device_t dev) +{ + struct iopwdog_softc *sc = device_get_softc(dev); + + sc->dev = dev; + sc->armed = 0; + EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0); + return (0); +} + +static device_method_t iopwdog_methods[] = { + DEVMETHOD(device_probe, iopwdog_probe), + DEVMETHOD(device_attach, iopwdog_attach), + {0, 0}, +}; + +static driver_t iopwdog_driver = { + "iopwdog", + iopwdog_methods, + sizeof(struct iopwdog_softc), +}; +static devclass_t iopwdog_devclass; + +DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0); diff --git a/sys/arm/xscale/i8134x/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h new file mode 100644 index 000000000000..53617f956582 --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321reg.h @@ -0,0 +1,547 @@ +/* $NetBSD: i80321reg.h,v 1.14 2003/12/19 10:08:11 gavan Exp $ */ + +/*- + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 _ARM_XSCALE_I80321REG_H_ +#define _ARM_XSCALE_I80321REG_H_ + +/* + * Register definitions for the Intel 80321 (``Verde'') I/O processor, + * based on the XScale core. + */ + +/* + * Base i80321 memory map: + * + * 0x0000.0000 - 0x7fff.ffff ATU Outbound Direct Addressing Window + * 0x8000.0000 - 0x9001.ffff ATU Outbound Translation Windows + * 0x9002.0000 - 0xffff.dfff External Memory + * 0xffff.e000 - 0xffff.e8ff Peripheral Memory Mapped Registers + * 0xffff.e900 - 0xffff.ffff Reserved + */ + +#define VERDE_OUT_DIRECT_WIN_BASE 0x00000000UL +#define VERDE_OUT_DIRECT_WIN_SIZE 0x80000000UL + +#define VERDE_OUT_XLATE_MEM_WIN_SIZE 0x04000000UL +#define VERDE_OUT_XLATE_IO_WIN_SIZE 0x00010000UL + +#define VERDE_OUT_XLATE_MEM_WIN0_BASE 0x80000000UL +#define VERDE_OUT_XLATE_MEM_WIN1_BASE 0x84000000UL + +#define VERDE_OUT_XLATE_IO_WIN0_BASE 0x90000000UL + +#define VERDE_EXTMEM_BASE 0x90020000UL + +#define VERDE_PMMR_BASE 0xffffe000UL +#define VERDE_PMMR_SIZE 0x00001700UL + +/* + * Peripheral Memory Mapped Registers. Defined as offsets + * from the VERDE_PMMR_BASE. + */ +#define VERDE_ATU_BASE 0x0100 +#define VERDE_ATU_SIZE 0x0100 + +#define VERDE_MU_BASE 0x0300 +#define VERDE_MU_SIZE 0x0100 + +#define VERDE_DMA_BASE 0x0400 +#define VERDE_DMA_BASE0 (VERDE_DMA_BASE + 0x00) +#define VERDE_DMA_BASE1 (VERDE_DMA_BASE + 0x40) +#define VERDE_DMA_SIZE 0x0100 +#define VERDE_DMA_CHSIZE 0x0040 + +#define VERDE_MCU_BASE 0x0500 +#define VERDE_MCU_SIZE 0x0100 + +#if defined(CPU_XSCALE_80321) +#define VERDE_SSP_BASE 0x0600 +#define VERDE_SSP_SIZE 0x0080 +#endif + +#define VERDE_PBIU_BASE 0x0680 +#define VERDE_PBIU_SIZE 0x0080 + +#if defined(CPU_XSCALE_80321) +#define VERDE_AAU_BASE 0x0800 +#define VERDE_AAU_SIZE 0x0100 +#endif + +#define VERDE_I2C_BASE 0x1680 +#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00) +#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20) +#define VERDE_I2C_SIZE 0x0080 +#define VERDE_I2C_CHSIZE 0x0020 + +/* + * Address Translation Unit + */ + /* 0x00 - 0x38 -- PCI configuration space header */ +#define ATU_IALR0 0x40 /* Inbound ATU Limit 0 */ +#define ATU_IATVR0 0x44 /* Inbound ATU Xlate Value 0 */ +#define ATU_ERLR 0x48 /* Expansion ROM Limit */ +#define ATU_ERTVR 0x4c /* Expansion ROM Xlate Value */ +#define ATU_IALR1 0x50 /* Inbound ATU Limit 1 */ +#define ATU_IALR2 0x54 /* Inbound ATU Limit 2 */ +#define ATU_IATVR2 0x58 /* Inbound ATU Xlate Value 2 */ +#define ATU_OIOWTVR 0x5c /* Outbound I/O Window Xlate Value */ +#define ATU_OMWTVR0 0x60 /* Outbound Mem Window Xlate Value 0 */ +#define ATU_OUMWTVR0 0x64 /* Outbound Mem Window Xlate Value 0 Upper */ +#define ATU_OMWTVR1 0x68 /* Outbound Mem Window Xlate Value 1 */ +#define ATU_OUMWTVR1 0x6c /* Outbound Mem Window Xlate Value 1 Upper */ +#define ATU_OUDWTVR 0x78 /* Outbound Mem Direct Xlate Value Upper */ +#define ATU_ATUCR 0x80 /* ATU Configuration */ +#define ATU_PCSR 0x84 /* PCI Configuration and Status */ +#define ATU_ATUISR 0x88 /* ATU Interrupt Status */ +#define ATU_ATUIMR 0x8c /* ATU Interrupt Mask */ +#define ATU_IABAR3 0x90 /* Inbound ATU Base Address 3 */ +#define ATU_IAUBAR3 0x94 /* Inbound ATU Base Address 3 Upper */ +#define ATU_IALR3 0x98 /* Inbound ATU Limit 3 */ +#define ATU_IATVR3 0x9c /* Inbound ATU Xlate Value 3 */ +#define ATU_OCCAR 0xa4 /* Outbound Configuration Cycle Address */ +#define ATU_OCCDR 0xac /* Outbound Configuration Cycle Data */ +#define ATU_MSI_PORT 0xb4 /* MSI port */ +#define ATU_PDSCR 0xbc /* PCI Bus Drive Strength Control */ +#define ATU_PCI_X_CAP_ID 0xe0 /* (1) */ +#define ATU_PCI_X_NEXT 0xe1 /* (1) */ +#define ATU_PCIXCMD 0xe2 /* PCI-X Command Register (2) */ +#define ATU_PCIXSR 0xe4 /* PCI-X Status Register */ + +#define ATUCR_DRC_ALIAS (1U << 19) +#define ATUCR_DAU2GXEN (1U << 18) +#define ATUCR_P_SERR_MA (1U << 16) +#define ATUCR_DTS (1U << 15) +#define ATUCR_P_SERR_DIE (1U << 9) +#define ATUCR_DAE (1U << 8) +#define ATUCR_BIST_IE (1U << 3) +#define ATUCR_OUT_EN (1U << 1) + +#define PCSR_DAAAPE (1U << 18) +#define PCSR_PCI_X_CAP (3U << 16) +#define PCSR_PCI_X_CAP_BORING (0 << 16) +#define PCSR_PCI_X_CAP_66 (1U << 16) +#define PCSR_PCI_X_CAP_100 (2U << 16) +#define PCSR_PCI_X_CAP_133 (3U << 16) +#define PCSR_OTQB (1U << 15) +#define PCSR_IRTQB (1U << 14) +#define PCSR_DTV (1U << 12) +#define PCSR_BUS66 (1U << 10) +#define PCSR_BUS64 (1U << 8) +#define PCSR_RIB (1U << 5) +#define PCSR_RPB (1U << 4) +#define PCSR_CCR (1U << 2) +#define PCSR_CPR (1U << 1) + +#define ATUISR_IMW1BU (1U << 14) +#define ATUISR_ISCEM (1U << 13) +#define ATUISR_RSCEM (1U << 12) +#define ATUISR_PST (1U << 11) +#define ATUISR_P_SERR_ASRT (1U << 10) +#define ATUISR_DPE (1U << 9) +#define ATUISR_BIST (1U << 8) +#define ATUISR_IBMA (1U << 7) +#define ATUISR_P_SERR_DET (1U << 4) +#define ATUISR_PMA (1U << 3) +#define ATUISR_PTAM (1U << 2) +#define ATUISR_PTAT (1U << 1) +#define ATUISR_PMPE (1U << 0) + +#define ATUIMR_IMW1BU (1U << 11) +#define ATUIMR_ISCEM (1U << 10) +#define ATUIMR_RSCEM (1U << 9) +#define ATUIMR_PST (1U << 8) +#define ATUIMR_DPE (1U << 7) +#define ATUIMR_P_SERR_ASRT (1U << 6) +#define ATUIMR_PMA (1U << 5) +#define ATUIMR_PTAM (1U << 4) +#define ATUIMR_PTAT (1U << 3) +#define ATUIMR_PMPE (1U << 2) +#define ATUIMR_IE_SERR_EN (1U << 1) +#define ATUIMR_ECC_TAE (1U << 0) + +#define PCIXCMD_MOST_1 (0 << 4) +#define PCIXCMD_MOST_2 (1 << 4) +#define PCIXCMD_MOST_3 (2 << 4) +#define PCIXCMD_MOST_4 (3 << 4) +#define PCIXCMD_MOST_8 (4 << 4) +#define PCIXCMD_MOST_12 (5 << 4) +#define PCIXCMD_MOST_16 (6 << 4) +#define PCIXCMD_MOST_32 (7 << 4) +#define PCIXCMD_MOST_MASK (7 << 4) +#define PCIXCMD_MMRBC_512 (0 << 2) +#define PCIXCMD_MMRBC_1024 (1 << 2) +#define PCIXCMD_MMRBC_2048 (2 << 2) +#define PCIXCMD_MMRBC_4096 (3 << 2) +#define PCIXCMD_MMRBC_MASK (3 << 2) +#define PCIXCMD_ERO (1U << 1) +#define PCIXCMD_DPERE (1U << 0) + +#define PCIXSR_RSCEM (1U << 29) +#define PCIXSR_DMCRS_MASK (7 << 26) +#define PCIXSR_DMOST_MASK (7 << 23) +#define PCIXSR_COMPLEX (1U << 20) +#define PCIXSR_USC (1U << 19) +#define PCIXSR_SCD (1U << 18) +#define PCIXSR_133_CAP (1U << 17) +#define PCIXSR_32PCI (1U << 16) /* 0 = 32, 1 = 64 */ +#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8) +#define PCIXSR_DEVNO(x) (((x) & 0xf8) >> 3) +#define PCIXSR_FUNCNO(x) ((x) & 0x7) + +/* + * Memory Controller Unit + */ +#define MCU_SDIR 0x00 /* DDR SDRAM Init. Register */ +#define MCU_SDCR 0x04 /* DDR SDRAM Control Register */ +#define MCU_SDBR 0x08 /* SDRAM Base Register */ +#define MCU_SBR0 0x0c /* SDRAM Boundary 0 */ +#define MCU_SBR1 0x10 /* SDRAM Boundary 1 */ +#define MCU_ECCR 0x34 /* ECC Control Register */ +#define MCU_ELOG0 0x38 /* ECC Log 0 */ +#define MCU_ELOG1 0x3c /* ECC Log 1 */ +#define MCU_ECAR0 0x40 /* ECC address 0 */ +#define MCU_ECAR1 0x44 /* ECC address 1 */ +#define MCU_ECTST 0x48 /* ECC test register */ +#define MCU_MCISR 0x4c /* MCU Interrupt Status Register */ +#define MCU_RFR 0x50 /* Refresh Frequency Register */ +#define MCU_DBUDSR 0x54 /* Data Bus Pull-up Drive Strength */ +#define MCU_DBDDSR 0x58 /* Data Bus Pull-down Drive Strength */ +#define MCU_CUDSR 0x5c /* Clock Pull-up Drive Strength */ +#define MCU_CDDSR 0x60 /* Clock Pull-down Drive Strength */ +#define MCU_CEUDSR 0x64 /* Clock En Pull-up Drive Strength */ +#define MCU_CEDDSR 0x68 /* Clock En Pull-down Drive Strength */ +#define MCU_CSUDSR 0x6c /* Chip Sel Pull-up Drive Strength */ +#define MCU_CSDDSR 0x70 /* Chip Sel Pull-down Drive Strength */ +#define MCU_REUDSR 0x74 /* Rx En Pull-up Drive Strength */ +#define MCU_REDDSR 0x78 /* Rx En Pull-down Drive Strength */ +#define MCU_ABUDSR 0x7c /* Addr Bus Pull-up Drive Strength */ +#define MCU_ABDDSR 0x80 /* Addr Bus Pull-down Drive Strength */ +#define MCU_DSDR 0x84 /* Data Strobe Delay Register */ +#define MCU_REDR 0x88 /* Rx Enable Delay Register */ + +#define SDCR_DIMMTYPE (1U << 1) /* 0 = unbuf, 1 = reg */ +#define SDCR_BUSWIDTH (1U << 2) /* 0 = 64, 1 = 32 */ + +#define SBRx_TECH (1U << 31) +#define SBRx_BOUND 0x0000003f + +#define ECCR_SBERE (1U << 0) +#define ECCR_MBERE (1U << 1) +#define ECCR_SBECE (1U << 2) +#define ECCR_ECCEN (1U << 3) + +#define ELOGx_SYNDROME 0x000000ff +#define ELOGx_ERRTYPE (1U << 8) /* 1 = multi-bit */ +#define ELOGx_RW (1U << 12) /* 1 = write error */ + /* + * Dev ID Func Requester + * 2 0 XScale core + * 2 1 ATU + * 13 0 DMA channel 0 + * 13 1 DMA channel 1 + * 26 0 ATU + */ +#define ELOGx_REQ_DEV(x) (((x) >> 19) & 0x1f) +#define ELOGx_REQ_FUNC(x) (((x) >> 16) & 0x3) + +#define MCISR_ECC_ERR0 (1U << 0) +#define MCISR_ECC_ERR1 (1U << 1) +#define MCISR_ECC_ERRN (1U << 2) + +/* + * Timers + * + * The i80321 timer registers are available in both memory-mapped + * and coprocessor spaces. Most of the registers are read-only + * if memory-mapped, so we access them via coprocessor space. + * + * TMR0 cp6 c0,1 0xffffe7e0 + * TMR1 cp6 c1,1 0xffffe7e4 + * TCR0 cp6 c2,1 0xffffe7e8 + * TCR1 cp6 c3,1 0xffffe7ec + * TRR0 cp6 c4,1 0xffffe7f0 + * TRR1 cp6 c5,1 0xffffe7f4 + * TISR cp6 c6,1 0xffffe7f8 + * WDTCR cp6 c7,1 0xffffe7fc + */ + +#define TMRx_TC (1U << 0) +#define TMRx_ENABLE (1U << 1) +#define TMRx_RELOAD (1U << 2) +#define TMRx_CSEL_CORE (0 << 4) +#define TMRx_CSEL_CORE_div4 (1 << 4) +#define TMRx_CSEL_CORE_div8 (2 << 4) +#define TMRx_CSEL_CORE_div16 (3 << 4) + +#define TISR_TMR0 (1U << 0) +#define TISR_TMR1 (1U << 1) + +#define WDTCR_ENABLE1 0x1e1e1e1e +#define WDTCR_ENABLE2 0xe1e1e1e1 + +/* + * Interrupt Controller Unit. + * + * INTCTL cp6 c0,0 0xffffe7d0 + * INTSTR cp6 c4,0 0xffffe7d4 + * IINTSRC cp6 c8,0 0xffffe7d8 + * FINTSRC cp6 c9,0 0xffffe7dc + * PIRSR 0xffffe1ec + */ + +#define ICU_PIRSR 0x01ec +#define ICU_GPOE 0x07c4 +#define ICU_GPID 0x07c8 +#define ICU_GPOD 0x07cc + +/* + * NOTE: WE USE THE `bitXX' BITS TO INDICATE PENDING SOFTWARE + * INTERRUPTS. See i80321_icu.c + */ +#define ICU_INT_HPI 31 /* high priority interrupt */ +#define ICU_INT_XINT0 27 /* external interrupts */ +#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0) +#define ICU_INT_bit26 26 + +#if defined (CPU_XSCALE_80219) +#define ICU_INT_bit25 25 /* reserved */ +#else +/* CPU_XSCALE_80321 */ +#define ICU_INT_SSP 25 /* SSP serial port */ +#endif + +#define ICU_INT_MUE 24 /* msg unit error */ + +#if defined (CPU_XSCALE_80219) +#define ICU_INT_bit23 23 /* reserved */ +#else +/* CPU_XSCALE_80321 */ +#define ICU_INT_AAUE 23 /* AAU error */ +#endif + +#define ICU_INT_bit22 22 +#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ +#define ICU_INT_DMA0E 20 /* DMA Ch 0 error */ +#define ICU_INT_MCUE 19 /* memory controller error */ +#define ICU_INT_ATUE 18 /* ATU error */ +#define ICU_INT_BIUE 17 /* bus interface unit error */ +#define ICU_INT_PMU 16 /* XScale PMU */ +#define ICU_INT_PPM 15 /* peripheral PMU */ +#define ICU_INT_BIST 14 /* ATU Start BIST */ +#define ICU_INT_MU 13 /* messaging unit */ +#define ICU_INT_I2C1 12 /* i2c unit 1 */ +#define ICU_INT_I2C0 11 /* i2c unit 0 */ +#define ICU_INT_TMR1 10 /* timer 1 */ +#define ICU_INT_TMR0 9 /* timer 0 */ +#define ICU_INT_CPPM 8 /* core processor PMU */ + +#if defined(CPU_XSCALE_80219) +#define ICU_INT_bit7 7 /* reserved */ +#define ICU_INT_bit6 6 /* reserved */ +#else +/* CPU_XSCALE_80321 */ +#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ +#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ +#endif + +#define ICU_INT_bit5 5 +#define ICU_INT_bit4 4 +#define ICU_INT_DMA1_EOC 3 /* DMA1 end-of-chain */ +#define ICU_INT_DMA1_EOT 2 /* DMA1 end-of-transfer */ +#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */ +#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ + +#if defined (CPU_XSCALE_80219) +#define ICU_INT_HWMASK (0xffffffff & \ + ~((1 << ICU_INT_bit26) | \ + (1 << ICU_INT_bit25) | \ + (1 << ICU_INT_bit23) | \ + (1 << ICU_INT_bit22) | \ + (1 << ICU_INT_bit7) | \ + (1 << ICU_INT_bit6) | \ + (1 << ICU_INT_bit5) | \ + (1 << ICU_INT_bit4))) + +#else +/* CPU_XSCALE_80321 */ +#define ICU_INT_HWMASK (0xffffffff & \ + ~((1 << ICU_INT_bit26) | \ + (1 << ICU_INT_bit22) | \ + (1 << ICU_INT_bit5) | \ + (1 << ICU_INT_bit4))) +#endif + +/* + * SSP Serial Port + */ +#if defined (CPU_XSCALE_80321) + +#define SSP_SSCR0 0x00 /* SSC control 0 */ +#define SSP_SSCR1 0x04 /* SSC control 1 */ +#define SSP_SSSR 0x08 /* SSP status */ +#define SSP_SSITR 0x0c /* SSP interrupt test */ +#define SSP_SSDR 0x10 /* SSP data */ + +#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */ +#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */ +#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */ +#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */ +#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */ +#define SSP_SSCR0_ECS (1U << 6)/* external clock select */ +#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */ +#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */ + /* bit rate = 3.6864 * 10e6 / + (2 * (SCR + 1)) */ + +#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */ +#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */ +#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */ +#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */ +#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase: + 0 = inactive full at start, + 1/2 at end of frame + 1 = inactive 1/2 at start, + full at end of frame */ +#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size: + 0 = 8 bit + 1 = 16 bit */ +#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */ +#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */ +#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */ +#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select: + 0 = Tx FIFO + 1 = Rx FIFO */ + +#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */ +#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */ +#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */ +#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */ +#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */ +#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */ +#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */ +#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */ + +#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */ +#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */ +#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */ + +#endif /* CPU_XSCALE_80321 */ + +/* + * Peripheral Bus Interface Unit + */ + +#define PBIU_PBCR 0x00 /* PBIU Control Register */ +#define PBIU_PBBAR0 0x08 /* PBIU Base Address Register 0 */ +#define PBIU_PBLR0 0x0c /* PBIU Limit Register 0 */ +#define PBIU_PBBAR1 0x10 /* PBIU Base Address Register 1 */ +#define PBIU_PBLR1 0x14 /* PBIU Limit Register 1 */ +#define PBIU_PBBAR2 0x18 /* PBIU Base Address Register 2 */ +#define PBIU_PBLR2 0x1c /* PBIU Limit Register 2 */ +#define PBIU_PBBAR3 0x20 /* PBIU Base Address Register 3 */ +#define PBIU_PBLR3 0x24 /* PBIU Limit Register 3 */ +#define PBIU_PBBAR4 0x28 /* PBIU Base Address Register 4 */ +#define PBIU_PBLR4 0x2c /* PBIU Limit Register 4 */ +#define PBIU_PBBAR5 0x30 /* PBIU Base Address Register 5 */ +#define PBIU_PBLR5 0x34 /* PBIU Limit Register 5 */ +#define PBIU_DSCR 0x38 /* PBIU Drive Strength Control Reg. */ +#define PBIU_MBR0 0x40 /* PBIU Memory-less Boot Reg. 0 */ +#define PBIU_MBR1 0x60 /* PBIU Memory-less Boot Reg. 1 */ +#define PBIU_MBR2 0x64 /* PBIU Memory-less Boot Reg. 2 */ + +#define PBIU_PBCR_PBIEN (1 << 0) +#define PBIU_PBCR_PBI100 (1 << 1) +#define PBIU_PBCR_PBI66 (2 << 1) +#define PBIU_PBCR_PBI33 (3 << 1) +#define PBIU_PBCR_PBBEN (1 << 3) + +#define PBIU_PBARx_WIDTH8 (0 << 0) +#define PBIU_PBARx_WIDTH16 (1 << 0) +#define PBIU_PBARx_WIDTH32 (2 << 0) +#define PBIU_PBARx_ADWAIT4 (0 << 2) +#define PBIU_PBARx_ADWAIT8 (1 << 2) +#define PBIU_PBARx_ADWAIT12 (2 << 2) +#define PBIU_PBARx_ADWAIT16 (3 << 2) +#define PBIU_PBARx_ADWAIT20 (4 << 2) +#define PBIU_PBARx_RCWAIT1 (0 << 6) +#define PBIU_PBARx_RCWAIT4 (1 << 6) +#define PBIU_PBARx_RCWAIT8 (2 << 6) +#define PBIU_PBARx_RCWAIT12 (3 << 6) +#define PBIU_PBARx_RCWAIT16 (4 << 6) +#define PBIU_PBARx_RCWAIT20 (5 << 6) +#define PBIU_PBARx_FWE (1 << 9) +#define PBIU_BASE_MASK 0xfffff000U + +#define PBIU_PBLRx_SIZE(x) (~((x) - 1)) + +/* + * Messaging Unit + */ +#define MU_IMR0 0x0010 /* MU Inbound Message Register 0 */ +#define MU_IMR1 0x0014 /* MU Inbound Message Register 1 */ +#define MU_OMR0 0x0018 /* MU Outbound Message Register 0 */ +#define MU_OMR1 0x001c /* MU Outbound Message Register 1 */ +#define MU_IDR 0x0020 /* MU Inbound Doorbell Register */ +#define MU_IISR 0x0024 /* MU Inbound Interrupt Status Reg */ +#define MU_IIMR 0x0028 /* MU Inbound Interrupt Mask Reg */ +#define MU_ODR 0x002c /* MU Outbound Doorbell Register */ +#define MU_OISR 0x0030 /* MU Outbound Interrupt Status Reg */ +#define MU_OIMR 0x0034 /* MU Outbound Interrupt Mask Reg */ +#define MU_MUCR 0x0050 /* MU Configuration Register */ +#define MU_QBAR 0x0054 /* MU Queue Base Address Register */ +#define MU_IFHPR 0x0060 /* MU Inbound Free Head Pointer Reg */ +#define MU_IFTPR 0x0064 /* MU Inbound Free Tail Pointer Reg */ +#define MU_IPHPR 0x0068 /* MU Inbound Post Head Pointer Reg */ +#define MU_IPTPR 0x006c /* MU Inbound Post Tail Pointer Reg */ +#define MU_OFHPR 0x0070 /* MU Outbound Free Head Pointer Reg */ +#define MU_OFTPR 0x0074 /* MU Outbound Free Tail Pointer Reg */ +#define MU_OPHPR 0x0078 /* MU Outbound Post Head Pointer Reg */ +#define MU_OPTPR 0x007c /* MU Outbound Post Tail Pointer Reg */ +#define MU_IAR 0x0080 /* MU Index Address Register */ + +#define MU_IIMR_IRI (1 << 6) /* Index Register Interrupt */ +#define MU_IIMR_OFQFI (1 << 5) /* Outbound Free Queue Full Int. */ +#define MU_IIMR_IPQI (1 << 4) /* Inbound Post Queue Interrupt */ +#define MU_IIMR_EDI (1 << 3) /* Error Doorbell Interrupt */ +#define MU_IIMR_IDI (1 << 2) /* Inbound Doorbell Interrupt */ +#define MU_IIMR_IM1I (1 << 1) /* Inbound Message 1 Interrupt */ +#define MU_IIMR_IM0I (1 << 0) /* Inbound Message 0 Interrupt */ + +#endif /* _ARM_XSCALE_I80321REG_H_ */ diff --git a/sys/arm/xscale/i8134x/i80321var.h b/sys/arm/xscale/i8134x/i80321var.h new file mode 100644 index 000000000000..0fead2577a2e --- /dev/null +++ b/sys/arm/xscale/i8134x/i80321var.h @@ -0,0 +1,137 @@ +/* $NetBSD: i80321var.h,v 1.8 2003/10/06 16:06:06 thorpej Exp $ */ + +/*- + * Copyright (c) 2002, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 _ARM_XSCALE_I80321VAR_H_ +#define _ARM_XSCALE_I80321VAR_H_ + +#include +#include +#include + +extern struct bus_space i80321_bs_tag; + +struct i80321_softc { + device_t dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + /* Handles for the various subregions. */ + bus_space_handle_t sc_atu_sh; + bus_space_handle_t sc_mcu_sh; + int sc_is_host; + + /* + * We expect the board-specific front-end to have already mapped + * the PCI I/O space .. it is only 64K, and I/O mappings tend to + * be smaller than a page size, so it's generally more efficient + * to map them all into virtual space in one fell swoop. + */ + vm_offset_t sc_iow_vaddr; /* I/O window vaddr */ + + /* + * Variables that define the Inbound windows. The base address of + * 0-2 are configured by a host via BARs. The xlate variable + * defines the start of the local address space that it maps to. + * The size variable defines the byte size. + * + * The first 3 windows are for incoming PCI memory read/write + * cycles from a host. The 4th window, not configured by the + * host (as it outside the normal BAR range) is the inbound + * window for PCI devices controlled by the i80321. + */ + struct { + uint32_t iwin_base_hi; + uint32_t iwin_base_lo; + uint32_t iwin_xlate; + uint32_t iwin_size; + } sc_iwin[4]; + + /* + * Variables that define the Outbound windows. + */ + struct { + uint32_t owin_xlate_lo; + uint32_t owin_xlate_hi; + } sc_owin[2]; + + /* + * This is the PCI address that the Outbound I/O + * window maps to. + */ + uint32_t sc_ioout_xlate; + + /* Bus space, DMA, and PCI tags for the PCI bus (private devices). */ + struct bus_space sc_pci_iot; + struct bus_space sc_pci_memt; + + /* GPIO state */ + uint8_t sc_gpio_dir; /* GPIO pin direction (1 == output) */ + uint8_t sc_gpio_val; /* GPIO output pin value */ + struct rman sc_irq_rman; + +}; + + +struct i80321_pci_softc { + device_t sc_dev; + bus_space_tag_t sc_st; + bus_space_handle_t sc_atu_sh; + bus_space_tag_t sc_pciio; + bus_space_tag_t sc_pcimem; + int sc_busno; + struct rman sc_mem_rman; + struct rman sc_io_rman; + struct rman sc_irq_rman; + uint32_t sc_mem; + uint32_t sc_io; +}; + +void i80321_sdram_bounds(bus_space_tag_t, bus_space_handle_t, + vm_paddr_t *, vm_size_t *); + +void i80321_attach(struct i80321_softc *); +void i80321_calibrate_delay(void); + +void i80321_bs_init(bus_space_tag_t, void *); +void i80321_io_bs_init(bus_space_tag_t, void *); +void i80321_mem_bs_init(bus_space_tag_t, void *); +extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin); + + +#endif /* _ARM_XSCALE_I80321VAR_H_ */ From 15baa0d59b98e699de5da7f35e19010d4fc8b4f0 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 09:15:44 +0000 Subject: [PATCH 147/236] ARM: Remove support for xscale i80219 and i80321 CPUs. We haven't single supported config/board with these CPUs. --- sys/arm/arm/cpufunc.c | 44 +- sys/arm/arm/elf_trampoline.c | 4 +- sys/arm/conf/NOTES | 2 - sys/arm/include/cpuconf.h | 14 +- sys/arm/include/cpufunc.h | 11 +- sys/arm/xscale/i80321/ep80219_machdep.c | 402 ----------------- sys/arm/xscale/i80321/files.ep80219 | 11 - sys/arm/xscale/i80321/files.i80219 | 11 - sys/arm/xscale/i80321/files.i80321 | 9 - sys/arm/xscale/i80321/files.iq31244 | 8 - sys/arm/xscale/i80321/i80321.c | 250 ----------- sys/arm/xscale/i80321/i80321_aau.c | 292 ------------- sys/arm/xscale/i80321/i80321_dma.c | 351 --------------- sys/arm/xscale/i80321/i80321_intr.h | 165 ------- sys/arm/xscale/i80321/i80321_mcu.c | 90 ---- sys/arm/xscale/i80321/i80321_pci.c | 401 ----------------- sys/arm/xscale/i80321/i80321_space.c | 209 --------- sys/arm/xscale/i80321/i80321_timer.c | 485 --------------------- sys/arm/xscale/i80321/i80321_wdog.c | 154 ------- sys/arm/xscale/i80321/i80321reg.h | 547 ------------------------ sys/arm/xscale/i80321/i80321var.h | 137 ------ sys/arm/xscale/i80321/iq31244_7seg.c | 390 ----------------- sys/arm/xscale/i80321/iq31244_machdep.c | 416 ------------------ sys/arm/xscale/i80321/iq80321.c | 394 ----------------- sys/arm/xscale/i80321/iq80321reg.h | 111 ----- sys/arm/xscale/i80321/iq80321var.h | 53 --- sys/arm/xscale/i80321/obio.c | 163 ------- sys/arm/xscale/i80321/obiovar.h | 58 --- sys/arm/xscale/i80321/std.ep80219 | 7 - sys/arm/xscale/i80321/std.i80219 | 5 - sys/arm/xscale/i80321/std.i80321 | 5 - sys/arm/xscale/i80321/std.iq31244 | 7 - sys/arm/xscale/i80321/uart_bus_i80321.c | 76 ---- sys/arm/xscale/i80321/uart_cpu_i80321.c | 67 --- sys/arm/xscale/i8134x/i80321reg.h | 110 +---- sys/conf/files.arm | 4 +- sys/conf/options.arm | 2 - 37 files changed, 29 insertions(+), 5436 deletions(-) delete mode 100644 sys/arm/xscale/i80321/ep80219_machdep.c delete mode 100644 sys/arm/xscale/i80321/files.ep80219 delete mode 100644 sys/arm/xscale/i80321/files.i80219 delete mode 100644 sys/arm/xscale/i80321/files.i80321 delete mode 100644 sys/arm/xscale/i80321/files.iq31244 delete mode 100644 sys/arm/xscale/i80321/i80321.c delete mode 100644 sys/arm/xscale/i80321/i80321_aau.c delete mode 100644 sys/arm/xscale/i80321/i80321_dma.c delete mode 100644 sys/arm/xscale/i80321/i80321_intr.h delete mode 100644 sys/arm/xscale/i80321/i80321_mcu.c delete mode 100644 sys/arm/xscale/i80321/i80321_pci.c delete mode 100644 sys/arm/xscale/i80321/i80321_space.c delete mode 100644 sys/arm/xscale/i80321/i80321_timer.c delete mode 100644 sys/arm/xscale/i80321/i80321_wdog.c delete mode 100644 sys/arm/xscale/i80321/i80321reg.h delete mode 100644 sys/arm/xscale/i80321/i80321var.h delete mode 100644 sys/arm/xscale/i80321/iq31244_7seg.c delete mode 100644 sys/arm/xscale/i80321/iq31244_machdep.c delete mode 100644 sys/arm/xscale/i80321/iq80321.c delete mode 100644 sys/arm/xscale/i80321/iq80321reg.h delete mode 100644 sys/arm/xscale/i80321/iq80321var.h delete mode 100644 sys/arm/xscale/i80321/obio.c delete mode 100644 sys/arm/xscale/i80321/obiovar.h delete mode 100644 sys/arm/xscale/i80321/std.ep80219 delete mode 100644 sys/arm/xscale/i80321/std.i80219 delete mode 100644 sys/arm/xscale/i80321/std.i80321 delete mode 100644 sys/arm/xscale/i80321/std.iq31244 delete mode 100644 sys/arm/xscale/i80321/uart_bus_i80321.c delete mode 100644 sys/arm/xscale/i80321/uart_cpu_i80321.c diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 514a6b1a4059..2b226ef988c8 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -60,18 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include -#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) -#include -#include -#endif - -/* - * Some definitions in i81342reg.h clash with i80321reg.h. - * This only happens for the LINT kernel. As it happens, - * we don't need anything from i81342reg.h that we already - * got from somewhere else during a LINT compile. - */ -#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT) +#if defined(CPU_XSCALE_81342) #include #endif @@ -306,9 +295,7 @@ struct cpu_functions pj4bv7_cpufuncs = { }; #endif /* CPU_MV_PJ4B */ -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) struct cpu_functions xscale_cpufuncs = { /* CPU functions */ @@ -359,8 +346,7 @@ struct cpu_functions xscale_cpufuncs = { xscale_setup /* cpu setup */ }; #endif -/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ #ifdef CPU_XSCALE_81342 struct cpu_functions xscalec3_cpufuncs = { @@ -588,10 +574,10 @@ u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ #if defined(CPU_ARM9) || \ defined (CPU_ARM9E) || \ - defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) || \ + defined(CPU_ARM1176) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ + defined(CPU_XSCALE_81342) || \ defined(CPU_CORTEXA) || defined(CPU_KRAIT) /* Global cache line sizes, use 32 as default */ @@ -829,18 +815,6 @@ set_cpufuncs() } #endif /* CPU_FA526 */ -#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) - if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || - cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 || - cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) { - cpufuncs = xscale_cpufuncs; - cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ - get_cachetype_cp15(); - pmap_pte_init_xscale(); - goto out; - } -#endif /* CPU_XSCALE_80321 */ - #if defined(CPU_XSCALE_81342) if (cputype == CPU_ID_81342) { cpufuncs = xscalec3_cpufuncs; @@ -1207,9 +1181,8 @@ fa526_setup(void) } #endif /* CPU_FA526 */ -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342) void xscale_setup(void) { @@ -1276,5 +1249,4 @@ xscale_setup(void) __asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl)); } -#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index 6c086ea6192c..e25a849c812b 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -67,9 +67,7 @@ extern void fa526_idcache_wbinv_all(void); extern void armv5_ec_idcache_wbinv_all(void); #elif defined(CPU_ARM1176) #define cpu_idcache_wbinv_all armv6_idcache_wbinv_all -#elif defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) +#elif defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) #define cpu_idcache_wbinv_all xscale_cache_purgeID extern void xscale_cache_purgeID(void); #elif defined(CPU_XSCALE_81342) diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES index f4259f2324d7..db64f8ebb625 100644 --- a/sys/arm/conf/NOTES +++ b/sys/arm/conf/NOTES @@ -5,8 +5,6 @@ machine arm cpu CPU_ARM9 cpu CPU_ARM9E cpu CPU_FA526 -cpu CPU_XSCALE_80219 -cpu CPU_XSCALE_80321 cpu CPU_XSCALE_81342 cpu CPU_XSCALE_IXP425 cpu CPU_XSCALE_IXP435 diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h index ecee28088255..24a3b8f1c2cd 100644 --- a/sys/arm/include/cpuconf.h +++ b/sys/arm/include/cpuconf.h @@ -53,7 +53,6 @@ #define CPU_NTYPES (defined(CPU_ARM9) + \ defined(CPU_ARM9E) + \ defined(CPU_ARM1176) + \ - defined(CPU_XSCALE_80321) + \ defined(CPU_XSCALE_PXA2X0) + \ defined(CPU_FA526) + \ defined(CPU_XSCALE_IXP425)) + \ @@ -71,8 +70,7 @@ #endif #if (defined(CPU_ARM9E) || \ - defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ + defined(CPU_XSCALE_81342) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)) #define ARM_ARCH_5 1 #else @@ -163,9 +161,8 @@ #define ARM_MMU_V7 0 #endif -#if (defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)) +#if (defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342)) #define ARM_MMU_XSCALE 1 #else #define ARM_MMU_XSCALE 0 @@ -180,11 +177,10 @@ /* * Step 4: Define features that may be present on a subset of CPUs * - * ARM_XSCALE_PMU Performance Monitoring Unit on 80200 and 80321 + * ARM_XSCALE_PMU Performance Monitoring Unit on 81342 */ -#if (defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)) +#if (defined(CPU_XSCALE_81342)) #define ARM_XSCALE_PMU 1 #else #define ARM_XSCALE_PMU 0 diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index aad0febfa470..726c808dbedb 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -342,10 +342,9 @@ void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t); #endif #if defined(CPU_ARM9) || defined(CPU_ARM9E) || \ - defined(CPU_XSCALE_80321) || \ defined(CPU_FA526) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) + defined(CPU_XSCALE_81342) void armv4_tlb_flushID (void); void armv4_tlb_flushD (void); @@ -355,9 +354,8 @@ void armv4_drain_writebuf (void); void armv4_idcache_inv_all (void); #endif -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342) void xscale_cpwait (void); void xscale_cpu_sleep (int mode); @@ -395,8 +393,7 @@ void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end); void xscale_context_switch (void); void xscale_setup (void); -#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ #ifdef CPU_XSCALE_81342 diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c deleted file mode 100644 index 6c0d1f5af410..000000000000 --- a/sys/arm/xscale/i80321/ep80219_machdep.c +++ /dev/null @@ -1,402 +0,0 @@ -/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ - -/*- - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * This code is derived from software written for Brini by Mark Brinicombe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. - * - * RiscBSD kernel project - * - * machdep.c - * - * Machine dependant functions for kernel setup - * - * This file needs a lot of work. - * - * Created : 17/09/94 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_kstack_pages.h" - -#define _ARM32_BUS_DMA_PRIVATE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ -#define KERNEL_PT_IOPXS 1 -#define KERNEL_PT_BEFOREKERN 2 -#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ -#define KERNEL_PT_AFKERNEL_NUM 9 - -/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ -#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) - -struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; - -/* Physical and virtual addresses for some global pages */ - -struct pv_addr systempage; -struct pv_addr msgbufpv; -struct pv_addr irqstack; -struct pv_addr undstack; -struct pv_addr abtstack; -struct pv_addr kernelstack; -struct pv_addr minidataclean; - - -/* #define IQ80321_OBIO_BASE 0xfe800000UL */ -/* #define IQ80321_OBIO_SIZE 0x00100000UL */ - -/* Static device mappings. */ -static const struct arm_devmap_entry ep80219_devmap[] = { - /* - * Map the on-board devices VA == PA so that we can access them - * with the MMU on or off. - */ - { - IQ80321_OBIO_BASE, - IQ80321_OBIO_BASE, - IQ80321_OBIO_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_IOW_VBASE, - VERDE_OUT_XLATE_IO_WIN0_BASE, - VERDE_OUT_XLATE_IO_WIN_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_80321_VBASE, - VERDE_PMMR_BASE, - VERDE_PMMR_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - 0, - 0, - 0, - 0, - 0, - } -}; - -extern vm_offset_t xscale_cache_clean_addr; - -void * -initarm(struct arm_boot_params *abp) -{ - struct pv_addr kernel_l1pt; - struct pv_addr dpcpu; - int loop, i; - u_int l1pagetable; - vm_offset_t freemempos; - vm_offset_t freemem_pt; - vm_offset_t afterkern; - vm_offset_t freemem_after; - vm_offset_t lastaddr; - uint32_t memsize, memstart; - - lastaddr = parse_boot_param(abp); - arm_physmem_kernaddr = abp->abp_physaddr; - set_cpufuncs(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, &thread0); - - /* Do basic tuning, hz etc */ - init_param1(); - - freemempos = 0xa0200000; - /* Define a macro to simplify memory allocation */ -#define valloc_pages(var, np) \ - alloc_pages((var).pv_pa, (np)); \ - (var).pv_va = (var).pv_pa + 0x20000000; - -#define alloc_pages(var, np) \ - freemempos -= (np * PAGE_SIZE); \ - (var) = freemempos; \ - memset((char *)(var), 0, ((np) * PAGE_SIZE)); - - while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) - freemempos -= PAGE_SIZE; - valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); - for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { - if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { - valloc_pages(kernel_pt_table[loop], - L2_TABLE_SIZE / PAGE_SIZE); - } else { - kernel_pt_table[loop].pv_pa = freemempos + - (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * - L2_TABLE_SIZE_REAL; - kernel_pt_table[loop].pv_va = - kernel_pt_table[loop].pv_pa + 0x20000000; - } - } - freemem_pt = freemempos; - freemempos = 0xa0100000; - /* - * Allocate a page for the system page mapped to V0x00000000 - * This page will just contain the system vectors and can be - * shared by all processes. - */ - valloc_pages(systempage, 1); - - /* Allocate dynamic per-cpu area. */ - valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); - dpcpu_init((void *)dpcpu.pv_va, 0); - - /* Allocate stacks for all modes */ - valloc_pages(irqstack, IRQ_STACK_SIZE); - valloc_pages(abtstack, ABT_STACK_SIZE); - valloc_pages(undstack, UND_STACK_SIZE); - valloc_pages(kernelstack, kstack_pages); - alloc_pages(minidataclean.pv_pa, 1); - valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); - /* - * Allocate memory for the l1 and l2 page tables. The scheme to avoid - * wasting memory by allocating the l1pt on the first 16k memory was - * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for - * this to work (which is supposed to be the case). - */ - - /* - * Now we start construction of the L1 page table - * We start by mapping the L2 page tables into the L1. - * This means that we can replace L1 mappings later on if necessary - */ - l1pagetable = kernel_l1pt.pv_va; - - /* Map the L2 pages tables in the L1 page table */ - pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1), - &kernel_pt_table[KERNEL_PT_SYS]); - pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, - &kernel_pt_table[KERNEL_PT_IOPXS]); - pmap_link_l2pt(l1pagetable, KERNBASE, - &kernel_pt_table[KERNEL_PT_BEFOREKERN]); - pmap_map_chunk(l1pagetable, KERNBASE, IQ80321_SDRAM_START, 0x100000, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, IQ80321_SDRAM_START + 0x100000, - 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, IQ80321_SDRAM_START + 0x200000, - (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1), - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1); - afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - - 1)); - for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { - pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, - &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); - } - pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - - - /* Map the Mini-Data cache clean area. */ - xscale_setup_minidata(l1pagetable, afterkern, - minidataclean.pv_pa); - - /* Map the vector page. */ - pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - arm_devmap_bootstrap(l1pagetable, ep80219_devmap); - /* - * Give the XScale global cache clean code an appropriately - * sized chunk of unmapped VA space starting at 0xff000000 - * (our device mappings end before this address). - */ - xscale_cache_clean_addr = 0xff000000U; - - cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); - cpu_tlb_flushID(); - cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); - /* - * Pages were allocated during the secondary bootstrap for the - * stacks for different CPU modes. - * We must now set the r13 registers in the different CPU modes to - * point to these stacks. - * Since the ARM stacks use STMFD etc. we must set r13 to the top end - * of the stack memory. - */ - set_stackptrs(0); - - /* - * We must now clean the cache again.... - * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() - * but since we are boot strapping the addresses used for the read - * may have just been remapped and thus the cache could be out - * of sync. A re-clean after the switch will cure this. - * After booting there are no gross relocations of the kernel thus - * this problem will not occur after initarm(). - */ - cpu_idcache_wbinv_all(); - cpu_setup(); - - /* - * Fetch the SDRAM start/size from the i80321 SDRAM configration - * registers. - */ - i80321_calibrate_delay(); - i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE, - &memstart, &memsize); - physmem = memsize / PAGE_SIZE; - cninit(); - - undefined_init(); - - init_proc0(kernelstack.pv_va); - - /* Enable MMU, I-cache, D-cache, write buffer. */ - - arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); - vm_max_kernel_address = 0xe0000000; - pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); - msgbufp = (void*)msgbufpv.pv_va; - msgbufinit(msgbufp, msgbufsize); - mutex_init(); - - /* - * Add the physical ram we have available. - * - * Exclude the kernel (and all the things we allocated which immediately - * follow the kernel) from the VM allocation pool but not from crash - * dumps. virtual_avail is a global variable which tracks the kva we've - * "allocated" while setting up pmaps. - * - * Prepare the list of physical memory available to the vm subsystem. - */ - arm_physmem_hardware_region(IQ80321_SDRAM_START, memsize); - arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - - freemem_pt, EXFLAG_NOALLOC); - arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - - freemempos, EXFLAG_NOALLOC); - arm_physmem_exclude_region(abp->abp_physaddr, - virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); - arm_physmem_init_kernel_globals(); - - init_param2(physmem); - kdb_init(); - return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - - sizeof(struct pcb))); -} - -extern int -machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) -{ - int bus; - int device; - int func; - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(pcib); - bus = pci_get_bus(dev); - device = pci_get_slot(dev); - func = pci_get_function(dev); - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - if (bus != busno) - goto no_mapping; - switch (device) { - /* EP80219 PCI */ - case 1: /* Ethernet i82555 10/100 */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0)); - return (ICU_INT_XINT(0)); - case 2: /* UART */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1)); - return (ICU_INT_XINT(1)); - case 3: - /* - * The S-ATA chips are behind the bridge, and all of - * the S-ATA interrupts are wired together. - */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2)); - return (ICU_INT_XINT(2)); - case 4: /* MINI-PIC_INT */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3)); - return( ICU_INT_XINT(3)); - default: -no_mapping: - printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); - - } - return (0); - -} diff --git a/sys/arm/xscale/i80321/files.ep80219 b/sys/arm/xscale/i80321/files.ep80219 deleted file mode 100644 index 0eaf9db2872c..000000000000 --- a/sys/arm/xscale/i80321/files.ep80219 +++ /dev/null @@ -1,11 +0,0 @@ -#$FreeBSD$ -# -# -# EP80219 Board Specific -# -arm/xscale/i80321/iq80321.c standard -arm/xscale/i80321/ep80219_machdep.c standard -arm/xscale/i80321/obio.c standard -arm/xscale/i80321/uart_cpu_i80321.c optional uart -arm/xscale/i80321/uart_bus_i80321.c optional uart -dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/xscale/i80321/files.i80219 b/sys/arm/xscale/i80321/files.i80219 deleted file mode 100644 index 306376bbdd25..000000000000 --- a/sys/arm/xscale/i80321/files.i80219 +++ /dev/null @@ -1,11 +0,0 @@ -#$FreeBSD$ -# -# IOP Specific -# -arm/xscale/i80321/i80321.c standard -arm/xscale/i80321/i80321_dma.c optional dma -arm/xscale/i80321/i80321_mcu.c standard -arm/xscale/i80321/i80321_pci.c optional pci -arm/xscale/i80321/i80321_space.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog diff --git a/sys/arm/xscale/i80321/files.i80321 b/sys/arm/xscale/i80321/files.i80321 deleted file mode 100644 index bd318af1f650..000000000000 --- a/sys/arm/xscale/i80321/files.i80321 +++ /dev/null @@ -1,9 +0,0 @@ -#$FreeBSD$ -arm/xscale/i80321/i80321.c standard -arm/xscale/i80321/i80321_aau.c optional aau -arm/xscale/i80321/i80321_dma.c optional dma -arm/xscale/i80321/i80321_mcu.c standard -arm/xscale/i80321/i80321_pci.c optional pci -arm/xscale/i80321/i80321_space.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog diff --git a/sys/arm/xscale/i80321/files.iq31244 b/sys/arm/xscale/i80321/files.iq31244 deleted file mode 100644 index d28d49b3a6b1..000000000000 --- a/sys/arm/xscale/i80321/files.iq31244 +++ /dev/null @@ -1,8 +0,0 @@ -#$FreeBSD$ -arm/xscale/i80321/iq80321.c standard -arm/xscale/i80321/iq31244_machdep.c standard -arm/xscale/i80321/iq31244_7seg.c optional iq31244_7seg -arm/xscale/i80321/obio.c standard -arm/xscale/i80321/uart_cpu_i80321.c optional uart -arm/xscale/i80321/uart_bus_i80321.c optional uart -dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/xscale/i80321/i80321.c b/sys/arm/xscale/i80321/i80321.c deleted file mode 100644 index e65f38df5873..000000000000 --- a/sys/arm/xscale/i80321/i80321.c +++ /dev/null @@ -1,250 +0,0 @@ -/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Autoconfiguration support for the Intel i80321 I/O Processor. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#define _ARM32_BUS_DMA_PRIVATE -#include -#include - -#include -#include -#include - -#include - -volatile uint32_t intr_enabled; -uint32_t intr_steer = 0; -/* - * Statically-allocated bus_space stucture used to access the - * i80321's own registers. - */ -struct bus_space i80321_bs_tag; - -/* - * There can be only one i80321, so we keep a global pointer to - * the softc, so board-specific code can use features of the - * i80321 without having to have a handle on the softc itself. - */ -struct i80321_softc *i80321_softc; - -#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) -/* - * i80321_attach: - * - * Board-independent attach routine for the i80321. - */ -void -i80321_attach(struct i80321_softc *sc) -{ - - i80321_softc = sc; - uint32_t preg; - - /* We expect the Memory Controller to be already sliced off. */ - - /* - * Program the Inbound windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, - (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, - sc->sc_iwin[0].iwin_xlate); - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS, sc->sc_iwin[0].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x04, sc->sc_iwin[0].iwin_base_hi); - } else { - sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS); - sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x04); - sc->sc_iwin[0].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo); - } - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, - (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); - - /* no xlate for window 1 */ - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x08, sc->sc_iwin[1].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x0c, sc->sc_iwin[1].iwin_base_hi); - } else { - sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x08); - sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x0c); - sc->sc_iwin[1].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); - } - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, - (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, - sc->sc_iwin[2].iwin_xlate); - - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x10, sc->sc_iwin[2].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x14, sc->sc_iwin[2].iwin_base_hi); - } else { - sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x10); - sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x14); - sc->sc_iwin[2].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); - } - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, - (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, - sc->sc_iwin[3].iwin_xlate); - - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); - } else { - sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, ATU_IABAR3); - sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, ATU_IAUBAR3); - sc->sc_iwin[3].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo); - } - /* - * Mask (disable) the ATU interrupt sources. - * XXX May want to revisit this if we encounter - * XXX an application that wants it. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_ATUIMR, - ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| - ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| - ATUIMR_PTAT|ATUIMR_PMPE); - - /* - * Program the outbound windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OIOWTVR, sc->sc_ioout_xlate); - - if (!sc->sc_is_host) { - sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo; - sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; - } - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); - - /* - * Set up the ATU configuration register. All we do - * right now is enable Outbound Windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, - ATUCR_OUT_EN); - - /* - * Enable bus mastering, memory access, SERR, and parity - * checking on the ATU. - */ - if (sc->sc_is_host) { - preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, - PCIR_COMMAND); - preg |= PCIM_CMD_MEMEN | - PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | - PCIM_CMD_SERRESPEN; - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_COMMAND, preg); - } - /* Initialize the bus space tags. */ - i80321_io_bs_init(&sc->sc_pci_iot, sc); - i80321_mem_bs_init(&sc->sc_pci_memt, sc); - intr_enabled = 0; - i80321_set_intrmask(); - i80321_set_intrsteer(); -} - - -static __inline uint32_t -i80321_iintsrc_read(void) -{ - uint32_t iintsrc; - - __asm __volatile("mrc p6, 0, %0, c8, c0, 0" - : "=r" (iintsrc)); - - /* - * The IINTSRC register shows bits that are active even - * if they are masked in INTCTL, so we have to mask them - * off with the interrupts we consider enabled. - */ - return (iintsrc & intr_enabled); -} - -int -arm_get_next_irq(int last __unused) -{ - int irq; - - if ((irq = i80321_iintsrc_read())) - return (ffs(irq) - 1); - return (-1); -} diff --git a/sys/arm/xscale/i80321/i80321_aau.c b/sys/arm/xscale/i80321/i80321_aau.c deleted file mode 100644 index 288411b71974..000000000000 --- a/sys/arm/xscale/i80321/i80321_aau.c +++ /dev/null @@ -1,292 +0,0 @@ -/*- - * Copyright (c) 2005 Olivier Houchard. 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef struct i80321_aaudesc_s { - vm_paddr_t next_desc; - uint32_t sar[4]; - vm_paddr_t local_addr; - vm_size_t count; - uint32_t descr_ctrl; -} __packed i80321_aaudesc_t; - -typedef struct i80321_aauring_s { - i80321_aaudesc_t *desc; - vm_paddr_t phys_addr; - bus_dmamap_t map; -} i80321_aauring_t; - -#define AAU_RING_SIZE 64 - -struct i80321_aau_softc { - bus_space_tag_t sc_st; - bus_space_handle_t sc_aau_sh; - bus_dma_tag_t dmatag; - i80321_aauring_t aauring[AAU_RING_SIZE]; - int flags; -#define BUSY 0x1 - int unit; - struct mtx mtx; -}; - -static int -i80321_aau_probe(device_t dev) -{ - device_set_desc(dev, "I80321 AAU"); - return (0); -} - -static struct i80321_aau_softc *aau_softc; - -static void -i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - vm_paddr_t *addr = (vm_paddr_t *)arg; - - *addr = segs->ds_addr; -} - -#define AAU_REG_WRITE(softc, reg, val) \ - bus_space_write_4((softc)->sc_st, (softc)->sc_aau_sh, \ - (reg), (val)) -#define AAU_REG_READ(softc, reg) \ - bus_space_read_4((softc)->sc_st, (softc)->sc_aau_sh, \ - (reg)) - -static int aau_bzero(void *, int, int); - -static int -i80321_aau_attach(device_t dev) -{ - struct i80321_aau_softc *softc = device_get_softc(dev); - struct i80321_softc *sc = device_get_softc(device_get_parent(dev)); - struct i80321_aaudesc_s *aaudescs; - - mtx_init(&softc->mtx, "AAU mtx", NULL, MTX_SPIN); - softc->sc_st = sc->sc_st; - if (bus_space_subregion(softc->sc_st, sc->sc_sh, VERDE_AAU_BASE, - VERDE_AAU_SIZE, &softc->sc_aau_sh) != 0) - panic("%s: unable to subregion AAU registers", - device_get_name(dev)); - if (bus_dma_tag_create(NULL, sizeof(i80321_aaudesc_t), 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - AAU_RING_SIZE * sizeof(i80321_aaudesc_t), - 1, sizeof(i80321_aaudesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex, - &Giant, &softc->dmatag)) - panic("Couldn't create a dma tag"); - if (bus_dmamem_alloc(softc->dmatag, (void **)&aaudescs, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->aauring[0].map)) - panic("Couldn't alloc dma memory"); - - for (int i = 0; i < AAU_RING_SIZE; i++) { - if (i > 0) - if (bus_dmamap_create(softc->dmatag, 0, - &softc->aauring[i].map)) - panic("Couldn't create dma map"); - softc->aauring[i].desc = &aaudescs[i]; - bus_dmamap_load(softc->dmatag, softc->aauring[i].map, - softc->aauring[i].desc, sizeof(i80321_aaudesc_t), - i80321_mapphys, &softc->aauring[i].phys_addr, 0); - bzero(softc->aauring[i].desc, sizeof(i80321_aaudesc_t)); - } - aau_softc = softc; - _arm_bzero = aau_bzero; - _min_bzero_size = 1024; - return (0); -} - -static __inline void -test_virt_addr(void *addr, int len) -{ - int to_nextpage; - - while (len > 0) { - *(char *)addr = 0; - to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)addr; - if (to_nextpage >= len) - break; - len -= to_nextpage; - addr = (void *)((vm_offset_t)addr + to_nextpage); - } -} - -static int -aau_bzero(void *dst, int len, int flags) -{ - struct i80321_aau_softc *sc = aau_softc; - i80321_aaudesc_t *desc; - int ret; - int csr; - int descnb = 0; - int tmplen = len; - int to_nextpagedst; - int min_hop; - vm_paddr_t pa, tmppa; - - if (!sc) - return (-1); - mtx_lock_spin(&sc->mtx); - if (sc->flags & BUSY) { - mtx_unlock_spin(&sc->mtx); - return (-1); - } - sc->flags |= BUSY; - mtx_unlock_spin(&sc->mtx); - desc = sc->aauring[0].desc; - if (flags & IS_PHYSICAL) { - desc->local_addr = (vm_paddr_t)dst; - desc->next_desc = 0; - desc->count = len; - desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */ - bus_dmamap_sync(sc->dmatag, sc->aauring[0].map, - BUS_DMASYNC_PREWRITE); - } else { - test_virt_addr(dst, len); - if ((vm_offset_t)dst & (31)) - cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32); - if (((vm_offset_t)dst + len) & 31) - cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31, - 32); - cpu_dcache_inv_range((vm_offset_t)dst, len); - while (tmplen > 0) { - pa = vtophys(dst); - to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)dst; - while (to_nextpagedst < tmplen) { - tmppa = vtophys((vm_offset_t)dst + - to_nextpagedst); - if (tmppa != pa + to_nextpagedst) - break; - to_nextpagedst += PAGE_SIZE; - } - min_hop = to_nextpagedst; - if (min_hop < 64) { - tmplen -= min_hop; - bzero(dst, min_hop); - cpu_dcache_wbinv_range((vm_offset_t)dst, - min_hop); - - dst = (void *)((vm_offset_t)dst + min_hop); - if (tmplen <= 0 && descnb > 0) { - sc->aauring[descnb - 1].desc->next_desc - = 0; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb - 1].map, - BUS_DMASYNC_PREWRITE); - } - continue; - } - desc->local_addr = pa; - desc->count = tmplen > min_hop ? min_hop : tmplen; - desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */; - if (min_hop < tmplen) { - tmplen -= min_hop; - dst = (void *)((vm_offset_t)dst + min_hop); - } else - tmplen = 0; - if (descnb + 1 >= AAU_RING_SIZE) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - if (tmplen > 0) { - desc->next_desc = sc->aauring[descnb + 1]. - phys_addr; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb].map, - BUS_DMASYNC_PREWRITE); - desc = sc->aauring[descnb + 1].desc; - descnb++; - } else { - desc->next_desc = 0; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb].map, - BUS_DMASYNC_PREWRITE); - } - - } - - } - AAU_REG_WRITE(sc, 0x0c /* Descriptor addr */, - sc->aauring[0].phys_addr); - AAU_REG_WRITE(sc, 0 /* Control register */, 1 << 0/* Start transfer */); - while ((csr = AAU_REG_READ(sc, 0x4)) & (1 << 10)); - /* Wait until it's done. */ - if (csr & (1 << 5)) /* error */ - ret = -1; - else - ret = 0; - /* Clear the interrupt. */ - AAU_REG_WRITE(sc, 0x4, csr); - /* Stop the AAU. */ - AAU_REG_WRITE(sc, 0, 0); - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (ret); -} - -static device_method_t i80321_aau_methods[] = { - DEVMETHOD(device_probe, i80321_aau_probe), - DEVMETHOD(device_attach, i80321_aau_attach), - {0, 0}, -}; - -static driver_t i80321_aau_driver = { - "i80321_aau", - i80321_aau_methods, - sizeof(struct i80321_aau_softc), -}; - -static devclass_t i80321_aau_devclass; - -DRIVER_MODULE(i80321_aau, iq, i80321_aau_driver, i80321_aau_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_dma.c b/sys/arm/xscale/i80321/i80321_dma.c deleted file mode 100644 index abf7dcc970e8..000000000000 --- a/sys/arm/xscale/i80321/i80321_dma.c +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * Copyright (c) 2005 Olivier Houchard. 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. - */ - -#include -__FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef struct i80321_dmadesc_s { - vm_paddr_t next_desc; - vm_paddr_t low_pciaddr; - vm_paddr_t high_pciaddr; - vm_paddr_t local_addr; - vm_size_t count; - uint32_t descr_ctrl; - uint64_t unused; -} __packed i80321_dmadesc_t; - -typedef struct i80321_dmaring_s { - i80321_dmadesc_t *desc; - vm_paddr_t phys_addr; - bus_dmamap_t map; -} i80321_dmaring_t; - -#define DMA_RING_SIZE 64 - -struct i80321_dma_softc { - bus_space_tag_t sc_st; - bus_space_handle_t sc_dma_sh; - bus_dma_tag_t dmatag; - i80321_dmaring_t dmaring[DMA_RING_SIZE]; - int flags; -#define BUSY 0x1 - int unit; - struct mtx mtx; -}; - -static int -i80321_dma_probe(device_t dev) -{ - device_set_desc(dev, "I80321 DMA Unit"); - return (0); -} - -static struct i80321_dma_softc *softcs[2]; /* XXX */ - -static void -i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - vm_paddr_t *addr = (vm_paddr_t *)arg; - - *addr = segs->ds_addr; -} - -#define DMA_REG_WRITE(softc, reg, val) \ - bus_space_write_4((softc)->sc_st, (softc)->sc_dma_sh, \ - (reg), (val)) -#define DMA_REG_READ(softc, reg) \ - bus_space_read_4((softc)->sc_st, (softc)->sc_dma_sh, \ - (reg)) - -#define DMA_CLEAN_MASK (0x2|0x4|0x8|0x20|0x100|0x200) -static int dma_memcpy(void *, void *, int, int); - -static int -i80321_dma_attach(device_t dev) -{ - struct i80321_dma_softc *softc = device_get_softc(dev); - struct i80321_softc *sc = device_get_softc(device_get_parent(dev)); - int unit = device_get_unit(dev); - i80321_dmadesc_t *dmadescs; - - mtx_init(&softc->mtx, "DMA engine mtx", NULL, MTX_SPIN); - softc->sc_st = sc->sc_st; - if (bus_space_subregion(softc->sc_st, sc->sc_sh, unit == 0 ? - VERDE_DMA_BASE0 : VERDE_DMA_BASE1, VERDE_DMA_SIZE, - &softc->sc_dma_sh) != 0) - panic("%s: unable to subregion DMA registers", - device_get_name(dev)); - if (bus_dma_tag_create(NULL, sizeof(i80321_dmadesc_t), - 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - DMA_RING_SIZE * sizeof(i80321_dmadesc_t), 1, - sizeof(i80321_dmadesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex, - &Giant, &softc->dmatag)) - panic("Couldn't create a dma tag"); - DMA_REG_WRITE(softc, 0, 0); - if (bus_dmamem_alloc(softc->dmatag, (void **)&dmadescs, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->dmaring[0].map)) - panic("Couldn't alloc dma memory"); - for (int i = 0; i < DMA_RING_SIZE; i++) { - if (i > 0) - if (bus_dmamap_create(softc->dmatag, 0, - &softc->dmaring[i].map)) - panic("Couldn't alloc dmamap"); - softc->dmaring[i].desc = &dmadescs[i]; - bus_dmamap_load(softc->dmatag, softc->dmaring[i].map, - softc->dmaring[i].desc, sizeof(i80321_dmadesc_t), - i80321_mapphys, &softc->dmaring[i].phys_addr, 0); - } - softc->unit = unit; - softcs[unit] = softc; - _arm_memcpy = dma_memcpy; - _min_memcpy_size = 1024; - return (0); -} - -static __inline int -virt_addr_is_valid(void *addr, int len, int write, int is_kernel) -{ - int to_nextpage; - char tmp = 0; - - while (len > 0) { - if (write) { - if (is_kernel) - *(char *)addr = 0; - else if (subyte(addr, 0) != 0) { - return (0); - } - } else { - if (is_kernel) - badaddr_read(addr, 1, &tmp); - else if (fubyte(addr) == -1) { - return (0); - } - } - to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)addr; - if (to_nextpage >= len) - break; - len -= to_nextpage; - addr = (void *)((vm_offset_t)addr + to_nextpage); - } - return (1); -} - -static int -dma_memcpy(void *dst, void *src, int len, int flags) -{ - struct i80321_dma_softc *sc; - i80321_dmadesc_t *desc; - int ret; - int csr; - int descnb = 0; - int tmplen = len; - int to_nextpagesrc, to_nextpagedst; - int min_hop; - vm_paddr_t pa, pa2, tmppa; - pmap_t pmap = vmspace_pmap(curthread->td_proc->p_vmspace); - - if (!softcs[0] || !softcs[1]) - return (-1); - mtx_lock_spin(&softcs[0]->mtx); - if (softcs[0]->flags & BUSY) { - mtx_unlock_spin(&softcs[0]->mtx); - mtx_lock_spin(&softcs[1]->mtx); - if (softcs[1]->flags & BUSY) { - mtx_unlock(&softcs[1]->mtx); - return (-1); - } - sc = softcs[1]; - } else - sc = softcs[0]; - sc->flags |= BUSY; - mtx_unlock_spin(&sc->mtx); - desc = sc->dmaring[0].desc; - if (flags & IS_PHYSICAL) { - desc->next_desc = 0; - desc->low_pciaddr = (vm_paddr_t)src; - desc->high_pciaddr = 0; - desc->local_addr = (vm_paddr_t)dst; - desc->count = len; - desc->descr_ctrl = 1 << 6; /* Local memory to local memory. */ - bus_dmamap_sync(sc->dmatag, - sc->dmaring[0].map, - BUS_DMASYNC_PREWRITE); - } else { - if (!virt_addr_is_valid(dst, len, 1, !(flags & DST_IS_USER)) || - !virt_addr_is_valid(src, len, 0, !(flags & SRC_IS_USER))) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - cpu_dcache_wb_range((vm_offset_t)src, len); - if ((vm_offset_t)dst & (31)) - cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32); - if (((vm_offset_t)dst + len) & 31) - cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31, - 32); - cpu_dcache_inv_range((vm_offset_t)dst, len); - while (tmplen > 0) { - pa = (flags & SRC_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)src) : - vtophys(src); - pa2 = (flags & DST_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)dst) : - vtophys(dst); - to_nextpagesrc = ((vm_offset_t)src & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)src; - to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)dst; - while (to_nextpagesrc < tmplen) { - tmppa = (flags & SRC_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)src + - to_nextpagesrc) : - vtophys((vm_offset_t)src + - to_nextpagesrc); - if (tmppa != pa + to_nextpagesrc) - break; - to_nextpagesrc += PAGE_SIZE; - } - while (to_nextpagedst < tmplen) { - tmppa = (flags & DST_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)dst + - to_nextpagedst) : - vtophys((vm_offset_t)dst + - to_nextpagedst); - if (tmppa != pa2 + to_nextpagedst) - break; - to_nextpagedst += PAGE_SIZE; - } - min_hop = to_nextpagedst > to_nextpagesrc ? - to_nextpagesrc : to_nextpagedst; - if (min_hop < 64) { - tmplen -= min_hop; - memcpy(dst, src, min_hop); - cpu_dcache_wbinv_range((vm_offset_t)dst, - min_hop); - - src = (void *)((vm_offset_t)src + min_hop); - dst = (void *)((vm_offset_t)dst + min_hop); - if (tmplen <= 0 && descnb > 0) { - sc->dmaring[descnb - 1].desc->next_desc - = 0; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb - 1].map, - BUS_DMASYNC_PREWRITE); - } - continue; - } - desc->low_pciaddr = pa; - desc->high_pciaddr = 0; - desc->local_addr = pa2; - desc->count = tmplen > min_hop ? min_hop : tmplen; - desc->descr_ctrl = 1 << 6; - if (min_hop < tmplen) { - tmplen -= min_hop; - src = (void *)((vm_offset_t)src + min_hop); - dst = (void *)((vm_offset_t)dst + min_hop); - } else - tmplen = 0; - if (descnb + 1 >= DMA_RING_SIZE) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - if (tmplen > 0) { - desc->next_desc = sc->dmaring[descnb + 1]. - phys_addr; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb].map, - BUS_DMASYNC_PREWRITE); - desc = sc->dmaring[descnb + 1].desc; - descnb++; - } else { - desc->next_desc = 0; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb].map, - BUS_DMASYNC_PREWRITE); - } - - } - - } - DMA_REG_WRITE(sc, 4 /* Status register */, - DMA_REG_READ(sc, 4) | DMA_CLEAN_MASK); - DMA_REG_WRITE(sc, 0x10 /* Descriptor addr */, - sc->dmaring[0].phys_addr); - DMA_REG_WRITE(sc, 0 /* Control register */, 1 | 2/* Start transfer */); - while ((csr = DMA_REG_READ(sc, 0x4)) & (1 << 10)); - /* Wait until it's done. */ - if (csr & 0x2e) /* error */ - ret = -1; - else - ret = 0; - DMA_REG_WRITE(sc, 0, 0); - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (ret); -} - -static device_method_t i80321_dma_methods[] = { - DEVMETHOD(device_probe, i80321_dma_probe), - DEVMETHOD(device_attach, i80321_dma_attach), - {0, 0}, -}; - -static driver_t i80321_dma_driver = { - "i80321_dma", - i80321_dma_methods, - sizeof(struct i80321_dma_softc), -}; - -static devclass_t i80321_dma_devclass; - -DRIVER_MODULE(i80321_dma, iq, i80321_dma_driver, i80321_dma_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_intr.h b/sys/arm/xscale/i80321/i80321_intr.h deleted file mode 100644 index 29003a05ce56..000000000000 --- a/sys/arm/xscale/i80321/i80321_intr.h +++ /dev/null @@ -1,165 +0,0 @@ -/* $NetBSD: i80321_intr.h,v 1.5 2004/01/12 10:25:06 scw Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _I80321_INTR_H_ -#define _I80321_INTR_H_ - -#define ARM_IRQ_HANDLER _C_LABEL(i80321_intr_dispatch) - -#ifndef _LOCORE - -#include -#include - -#include - -void i80321_do_pending(void); - -extern __volatile uint32_t intr_enabled; -extern uint32_t intr_steer; - -static __inline void __attribute__((__unused__)) -i80321_set_intrmask(void) -{ - - __asm __volatile("mcr p6, 0, %0, c0, c0, 0" - : - : "r" (intr_enabled & ICU_INT_HWMASK)); -} - -static __inline void -i80321_set_intrsteer(void) -{ - - __asm __volatile("mcr p6, 0, %0, c4, c0, 0" - : - : "r" (intr_steer & ICU_INT_HWMASK)); -} - -#if defined ( CPU_XSCALE_80219 ) -#define INT_SWMASK \ - ((1U << ICU_INT_bit26) | \ - (1U << ICU_INT_bit25) | \ - (1U << ICU_INT_bit23) | \ - (1U << ICU_INT_bit22) | \ - (1U << ICU_INT_bit7) | \ - (1U << ICU_INT_bit6) | \ - (1U << ICU_INT_bit5) | \ - (1U << ICU_INT_bit4)) -#else -#define INT_SWMASK \ - ((1U << ICU_INT_bit26) | (1U << ICU_INT_bit22) | \ - (1U << ICU_INT_bit5) | (1U << ICU_INT_bit4)) -#endif - -#if 0 -static __inline void __attribute__((__unused__)) -i80321_splx(int new) -{ - extern __volatile uint32_t intr_enabled; - extern __volatile int current_spl_level; - extern __volatile int i80321_ipending; - extern void i80321_do_pending(void); - int oldirqstate, hwpend; - - /* Don't let the compiler re-order this code with preceding code */ - __insn_barrier(); - - current_spl_level = new; - - hwpend = (i80321_ipending & ICU_INT_HWMASK) & ~new; - if (hwpend != 0) { - oldirqstate = disable_interrupts(PSR_I); - intr_enabled |= hwpend; - i80321_set_intrmask(); - restore_interrupts(oldirqstate); - } - - if ((i80321_ipending & INT_SWMASK) & ~new) - i80321_do_pending(); -} - -static __inline int __attribute__((__unused__)) -i80321_splraise(int ipl) -{ - extern __volatile int current_spl_level; - extern int i80321_imask[]; - int old; - - old = current_spl_level; - current_spl_level |= i80321_imask[ipl]; - - /* Don't let the compiler re-order this code with subsequent code */ - __insn_barrier(); - - return (old); -} - -static __inline int __attribute__((__unused__)) -i80321_spllower(int ipl) -{ - extern __volatile int current_spl_level; - extern int i80321_imask[]; - int old = current_spl_level; - - i80321_splx(i80321_imask[ipl]); - return(old); -} - -#endif -#if !defined(EVBARM_SPL_NOINLINE) - -#define splx(new) i80321_splx(new) -#define _spllower(ipl) i80321_spllower(ipl) -#define _splraise(ipl) i80321_splraise(ipl) -void _setsoftintr(int); - -#else - -int _splraise(int); -int _spllower(int); -void splx(int); -void _setsoftintr(int); - -#endif /* ! EVBARM_SPL_NOINLINE */ - -#endif /* _LOCORE */ - -#endif /* _I80321_INTR_H_ */ diff --git a/sys/arm/xscale/i80321/i80321_mcu.c b/sys/arm/xscale/i80321/i80321_mcu.c deleted file mode 100644 index a51a43348618..000000000000 --- a/sys/arm/xscale/i80321/i80321_mcu.c +++ /dev/null @@ -1,90 +0,0 @@ -/* $NetBSD: i80321_mcu.c,v 1.2 2003/07/15 00:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Intel i80321 I/O Processor memory controller support. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include - -#include -#include - -/* - * i80321_sdram_bounds: - * - * Retrieve the start and size of SDRAM. - */ -void -i80321_sdram_bounds(bus_space_tag_t st, bus_space_handle_t sh, - vm_paddr_t *start, vm_size_t *size) -{ - uint32_t sdbr, sbr0, sbr1; - uint32_t bank0, bank1; - - sdbr = bus_space_read_4(st, sh, MCU_SDBR); - sbr0 = bus_space_read_4(st, sh, MCU_SBR0); - sbr1 = bus_space_read_4(st, sh, MCU_SBR1); - -#ifdef VERBOSE_INIT_ARM - printf("i80321: SBDR = 0x%08x SBR0 = 0x%08x SBR1 = 0x%08x\n", - sdbr, sbr0, sbr1); -#endif - - *start = sdbr; - - sdbr = (sdbr >> 25) & 0x1f; - - sbr0 &= 0x3f; - sbr1 &= 0x3f; - - bank0 = (sbr0 - sdbr) << 25; - bank1 = (sbr1 - sbr0) << 25; - -#ifdef VERBOSE_INIT_ARM - printf("i80321: BANK0 = 0x%08x BANK1 = 0x%08x\n", bank0, bank1); -#endif - - *size = bank0 + bank1; -} diff --git a/sys/arm/xscale/i80321/i80321_pci.c b/sys/arm/xscale/i80321/i80321_pci.c deleted file mode 100644 index 5f78577e8704..000000000000 --- a/sys/arm/xscale/i80321/i80321_pci.c +++ /dev/null @@ -1,401 +0,0 @@ -/* $NetBSD: i80321_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * PCI configuration support for i80321 I/O Processor chip. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "pcib_if.h" - -#include -extern struct i80321_softc *i80321_softc; - -static int -i80321_pci_probe(device_t dev) -{ - device_set_desc(dev, "i80321 PCI bus"); - return (0); -} - -static int -i80321_pci_attach(device_t dev) -{ - - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(dev); - - sc->sc_st = i80321_softc->sc_st; - sc->sc_atu_sh = i80321_softc->sc_atu_sh; - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - sc->sc_dev = dev; - sc->sc_busno = busno; - sc->sc_pciio = &i80321_softc->sc_pci_iot; - sc->sc_pcimem = &i80321_softc->sc_pci_memt; - sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo + - VERDE_OUT_XLATE_MEM_WIN_SIZE; - - sc->sc_io = i80321_softc->sc_iow_vaddr; - /* Initialize memory and i/o rmans. */ - sc->sc_io_rman.rm_type = RMAN_ARRAY; - sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports"; - if (rman_init(&sc->sc_io_rman) != 0 || - rman_manage_region(&sc->sc_io_rman, - sc->sc_io, - sc->sc_io + - VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) { - panic("i80321_pci_probe: failed to set up I/O rman"); - } - sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "I80321 PCI Memory"; - if (rman_init(&sc->sc_mem_rman) != 0 || - rman_manage_region(&sc->sc_mem_rman, - 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) { - panic("i80321_pci_probe: failed to set up memory rman"); - } - sc->sc_irq_rman.rm_type = RMAN_ARRAY; - sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs"; - if (rman_init(&sc->sc_irq_rman) != 0 || - rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0) - panic("i80321_pci_probe: failed to set up IRQ rman"); - device_add_child(dev, "pci", -1); - return (bus_generic_attach(dev)); -} - -static int -i80321_pci_maxslots(device_t dev) -{ - return (PCI_SLOTMAX); -} - - - -static int -i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func, - int reg, uint32_t *addr) -{ - uint32_t busno; - - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - - /* - * If the bus # is the same as our own, then use Type 0 cycles, - * else use Type 1. - * - * XXX We should filter out all non-private devices here! - * XXX How does private space interact with PCI-PCI bridges? - */ - if (bus == busno) { - if (slot > (31 - 16)) - return (1); - /* - * NOTE: PCI-X requires that that devices updated their - * PCIXSR on every config write with the device number - * specified in AD[15:11]. If we don't set this field, - * each device could end of thinking it is at device 0, - * which can cause a number of problems. Doing this - * unconditionally should be OK when only PCI devices - * are present. - */ - bus &= 0xff; - slot &= 0x1f; - func &= 0x07; - - *addr = (1U << (slot + 16)) | - (slot << 11) | (func << 8) | reg; - } else { - *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1; - } - - return (0); -} - -static u_int32_t -i80321_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - uint32_t isr; - uint32_t addr; - u_int32_t ret = 0; - vm_offset_t va; - int err = 0; - if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) - return (-1); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, - addr); - - va = sc->sc_atu_sh; - switch (bytes) { - case 1: - err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 1, &ret); - break; - case 2: - err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 2, &ret); - break; - case 4: - err = badaddr_read((void *)(va + ATU_OCCDR), 4, &ret); - break; - default: - printf("i80321_read_config: invalid size %d\n", bytes); - ret = -1; - } - if (err) { - - isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR, - isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM| - ATUISR_PTAT|ATUISR_PMPE)); - return (-1); - } - return (ret); -} - -static void -i80321_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, u_int32_t data, int bytes) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - uint32_t addr; - - if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) - return; - - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, - addr); - switch (bytes) { - case 1: - bus_space_write_1(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + - (reg & 3), data); - break; - case 2: - bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + - (reg & 3), data); - break; - case 4: - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, data); - break; - default: - printf("i80321_pci_write_config: Invalid size : %d\n", bytes); - } - -} - -static int -i80321_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = 0; - return (0); - case PCIB_IVAR_BUS: - *result = sc->sc_busno; - return (0); - - } - return (ENOENT); -} - -static int -i80321_write_ivar(device_t dev, device_t child, int which, uintptr_t result) -{ - struct i80321_pci_softc * sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - return (EINVAL); - case PCIB_IVAR_BUS: - sc->sc_busno = result; - return (0); - } - return (ENOENT); -} - -static struct resource * -i80321_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct i80321_pci_softc *sc = device_get_softc(bus); - struct resource *rv; - struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; - - switch (type) { - case SYS_RES_IRQ: - rm = &sc->sc_irq_rman; - break; - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - bt = sc->sc_pcimem; - bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 : - sc->sc_mem; - start &= (0x1000000 - 1); - end &= (0x1000000 - 1); - break; - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - bt = sc->sc_pciio; - bh = sc->sc_io; - if (start < sc->sc_io) { - start = start - 0x90000000 + sc->sc_io; - end = end - 0x90000000 + sc->sc_io; - } - break; - default: - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) - return (NULL); - rman_set_rid(rv, *rid); - if (type != SYS_RES_IRQ) { - if (type == SYS_RES_MEMORY) - bh += (rman_get_start(rv)); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (flags & RF_ACTIVE) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } - } - } - return (rv); -} - -static int -i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - u_long p; - int error; - - if (type == SYS_RES_MEMORY) { - error = bus_space_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, &p); - if (error) - return (error); - rman_set_bushandle(r, p); - - } - return (rman_activate_resource(r)); -} - -static int -i80321_pci_setup_intr(device_t dev, device_t child, - struct resource *ires, int flags, driver_filter_t *filt, - driver_intr_t *intr, void *arg, void **cookiep) -{ - return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - filt, intr, arg, cookiep)); -} - -static int -i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); -} - -static device_method_t i80321_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, i80321_pci_probe), - DEVMETHOD(device_attach, i80321_pci_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, i80321_read_ivar), - DEVMETHOD(bus_write_ivar, i80321_write_ivar), - DEVMETHOD(bus_alloc_resource, i80321_pci_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr), - DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, i80321_pci_maxslots), - DEVMETHOD(pcib_read_config, i80321_pci_read_config), - DEVMETHOD(pcib_write_config, i80321_pci_write_config), - DEVMETHOD(pcib_route_interrupt, machdep_pci_route_interrupt), - - DEVMETHOD_END -}; - -static driver_t i80321_pci_driver = { - "pcib", - i80321_pci_methods, - sizeof(struct i80321_pci_softc), -}; - -static devclass_t i80321_pci_devclass; - -DRIVER_MODULE(ipci, iq, i80321_pci_driver, i80321_pci_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_space.c b/sys/arm/xscale/i80321/i80321_space.c deleted file mode 100644 index 64c222522cd2..000000000000 --- a/sys/arm/xscale/i80321/i80321_space.c +++ /dev/null @@ -1,209 +0,0 @@ -/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * bus_space functions for i80321 I/O Processor. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -/* Prototypes for all the bus_space structure functions */ -bs_protos(i80321); -bs_protos(i80321_io); -bs_protos(i80321_mem); - -void -i80321_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; -} - -void -i80321_io_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; - - bs->bs_map = i80321_io_bs_map; - bs->bs_unmap = i80321_io_bs_unmap; - bs->bs_alloc = i80321_io_bs_alloc; - bs->bs_free = i80321_io_bs_free; - -} - -void -i80321_mem_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; - - bs->bs_map = i80321_mem_bs_map; - bs->bs_unmap = i80321_mem_bs_unmap; - bs->bs_alloc = i80321_mem_bs_alloc; - bs->bs_free = i80321_mem_bs_free; - -} - -/* *** Routines shared by i80321, PCI IO, and PCI MEM. *** */ - -int -i80321_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, - bus_size_t size, bus_space_handle_t *nbshp) -{ - - *nbshp = bsh + offset; - return (0); -} - -void -i80321_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, - bus_size_t len, int flags) -{ - - /* Nothing to do. */ -} - -/* *** Routines for PCI IO. *** */ - -extern struct i80321_softc *i80321_softc; -int -i80321_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, - bus_space_handle_t *bshp) -{ - struct i80321_softc *sc = i80321_softc; - vm_offset_t winvaddr; - uint32_t busbase; - - if (bpa >= sc->sc_ioout_xlate && - bpa < (sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE)) { - busbase = sc->sc_ioout_xlate; - winvaddr = sc->sc_iow_vaddr; - } else - return (EINVAL); - - if ((bpa + size) >= (busbase + VERDE_OUT_XLATE_IO_WIN_SIZE)) - return (EINVAL); - - /* - * Found the window -- PCI I/O space is mapped at a fixed - * virtual address by board-specific code. Translate the - * bus address to the virtual address. - */ - *bshp = winvaddr + (bpa - busbase); - - return (0); -} - -void -i80321_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) -{ - - /* Nothing to do. */ -} - -int -i80321_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, - bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, - bus_addr_t *bpap, bus_space_handle_t *bshp) -{ - - panic("i80321_io_bs_alloc(): not implemented"); -} - -void -i80321_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) -{ - - panic("i80321_io_bs_free(): not implemented"); -} - - -/* *** Routines for PCI MEM. *** */ -extern int badaddr_read(void *, int, void *); -int -i80321_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, - bus_space_handle_t *bshp) -{ - - *bshp = (vm_offset_t)pmap_mapdev(bpa, size); - return (0); -} - -void -i80321_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) -{ - - pmap_unmapdev((vm_offset_t)h, size); -} - -int -i80321_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, - bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, - bus_addr_t *bpap, bus_space_handle_t *bshp) -{ - - panic("i80321_mem_bs_alloc(): not implemented"); -} - -void -i80321_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) -{ - - panic("i80321_mem_bs_free(): not implemented"); -} diff --git a/sys/arm/xscale/i80321/i80321_timer.c b/sys/arm/xscale/i80321/i80321_timer.c deleted file mode 100644 index 3b4e5a11b552..000000000000 --- a/sys/arm/xscale/i80321/i80321_timer.c +++ /dev/null @@ -1,485 +0,0 @@ -/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Timer/clock support for the Intel i80321 I/O processor. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CPU_XSCALE_81342 -#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because - definitions overrides the ones from i80321reg.h - */ -#endif -#include "opt_timer.h" - -void (*i80321_hardclock_hook)(void) = NULL; -struct i80321_timer_softc { - device_t dev; -} timer_softc; - - -static unsigned i80321_timer_get_timecount(struct timecounter *tc); - - -static uint32_t counts_per_hz; - -#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) -static uint32_t offset; -static uint32_t last = -1; -#endif - -static int ticked = 0; - -#ifndef COUNTS_PER_SEC -#define COUNTS_PER_SEC 200000000 /* 200MHz */ -#endif - -#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000) - -static struct timecounter i80321_timer_timecounter = { - i80321_timer_get_timecount, /* get_timecount */ - NULL, /* no poll_pps */ - ~0u, /* counter_mask */ -#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) - COUNTS_PER_SEC, -#else - COUNTS_PER_SEC * 3, /* frequency */ -#endif - "i80321 timer", /* name */ - 1000 /* quality */ -}; - -static int -i80321_timer_probe(device_t dev) -{ - - device_set_desc(dev, "i80321 timer"); - return (0); -} - -static int -i80321_timer_attach(device_t dev) -{ - timer_softc.dev = dev; - - return (0); -} - -static device_method_t i80321_timer_methods[] = { - DEVMETHOD(device_probe, i80321_timer_probe), - DEVMETHOD(device_attach, i80321_timer_attach), - {0, 0}, -}; - -static driver_t i80321_timer_driver = { - "itimer", - i80321_timer_methods, - sizeof(struct i80321_timer_softc), -}; -static devclass_t i80321_timer_devclass; - -DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0); - -int clockhandler(void *); - - -static __inline uint32_t -tmr1_read(void) -{ - uint32_t rv; - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mrc p6, 0, %0, c1, c9, 0" -#else - __asm __volatile("mrc p6, 0, %0, c1, c1, 0" -#endif - : "=r" (rv)); - return (rv); -} - -static __inline void -tmr1_write(uint32_t val) -{ - - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c1, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c1, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline uint32_t -tcr1_read(void) -{ - uint32_t rv; - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mrc p6, 0, %0, c3, c9, 0" -#else - __asm __volatile("mrc p6, 0, %0, c3, c1, 0" -#endif - : "=r" (rv)); - return (rv); -} -static __inline void -tcr1_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c3, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c3, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline void -trr1_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c5, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c5, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline uint32_t -tmr0_read(void) -{ - uint32_t rv; - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mrc p6, 0, %0, c0, c9, 0" -#else - __asm __volatile("mrc p6, 0, %0, c0, c1, 0" -#endif - : "=r" (rv)); - return (rv); -} - -static __inline void -tmr0_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c0, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c0, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline uint32_t -tcr0_read(void) -{ - uint32_t rv; - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mrc p6, 0, %0, c2, c9, 0" -#else - __asm __volatile("mrc p6, 0, %0, c2, c1, 0" -#endif - : "=r" (rv)); - return (rv); -} -static __inline void -tcr0_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c2, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c2, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline void -trr0_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c4, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c4, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline void -tisr_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c6, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c6, c1, 0" -#endif - : - : "r" (val)); -} - -static __inline uint32_t -tisr_read(void) -{ - int ret; - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mrc p6, 0, %0, c6, c9, 0" : "=r" (ret)); -#else - __asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret)); -#endif - return (ret); -} - -static unsigned -i80321_timer_get_timecount(struct timecounter *tc) -{ -#if defined(XSCALE_DISABLE_CCNT) || defined(CPU_XSCALE_81342) - uint32_t cur = tcr0_read(); - - if (cur > last && last != -1) { - offset += counts_per_hz; - if (ticked > 0) - ticked--; - } - if (ticked) { - offset += ticked * counts_per_hz; - ticked = 0; - } - return (counts_per_hz - cur + offset); -#else - uint32_t ret; - - __asm __volatile("mrc p14, 0, %0, c1, c0, 0\n" - : "=r" (ret)); - return (ret); -#endif -} - -/* - * i80321_calibrate_delay: - * - * Calibrate the delay loop. - */ -void -i80321_calibrate_delay(void) -{ - - /* - * Just use hz=100 for now -- we'll adjust it, if necessary, - * in cpu_initclocks(). - */ - counts_per_hz = COUNTS_PER_SEC / 100; - - tmr0_write(0); /* stop timer */ - tisr_write(TISR_TMR0); /* clear interrupt */ - trr0_write(counts_per_hz); /* reload value */ - tcr0_write(counts_per_hz); /* current value */ - - tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); -} - -/* - * cpu_initclocks: - * - * Initialize the clock and get them going. - */ -void -cpu_initclocks(void) -{ - u_int oldirqstate; - struct resource *irq; - int rid = 0; - void *ihl; - device_t dev = timer_softc.dev; - - if (hz < 50 || COUNTS_PER_SEC % hz) { - printf("Cannot get %d Hz clock; using 100 Hz\n", hz); - hz = 100; - } - tick = 1000000 / hz; /* number of microseconds between interrupts */ - - /* - * We only have one timer available; stathz and profhz are - * always left as 0 (the upper-layer clock code deals with - * this situation). - */ - if (stathz != 0) - printf("Cannot get %d Hz statclock\n", stathz); - stathz = 0; - - if (profhz != 0) - printf("Cannot get %d Hz profclock\n", profhz); - profhz = 0; - - /* Report the clock frequency. */ - - oldirqstate = disable_interrupts(PSR_I); - - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, -#ifdef CPU_XSCALE_81342 - ICU_INT_TIMER0, ICU_INT_TIMER0, -#else - ICU_INT_TMR0, ICU_INT_TMR0, -#endif - 1, RF_ACTIVE); - if (!irq) - panic("Unable to setup the clock irq handler.\n"); - else - bus_setup_intr(dev, irq, INTR_TYPE_CLK, clockhandler, NULL, - NULL, &ihl); - tmr0_write(0); /* stop timer */ - tisr_write(TISR_TMR0); /* clear interrupt */ - - counts_per_hz = COUNTS_PER_SEC / hz; - - trr0_write(counts_per_hz); /* reload value */ - tcr0_write(counts_per_hz); /* current value */ - tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE); - - tc_init(&i80321_timer_timecounter); - restore_interrupts(oldirqstate); - rid = 0; -#if !defined(XSCALE_DISABLE_CCNT) && !defined(CPU_XSCALE_81342) - /* Enable the clock count register. */ - __asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid)); - rid &= ~(1 << 3); - rid |= (1 << 2) | 1; - __asm __volatile("mcr p14, 0, %0, c0, c0, 0\n" - : : "r" (rid)); -#endif -} - - -/* - * DELAY: - * - * Delay for at least N microseconds. - */ -void -DELAY(int n) -{ - uint32_t cur, last, delta, usecs; - - /* - * This works by polling the timer and counting the - * number of microseconds that go by. - */ - last = tcr0_read(); - delta = usecs = 0; - - while (n > usecs) { - cur = tcr0_read(); - - /* Check to see if the timer has wrapped around. */ - if (last < cur) - delta += (last + (counts_per_hz - cur)); - else - delta += (last - cur); - - last = cur; - - if (delta >= COUNTS_PER_USEC) { - usecs += delta / COUNTS_PER_USEC; - delta %= COUNTS_PER_USEC; - } - } -} - -/* - * clockhandler: - * - * Handle the hardclock interrupt. - */ -int -clockhandler(void *arg) -{ - struct trapframe *frame = arg; - - ticked++; - tisr_write(TISR_TMR0); - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); - - if (i80321_hardclock_hook != NULL) - (*i80321_hardclock_hook)(); - return (FILTER_HANDLED); -} - -void -cpu_startprofclock(void) -{ -} - -void -cpu_stopprofclock(void) -{ - -} diff --git a/sys/arm/xscale/i80321/i80321_wdog.c b/sys/arm/xscale/i80321/i80321_wdog.c deleted file mode 100644 index 9be98d2f7e25..000000000000 --- a/sys/arm/xscale/i80321/i80321_wdog.c +++ /dev/null @@ -1,154 +0,0 @@ -/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2005 Olivier Houchard - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Watchdog timer support for the Intel i80321 I/O processor. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -struct iopwdog_softc { - device_t dev; - int armed; - int wdog_period; -}; - -static __inline void -wdtcr_write(uint32_t val) -{ - -#ifdef CPU_XSCALE_81342 - __asm __volatile("mcr p6, 0, %0, c7, c9, 0" -#else - __asm __volatile("mcr p6, 0, %0, c7, c1, 0" -#endif - : - : "r" (val)); -} - -static void -iopwdog_tickle(void *arg) -{ - struct iopwdog_softc *sc = arg; - - if (!sc->armed) - return; - wdtcr_write(WDTCR_ENABLE1); - wdtcr_write(WDTCR_ENABLE2); -} - -static int -iopwdog_probe(device_t dev) -{ - struct iopwdog_softc *sc = device_get_softc(dev); - char buf[128]; - - /* - * XXX Should compute the period based on processor speed. - * For a 600MHz XScale core, the wdog must be tickled approx. - * every 7 seconds. - */ - - sc->wdog_period = 7; - sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds", - sc->wdog_period); - device_set_desc_copy(dev, buf); - - return (0); -} - -static void -iopwdog_watchdog_fn(void *private, u_int cmd, int *error) -{ - struct iopwdog_softc *sc = private; - - cmd &= WD_INTERVAL; - if (cmd > 0 && cmd <= 63 - && (uint64_t)1<wdog_period * 1000000000) { - /* Valid value -> Enable watchdog */ - iopwdog_tickle(sc); - sc->armed = 1; - *error = 0; - } else { - /* Can't disable this watchdog! */ - if (sc->armed) - *error = EOPNOTSUPP; - } -} - -static int -iopwdog_attach(device_t dev) -{ - struct iopwdog_softc *sc = device_get_softc(dev); - - sc->dev = dev; - sc->armed = 0; - EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0); - return (0); -} - -static device_method_t iopwdog_methods[] = { - DEVMETHOD(device_probe, iopwdog_probe), - DEVMETHOD(device_attach, iopwdog_attach), - {0, 0}, -}; - -static driver_t iopwdog_driver = { - "iopwdog", - iopwdog_methods, - sizeof(struct iopwdog_softc), -}; -static devclass_t iopwdog_devclass; - -DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321reg.h b/sys/arm/xscale/i80321/i80321reg.h deleted file mode 100644 index 53617f956582..000000000000 --- a/sys/arm/xscale/i80321/i80321reg.h +++ /dev/null @@ -1,547 +0,0 @@ -/* $NetBSD: i80321reg.h,v 1.14 2003/12/19 10:08:11 gavan Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _ARM_XSCALE_I80321REG_H_ -#define _ARM_XSCALE_I80321REG_H_ - -/* - * Register definitions for the Intel 80321 (``Verde'') I/O processor, - * based on the XScale core. - */ - -/* - * Base i80321 memory map: - * - * 0x0000.0000 - 0x7fff.ffff ATU Outbound Direct Addressing Window - * 0x8000.0000 - 0x9001.ffff ATU Outbound Translation Windows - * 0x9002.0000 - 0xffff.dfff External Memory - * 0xffff.e000 - 0xffff.e8ff Peripheral Memory Mapped Registers - * 0xffff.e900 - 0xffff.ffff Reserved - */ - -#define VERDE_OUT_DIRECT_WIN_BASE 0x00000000UL -#define VERDE_OUT_DIRECT_WIN_SIZE 0x80000000UL - -#define VERDE_OUT_XLATE_MEM_WIN_SIZE 0x04000000UL -#define VERDE_OUT_XLATE_IO_WIN_SIZE 0x00010000UL - -#define VERDE_OUT_XLATE_MEM_WIN0_BASE 0x80000000UL -#define VERDE_OUT_XLATE_MEM_WIN1_BASE 0x84000000UL - -#define VERDE_OUT_XLATE_IO_WIN0_BASE 0x90000000UL - -#define VERDE_EXTMEM_BASE 0x90020000UL - -#define VERDE_PMMR_BASE 0xffffe000UL -#define VERDE_PMMR_SIZE 0x00001700UL - -/* - * Peripheral Memory Mapped Registers. Defined as offsets - * from the VERDE_PMMR_BASE. - */ -#define VERDE_ATU_BASE 0x0100 -#define VERDE_ATU_SIZE 0x0100 - -#define VERDE_MU_BASE 0x0300 -#define VERDE_MU_SIZE 0x0100 - -#define VERDE_DMA_BASE 0x0400 -#define VERDE_DMA_BASE0 (VERDE_DMA_BASE + 0x00) -#define VERDE_DMA_BASE1 (VERDE_DMA_BASE + 0x40) -#define VERDE_DMA_SIZE 0x0100 -#define VERDE_DMA_CHSIZE 0x0040 - -#define VERDE_MCU_BASE 0x0500 -#define VERDE_MCU_SIZE 0x0100 - -#if defined(CPU_XSCALE_80321) -#define VERDE_SSP_BASE 0x0600 -#define VERDE_SSP_SIZE 0x0080 -#endif - -#define VERDE_PBIU_BASE 0x0680 -#define VERDE_PBIU_SIZE 0x0080 - -#if defined(CPU_XSCALE_80321) -#define VERDE_AAU_BASE 0x0800 -#define VERDE_AAU_SIZE 0x0100 -#endif - -#define VERDE_I2C_BASE 0x1680 -#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00) -#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20) -#define VERDE_I2C_SIZE 0x0080 -#define VERDE_I2C_CHSIZE 0x0020 - -/* - * Address Translation Unit - */ - /* 0x00 - 0x38 -- PCI configuration space header */ -#define ATU_IALR0 0x40 /* Inbound ATU Limit 0 */ -#define ATU_IATVR0 0x44 /* Inbound ATU Xlate Value 0 */ -#define ATU_ERLR 0x48 /* Expansion ROM Limit */ -#define ATU_ERTVR 0x4c /* Expansion ROM Xlate Value */ -#define ATU_IALR1 0x50 /* Inbound ATU Limit 1 */ -#define ATU_IALR2 0x54 /* Inbound ATU Limit 2 */ -#define ATU_IATVR2 0x58 /* Inbound ATU Xlate Value 2 */ -#define ATU_OIOWTVR 0x5c /* Outbound I/O Window Xlate Value */ -#define ATU_OMWTVR0 0x60 /* Outbound Mem Window Xlate Value 0 */ -#define ATU_OUMWTVR0 0x64 /* Outbound Mem Window Xlate Value 0 Upper */ -#define ATU_OMWTVR1 0x68 /* Outbound Mem Window Xlate Value 1 */ -#define ATU_OUMWTVR1 0x6c /* Outbound Mem Window Xlate Value 1 Upper */ -#define ATU_OUDWTVR 0x78 /* Outbound Mem Direct Xlate Value Upper */ -#define ATU_ATUCR 0x80 /* ATU Configuration */ -#define ATU_PCSR 0x84 /* PCI Configuration and Status */ -#define ATU_ATUISR 0x88 /* ATU Interrupt Status */ -#define ATU_ATUIMR 0x8c /* ATU Interrupt Mask */ -#define ATU_IABAR3 0x90 /* Inbound ATU Base Address 3 */ -#define ATU_IAUBAR3 0x94 /* Inbound ATU Base Address 3 Upper */ -#define ATU_IALR3 0x98 /* Inbound ATU Limit 3 */ -#define ATU_IATVR3 0x9c /* Inbound ATU Xlate Value 3 */ -#define ATU_OCCAR 0xa4 /* Outbound Configuration Cycle Address */ -#define ATU_OCCDR 0xac /* Outbound Configuration Cycle Data */ -#define ATU_MSI_PORT 0xb4 /* MSI port */ -#define ATU_PDSCR 0xbc /* PCI Bus Drive Strength Control */ -#define ATU_PCI_X_CAP_ID 0xe0 /* (1) */ -#define ATU_PCI_X_NEXT 0xe1 /* (1) */ -#define ATU_PCIXCMD 0xe2 /* PCI-X Command Register (2) */ -#define ATU_PCIXSR 0xe4 /* PCI-X Status Register */ - -#define ATUCR_DRC_ALIAS (1U << 19) -#define ATUCR_DAU2GXEN (1U << 18) -#define ATUCR_P_SERR_MA (1U << 16) -#define ATUCR_DTS (1U << 15) -#define ATUCR_P_SERR_DIE (1U << 9) -#define ATUCR_DAE (1U << 8) -#define ATUCR_BIST_IE (1U << 3) -#define ATUCR_OUT_EN (1U << 1) - -#define PCSR_DAAAPE (1U << 18) -#define PCSR_PCI_X_CAP (3U << 16) -#define PCSR_PCI_X_CAP_BORING (0 << 16) -#define PCSR_PCI_X_CAP_66 (1U << 16) -#define PCSR_PCI_X_CAP_100 (2U << 16) -#define PCSR_PCI_X_CAP_133 (3U << 16) -#define PCSR_OTQB (1U << 15) -#define PCSR_IRTQB (1U << 14) -#define PCSR_DTV (1U << 12) -#define PCSR_BUS66 (1U << 10) -#define PCSR_BUS64 (1U << 8) -#define PCSR_RIB (1U << 5) -#define PCSR_RPB (1U << 4) -#define PCSR_CCR (1U << 2) -#define PCSR_CPR (1U << 1) - -#define ATUISR_IMW1BU (1U << 14) -#define ATUISR_ISCEM (1U << 13) -#define ATUISR_RSCEM (1U << 12) -#define ATUISR_PST (1U << 11) -#define ATUISR_P_SERR_ASRT (1U << 10) -#define ATUISR_DPE (1U << 9) -#define ATUISR_BIST (1U << 8) -#define ATUISR_IBMA (1U << 7) -#define ATUISR_P_SERR_DET (1U << 4) -#define ATUISR_PMA (1U << 3) -#define ATUISR_PTAM (1U << 2) -#define ATUISR_PTAT (1U << 1) -#define ATUISR_PMPE (1U << 0) - -#define ATUIMR_IMW1BU (1U << 11) -#define ATUIMR_ISCEM (1U << 10) -#define ATUIMR_RSCEM (1U << 9) -#define ATUIMR_PST (1U << 8) -#define ATUIMR_DPE (1U << 7) -#define ATUIMR_P_SERR_ASRT (1U << 6) -#define ATUIMR_PMA (1U << 5) -#define ATUIMR_PTAM (1U << 4) -#define ATUIMR_PTAT (1U << 3) -#define ATUIMR_PMPE (1U << 2) -#define ATUIMR_IE_SERR_EN (1U << 1) -#define ATUIMR_ECC_TAE (1U << 0) - -#define PCIXCMD_MOST_1 (0 << 4) -#define PCIXCMD_MOST_2 (1 << 4) -#define PCIXCMD_MOST_3 (2 << 4) -#define PCIXCMD_MOST_4 (3 << 4) -#define PCIXCMD_MOST_8 (4 << 4) -#define PCIXCMD_MOST_12 (5 << 4) -#define PCIXCMD_MOST_16 (6 << 4) -#define PCIXCMD_MOST_32 (7 << 4) -#define PCIXCMD_MOST_MASK (7 << 4) -#define PCIXCMD_MMRBC_512 (0 << 2) -#define PCIXCMD_MMRBC_1024 (1 << 2) -#define PCIXCMD_MMRBC_2048 (2 << 2) -#define PCIXCMD_MMRBC_4096 (3 << 2) -#define PCIXCMD_MMRBC_MASK (3 << 2) -#define PCIXCMD_ERO (1U << 1) -#define PCIXCMD_DPERE (1U << 0) - -#define PCIXSR_RSCEM (1U << 29) -#define PCIXSR_DMCRS_MASK (7 << 26) -#define PCIXSR_DMOST_MASK (7 << 23) -#define PCIXSR_COMPLEX (1U << 20) -#define PCIXSR_USC (1U << 19) -#define PCIXSR_SCD (1U << 18) -#define PCIXSR_133_CAP (1U << 17) -#define PCIXSR_32PCI (1U << 16) /* 0 = 32, 1 = 64 */ -#define PCIXSR_BUSNO(x) (((x) & 0xff00) >> 8) -#define PCIXSR_DEVNO(x) (((x) & 0xf8) >> 3) -#define PCIXSR_FUNCNO(x) ((x) & 0x7) - -/* - * Memory Controller Unit - */ -#define MCU_SDIR 0x00 /* DDR SDRAM Init. Register */ -#define MCU_SDCR 0x04 /* DDR SDRAM Control Register */ -#define MCU_SDBR 0x08 /* SDRAM Base Register */ -#define MCU_SBR0 0x0c /* SDRAM Boundary 0 */ -#define MCU_SBR1 0x10 /* SDRAM Boundary 1 */ -#define MCU_ECCR 0x34 /* ECC Control Register */ -#define MCU_ELOG0 0x38 /* ECC Log 0 */ -#define MCU_ELOG1 0x3c /* ECC Log 1 */ -#define MCU_ECAR0 0x40 /* ECC address 0 */ -#define MCU_ECAR1 0x44 /* ECC address 1 */ -#define MCU_ECTST 0x48 /* ECC test register */ -#define MCU_MCISR 0x4c /* MCU Interrupt Status Register */ -#define MCU_RFR 0x50 /* Refresh Frequency Register */ -#define MCU_DBUDSR 0x54 /* Data Bus Pull-up Drive Strength */ -#define MCU_DBDDSR 0x58 /* Data Bus Pull-down Drive Strength */ -#define MCU_CUDSR 0x5c /* Clock Pull-up Drive Strength */ -#define MCU_CDDSR 0x60 /* Clock Pull-down Drive Strength */ -#define MCU_CEUDSR 0x64 /* Clock En Pull-up Drive Strength */ -#define MCU_CEDDSR 0x68 /* Clock En Pull-down Drive Strength */ -#define MCU_CSUDSR 0x6c /* Chip Sel Pull-up Drive Strength */ -#define MCU_CSDDSR 0x70 /* Chip Sel Pull-down Drive Strength */ -#define MCU_REUDSR 0x74 /* Rx En Pull-up Drive Strength */ -#define MCU_REDDSR 0x78 /* Rx En Pull-down Drive Strength */ -#define MCU_ABUDSR 0x7c /* Addr Bus Pull-up Drive Strength */ -#define MCU_ABDDSR 0x80 /* Addr Bus Pull-down Drive Strength */ -#define MCU_DSDR 0x84 /* Data Strobe Delay Register */ -#define MCU_REDR 0x88 /* Rx Enable Delay Register */ - -#define SDCR_DIMMTYPE (1U << 1) /* 0 = unbuf, 1 = reg */ -#define SDCR_BUSWIDTH (1U << 2) /* 0 = 64, 1 = 32 */ - -#define SBRx_TECH (1U << 31) -#define SBRx_BOUND 0x0000003f - -#define ECCR_SBERE (1U << 0) -#define ECCR_MBERE (1U << 1) -#define ECCR_SBECE (1U << 2) -#define ECCR_ECCEN (1U << 3) - -#define ELOGx_SYNDROME 0x000000ff -#define ELOGx_ERRTYPE (1U << 8) /* 1 = multi-bit */ -#define ELOGx_RW (1U << 12) /* 1 = write error */ - /* - * Dev ID Func Requester - * 2 0 XScale core - * 2 1 ATU - * 13 0 DMA channel 0 - * 13 1 DMA channel 1 - * 26 0 ATU - */ -#define ELOGx_REQ_DEV(x) (((x) >> 19) & 0x1f) -#define ELOGx_REQ_FUNC(x) (((x) >> 16) & 0x3) - -#define MCISR_ECC_ERR0 (1U << 0) -#define MCISR_ECC_ERR1 (1U << 1) -#define MCISR_ECC_ERRN (1U << 2) - -/* - * Timers - * - * The i80321 timer registers are available in both memory-mapped - * and coprocessor spaces. Most of the registers are read-only - * if memory-mapped, so we access them via coprocessor space. - * - * TMR0 cp6 c0,1 0xffffe7e0 - * TMR1 cp6 c1,1 0xffffe7e4 - * TCR0 cp6 c2,1 0xffffe7e8 - * TCR1 cp6 c3,1 0xffffe7ec - * TRR0 cp6 c4,1 0xffffe7f0 - * TRR1 cp6 c5,1 0xffffe7f4 - * TISR cp6 c6,1 0xffffe7f8 - * WDTCR cp6 c7,1 0xffffe7fc - */ - -#define TMRx_TC (1U << 0) -#define TMRx_ENABLE (1U << 1) -#define TMRx_RELOAD (1U << 2) -#define TMRx_CSEL_CORE (0 << 4) -#define TMRx_CSEL_CORE_div4 (1 << 4) -#define TMRx_CSEL_CORE_div8 (2 << 4) -#define TMRx_CSEL_CORE_div16 (3 << 4) - -#define TISR_TMR0 (1U << 0) -#define TISR_TMR1 (1U << 1) - -#define WDTCR_ENABLE1 0x1e1e1e1e -#define WDTCR_ENABLE2 0xe1e1e1e1 - -/* - * Interrupt Controller Unit. - * - * INTCTL cp6 c0,0 0xffffe7d0 - * INTSTR cp6 c4,0 0xffffe7d4 - * IINTSRC cp6 c8,0 0xffffe7d8 - * FINTSRC cp6 c9,0 0xffffe7dc - * PIRSR 0xffffe1ec - */ - -#define ICU_PIRSR 0x01ec -#define ICU_GPOE 0x07c4 -#define ICU_GPID 0x07c8 -#define ICU_GPOD 0x07cc - -/* - * NOTE: WE USE THE `bitXX' BITS TO INDICATE PENDING SOFTWARE - * INTERRUPTS. See i80321_icu.c - */ -#define ICU_INT_HPI 31 /* high priority interrupt */ -#define ICU_INT_XINT0 27 /* external interrupts */ -#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0) -#define ICU_INT_bit26 26 - -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit25 25 /* reserved */ -#else -/* CPU_XSCALE_80321 */ -#define ICU_INT_SSP 25 /* SSP serial port */ -#endif - -#define ICU_INT_MUE 24 /* msg unit error */ - -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit23 23 /* reserved */ -#else -/* CPU_XSCALE_80321 */ -#define ICU_INT_AAUE 23 /* AAU error */ -#endif - -#define ICU_INT_bit22 22 -#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ -#define ICU_INT_DMA0E 20 /* DMA Ch 0 error */ -#define ICU_INT_MCUE 19 /* memory controller error */ -#define ICU_INT_ATUE 18 /* ATU error */ -#define ICU_INT_BIUE 17 /* bus interface unit error */ -#define ICU_INT_PMU 16 /* XScale PMU */ -#define ICU_INT_PPM 15 /* peripheral PMU */ -#define ICU_INT_BIST 14 /* ATU Start BIST */ -#define ICU_INT_MU 13 /* messaging unit */ -#define ICU_INT_I2C1 12 /* i2c unit 1 */ -#define ICU_INT_I2C0 11 /* i2c unit 0 */ -#define ICU_INT_TMR1 10 /* timer 1 */ -#define ICU_INT_TMR0 9 /* timer 0 */ -#define ICU_INT_CPPM 8 /* core processor PMU */ - -#if defined(CPU_XSCALE_80219) -#define ICU_INT_bit7 7 /* reserved */ -#define ICU_INT_bit6 6 /* reserved */ -#else -/* CPU_XSCALE_80321 */ -#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ -#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ -#endif - -#define ICU_INT_bit5 5 -#define ICU_INT_bit4 4 -#define ICU_INT_DMA1_EOC 3 /* DMA1 end-of-chain */ -#define ICU_INT_DMA1_EOT 2 /* DMA1 end-of-transfer */ -#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */ -#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ - -#if defined (CPU_XSCALE_80219) -#define ICU_INT_HWMASK (0xffffffff & \ - ~((1 << ICU_INT_bit26) | \ - (1 << ICU_INT_bit25) | \ - (1 << ICU_INT_bit23) | \ - (1 << ICU_INT_bit22) | \ - (1 << ICU_INT_bit7) | \ - (1 << ICU_INT_bit6) | \ - (1 << ICU_INT_bit5) | \ - (1 << ICU_INT_bit4))) - -#else -/* CPU_XSCALE_80321 */ -#define ICU_INT_HWMASK (0xffffffff & \ - ~((1 << ICU_INT_bit26) | \ - (1 << ICU_INT_bit22) | \ - (1 << ICU_INT_bit5) | \ - (1 << ICU_INT_bit4))) -#endif - -/* - * SSP Serial Port - */ -#if defined (CPU_XSCALE_80321) - -#define SSP_SSCR0 0x00 /* SSC control 0 */ -#define SSP_SSCR1 0x04 /* SSC control 1 */ -#define SSP_SSSR 0x08 /* SSP status */ -#define SSP_SSITR 0x0c /* SSP interrupt test */ -#define SSP_SSDR 0x10 /* SSP data */ - -#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */ -#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */ -#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */ -#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */ -#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */ -#define SSP_SSCR0_ECS (1U << 6)/* external clock select */ -#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */ -#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */ - /* bit rate = 3.6864 * 10e6 / - (2 * (SCR + 1)) */ - -#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */ -#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */ -#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */ -#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */ -#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase: - 0 = inactive full at start, - 1/2 at end of frame - 1 = inactive 1/2 at start, - full at end of frame */ -#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size: - 0 = 8 bit - 1 = 16 bit */ -#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */ -#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */ -#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */ -#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select: - 0 = Tx FIFO - 1 = Rx FIFO */ - -#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */ -#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */ -#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */ -#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */ -#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */ -#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */ -#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */ -#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */ - -#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */ -#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */ -#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */ - -#endif /* CPU_XSCALE_80321 */ - -/* - * Peripheral Bus Interface Unit - */ - -#define PBIU_PBCR 0x00 /* PBIU Control Register */ -#define PBIU_PBBAR0 0x08 /* PBIU Base Address Register 0 */ -#define PBIU_PBLR0 0x0c /* PBIU Limit Register 0 */ -#define PBIU_PBBAR1 0x10 /* PBIU Base Address Register 1 */ -#define PBIU_PBLR1 0x14 /* PBIU Limit Register 1 */ -#define PBIU_PBBAR2 0x18 /* PBIU Base Address Register 2 */ -#define PBIU_PBLR2 0x1c /* PBIU Limit Register 2 */ -#define PBIU_PBBAR3 0x20 /* PBIU Base Address Register 3 */ -#define PBIU_PBLR3 0x24 /* PBIU Limit Register 3 */ -#define PBIU_PBBAR4 0x28 /* PBIU Base Address Register 4 */ -#define PBIU_PBLR4 0x2c /* PBIU Limit Register 4 */ -#define PBIU_PBBAR5 0x30 /* PBIU Base Address Register 5 */ -#define PBIU_PBLR5 0x34 /* PBIU Limit Register 5 */ -#define PBIU_DSCR 0x38 /* PBIU Drive Strength Control Reg. */ -#define PBIU_MBR0 0x40 /* PBIU Memory-less Boot Reg. 0 */ -#define PBIU_MBR1 0x60 /* PBIU Memory-less Boot Reg. 1 */ -#define PBIU_MBR2 0x64 /* PBIU Memory-less Boot Reg. 2 */ - -#define PBIU_PBCR_PBIEN (1 << 0) -#define PBIU_PBCR_PBI100 (1 << 1) -#define PBIU_PBCR_PBI66 (2 << 1) -#define PBIU_PBCR_PBI33 (3 << 1) -#define PBIU_PBCR_PBBEN (1 << 3) - -#define PBIU_PBARx_WIDTH8 (0 << 0) -#define PBIU_PBARx_WIDTH16 (1 << 0) -#define PBIU_PBARx_WIDTH32 (2 << 0) -#define PBIU_PBARx_ADWAIT4 (0 << 2) -#define PBIU_PBARx_ADWAIT8 (1 << 2) -#define PBIU_PBARx_ADWAIT12 (2 << 2) -#define PBIU_PBARx_ADWAIT16 (3 << 2) -#define PBIU_PBARx_ADWAIT20 (4 << 2) -#define PBIU_PBARx_RCWAIT1 (0 << 6) -#define PBIU_PBARx_RCWAIT4 (1 << 6) -#define PBIU_PBARx_RCWAIT8 (2 << 6) -#define PBIU_PBARx_RCWAIT12 (3 << 6) -#define PBIU_PBARx_RCWAIT16 (4 << 6) -#define PBIU_PBARx_RCWAIT20 (5 << 6) -#define PBIU_PBARx_FWE (1 << 9) -#define PBIU_BASE_MASK 0xfffff000U - -#define PBIU_PBLRx_SIZE(x) (~((x) - 1)) - -/* - * Messaging Unit - */ -#define MU_IMR0 0x0010 /* MU Inbound Message Register 0 */ -#define MU_IMR1 0x0014 /* MU Inbound Message Register 1 */ -#define MU_OMR0 0x0018 /* MU Outbound Message Register 0 */ -#define MU_OMR1 0x001c /* MU Outbound Message Register 1 */ -#define MU_IDR 0x0020 /* MU Inbound Doorbell Register */ -#define MU_IISR 0x0024 /* MU Inbound Interrupt Status Reg */ -#define MU_IIMR 0x0028 /* MU Inbound Interrupt Mask Reg */ -#define MU_ODR 0x002c /* MU Outbound Doorbell Register */ -#define MU_OISR 0x0030 /* MU Outbound Interrupt Status Reg */ -#define MU_OIMR 0x0034 /* MU Outbound Interrupt Mask Reg */ -#define MU_MUCR 0x0050 /* MU Configuration Register */ -#define MU_QBAR 0x0054 /* MU Queue Base Address Register */ -#define MU_IFHPR 0x0060 /* MU Inbound Free Head Pointer Reg */ -#define MU_IFTPR 0x0064 /* MU Inbound Free Tail Pointer Reg */ -#define MU_IPHPR 0x0068 /* MU Inbound Post Head Pointer Reg */ -#define MU_IPTPR 0x006c /* MU Inbound Post Tail Pointer Reg */ -#define MU_OFHPR 0x0070 /* MU Outbound Free Head Pointer Reg */ -#define MU_OFTPR 0x0074 /* MU Outbound Free Tail Pointer Reg */ -#define MU_OPHPR 0x0078 /* MU Outbound Post Head Pointer Reg */ -#define MU_OPTPR 0x007c /* MU Outbound Post Tail Pointer Reg */ -#define MU_IAR 0x0080 /* MU Index Address Register */ - -#define MU_IIMR_IRI (1 << 6) /* Index Register Interrupt */ -#define MU_IIMR_OFQFI (1 << 5) /* Outbound Free Queue Full Int. */ -#define MU_IIMR_IPQI (1 << 4) /* Inbound Post Queue Interrupt */ -#define MU_IIMR_EDI (1 << 3) /* Error Doorbell Interrupt */ -#define MU_IIMR_IDI (1 << 2) /* Inbound Doorbell Interrupt */ -#define MU_IIMR_IM1I (1 << 1) /* Inbound Message 1 Interrupt */ -#define MU_IIMR_IM0I (1 << 0) /* Inbound Message 0 Interrupt */ - -#endif /* _ARM_XSCALE_I80321REG_H_ */ diff --git a/sys/arm/xscale/i80321/i80321var.h b/sys/arm/xscale/i80321/i80321var.h deleted file mode 100644 index 0fead2577a2e..000000000000 --- a/sys/arm/xscale/i80321/i80321var.h +++ /dev/null @@ -1,137 +0,0 @@ -/* $NetBSD: i80321var.h,v 1.8 2003/10/06 16:06:06 thorpej Exp $ */ - -/*- - * Copyright (c) 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _ARM_XSCALE_I80321VAR_H_ -#define _ARM_XSCALE_I80321VAR_H_ - -#include -#include -#include - -extern struct bus_space i80321_bs_tag; - -struct i80321_softc { - device_t dev; - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - /* Handles for the various subregions. */ - bus_space_handle_t sc_atu_sh; - bus_space_handle_t sc_mcu_sh; - int sc_is_host; - - /* - * We expect the board-specific front-end to have already mapped - * the PCI I/O space .. it is only 64K, and I/O mappings tend to - * be smaller than a page size, so it's generally more efficient - * to map them all into virtual space in one fell swoop. - */ - vm_offset_t sc_iow_vaddr; /* I/O window vaddr */ - - /* - * Variables that define the Inbound windows. The base address of - * 0-2 are configured by a host via BARs. The xlate variable - * defines the start of the local address space that it maps to. - * The size variable defines the byte size. - * - * The first 3 windows are for incoming PCI memory read/write - * cycles from a host. The 4th window, not configured by the - * host (as it outside the normal BAR range) is the inbound - * window for PCI devices controlled by the i80321. - */ - struct { - uint32_t iwin_base_hi; - uint32_t iwin_base_lo; - uint32_t iwin_xlate; - uint32_t iwin_size; - } sc_iwin[4]; - - /* - * Variables that define the Outbound windows. - */ - struct { - uint32_t owin_xlate_lo; - uint32_t owin_xlate_hi; - } sc_owin[2]; - - /* - * This is the PCI address that the Outbound I/O - * window maps to. - */ - uint32_t sc_ioout_xlate; - - /* Bus space, DMA, and PCI tags for the PCI bus (private devices). */ - struct bus_space sc_pci_iot; - struct bus_space sc_pci_memt; - - /* GPIO state */ - uint8_t sc_gpio_dir; /* GPIO pin direction (1 == output) */ - uint8_t sc_gpio_val; /* GPIO output pin value */ - struct rman sc_irq_rman; - -}; - - -struct i80321_pci_softc { - device_t sc_dev; - bus_space_tag_t sc_st; - bus_space_handle_t sc_atu_sh; - bus_space_tag_t sc_pciio; - bus_space_tag_t sc_pcimem; - int sc_busno; - struct rman sc_mem_rman; - struct rman sc_io_rman; - struct rman sc_irq_rman; - uint32_t sc_mem; - uint32_t sc_io; -}; - -void i80321_sdram_bounds(bus_space_tag_t, bus_space_handle_t, - vm_paddr_t *, vm_size_t *); - -void i80321_attach(struct i80321_softc *); -void i80321_calibrate_delay(void); - -void i80321_bs_init(bus_space_tag_t, void *); -void i80321_io_bs_init(bus_space_tag_t, void *); -void i80321_mem_bs_init(bus_space_tag_t, void *); -extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin); - - -#endif /* _ARM_XSCALE_I80321VAR_H_ */ diff --git a/sys/arm/xscale/i80321/iq31244_7seg.c b/sys/arm/xscale/i80321/iq31244_7seg.c deleted file mode 100644 index 3737094b2172..000000000000 --- a/sys/arm/xscale/i80321/iq31244_7seg.c +++ /dev/null @@ -1,390 +0,0 @@ -/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Support for the 7-segment display on the Intel IQ31244. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v) - -static int snakestate; - -/* - * The 7-segment display looks like so: - * - * A - * +-----+ - * | | - * F | | B - * | G | - * +-----+ - * | | - * E | | C - * | D | - * +-----+ o DP - * - * Setting a bit clears the corresponding segment on the - * display. - */ -#define SEG_A (1 << 0) -#define SEG_B (1 << 1) -#define SEG_C (1 << 2) -#define SEG_D (1 << 3) -#define SEG_E (1 << 4) -#define SEG_F (1 << 5) -#define SEG_G (1 << 6) -#define SEG_DP (1 << 7) - -static const uint8_t digitmap[] = { -/* +#####+ - * # # - * # # - * # # - * +-----+ - * # # - * # # - * # # - * +#####+ - */ - SEG_G, - -/* +-----+ - * | # - * | # - * | # - * +-----+ - * | # - * | # - * | # - * +-----+ - */ - SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, - -/* +#####+ - * | # - * | # - * | # - * +#####+ - * # | - * # | - * # | - * +#####+ - */ - SEG_C|SEG_F, - -/* +#####+ - * | # - * | # - * | # - * +#####+ - * | # - * | # - * | # - * +#####+ - */ - SEG_E|SEG_F, - -/* +-----+ - * # # - * # # - * # # - * +#####+ - * | # - * | # - * | # - * +-----+ - */ - SEG_A|SEG_D|SEG_E, - -/* +#####+ - * # | - * # | - * # | - * +#####+ - * | # - * | # - * | # - * +#####+ - */ - SEG_B|SEG_E, - -/* +#####+ - * # | - * # | - * # | - * +#####+ - * # # - * # # - * # # - * +#####+ - */ - SEG_B, - -/* +#####+ - * | # - * | # - * | # - * +-----+ - * | # - * | # - * | # - * +-----+ - */ - SEG_D|SEG_E|SEG_F, - -/* +#####+ - * # # - * # # - * # # - * +#####+ - * # # - * # # - * # # - * +#####+ - */ - 0, - -/* +#####+ - * # # - * # # - * # # - * +#####+ - * | # - * | # - * | # - * +-----+ - */ - SEG_D|SEG_E, -}; - -static uint8_t -iq80321_7seg_xlate(char c) -{ - uint8_t rv; - - if (c >= '0' && c <= '9') - rv = digitmap[c - '0']; - else if (c == '.') - rv = (uint8_t) ~SEG_DP; - else - rv = 0xff; - - return (rv); -} - -void -iq80321_7seg(char a, char b) -{ - uint8_t msb, lsb; - - msb = iq80321_7seg_xlate(a); - lsb = iq80321_7seg_xlate(b); - - snakestate = 0; - - WRITE(IQ80321_7SEG_MSB, msb); - WRITE(IQ80321_7SEG_LSB, lsb); -} - -static const uint8_t snakemap[][2] = { - -/* +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_A, ~SEG_A }, - -/* +-----+ +-----+ - * # | | # - * # | | # - * # | | # - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_F, ~SEG_B }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_G, ~SEG_G }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | # # | - * | # # | - * | # # | - * +-----+ +-----+ - */ - { ~SEG_C, ~SEG_E }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - */ - { ~SEG_D, ~SEG_D }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * # | | # - * # | | # - * # | | # - * +-----+ +-----+ - */ - { ~SEG_E, ~SEG_C }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_G, ~SEG_G }, - -/* +-----+ +-----+ - * | # # | - * | # # | - * | # # | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_B, ~SEG_F }, -}; - -static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg"); -static int freq = 20; -SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0, - "7 Seg update frequency"); -static void -iq31244_7seg_snake(void) -{ - static int snakefreq; - int cur = snakestate; - - snakefreq++; - if ((snakefreq % freq)) - return; - WRITE(IQ80321_7SEG_MSB, snakemap[cur][0]); - WRITE(IQ80321_7SEG_LSB, snakemap[cur][1]); - - snakestate = (cur + 1) & 7; -} - -struct iq31244_7seg_softc { - device_t dev; -}; - -static int -iq31244_7seg_probe(device_t dev) -{ - - device_set_desc(dev, "IQ31244 7seg"); - return (0); -} - -extern void (*i80321_hardclock_hook)(void); -static int -iq31244_7seg_attach(device_t dev) -{ - - i80321_hardclock_hook = iq31244_7seg_snake; - return (0); -} - -static device_method_t iq31244_7seg_methods[] = { - DEVMETHOD(device_probe, iq31244_7seg_probe), - DEVMETHOD(device_attach, iq31244_7seg_attach), - {0, 0}, -}; - -static driver_t iq31244_7seg_driver = { - "iqseg", - iq31244_7seg_methods, - sizeof(struct iq31244_7seg_softc), -}; -static devclass_t iq31244_7seg_devclass; - -DRIVER_MODULE(iqseg, iq, iq31244_7seg_driver, iq31244_7seg_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c deleted file mode 100644 index eb19f78d2a3e..000000000000 --- a/sys/arm/xscale/i80321/iq31244_machdep.c +++ /dev/null @@ -1,416 +0,0 @@ -/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ - -/*- - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * This code is derived from software written for Brini by Mark Brinicombe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. - * - * RiscBSD kernel project - * - * machdep.c - * - * Machine dependant functions for kernel setup - * - * This file needs a lot of work. - * - * Created : 17/09/94 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_kstack_pages.h" - -#define _ARM32_BUS_DMA_PRIVATE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ -#define KERNEL_PT_IOPXS 1 -#define KERNEL_PT_BEFOREKERN 2 -#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ -#define KERNEL_PT_AFKERNEL_NUM 9 - -/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ -#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) - -struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; - -/* Physical and virtual addresses for some global pages */ - -struct pv_addr systempage; -struct pv_addr msgbufpv; -struct pv_addr irqstack; -struct pv_addr undstack; -struct pv_addr abtstack; -struct pv_addr kernelstack; -struct pv_addr minidataclean; - -#define IQ80321_OBIO_BASE 0xfe800000UL -#define IQ80321_OBIO_SIZE 0x00100000UL -/* Static device mappings. */ -static const struct arm_devmap_entry iq80321_devmap[] = { - /* - * Map the on-board devices VA == PA so that we can access them - * with the MMU on or off. - */ - { - IQ80321_OBIO_BASE, - IQ80321_OBIO_BASE, - IQ80321_OBIO_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_IOW_VBASE, - VERDE_OUT_XLATE_IO_WIN0_BASE, - VERDE_OUT_XLATE_IO_WIN_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - - { - IQ80321_80321_VBASE, - VERDE_PMMR_BASE, - VERDE_PMMR_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - 0, - 0, - 0, - 0, - 0, - } -}; - -#define SDRAM_START 0xa0000000 - -extern vm_offset_t xscale_cache_clean_addr; - -void * -initarm(struct arm_boot_params *abp) -{ - struct pv_addr kernel_l1pt; - struct pv_addr dpcpu; - int loop, i; - u_int l1pagetable; - vm_offset_t freemempos; - vm_offset_t freemem_pt; - vm_offset_t afterkern; - vm_offset_t freemem_after; - vm_offset_t lastaddr; - uint32_t memsize, memstart; - - lastaddr = parse_boot_param(abp); - arm_physmem_kernaddr = abp->abp_physaddr; - set_cpufuncs(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, &thread0); - - /* Do basic tuning, hz etc */ - init_param1(); - - freemempos = 0xa0200000; - /* Define a macro to simplify memory allocation */ -#define valloc_pages(var, np) \ - alloc_pages((var).pv_pa, (np)); \ - (var).pv_va = (var).pv_pa + 0x20000000; - -#define alloc_pages(var, np) \ - freemempos -= (np * PAGE_SIZE); \ - (var) = freemempos; \ - memset((char *)(var), 0, ((np) * PAGE_SIZE)); - - while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) - freemempos -= PAGE_SIZE; - valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); - for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { - if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { - valloc_pages(kernel_pt_table[loop], - L2_TABLE_SIZE / PAGE_SIZE); - } else { - kernel_pt_table[loop].pv_pa = freemempos + - (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * - L2_TABLE_SIZE_REAL; - kernel_pt_table[loop].pv_va = - kernel_pt_table[loop].pv_pa + 0x20000000; - } - } - freemem_pt = freemempos; - freemempos = 0xa0100000; - /* - * Allocate a page for the system page mapped to V0x00000000 - * This page will just contain the system vectors and can be - * shared by all processes. - */ - valloc_pages(systempage, 1); - - /* Allocate dynamic per-cpu area. */ - valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); - dpcpu_init((void *)dpcpu.pv_va, 0); - - /* Allocate stacks for all modes */ - valloc_pages(irqstack, IRQ_STACK_SIZE); - valloc_pages(abtstack, ABT_STACK_SIZE); - valloc_pages(undstack, UND_STACK_SIZE); - valloc_pages(kernelstack, kstack_pages); - alloc_pages(minidataclean.pv_pa, 1); - valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); - /* - * Allocate memory for the l1 and l2 page tables. The scheme to avoid - * wasting memory by allocating the l1pt on the first 16k memory was - * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for - * this to work (which is supposed to be the case). - */ - - /* - * Now we start construction of the L1 page table - * We start by mapping the L2 page tables into the L1. - * This means that we can replace L1 mappings later on if necessary - */ - l1pagetable = kernel_l1pt.pv_va; - - /* Map the L2 pages tables in the L1 page table */ - pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1), - &kernel_pt_table[KERNEL_PT_SYS]); - pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, - &kernel_pt_table[KERNEL_PT_IOPXS]); - pmap_link_l2pt(l1pagetable, KERNBASE, - &kernel_pt_table[KERNEL_PT_BEFOREKERN]); - pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000, - 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000, - (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1), - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1); - afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - - 1)); - for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { - pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, - &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); - } - pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - - - /* Map the Mini-Data cache clean area. */ - xscale_setup_minidata(l1pagetable, afterkern, - minidataclean.pv_pa); - - /* Map the vector page. */ - pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - arm_devmap_bootstrap(l1pagetable, iq80321_devmap); - /* - * Give the XScale global cache clean code an appropriately - * sized chunk of unmapped VA space starting at 0xff000000 - * (our device mappings end before this address). - */ - xscale_cache_clean_addr = 0xff000000U; - - cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); - cpu_tlb_flushID(); - cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); - /* - * Pages were allocated during the secondary bootstrap for the - * stacks for different CPU modes. - * We must now set the r13 registers in the different CPU modes to - * point to these stacks. - * Since the ARM stacks use STMFD etc. we must set r13 to the top end - * of the stack memory. - */ - set_stackptrs(0); - - /* - * We must now clean the cache again.... - * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() - * but since we are boot strapping the addresses used for the read - * may have just been remapped and thus the cache could be out - * of sync. A re-clean after the switch will cure this. - * After booting there are no gross relocations of the kernel thus - * this problem will not occur after initarm(). - */ - cpu_idcache_wbinv_all(); - cpu_setup(); - - /* - * Fetch the SDRAM start/size from the i80321 SDRAM configration - * registers. - */ - i80321_calibrate_delay(); - i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE, - &memstart, &memsize); - physmem = memsize / PAGE_SIZE; - cninit(); - - undefined_init(); - - init_proc0(kernelstack.pv_va); - - /* Enable MMU, I-cache, D-cache, write buffer. */ - - arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); - pmap_curmaxkvaddr = afterkern + PAGE_SIZE; - vm_max_kernel_address = 0xe0000000; - pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); - msgbufp = (void*)msgbufpv.pv_va; - msgbufinit(msgbufp, msgbufsize); - mutex_init(); - - /* - * Add the physical ram we have available. - * - * Exclude the kernel (and all the things we allocated which immediately - * follow the kernel) from the VM allocation pool but not from crash - * dumps. virtual_avail is a global variable which tracks the kva we've - * "allocated" while setting up pmaps. - * - * Prepare the list of physical memory available to the vm subsystem. - */ - arm_physmem_hardware_region(SDRAM_START, memsize); - arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - - freemem_pt, EXFLAG_NOALLOC); - arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - - freemempos, EXFLAG_NOALLOC); - arm_physmem_exclude_region(abp->abp_physaddr, - virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); - arm_physmem_init_kernel_globals(); - - init_param2(physmem); - kdb_init(); - return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - - sizeof(struct pcb))); -} - -extern int -machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) -{ - int bus; - int device; - int func; - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(pcib); - bus = pci_get_bus(dev); - device = pci_get_slot(dev); - func = pci_get_function(dev); - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - if (bus != busno) - goto no_mapping; - switch (device) { - /* IQ31244 PCI */ - case 1: /* PCIX-PCIX bridge */ - /* - * The S-ATA chips are behind the bridge, and all of - * the S-ATA interrupts are wired together. - */ - return (ICU_INT_XINT(2)); - case 2: /* PCI slot */ - /* All pins are wired together. */ - return (ICU_INT_XINT(3)); - case 3: /* i82546 dual Gig-E */ - if (pin == 1 || pin == 2) - return (ICU_INT_XINT(0)); - goto no_mapping; - /* IQ80321 PCI */ - case 4: /* i82544 Gig-E */ - case 8: /* - * Apparently you can set the device for the ethernet adapter - * to 8 with a jumper, so handle that as well - */ - if (pin == 1) - return (ICU_INT_XINT(0)); - goto no_mapping; - case 6: /* S-PCI-X slot */ - if (pin == 1) - return (ICU_INT_XINT(2)); - if (pin == 2) - return (ICU_INT_XINT(3)); - goto no_mapping; - default: -no_mapping: - printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); - - } - return (0); - -} diff --git a/sys/arm/xscale/i80321/iq80321.c b/sys/arm/xscale/i80321/iq80321.c deleted file mode 100644 index fb344556ccb0..000000000000 --- a/sys/arm/xscale/i80321/iq80321.c +++ /dev/null @@ -1,394 +0,0 @@ -/* $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * IQ80321 front-end for the i80321 I/O Processor. We take care - * of setting up the i80321 memory map, PCI interrupt routing, etc., - * which are all specific to the board the i80321 is wired up to. - */ - -#include -__FBSDID("$FreeBSD$"); - -#define _ARM32_BUS_DMA_PRIVATE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - - -int iq80321_probe(device_t); -void iq80321_identify(driver_t *, device_t); -int iq80321_attach(device_t); - -int -iq80321_probe(device_t dev) -{ - device_set_desc(dev, "Intel 80321"); - return (BUS_PROBE_NOWILDCARD); -} - -void -iq80321_identify(driver_t *driver, device_t parent) -{ - - BUS_ADD_CHILD(parent, 0, "iq", 0); -} - -static struct arm32_dma_range i80321_dr; -static int dma_range_init = 0; - -struct arm32_dma_range * -bus_dma_get_range(void) -{ - if (dma_range_init == 0) - return (NULL); - return (&i80321_dr); -} - -int -bus_dma_get_range_nb(void) -{ - if (dma_range_init == 0) - return (0); - return (1); -} - -#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008 -#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004 - -int -iq80321_attach(device_t dev) -{ - struct i80321_softc *sc = device_get_softc(dev); - int b0u, b0l, b1u, b1l; - vm_paddr_t memstart = 0; - vm_size_t memsize = 0; - int busno; - - /* - * Fill in the space tag for the i80321's own devices, - * and hand-craft the space handle for it (the device - * was mapped during early bootstrap). - */ - i80321_bs_init(&i80321_bs_tag, sc); - sc->sc_st = &i80321_bs_tag; - sc->sc_sh = IQ80321_80321_VBASE; - sc->dev = dev; - sc->sc_is_host = 1; - - /* - * Slice off a subregion for the Memory Controller -- we need it - * here in order read the memory size. - */ - if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE, - VERDE_MCU_SIZE, &sc->sc_mcu_sh)) - panic("%s: unable to subregion MCU registers", - device_get_name(dev)); - - if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, - VERDE_ATU_SIZE, &sc->sc_atu_sh)) - panic("%s: unable to subregion ATU registers", - device_get_name(dev)); - - /* - * We have mapped the PCI I/O windows in the early - * bootstrap phase. - */ - sc->sc_iow_vaddr = IQ80321_IOW_VBASE; - - /* - * Check the configuration of the ATU to see if another BIOS - * has configured us. If a PC BIOS didn't configure us, then: - * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c. - * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c. - * If a BIOS has configured us, at least one of those should be - * different. This is pretty fragile, but it's not clear what - * would work better. - */ - b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0); - b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4); - b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8); - b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc); - -#ifdef VERBOSE_INIT_ARM - printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", - b0l,b0u, b1l, b1u ); -#endif - -#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 - b0l &= PCI_MAPREG_MEM_ADDR_MASK; - b0u &= PCI_MAPREG_MEM_ADDR_MASK; - b1l &= PCI_MAPREG_MEM_ADDR_MASK; - b1u &= PCI_MAPREG_MEM_ADDR_MASK; - -#ifdef VERBOSE_INIT_ARM - printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", - b0l,b0u, b1l, b1u ); -#endif - - if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0)) - sc->sc_is_host = 0; - else - sc->sc_is_host = 1; - - /* FIXME: i force it's */ - -#ifdef CPU_XSCALE_80219 - sc->sc_is_host = 1; -#endif - - i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize); - /* - * We set up the Inbound Windows as follows: - * - * 0 Access to i80321 PMMRs - * - * 1 Reserve space for private devices - * - * 2 RAM access - * - * 3 Unused. - * - * This chunk needs to be customized for each IOP321 application. - */ -#if 0 - sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE; - sc->sc_iwin[0].iwin_base_hi = 0; - sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE; - sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE; -#endif - if (sc->sc_is_host) { - - /* Map PCI:Local 1:1. */ - sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - sc->sc_iwin[1].iwin_base_hi = 0; - } else { - - sc->sc_iwin[1].iwin_base_lo = 0; - sc->sc_iwin[1].iwin_base_hi = 0; - } - sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE; - sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE; - - if (sc->sc_is_host) { - sc->sc_iwin[2].iwin_base_lo = memstart | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - sc->sc_iwin[2].iwin_base_hi = 0; - } else { - sc->sc_iwin[2].iwin_base_lo = 0; - sc->sc_iwin[2].iwin_base_hi = 0; - } - sc->sc_iwin[2].iwin_xlate = memstart; - sc->sc_iwin[2].iwin_size = memsize; - - if (sc->sc_is_host) { - sc->sc_iwin[3].iwin_base_lo = 0 | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - } else { - sc->sc_iwin[3].iwin_base_lo = 0; - } - sc->sc_iwin[3].iwin_base_hi = 0; - sc->sc_iwin[3].iwin_xlate = 0; - sc->sc_iwin[3].iwin_size = 0; - -#ifdef VERBOSE_INIT_ARM - printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", - sc->sc_iwin[1].iwin_base_hi, - sc->sc_iwin[1].iwin_base_lo, - sc->sc_iwin[1].iwin_xlate, - sc->sc_iwin[1].iwin_size - ); - printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", - sc->sc_iwin[2].iwin_base_hi, - sc->sc_iwin[2].iwin_base_lo, - sc->sc_iwin[2].iwin_xlate, - sc->sc_iwin[2].iwin_size - ); -#endif - - /* - * We set up the Outbound Windows as follows: - * - * 0 Access to private PCI space. - * - * 1 Unused. - */ -#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) - sc->sc_owin[0].owin_xlate_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); - sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; - /* - * Set the Secondary Outbound I/O window to map - * to PCI address 0 for all 64K of the I/O space. - */ - sc->sc_ioout_xlate = 0; - i80321_attach(sc); - i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate; - i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); - i80321_dr.dr_len = sc->sc_iwin[2].iwin_size; - dma_range_init = 1; - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - sc->sc_irq_rman.rm_type = RMAN_ARRAY; - sc->sc_irq_rman.rm_descr = "i80321 IRQs"; - if (rman_init(&sc->sc_irq_rman) != 0 || - rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0) - panic("i80321_attach: failed to set up IRQ rman"); - - device_add_child(dev, "obio", 0); - device_add_child(dev, "itimer", 0); - device_add_child(dev, "iopwdog", 0); -#ifndef CPU_XSCALE_80219 - device_add_child(dev, "iqseg", 0); -#endif - device_add_child(dev, "pcib", busno); - device_add_child(dev, "i80321_dma", 0); - device_add_child(dev, "i80321_dma", 1); -#ifndef CPU_XSCALE_80219 - device_add_child(dev, "i80321_aau", 0); -#endif - bus_generic_probe(dev); - bus_generic_attach(dev); - - return (0); -} - -void -arm_mask_irq(uintptr_t nb) -{ - intr_enabled &= ~(1 << nb); - i80321_set_intrmask(); -} - -void -arm_unmask_irq(uintptr_t nb) -{ - intr_enabled |= (1 << nb); - i80321_set_intrmask(); -} - - -void -cpu_reset() -{ - (void) disable_interrupts(PSR_I|PSR_F); - *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE + - ATU_PCSR) = PCSR_RIB | PCSR_RPB; - printf("Reset failed!\n"); - for(;;); -} - -static struct resource * -iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct i80321_softc *sc = device_get_softc(dev); - struct resource *rv; - - if (type == SYS_RES_IRQ) { - rv = rman_reserve_resource(&sc->sc_irq_rman, - start, end, count, flags, child); - if (rv != NULL) - rman_set_rid(rv, *rid); - return (rv); - } - return (NULL); -} - -static int -iq80321_setup_intr(device_t dev, device_t child, - struct resource *ires, int flags, driver_filter_t *filt, - driver_intr_t *intr, void *arg, void **cookiep) -{ - int error; - - error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - filt, intr, arg, cookiep); - if (error) - return (error); - intr_enabled |= 1 << rman_get_start(ires); - i80321_set_intrmask(); - - return (0); -} - -static int -iq80321_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); -} - -static device_method_t iq80321_methods[] = { - DEVMETHOD(device_probe, iq80321_probe), - DEVMETHOD(device_attach, iq80321_attach), - DEVMETHOD(device_identify, iq80321_identify), - DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource), - DEVMETHOD(bus_setup_intr, iq80321_setup_intr), - DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr), - {0, 0}, -}; - -static driver_t iq80321_driver = { - "iq", - iq80321_methods, - sizeof(struct i80321_softc), -}; -static devclass_t iq80321_devclass; - -DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/iq80321reg.h b/sys/arm/xscale/i80321/iq80321reg.h deleted file mode 100644 index d887fcd92663..000000000000 --- a/sys/arm/xscale/i80321/iq80321reg.h +++ /dev/null @@ -1,111 +0,0 @@ -/* $NetBSD: iq80321reg.h,v 1.4 2003/05/14 19:46:39 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _IQ80321REG_H_ -#define _IQ80321REG_H_ - -/* - * Memory map and register definitions for the Intel IQ80321 - * Evaluation Board. - */ - -/* - * The memory map of the IQ80321 looks like so: - * - * ------------------------------ - * Intel 80321 IOP Reserved - * FFFF E900 ------------------------------ - * Peripheral Memory Mapped - * Registers - * FFFF E000 ------------------------------ - * On-board devices - * FE80 0000 ------------------------------ - * SDRAM - * A000 0000 ------------------------------ - * Reserved - * 9100 0000 ------------------------------ - * Flash - * 9080 0000 ------------------------------ - * Reserved - * 9002 0000 ------------------------------ - * ATU Outbound Transaction - * Windows - * 8000 0000 ------------------------------ - * ATU Outbound Direct - * Addressing Windows - * 0000 1000 ------------------------------ - * Initialization Boot Code - * from Flash - * 0000 0000 ------------------------------ - */ - -/* - * We allocate a page table for VA 0xfe400000 (4MB) and map the - * PCI I/O space (64K) and i80321 memory-mapped registers (4K) there. - */ -#define IQ80321_IOPXS_VBASE 0xfe400000UL -#define IQ80321_IOW_VBASE IQ80321_IOPXS_VBASE -#define IQ80321_80321_VBASE (IQ80321_IOW_VBASE + \ - VERDE_OUT_XLATE_IO_WIN_SIZE) - -#define IQ80321_SDRAM_START 0xa0000000 -/* - * The IQ80321 on-board devices are mapped VA==PA during bootstrap. - * Conveniently, the size of the on-board register space is 1 section - * mapping. - */ -#define IQ80321_OBIO_BASE 0xfe800000UL -#define IQ80321_OBIO_SIZE 0x00100000UL /* 1MB */ - -#define IQ80321_UART1 0xfe800000UL /* TI 16550 */ - -#if defined( CPU_XSCALE_80321 ) -#define IQ80321_7SEG_MSB 0xfe840000UL -#define IQ80321_7SEG_LSB 0xfe850000UL - -#define IQ80321_ROT_SWITCH 0xfe8d0000UL - -#define IQ80321_BATTERY_STAT 0xfe8f0000UL -#define BATTERY_STAT_PRES (1U << 0) -#define BATTERY_STAT_CHRG (1U << 1) -#define BATTERY_STAT_DISCHRG (1U << 2) -#endif /* CPU_XSCALE_80321 */ - -#endif /* _IQ80321REG_H_ */ diff --git a/sys/arm/xscale/i80321/iq80321var.h b/sys/arm/xscale/i80321/iq80321var.h deleted file mode 100644 index 4a035001bdf5..000000000000 --- a/sys/arm/xscale/i80321/iq80321var.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $NetBSD: iq80321var.h,v 1.1 2002/03/27 21:51:30 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _IQ80321_IQ80321VAR_H_ -#define _IQ80321_IQ80321VAR_H_ - -#include - -void iq80321_7seg(char, char); -void iq80321_7seg_snake(void); - -#if 0 -void iq80321_pci_init(pci_chipset_tag_t, void *); -#endif - -#endif /* _IQ80321_IQ80321VAR_H_ */ diff --git a/sys/arm/xscale/i80321/obio.c b/sys/arm/xscale/i80321/obio.c deleted file mode 100644 index 55218ccd20d1..000000000000 --- a/sys/arm/xscale/i80321/obio.c +++ /dev/null @@ -1,163 +0,0 @@ -/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * On-board device autoconfiguration support for Intel IQ80321 - * evaluation boards. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -bus_space_tag_t obio_bs_tag; - -int obio_probe(device_t); -int obio_attach(device_t); - -int -obio_probe(device_t dev) -{ - return (0); -} - -int -obio_attach(device_t dev) -{ - struct obio_softc *sc = device_get_softc(dev); - - obio_bs_tag = arm_base_bs_tag; - sc->oba_st = obio_bs_tag; - sc->oba_addr = IQ80321_OBIO_BASE; - sc->oba_size = IQ80321_OBIO_SIZE; - sc->oba_rman.rm_type = RMAN_ARRAY; - sc->oba_rman.rm_descr = "OBIO I/O"; - if (rman_init(&sc->oba_rman) != 0 || - rman_manage_region(&sc->oba_rman, - sc->oba_addr, sc->oba_addr + sc->oba_size) != 0) - panic("obio_attach: failed to set up I/O rman"); - sc->oba_irq_rman.rm_type = RMAN_ARRAY; - sc->oba_irq_rman.rm_descr = "OBIO IRQ"; - if (rman_init(&sc->oba_irq_rman) != 0 || - rman_manage_region(&sc->oba_irq_rman, 28, 28) != 0) - panic("obio_attach: failed to set up IRQ rman"); - device_add_child(dev, "uart", 0); - bus_generic_probe(dev); - bus_generic_attach(dev); - return (0); -} - -static struct resource * -obio_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct resource *rv; - struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; - struct obio_softc *sc = device_get_softc(bus); - - switch (type) { - case SYS_RES_IRQ: - rm = &sc->oba_irq_rman; - break; - case SYS_RES_MEMORY: - return (NULL); - case SYS_RES_IOPORT: - rm = &sc->oba_rman; - bt = sc->oba_st; - bh = sc->oba_addr; - start = bh; - break; - default: - return (NULL); - } - - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) - return (NULL); - if (type == SYS_RES_IRQ) - return (rv); - rman_set_rid(rv, *rid); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - - return (rv); - -} - -static int -obio_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - return (0); -} -static device_method_t obio_methods[] = { - DEVMETHOD(device_probe, obio_probe), - DEVMETHOD(device_attach, obio_attach), - - DEVMETHOD(bus_alloc_resource, obio_alloc_resource), - DEVMETHOD(bus_activate_resource, obio_activate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - {0, 0}, -}; - -static driver_t obio_driver = { - "obio", - obio_methods, - sizeof(struct obio_softc), -}; -static devclass_t obio_devclass; - -DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/obiovar.h b/sys/arm/xscale/i80321/obiovar.h deleted file mode 100644 index 182b52f57f5a..000000000000 --- a/sys/arm/xscale/i80321/obiovar.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */ - -/*- - * Copyright (c) 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * 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 _IQ80321_OBIOVAR_H_ -#define _IQ80321_OBIOVAR_H_ - -#include - -struct obio_softc { - bus_space_tag_t oba_st; /* bus space tag */ - bus_addr_t oba_addr; /* address of device */ - bus_size_t oba_size; /* size of device */ - int oba_width; /* bus width */ - int oba_irq; /* XINT interrupt bit # */ - struct rman oba_rman; - struct rman oba_irq_rman; - -}; -extern bus_space_tag_t obio_bs_tag; - -#endif /* _IQ80321_OBIOVAR_H_ */ diff --git a/sys/arm/xscale/i80321/std.ep80219 b/sys/arm/xscale/i80321/std.ep80219 deleted file mode 100644 index 9f5cbb755519..000000000000 --- a/sys/arm/xscale/i80321/std.ep80219 +++ /dev/null @@ -1,7 +0,0 @@ -#EP80219 board configuration -#$FreeBSD$ -include "../xscale/i80321/std.i80219" -files "../xscale/i80321/files.ep80219" -makeoptions KERNPHYSADDR=0xa0200000 -makeoptions KERNVIRTADDR=0xc0200000 -options COUNTS_PER_SEC=198000000 diff --git a/sys/arm/xscale/i80321/std.i80219 b/sys/arm/xscale/i80321/std.i80219 deleted file mode 100644 index 7cc8f377a876..000000000000 --- a/sys/arm/xscale/i80321/std.i80219 +++ /dev/null @@ -1,5 +0,0 @@ -#XScale i80219 generic configuration -#$FreeBSD$ -files "../xscale/i80321/files.i80219" -include "../xscale/std.xscale-be" -cpu CPU_XSCALE_80219 diff --git a/sys/arm/xscale/i80321/std.i80321 b/sys/arm/xscale/i80321/std.i80321 deleted file mode 100644 index 8142bdf0803e..000000000000 --- a/sys/arm/xscale/i80321/std.i80321 +++ /dev/null @@ -1,5 +0,0 @@ -#XScale i80321 generic configuration -#$FreeBSD$ -files "../xscale/i80321/files.i80321" -include "../xscale/std.xscale-be" -cpu CPU_XSCALE_80321 diff --git a/sys/arm/xscale/i80321/std.iq31244 b/sys/arm/xscale/i80321/std.iq31244 deleted file mode 100644 index c4c23bf7d620..000000000000 --- a/sys/arm/xscale/i80321/std.iq31244 +++ /dev/null @@ -1,7 +0,0 @@ -#IQ31244 board configuration -#$FreeBSD$ -include "../xscale/i80321/std.i80321" -files "../xscale/i80321/files.iq31244" -makeoptions KERNPHYSADDR=0xa0200000 -makeoptions KERNVIRTADDR=0xc0200000 -options COUNTS_PER_SEC=198000000 diff --git a/sys/arm/xscale/i80321/uart_bus_i80321.c b/sys/arm/xscale/i80321/uart_bus_i80321.c deleted file mode 100644 index 5bb903df64cd..000000000000 --- a/sys/arm/xscale/i80321/uart_bus_i80321.c +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright (c) 2004 Olivier Houchard. 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "uart_if.h" - -static int uart_i80321_probe(device_t dev); - -static device_method_t uart_i80321_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uart_i80321_probe), - DEVMETHOD(device_attach, uart_bus_attach), - DEVMETHOD(device_detach, uart_bus_detach), - { 0, 0 } -}; - -static driver_t uart_i80321_driver = { - uart_driver_name, - uart_i80321_methods, - sizeof(struct uart_softc), -}; - -extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; -static int -uart_i80321_probe(device_t dev) -{ - struct uart_softc *sc; - - sc = device_get_softc(dev); - sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); - sc->sc_class = &uart_ns8250_class; - bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); - return(uart_bus_probe(dev, 0, 0, 0, 0)); -} - - -DRIVER_MODULE(uart, obio, uart_i80321_driver, uart_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/uart_cpu_i80321.c b/sys/arm/xscale/i80321/uart_cpu_i80321.c deleted file mode 100644 index a3faec7289df..000000000000 --- a/sys/arm/xscale/i80321/uart_cpu_i80321.c +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 2003 Marcel Moolenaar - * 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -bus_space_tag_t uart_bus_space_io; -bus_space_tag_t uart_bus_space_mem; - -int -uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) -{ - return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); -} - -int -uart_cpu_getdev(int devtype, struct uart_devinfo *di) -{ - di->ops = uart_getops(&uart_ns8250_class); - di->bas.chan = 0; - di->bas.bst = obio_bs_tag; - di->bas.regshft = 0; - di->bas.rclk = 0; - di->baudrate = 115200; - di->databits = 8; - di->stopbits = 1; - di->parity = UART_PARITY_NONE; - uart_bus_space_io = obio_bs_tag; - uart_bus_space_mem = NULL; - di->bas.bsh = 0xfe800000; - return (0); -} diff --git a/sys/arm/xscale/i8134x/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h index 53617f956582..115900c58291 100644 --- a/sys/arm/xscale/i8134x/i80321reg.h +++ b/sys/arm/xscale/i8134x/i80321reg.h @@ -91,19 +91,9 @@ #define VERDE_MCU_BASE 0x0500 #define VERDE_MCU_SIZE 0x0100 -#if defined(CPU_XSCALE_80321) -#define VERDE_SSP_BASE 0x0600 -#define VERDE_SSP_SIZE 0x0080 -#endif - #define VERDE_PBIU_BASE 0x0680 #define VERDE_PBIU_SIZE 0x0080 -#if defined(CPU_XSCALE_80321) -#define VERDE_AAU_BASE 0x0800 -#define VERDE_AAU_SIZE 0x0100 -#endif - #define VERDE_I2C_BASE 0x1680 #define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00) #define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20) @@ -340,21 +330,13 @@ #define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0) #define ICU_INT_bit26 26 -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit25 25 /* reserved */ -#else /* CPU_XSCALE_80321 */ -#define ICU_INT_SSP 25 /* SSP serial port */ -#endif +//#define ICU_INT_SSP 25 /* SSP serial port */ #define ICU_INT_MUE 24 /* msg unit error */ -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit23 23 /* reserved */ -#else /* CPU_XSCALE_80321 */ -#define ICU_INT_AAUE 23 /* AAU error */ -#endif +//#define ICU_INT_AAUE 23 /* AAU error */ #define ICU_INT_bit22 22 #define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ @@ -372,14 +354,9 @@ #define ICU_INT_TMR0 9 /* timer 0 */ #define ICU_INT_CPPM 8 /* core processor PMU */ -#if defined(CPU_XSCALE_80219) -#define ICU_INT_bit7 7 /* reserved */ -#define ICU_INT_bit6 6 /* reserved */ -#else /* CPU_XSCALE_80321 */ -#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ -#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ -#endif +//#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ +//#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ #define ICU_INT_bit5 5 #define ICU_INT_bit4 4 @@ -388,81 +365,12 @@ #define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */ #define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ -#if defined (CPU_XSCALE_80219) -#define ICU_INT_HWMASK (0xffffffff & \ - ~((1 << ICU_INT_bit26) | \ - (1 << ICU_INT_bit25) | \ - (1 << ICU_INT_bit23) | \ - (1 << ICU_INT_bit22) | \ - (1 << ICU_INT_bit7) | \ - (1 << ICU_INT_bit6) | \ - (1 << ICU_INT_bit5) | \ - (1 << ICU_INT_bit4))) - -#else /* CPU_XSCALE_80321 */ -#define ICU_INT_HWMASK (0xffffffff & \ - ~((1 << ICU_INT_bit26) | \ - (1 << ICU_INT_bit22) | \ - (1 << ICU_INT_bit5) | \ - (1 << ICU_INT_bit4))) -#endif - -/* - * SSP Serial Port - */ -#if defined (CPU_XSCALE_80321) - -#define SSP_SSCR0 0x00 /* SSC control 0 */ -#define SSP_SSCR1 0x04 /* SSC control 1 */ -#define SSP_SSSR 0x08 /* SSP status */ -#define SSP_SSITR 0x0c /* SSP interrupt test */ -#define SSP_SSDR 0x10 /* SSP data */ - -#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */ -#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */ -#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */ -#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */ -#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */ -#define SSP_SSCR0_ECS (1U << 6)/* external clock select */ -#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */ -#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */ - /* bit rate = 3.6864 * 10e6 / - (2 * (SCR + 1)) */ - -#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */ -#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */ -#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */ -#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */ -#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase: - 0 = inactive full at start, - 1/2 at end of frame - 1 = inactive 1/2 at start, - full at end of frame */ -#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size: - 0 = 8 bit - 1 = 16 bit */ -#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */ -#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */ -#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */ -#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select: - 0 = Tx FIFO - 1 = Rx FIFO */ - -#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */ -#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */ -#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */ -#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */ -#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */ -#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */ -#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */ -#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */ - -#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */ -#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */ -#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */ - -#endif /* CPU_XSCALE_80321 */ +//#define ICU_INT_HWMASK (0xffffffff & \ +// ~((1 << ICU_INT_bit26) | \ +// (1 << ICU_INT_bit22) | \ +// (1 << ICU_INT_bit5) | \ +// (1 << ICU_INT_bit4))) /* * Peripheral Bus Interface Unit diff --git a/sys/conf/files.arm b/sys/conf/files.arm index 9f3a6bffedc0..bc5d8a39fd6d 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -14,14 +14,14 @@ arm/arm/cpufunc_asm.S standard arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 | cpu_arm9e arm/arm/cpufunc_asm_arm11.S optional cpu_arm1176 arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176 -arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 +arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342 arm/arm/cpufunc_asm_armv5_ec.S optional cpu_arm9e arm/arm/cpufunc_asm_armv6.S optional cpu_arm1176 arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b arm/arm/cpufunc_asm_fa526.S optional cpu_fa526 arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e -arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 +arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342 arm/arm/cpufunc_asm_xscale_c3.S optional cpu_xscale_81342 arm/arm/cpuinfo.c standard arm/arm/cpu_asm-v6.S optional armv6 diff --git a/sys/conf/options.arm b/sys/conf/options.arm index ef664136547c..7beae5bd6833 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -15,8 +15,6 @@ CPU_CORTEXA opt_global.h CPU_KRAIT opt_global.h CPU_FA526 opt_global.h CPU_MV_PJ4B opt_global.h -CPU_XSCALE_80219 opt_global.h -CPU_XSCALE_80321 opt_global.h CPU_XSCALE_81342 opt_global.h CPU_XSCALE_IXP425 opt_global.h CPU_XSCALE_IXP435 opt_global.h From 71c4d79a10b7c1bad1feb0b4efaaca9c1c9ee341 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 10:39:29 +0000 Subject: [PATCH 148/236] ARM: Remove C++ comments erroneously committed in r295200. --- sys/arm/xscale/i8134x/i80321reg.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/arm/xscale/i8134x/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h index 115900c58291..b6dd4fea14da 100644 --- a/sys/arm/xscale/i8134x/i80321reg.h +++ b/sys/arm/xscale/i8134x/i80321reg.h @@ -331,12 +331,12 @@ #define ICU_INT_bit26 26 /* CPU_XSCALE_80321 */ -//#define ICU_INT_SSP 25 /* SSP serial port */ +#define ICU_INT_SSP 25 /* SSP serial port */ #define ICU_INT_MUE 24 /* msg unit error */ /* CPU_XSCALE_80321 */ -//#define ICU_INT_AAUE 23 /* AAU error */ +#define ICU_INT_AAUE 23 /* AAU error */ #define ICU_INT_bit22 22 #define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ @@ -355,8 +355,8 @@ #define ICU_INT_CPPM 8 /* core processor PMU */ /* CPU_XSCALE_80321 */ -//#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ -//#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ +#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ +#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ #define ICU_INT_bit5 5 #define ICU_INT_bit4 4 @@ -366,11 +366,11 @@ #define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ /* CPU_XSCALE_80321 */ -//#define ICU_INT_HWMASK (0xffffffff & \ -// ~((1 << ICU_INT_bit26) | \ -// (1 << ICU_INT_bit22) | \ -// (1 << ICU_INT_bit5) | \ -// (1 << ICU_INT_bit4))) +#define ICU_INT_HWMASK (0xffffffff & \ + ~((1 << ICU_INT_bit26) | \ + (1 << ICU_INT_bit22) | \ + (1 << ICU_INT_bit5) | \ + (1 << ICU_INT_bit4))) /* * Peripheral Bus Interface Unit From 5b67986f72e761e7f1f2a034689457476a2357c3 Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 3 Feb 2016 11:03:44 +0000 Subject: [PATCH 149/236] Try to fix a bug introduced in r228623. We started to copy the ifa_msghdr as otherwise platforms with strict alignment would break. It's unclear to me if there's also a problem with access to the address list following the structure. However we never copied the address list after the structure and thus are pointing at random memory. For now just use a pointer to the original memory for accessing the address list making it at least work on platforms with weak memory access. PR: 195445 Reported by: wolfgang lyxys.ka.sub.org Tested by: wolfgang lyxys.ka.sub.org (x86) MFC after: 3 days --- contrib/bsnmp/snmp_mibII/mibII.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c index b62ee66d6d61..9079d1d3b58c 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.c +++ b/contrib/bsnmp/snmp_mibII/mibII.c @@ -982,7 +982,7 @@ handle_rtmsg(struct rt_msghdr *rtm) { struct sockaddr *addrs[RTAX_MAX]; struct if_msghdr *ifm; - struct ifa_msghdr ifam; + struct ifa_msghdr ifam, *ifamp; struct ifma_msghdr *ifmam; #ifdef RTM_IFANNOUNCE struct if_announcemsghdr *ifan; @@ -1002,8 +1002,9 @@ handle_rtmsg(struct rt_msghdr *rtm) switch (rtm->rtm_type) { case RTM_NEWADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) break; @@ -1029,8 +1030,9 @@ handle_rtmsg(struct rt_msghdr *rtm) break; case RTM_DELADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL) break; From 9b1e69366637d18110038c26a3509bea536ae11a Mon Sep 17 00:00:00 2001 From: ume Date: Wed, 3 Feb 2016 11:44:43 +0000 Subject: [PATCH 150/236] The charset of NLS catalogs were converted to UTF-8 since r231990. --- bin/csh/Makefile | 55 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/bin/csh/Makefile b/bin/csh/Makefile index 51ef3dd9c306..18e266535e9a 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -51,41 +51,40 @@ FILESDIR= ${SHAREDIR}/examples/tcsh FILES= complete.tcsh csh-mode.el .endif -CATALOGS= et:et_EE.ISO8859-15 \ - finnish:fi_FI.ISO8859-1 \ - french:fr_FR.ISO8859-1 \ - german:de_DE.ISO8859-1 \ - greek:el_GR.ISO8859-7 \ - italian:it_IT.ISO8859-1 \ - ja:ja_JP.eucJP \ - russian:ru_RU.KOI8-R \ - spanish:es_ES.ISO8859-1 \ - ukrainian:uk_UA.KOI8-U +CATALOGS= et:et_EE.UTF-8 \ + finnish:fi_FI.UTF-8 \ + french:fr_FR.UTF-8 \ + german:de_DE.UTF-8 \ + greek:el_GR.UTF-8 \ + italian:it_IT.UTF-8 \ + ja:ja_JP.UTF-8 \ + russian:ru_RU.UTF-8 \ + spanish:es_ES.UTF-8 \ + ukrainian:uk_UA.UTF-8 -NLSLINKS_fi_FI.ISO8859-1= fi_FI.ISO8859-15 -NLSLINKS_fr_FR.ISO8859-1= fr_BE.ISO8859-1 fr_BE.ISO8859-15 \ - fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \ - fr_CH.ISO8859-15 fr_FR.ISO8859-15 -NLSLINKS_de_DE.ISO8859-1= de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \ - de_CH.ISO8859-15 de_DE.ISO8859-15 -NLSLINKS_it_IT.ISO8859-1= it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-15 -NLSLINKS_es_ES.ISO8859-1= es_ES.ISO8859-15 +NLSLINKS_de_DE.UTF-8 = de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8 +NLSLINKS_fr_FR.UTF-8 = fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 +NLSLINKS_it_IT.UTF-8 = it_CH.UTF-8 .if ${MK_NLS_CATALOGS} == "no" || defined(RESCUE) CFLAGS+= -DNO_NLS_CATALOGS .else CFLAGS+= -DHAVE_ICONV .if ${MK_ICONV} != "no" -NLSLINKS_de_DE.ISO8859-1 += de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8 -NLSLINKS_el_GR.ISO8859-7 = el_GR.UTF-8 -NLSLINKS_es_ES.ISO8859-1 += es_ES.UTF-8 -NLSLINKS_et_EE.ISO8859-15 = et_EE.UTF-8 -NLSLINKS_fi_FI.ISO8859-1 += fi_FI.UTF-8 -NLSLINKS_fr_FR.ISO8859-1 += fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 fr_FR.UTF-8 -NLSLINKS_it_IT.ISO8859-1 += it_CH.UTF-8 it_IT.UTF-8 -NLSLINKS_ja_JP.eucJP = ja_JP.SJIS ja_JP.UTF-8 -NLSLINKS_ru_RU.KOI8-R = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.UTF-8 -NLSLINKS_uk_UA.KOI8-U = uk_UA.ISO8859-5 uk_UA.UTF-8 +NLSLINKS_de_DE.UTF-8 += de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \ + de_CH.ISO8859-15 de_DE.ISO8859-1 de_DE.ISO8859-15 +NLSLINKS_el_GR.UTF-8 = el_GR.ISO8859-7 +NLSLINKS_es_ES.UTF-8 = es_ES.ISO8859-1 es_ES.ISO8859-15 +NLSLINKS_et_EE.UTF-8 = et_EE.ISO8859-15 +NLSLINKS_fi_FI.UTF-8 = fi_FI.ISO8859-1 fi_FI.ISO8859-15 +NLSLINKS_fr_FR.UTF-8 += fr_BE.ISO8859-1 fr_BE.ISO8859-15 \ + fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \ + fr_CH.ISO8859-15 fr_FR.ISO8859-1 fr_FR.ISO8859-15 +NLSLINKS_it_IT.UTF-8 += it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-1 \ + it_IT.ISO8859-15 +NLSLINKS_ja_JP.UTF-8 = ja_JP.SJIS ja_JP.eucJP +NLSLINKS_ru_RU.UTF-8 = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.KOI8-R +NLSLINKS_uk_UA.UTF-8 = uk_UA.ISO8859-5 uk_UA.KOI8-U .else # Above links can be installed from ports/shells/tcsh_nls From 8fba5119d8c590b526917c91f673b02f4e5d6062 Mon Sep 17 00:00:00 2001 From: skra Date: Wed, 3 Feb 2016 12:11:07 +0000 Subject: [PATCH 151/236] Partly revert r295168 and define PTE_DEVICE in pmap-v6.h header again. It turned out that devmap.c is not only file in which PTE_DEVICE is used and simultaneously, built for both armv4 and armv6 platforms. When I tried to build all arm kernels before r295168 commit, it was hid by some other local changes in my tree. I hope that this is just temporary workaround before VM_MEMATTR_DEVICE could be used instead of PTE_DEVICE outside of pmap code for __ARM_ARCH < 6. --- sys/arm/arm/devmap.c | 3 --- sys/arm/include/pmap-v6.h | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/arm/arm/devmap.c b/sys/arm/arm/devmap.c index 4dffa8cc7a2b..011b5797881a 100644 --- a/sys/arm/arm/devmap.c +++ b/sys/arm/arm/devmap.c @@ -55,9 +55,6 @@ static boolean_t devmap_bootstrap_done = false; #define PTE_DEVICE VM_MEMATTR_DEVICE #elif defined(__arm__) #define MAX_VADDR ARM_VECTORS_HIGH -#if __ARM_ARCH >= 6 -#define PTE_DEVICE VM_MEMATTR_DEVICE -#endif #endif /* diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index d5223845fb02..b380c29dded0 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -250,6 +250,8 @@ void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t, */ void vector_page_setprot(int); +#define PTE_DEVICE VM_MEMATTR_DEVICE + #endif /* _KERNEL */ // ----------------------------------------------------------------------------- From 3deeea8140f02e68d569a9d3e8f4f101d8fbdb49 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 13:47:50 +0000 Subject: [PATCH 152/236] ARM: Replace only once used cpu_icache_sync_all() by ranged equivalent. Remove it from cpu_functions table. --- sys/arm/arm/cpufunc.c | 9 --------- sys/arm/arm/cpufunc_asm_arm11x6.S | 6 ------ sys/arm/arm/cpufunc_asm_arm9.S | 4 +--- sys/arm/arm/cpufunc_asm_armv5_ec.S | 4 +--- sys/arm/arm/cpufunc_asm_armv7.S | 10 ---------- sys/arm/arm/cpufunc_asm_fa526.S | 13 ++++++------- sys/arm/arm/elf_machdep.c | 2 +- sys/arm/arm/genassym.c | 1 - sys/arm/include/cpufunc.h | 12 ++---------- 9 files changed, 11 insertions(+), 50 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 2b226ef988c8..370bab7c53dc 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -110,7 +110,6 @@ struct cpu_functions arm9_cpufuncs = { /* Cache operations */ - arm9_icache_sync_all, /* icache_sync_all */ arm9_icache_sync_range, /* icache_sync_range */ arm9_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -162,7 +161,6 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Cache operations */ - armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -213,7 +211,6 @@ struct cpu_functions sheeva_cpufuncs = { /* Cache operations */ - armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -264,7 +261,6 @@ struct cpu_functions pj4bv7_cpufuncs = { armv7_tlb_flushID_SE, /* tlb_flushD_SE */ /* Cache operations */ - armv7_idcache_wbinv_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -316,7 +312,6 @@ struct cpu_functions xscale_cpufuncs = { /* Cache operations */ - xscale_cache_syncI, /* icache_sync_all */ xscale_cache_syncI_rng, /* icache_sync_range */ xscale_cache_purgeD, /* dcache_wbinv_all */ @@ -368,7 +363,6 @@ struct cpu_functions xscalec3_cpufuncs = { /* Cache operations */ - xscalec3_cache_syncI, /* icache_sync_all */ xscalec3_cache_syncI_rng, /* icache_sync_range */ xscalec3_cache_purgeD, /* dcache_wbinv_all */ @@ -420,7 +414,6 @@ struct cpu_functions fa526_cpufuncs = { /* Cache operations */ - fa526_icache_sync_all, /* icache_sync_all */ fa526_icache_sync_range, /* icache_sync_range */ fa526_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -472,7 +465,6 @@ struct cpu_functions arm1176_cpufuncs = { /* Cache operations */ - arm11x6_icache_sync_all, /* icache_sync_all */ arm11x6_icache_sync_range, /* icache_sync_range */ arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -528,7 +520,6 @@ struct cpu_functions cortexa_cpufuncs = { /* Cache operations */ - armv7_icache_sync_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ diff --git a/sys/arm/arm/cpufunc_asm_arm11x6.S b/sys/arm/arm/cpufunc_asm_arm11x6.S index be6d5309d935..793c690c9fd3 100644 --- a/sys/arm/arm/cpufunc_asm_arm11x6.S +++ b/sys/arm/arm/cpufunc_asm_arm11x6.S @@ -132,12 +132,6 @@ ENTRY_NP(arm11x6_dcache_wbinv_all) RET END(arm11x6_dcache_wbinv_all) -ENTRY_NP(arm11x6_icache_sync_all) - Flush_D_cache(r0) - Invalidate_I_cache(r0, r1) - RET -END(arm11x6_icache_sync_all) - ENTRY_NP(arm11x6_icache_sync_range) add r1, r1, r0 sub r1, r1, #1 diff --git a/sys/arm/arm/cpufunc_asm_arm9.S b/sys/arm/arm/cpufunc_asm_arm9.S index 9247b0c42b1c..aaadcfe6cc2b 100644 --- a/sys/arm/arm/cpufunc_asm_arm9.S +++ b/sys/arm/arm/cpufunc_asm_arm9.S @@ -85,9 +85,7 @@ ENTRY_NP(arm9_icache_sync_range) subs r1, r1, ip bhi .Larm9_sync_next mov pc, lr -END(arm9_icache_sync_range) -ENTRY_NP(arm9_icache_sync_all) .Larm9_icache_sync_all: /* * We assume that the code here can never be out of sync with the @@ -109,7 +107,7 @@ ENTRY_NP(arm9_icache_sync_all) subs s_max, s_max, s_inc bhs .Lnext_set /* Next set */ mov pc, lr -END(arm9_icache_sync_all) +END(arm9_icache_sync_range) .Larm9_line_size: .word _C_LABEL(arm_pdcache_line_size) diff --git a/sys/arm/arm/cpufunc_asm_armv5_ec.S b/sys/arm/arm/cpufunc_asm_armv5_ec.S index 31174c659377..29e22b0975f0 100644 --- a/sys/arm/arm/cpufunc_asm_armv5_ec.S +++ b/sys/arm/arm/cpufunc_asm_armv5_ec.S @@ -91,9 +91,7 @@ ENTRY_NP(armv5_ec_icache_sync_range) bpl 1b mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ RET -END(armv5_ec_icache_sync_range) -ENTRY_NP(armv5_ec_icache_sync_all) .Larmv5_ec_icache_sync_all: /* * We assume that the code here can never be out of sync with the @@ -109,7 +107,7 @@ ENTRY_NP(armv5_ec_icache_sync_all) bne 1b /* More to do? */ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ RET -END(armv5_ec_icache_sync_all) +END(armv5_ec_icache_sync_range) .Larmv5_ec_line_size: .word _C_LABEL(arm_pdcache_line_size) diff --git a/sys/arm/arm/cpufunc_asm_armv7.S b/sys/arm/arm/cpufunc_asm_armv7.S index 42ccc6dd47e2..affd52811282 100644 --- a/sys/arm/arm/cpufunc_asm_armv7.S +++ b/sys/arm/arm/cpufunc_asm_armv7.S @@ -252,16 +252,6 @@ ENTRY(armv7_idcache_wbinv_range) RET END(armv7_idcache_wbinv_range) -ENTRY_NP(armv7_icache_sync_all) -#ifdef SMP - mcr CP15_ICIALLUIS -#else - mcr CP15_ICIALLU -#endif - dsb /* data synchronization barrier */ - isb /* instruction synchronization barrier */ - RET -END(armv7_icache_sync_all) ENTRY_NP(armv7_icache_sync_range) ldr ip, .Larmv7_icache_line_size diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index 38cb11ad5323..20530ac41951 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -83,12 +83,6 @@ ENTRY(fa526_idcache_wbinv_all) mov pc, lr END(fa526_idcache_wbinv_all) -ENTRY(fa526_icache_sync_all) - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */ - mov pc, lr -END(fa526_icache_sync_all) - ENTRY(fa526_dcache_wbinv_all) mov r0, #0 mcr p15, 0, r0, c7, c14, 0 /* clean and invalidate D$ */ @@ -170,7 +164,7 @@ END(fa526_idcache_wbinv_range) ENTRY(fa526_icache_sync_range) cmp r1, #0x4000 - bhs _C_LABEL(fa526_icache_sync_all) + bhs .Lfa526_icache_sync_all and r2, r0, #(CACHELINE_SIZE - 1) add r1, r1, r2 @@ -184,6 +178,11 @@ ENTRY(fa526_icache_sync_range) 2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ mov pc, lr + +.Lfa526_icache_sync_all: + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */ + mov pc, lr END(fa526_icache_sync_range) ENTRY(fa526_context_switch) diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 7dbdc912c821..2ec659aba802 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -282,7 +282,7 @@ elf_cpu_load_file(linker_file_t lf) #else cpu_dcache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size); cpu_l2cache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size); - cpu_icache_sync_all(); + cpu_icache_sync_range((vm_offset_t)lf->address, (vm_size_t)lf->size); #endif return (0); } diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index eb4e51b81bba..31910b787903 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -101,7 +101,6 @@ ASSYM(CF_L2CACHE_WB_RANGE, offsetof(struct cpu_functions, cf_l2cache_wb_range)); ASSYM(CF_IDCACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_idcache_wbinv_all)); ASSYM(CF_L2CACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_l2cache_wbinv_all)); ASSYM(CF_TLB_FLUSHID_SE, offsetof(struct cpu_functions, cf_tlb_flushID_SE)); -ASSYM(CF_ICACHE_SYNC, offsetof(struct cpu_functions, cf_icache_sync_all)); ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap)); ASSYM(V_SOFT, offsetof(struct vmmeter, v_soft)); diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 726c808dbedb..85826f0b4dd8 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -79,7 +79,6 @@ struct cpu_functions { * * We define the following primitives: * - * icache_sync_all Synchronize I-cache * icache_sync_range Synchronize I-cache range * * dcache_wbinv_all Write-back and Invalidate D-cache @@ -104,7 +103,7 @@ struct cpu_functions { * state (such as when it may have lines tagged as valid * that belong to a previous set of mappings). * - * I-cache Synch (all or range): + * I-cache Sync range: * The goal is to synchronize the instruction stream, * so you may beed to write-back dirty D-cache blocks * first. If a range is requested, and you can't @@ -130,7 +129,6 @@ struct cpu_functions { * Valid virtual addresses must be passed to each * cache operation. */ - void (*cf_icache_sync_all) (void); void (*cf_icache_sync_range) (vm_offset_t, vm_size_t); void (*cf_dcache_wbinv_all) (void); @@ -173,7 +171,6 @@ extern u_int cputype; #define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD() #define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e) -#define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all() #define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s)) #define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all() @@ -214,7 +211,6 @@ void fa526_context_switch (void); void fa526_cpu_sleep (int); void fa526_tlb_flushID_SE (u_int); -void fa526_icache_sync_all (void); void fa526_icache_sync_range(vm_offset_t start, vm_size_t end); void fa526_dcache_wbinv_all (void); void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end); @@ -231,8 +227,7 @@ void arm9_tlb_flushID_SE (u_int va); void arm9_context_switch (void); #endif -#if defined(CPU_ARM9) -void arm9_icache_sync_all (void); +#if defined(CPU_ARM9) void arm9_icache_sync_range (vm_offset_t, vm_size_t); void arm9_dcache_wbinv_all (void); @@ -275,7 +270,6 @@ void armv6_idcache_wbinv_all (void); void armv7_setttb (u_int); void armv7_tlb_flushID (void); void armv7_tlb_flushID_SE (u_int); -void armv7_icache_sync_all (void); void armv7_icache_sync_range (vm_offset_t, vm_size_t); void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t); void armv7_idcache_inv_all (void); @@ -319,7 +313,6 @@ void armv6_idcache_inv_all (void); void arm11x6_setttb (u_int); void arm11x6_idcache_wbinv_all (void); void arm11x6_dcache_wbinv_all (void); -void arm11x6_icache_sync_all (void); void arm11x6_icache_sync_range (vm_offset_t, vm_size_t); void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t); void arm11x6_setup (void); @@ -329,7 +322,6 @@ void arm11x6_sleep (int); /* no ref. for errata */ #if defined(CPU_ARM9E) void armv5_ec_setttb(u_int); -void armv5_ec_icache_sync_all(void); void armv5_ec_icache_sync_range(vm_offset_t, vm_size_t); void armv5_ec_dcache_wbinv_all(void); From fcb93180f54ede665ea60822a8bd1766002246d0 Mon Sep 17 00:00:00 2001 From: pfg Date: Wed, 3 Feb 2016 14:31:23 +0000 Subject: [PATCH 153/236] Revert r294695: ext2fs: passthrough any extra timestamps to the dinode struct. While it passed the classic testing, the change appears to have caused some regression and still requires some more precautions. PR: 206820 MFC after: 3 days --- sys/fs/ext2fs/ext2_inode_cnv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index 78679cff0fdb..d62e9ba0a92e 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -149,11 +149,13 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei) ei->e2di_atime = ip->i_atime; ei->e2di_mtime = ip->i_mtime; ei->e2di_ctime = ip->i_ctime; - ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); - ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); - ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); - ei->e2di_crtime = ip->i_birthtime; - ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + if (E2DI_HAS_XTIME(ip)) { + ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); + ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); + ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); + ei->e2di_crtime = ip->i_birthtime; + ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + } ei->e2di_flags = 0; ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0; ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0; From 960d14828b1b4d2b62d2fe8f0f67e4325b81cadf Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 3 Feb 2016 14:34:25 +0000 Subject: [PATCH 154/236] Still open the network interface when EFI_OPEN_PROTOCOL_EXCLUSIVE failed. Not all UEFI implementations support this protocol. --- sys/boot/efi/libefi/efinet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index d9ecdcc45f1c..b7888aaed5fc 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -309,8 +309,8 @@ efinet_dev_init() status = BS->OpenProtocol(h, &sn_guid, (void **)&net, IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE); if (status != EFI_SUCCESS) { - printf("Unable to open network interface %d\n", i); - continue; + printf("Unable to open network interface %d for " + "exclusive access\n", i); } dif->dif_unit = i; From dac55bd53a9f0a5723fd92b25c6b2be58c7c0142 Mon Sep 17 00:00:00 2001 From: jceel Date: Wed, 3 Feb 2016 15:45:13 +0000 Subject: [PATCH 155/236] Add an additional, libucl-based configuration file parser to ctld. Default ctld behavior remains unchanged - libucl parser can be selected explicitly by adding -u switch to ctld command line. Reviewed by: trasz Approved by: trasz (mentor) MFC after: 1 month Relnotes: yes Sponsored by: iXsystems, Inc. Differential Revision: https://reviews.freebsd.org/D4534 --- usr.sbin/ctld/Makefile | 7 +- usr.sbin/ctld/ctld.c | 112 ++++- usr.sbin/ctld/ctld.h | 4 +- usr.sbin/ctld/parse.y | 93 +--- usr.sbin/ctld/uclparse.c | 900 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 1023 insertions(+), 93 deletions(-) create mode 100644 usr.sbin/ctld/uclparse.c diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile index 6169d308ef2c..664dc22efbb1 100644 --- a/usr.sbin/ctld/Makefile +++ b/usr.sbin/ctld/Makefile @@ -1,8 +1,11 @@ # $FreeBSD$ +CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include +.PATH: ${.CURDIR}/../../contrib/libucl/include + PROG= ctld SRCS= chap.c ctld.c discovery.c isns.c kernel.c keys.c log.c -SRCS+= login.c parse.y pdu.c token.l y.tab.h +SRCS+= login.c parse.y pdu.c token.l y.tab.h uclparse.c CFLAGS+= -I${.CURDIR} CFLAGS+= -I${.CURDIR}/../../sys CFLAGS+= -I${.CURDIR}/../../sys/cam/ctl @@ -10,7 +13,7 @@ CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi #CFLAGS+= -DICL_KERNEL_PROXY MAN= ctld.8 ctl.conf.5 -LIBADD= bsdxml l md sbuf util +LIBADD= bsdxml l md sbuf util ucl m YFLAGS+= -v CLEANFILES= y.tab.c y.tab.h y.output diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c index 92fa5539f7f6..6c8b4a89fe93 100644 --- a/usr.sbin/ctld/ctld.c +++ b/usr.sbin/ctld/ctld.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2491,6 +2492,104 @@ register_signals(void) log_err(1, "sigaction"); } +static void +check_perms(const char *path) +{ + struct stat sb; + int error; + + error = stat(path, &sb); + if (error != 0) { + log_warn("stat"); + return; + } + if (sb.st_mode & S_IWOTH) { + log_warnx("%s is world-writable", path); + } else if (sb.st_mode & S_IROTH) { + log_warnx("%s is world-readable", path); + } else if (sb.st_mode & S_IXOTH) { + /* + * Ok, this one doesn't matter, but still do it, + * just for consistency. + */ + log_warnx("%s is world-executable", path); + } + + /* + * XXX: Should we also check for owner != 0? + */ +} + +static struct conf * +conf_new_from_file(const char *path, struct conf *oldconf, bool ucl) +{ + struct conf *conf; + struct auth_group *ag; + struct portal_group *pg; + struct pport *pp; + int error; + + log_debugx("obtaining configuration from %s", path); + + conf = conf_new(); + + TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) + pport_copy(pp, conf); + + ag = auth_group_new(conf, "default"); + assert(ag != NULL); + + ag = auth_group_new(conf, "no-authentication"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_NO_AUTHENTICATION; + + ag = auth_group_new(conf, "no-access"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_DENY; + + pg = portal_group_new(conf, "default"); + assert(pg != NULL); + + if (ucl) + error = uclparse_conf(conf, path); + else + error = parse_conf(conf, path); + + if (error != 0) { + conf_delete(conf); + return (NULL); + } + + check_perms(path); + + if (conf->conf_default_ag_defined == false) { + log_debugx("auth-group \"default\" not defined; " + "going with defaults"); + ag = auth_group_find(conf, "default"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_DENY; + } + + if (conf->conf_default_pg_defined == false) { + log_debugx("portal-group \"default\" not defined; " + "going with defaults"); + pg = portal_group_find(conf, "default"); + assert(pg != NULL); + portal_group_add_listen(pg, "0.0.0.0:3260", false); + portal_group_add_listen(pg, "[::]:3260", false); + } + + conf->conf_kernel_port_on = true; + + error = conf_verify(conf); + if (error != 0) { + conf_delete(conf); + return (NULL); + } + + return (conf); +} + int main(int argc, char **argv) { @@ -2499,13 +2598,17 @@ main(int argc, char **argv) const char *config_path = DEFAULT_CONFIG_PATH; int debug = 0, ch, error; bool dont_daemonize = false; + bool use_ucl = false; - while ((ch = getopt(argc, argv, "df:R")) != -1) { + while ((ch = getopt(argc, argv, "duf:R")) != -1) { switch (ch) { case 'd': dont_daemonize = true; debug++; break; + case 'u': + use_ucl = true; + break; case 'f': config_path = optarg; break; @@ -2529,7 +2632,8 @@ main(int argc, char **argv) kernel_init(); oldconf = conf_new_from_kernel(); - newconf = conf_new_from_file(config_path, oldconf); + newconf = conf_new_from_file(config_path, oldconf, use_ucl); + if (newconf == NULL) log_errx(1, "configuration error; exiting"); if (debug > 0) { @@ -2564,7 +2668,9 @@ main(int argc, char **argv) if (sighup_received) { sighup_received = false; log_debugx("received SIGHUP, reloading configuration"); - tmpconf = conf_new_from_file(config_path, newconf); + tmpconf = conf_new_from_file(config_path, newconf, + use_ucl); + if (tmpconf == NULL) { log_warnx("configuration error, " "continuing with old configuration"); diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h index 808b722aa542..e9152329121f 100644 --- a/usr.sbin/ctld/ctld.h +++ b/usr.sbin/ctld/ctld.h @@ -297,8 +297,10 @@ int rchap_receive(struct rchap *rchap, char *rchap_get_response(struct rchap *rchap); void rchap_delete(struct rchap *rchap); +int parse_conf(struct conf *conf, const char *path); +int uclparse_conf(struct conf *conf, const char *path); + struct conf *conf_new(void); -struct conf *conf_new_from_file(const char *path, struct conf *old); struct conf *conf_new_from_kernel(void); void conf_delete(struct conf *conf); int conf_verify(struct conf *conf); diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y index afbf315bf02d..820b4c7d4bc1 100644 --- a/usr.sbin/ctld/parse.y +++ b/usr.sbin/ctld/parse.y @@ -1044,70 +1044,18 @@ yyerror(const char *str) lineno, yytext, str); } -static void -check_perms(const char *path) +int +parse_conf(struct conf *newconf, const char *path) { - struct stat sb; int error; - error = stat(path, &sb); - if (error != 0) { - log_warn("stat"); - return; - } - if (sb.st_mode & S_IWOTH) { - log_warnx("%s is world-writable", path); - } else if (sb.st_mode & S_IROTH) { - log_warnx("%s is world-readable", path); - } else if (sb.st_mode & S_IXOTH) { - /* - * Ok, this one doesn't matter, but still do it, - * just for consistency. - */ - log_warnx("%s is world-executable", path); - } - - /* - * XXX: Should we also check for owner != 0? - */ -} - -struct conf * -conf_new_from_file(const char *path, struct conf *oldconf) -{ - struct auth_group *ag; - struct portal_group *pg; - struct pport *pp; - int error; - - log_debugx("obtaining configuration from %s", path); - - conf = conf_new(); - - TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) - pport_copy(pp, conf); - - ag = auth_group_new(conf, "default"); - assert(ag != NULL); - - ag = auth_group_new(conf, "no-authentication"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_NO_AUTHENTICATION; - - ag = auth_group_new(conf, "no-access"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_DENY; - - pg = portal_group_new(conf, "default"); - assert(pg != NULL); - + conf = newconf; yyin = fopen(path, "r"); if (yyin == NULL) { log_warn("unable to open configuration file %s", path); - conf_delete(conf); - return (NULL); + return (1); } - check_perms(path); + lineno = 1; yyrestart(yyin); error = yyparse(); @@ -1116,35 +1064,6 @@ conf_new_from_file(const char *path, struct conf *oldconf) target = NULL; lun = NULL; fclose(yyin); - if (error != 0) { - conf_delete(conf); - return (NULL); - } - if (conf->conf_default_ag_defined == false) { - log_debugx("auth-group \"default\" not defined; " - "going with defaults"); - ag = auth_group_find(conf, "default"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_DENY; - } - - if (conf->conf_default_pg_defined == false) { - log_debugx("portal-group \"default\" not defined; " - "going with defaults"); - pg = portal_group_find(conf, "default"); - assert(pg != NULL); - portal_group_add_listen(pg, "0.0.0.0:3260", false); - portal_group_add_listen(pg, "[::]:3260", false); - } - - conf->conf_kernel_port_on = true; - - error = conf_verify(conf); - if (error != 0) { - conf_delete(conf); - return (NULL); - } - - return (conf); + return (error); } diff --git a/usr.sbin/ctld/uclparse.c b/usr.sbin/ctld/uclparse.c new file mode 100644 index 000000000000..fb2cce0a144e --- /dev/null +++ b/usr.sbin/ctld/uclparse.c @@ -0,0 +1,900 @@ +/*- + * Copyright (c) 2015 iXsystems Inc. + * All rights reserved. + * + * This software was developed by Jakub Klama + * under sponsorship from iXsystems Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ctld.h" + +static struct conf *conf = NULL; + +static int uclparse_toplevel(const ucl_object_t *); +static int uclparse_chap(struct auth_group *, const ucl_object_t *); +static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *); +static int uclparse_lun(const char *, const ucl_object_t *); +static int uclparse_auth_group(const char *, const ucl_object_t *); +static int uclparse_portal_group(const char *, const ucl_object_t *); +static int uclparse_target(const char *, const ucl_object_t *); +static int uclparse_target_portal_group(struct target *, const ucl_object_t *); +static int uclparse_target_lun(struct target *, const ucl_object_t *); + +static int +uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj) +{ + const struct auth *ca; + const ucl_object_t *user, *secret; + + user = ucl_object_find_key(obj, "user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap section in auth-group \"%s\" is missing " + "\"user\" string key", auth_group->ag_name); + return (1); + } + + secret = ucl_object_find_key(obj, "secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap section in auth-group \"%s\" is missing " + "\"secret\" string key", auth_group->ag_name); + } + + ca = auth_new_chap(auth_group, + ucl_object_tostring(user), + ucl_object_tostring(secret)); + + if (ca == NULL) + return (1); + + return (0); +} + +static int +uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj) +{ + const struct auth *ca; + const ucl_object_t *user, *secret, *mutual_user; + const ucl_object_t *mutual_secret; + + user = ucl_object_find_key(obj, "user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"user\" string key", auth_group->ag_name); + return (1); + } + + secret = ucl_object_find_key(obj, "secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"secret\" string key", auth_group->ag_name); + return (1); + } + + mutual_user = ucl_object_find_key(obj, "mutual-user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"mutual-user\" string key", auth_group->ag_name); + return (1); + } + + mutual_secret = ucl_object_find_key(obj, "mutual-secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"mutual-secret\" string key", auth_group->ag_name); + return (1); + } + + ca = auth_new_chap_mutual(auth_group, + ucl_object_tostring(user), + ucl_object_tostring(secret), + ucl_object_tostring(mutual_user), + ucl_object_tostring(mutual_secret)); + + if (ca == NULL) + return (1); + + return (0); +} + +static int +uclparse_target_portal_group(struct target *target, const ucl_object_t *obj) +{ + struct portal_group *tpg; + struct auth_group *tag = NULL; + struct port *tp; + const ucl_object_t *portal_group, *auth_group; + + portal_group = ucl_object_find_key(obj, "name"); + if (!portal_group || portal_group->type != UCL_STRING) { + log_warnx("portal-group section in target \"%s\" is missing " + "\"name\" string key", target->t_name); + return (1); + } + + auth_group = ucl_object_find_key(obj, "auth-group-name"); + if (auth_group && auth_group->type != UCL_STRING) { + log_warnx("portal-group section in target \"%s\" is missing " + "\"auth-group-name\" string key", target->t_name); + return (1); + } + + + tpg = portal_group_find(conf, ucl_object_tostring(portal_group)); + if (tpg == NULL) { + log_warnx("unknown portal-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(portal_group), target->t_name); + return (1); + } + + if (auth_group) { + tag = auth_group_find(conf, ucl_object_tostring(auth_group)); + if (tag == NULL) { + log_warnx("unknown auth-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(auth_group), + target->t_name); + return (1); + } + } + + tp = port_new(conf, target, tpg); + if (tp == NULL) { + log_warnx("can't link portal-group \"%s\" to target " + "\"%s\"", ucl_object_tostring(portal_group), target->t_name); + return (1); + } + tp->p_auth_group = tag; + + return (0); +} + +static int +uclparse_target_lun(struct target *target, const ucl_object_t *obj) +{ + struct lun *lun; + + if (obj->type == UCL_INT) { + char *name; + + asprintf(&name, "%s,lun,%ju", target->t_name, + ucl_object_toint(obj)); + lun = lun_new(conf, name); + if (lun == NULL) + return (1); + + lun_set_scsiname(lun, name); + target->t_luns[ucl_object_toint(obj)] = lun; + return (0); + } + + if (obj->type == UCL_OBJECT) { + const ucl_object_t *num = ucl_object_find_key(obj, "number"); + const ucl_object_t *name = ucl_object_find_key(obj, "name"); + + if (num == NULL || num->type != UCL_INT) { + log_warnx("lun section in target \"%s\" is missing " + "\"number\" integer property", target->t_name); + return (1); + } + + if (name == NULL || name->type != UCL_STRING) { + log_warnx("lun section in target \"%s\" is missing " + "\"name\" string property", target->t_name); + return (1); + } + + lun = lun_find(conf, ucl_object_tostring(name)); + if (lun == NULL) + return (1); + + target->t_luns[ucl_object_toint(num)] = lun; + } + + return (0); +} + +static int +uclparse_toplevel(const ucl_object_t *top) +{ + ucl_object_iter_t it = NULL, iter = NULL; + const ucl_object_t *obj = NULL, *child = NULL; + int err = 0; + + /* Pass 1 - everything except targets */ + while ((obj = ucl_iterate_object(top, &it, true))) { + const char *key = ucl_object_key(obj); + + if (!strcmp(key, "debug")) { + if (obj->type == UCL_INT) + conf->conf_debug = ucl_object_toint(obj); + else { + log_warnx("\"debug\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "timeout")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"timeout\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "maxproc")) { + if (obj->type == UCL_INT) + conf->conf_maxproc = ucl_object_toint(obj); + else { + log_warnx("\"maxproc\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "pidfile")) { + if (obj->type == UCL_STRING) + conf->conf_pidfile_path = strdup( + ucl_object_tostring(obj)); + else { + log_warnx("\"pidfile\" property value is not string"); + return (1); + } + } + + if (!strcmp(key, "isns-server")) { + if (obj->type == UCL_ARRAY) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, + true))) { + if (child->type != UCL_STRING) + return (1); + + err = isns_new(conf, + ucl_object_tostring(child)); + if (err != 0) { + return (1); + } + } + } else { + log_warnx("\"isns-server\" property value is " + "not an array"); + return (1); + } + } + + if (!strcmp(key, "isns-period")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"isns-period\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "isns-timeout")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"isns-timeout\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "auth-group")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_auth_group(ucl_object_key(child), child); + } + } else { + log_warnx("\"auth-group\" section is not an object"); + return (1); + } + } + + if (!strcmp(key, "portal-group")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_portal_group(ucl_object_key(child), child); + } + } else { + log_warnx("\"portal-group\" section is not an object"); + return (1); + } + } + + if (!strcmp(key, "lun")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_lun(ucl_object_key(child), child); + } + } else { + log_warnx("\"lun\" section is not an object"); + return (1); + } + } + } + + /* Pass 2 - targets */ + it = NULL; + while ((obj = ucl_iterate_object(top, &it, true))) { + const char *key = ucl_object_key(obj); + + if (!strcmp(key, "target")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, + true))) { + uclparse_target(ucl_object_key(child), + child); + } + } else { + log_warnx("\"target\" section is not an object"); + return (1); + } + } + } + + return (0); +} + +static int +uclparse_auth_group(const char *name, const ucl_object_t *top) +{ + struct auth_group *auth_group; + const struct auth_name *an; + const struct auth_portal *ap; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + int err; + + if (!strcmp(name, "default") && + conf->conf_default_ag_defined == false) { + auth_group = auth_group_find(conf, name); + conf->conf_default_ag_defined = true; + } else { + auth_group = auth_group_new(conf, name); + } + + if (auth_group == NULL) + return (1); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "auth-type")) { + const char *value = ucl_object_tostring(obj); + + err = auth_group_set_type(auth_group, value); + if (err) + return (1); + } + + if (!strcmp(key, "chap")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"chap\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_chap(auth_group, tmp) != 0) + return (1); + } + } + + if (!strcmp(key, "chap-mutual")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"chap-mutual\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_chap_mutual(auth_group, tmp) != 0) + return (1); + } + } + + if (!strcmp(key, "initiator-name")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"initiator-name\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + const char *value = ucl_object_tostring(tmp); + + an = auth_name_new(auth_group, value); + if (an == NULL) + return (1); + } + } + + if (!strcmp(key, "initiator-portal")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"initiator-portal\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + const char *value = ucl_object_tostring(tmp); + + ap = auth_portal_new(auth_group, value); + if (ap == NULL) + return (1); + } + } + } + + return (0); +} + +static int +uclparse_portal_group(const char *name, const ucl_object_t *top) +{ + struct portal_group *portal_group; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + + if (strcmp(name, "default") == 0 && + conf->conf_default_pg_defined == false) { + portal_group = portal_group_find(conf, name); + conf->conf_default_pg_defined = true; + } else { + portal_group = portal_group_new(conf, name); + } + + if (portal_group == NULL) + return (1); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "discovery-auth-group")) { + portal_group->pg_discovery_auth_group = + auth_group_find(conf, ucl_object_tostring(obj)); + if (portal_group->pg_discovery_auth_group == NULL) { + log_warnx("unknown discovery-auth-group \"%s\" " + "for portal-group \"%s\"", + ucl_object_tostring(obj), + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "discovery-filter")) { + if (obj->type != UCL_STRING) { + log_warnx("\"discovery-filter\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + + if (portal_group_set_filter(portal_group, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "listen")) { + if (obj->type == UCL_STRING) { + if (portal_group_add_listen(portal_group, + ucl_object_tostring(obj), false) != 0) + return (1); + } else if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (portal_group_add_listen( + portal_group, + ucl_object_tostring(tmp), + false) != 0) + return (1); + } + } else { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "listen-iser")) { + if (obj->type == UCL_STRING) { + if (portal_group_add_listen(portal_group, + ucl_object_tostring(obj), true) != 0) + return (1); + } else if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (portal_group_add_listen( + portal_group, + ucl_object_tostring(tmp), + true) != 0) + return (1); + } + } else { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "redirect")) { + if (obj->type != UCL_STRING) { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + + if (portal_group_set_redirection(portal_group, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "options")) { + if (obj->type != UCL_OBJECT) { + log_warnx("\"options\" property of portal group " + "\"%s\" is not an object", portal_group->pg_name); + return (1); + } + + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + option_new(&portal_group->pg_options, + ucl_object_key(tmp), + ucl_object_tostring_forced(tmp)); + } + } + } + + return (0); +} + +static int +uclparse_target(const char *name, const ucl_object_t *top) +{ + struct target *target; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + + target = target_new(conf, name); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "alias")) { + if (obj->type != UCL_STRING) { + log_warnx("\"alias\" property of target " + "\"%s\" is not a string", target->t_name); + return (1); + } + + target->t_alias = strdup(ucl_object_tostring(obj)); + } + + if (!strcmp(key, "auth-group")) { + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) + log_warnx("auth-group for target \"%s\" " + "specified more than once", + target->t_name); + else + log_warnx("cannot use both auth-group " + "and explicit authorisations for " + "target \"%s\"", target->t_name); + return (1); + } + target->t_auth_group = auth_group_find(conf, + ucl_object_tostring(obj)); + if (target->t_auth_group == NULL) { + log_warnx("unknown auth-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(obj), + target->t_name); + return (1); + } + } + + if (!strcmp(key, "auth-type")) { + int error; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "auth-type for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + error = auth_group_set_type(target->t_auth_group, + ucl_object_tostring(obj)); + if (error != 0) + return (1); + } + + if (!strcmp(key, "chap")) { + if (uclparse_chap(target->t_auth_group, obj) != 0) + return (1); + } + + if (!strcmp(key, "chap-mutual")) { + if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) + return (1); + } + + if (!strcmp(key, "initiator-name")) { + const struct auth_name *an; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "initiator-name for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + an = auth_name_new(target->t_auth_group, + ucl_object_tostring(obj)); + if (an == NULL) + return (1); + } + + if (!strcmp(key, "initiator-portal")) { + const struct auth_portal *ap; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "initiator-portal for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + ap = auth_portal_new(target->t_auth_group, + ucl_object_tostring(obj)); + if (ap == NULL) + return (1); + } + + if (!strcmp(key, "portal-group")) { + if (obj->type == UCL_OBJECT) { + if (uclparse_target_portal_group(target, obj) != 0) + return (1); + } + + if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (uclparse_target_portal_group(target, + tmp) != 0) + return (1); + } + } + } + + if (!strcmp(key, "port")) { + struct pport *pp; + struct port *tp; + const char *value = ucl_object_tostring(obj); + + pp = pport_find(conf, value); + if (pp == NULL) { + log_warnx("unknown port \"%s\" for target \"%s\"", + value, target->t_name); + return (1); + } + if (!TAILQ_EMPTY(&pp->pp_ports)) { + log_warnx("can't link port \"%s\" to target \"%s\", " + "port already linked to some target", + value, target->t_name); + return (1); + } + tp = port_new_pp(conf, target, pp); + if (tp == NULL) { + log_warnx("can't link port \"%s\" to target \"%s\"", + value, target->t_name); + return (1); + } + } + + if (!strcmp(key, "redirect")) { + if (obj->type != UCL_STRING) { + log_warnx("\"redirect\" property of target " + "\"%s\" is not a string", target->t_name); + return (1); + } + + if (target_set_redirection(target, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "lun")) { + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_target_lun(target, tmp) != 0) + return (1); + } + } + } + + return (0); +} + +static int +uclparse_lun(const char *name, const ucl_object_t *top) +{ + struct lun *lun; + ucl_object_iter_t it = NULL, child_it = NULL; + const ucl_object_t *obj = NULL, *child = NULL; + const char *key; + + lun = lun_new(conf, name); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "backend")) { + if (obj->type != UCL_STRING) { + log_warnx("\"backend\" property of lun " + "\"%s\" is not a string", + lun->l_name); + return (1); + } + + lun_set_backend(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "blocksize")) { + if (obj->type != UCL_INT) { + log_warnx("\"blocksize\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_blocksize(lun, ucl_object_toint(obj)); + } + + if (!strcmp(key, "device-id")) { + if (obj->type != UCL_STRING) { + log_warnx("\"device-id\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_device_id(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "options")) { + if (obj->type != UCL_OBJECT) { + log_warnx("\"options\" property of lun " + "\"%s\" is not an object", lun->l_name); + return (1); + } + + while ((child = ucl_iterate_object(obj, &child_it, + true))) { + option_new(&lun->l_options, + ucl_object_key(child), + ucl_object_tostring_forced(child)); + } + } + + if (!strcmp(key, "path")) { + if (obj->type != UCL_STRING) { + log_warnx("\"path\" property of lun " + "\"%s\" is not a string", lun->l_name); + return (1); + } + + lun_set_path(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "serial")) { + if (obj->type != UCL_STRING) { + log_warnx("\"serial\" property of lun " + "\"%s\" is not a string", lun->l_name); + return (1); + } + + lun_set_serial(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "size")) { + if (obj->type != UCL_INT) { + log_warnx("\"size\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_size(lun, ucl_object_toint(obj)); + } + } + + return (0); +} + +int +uclparse_conf(struct conf *newconf, const char *path) +{ + struct ucl_parser *parser; + int error; + + conf = newconf; + parser = ucl_parser_new(0); + ucl_parser_add_file(parser, path); + + if (ucl_parser_get_error(parser)) { + log_warn("unable to parse configuration file %s: %s", path, + ucl_parser_get_error(parser)); + return (1); + } + + error = uclparse_toplevel(ucl_parser_get_object(parser)); + + return (error); +} From 9ad64bd8b3b9fdd2ebb2e8a3ccfb22c26b054885 Mon Sep 17 00:00:00 2001 From: mmel Date: Wed, 3 Feb 2016 16:44:06 +0000 Subject: [PATCH 156/236] ARM: Consistently use cpu_setttb() instead of setttb(). Remove unused #define for drain_writebuf. --- sys/arm/arm/machdep.c | 6 +++--- sys/arm/at91/at91_machdep.c | 4 ++-- sys/arm/cavium/cns11xx/econa_machdep.c | 4 ++-- sys/arm/include/cpufunc.h | 3 --- sys/arm/xscale/i8134x/crb_machdep.c | 4 ++-- sys/arm/xscale/ixp425/avila_machdep.c | 4 ++-- sys/arm/xscale/pxa/pxa_machdep.c | 4 ++-- 7 files changed, 13 insertions(+), 16 deletions(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 8d7c39c4d0b9..b4bfa6222c86 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -1622,7 +1622,7 @@ initarm(struct arm_boot_params *abp) cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT); pmap_pa = kernel_l1pt.pv_pa; - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)); @@ -1675,7 +1675,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. @@ -1867,7 +1867,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index 936f145909de..e904780877f0 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -566,7 +566,7 @@ initarm(struct arm_boot_params *abp) arm_devmap_bootstrap(l1pagetable, at91_devmap); cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)); @@ -612,7 +612,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/cavium/cns11xx/econa_machdep.c b/sys/arm/cavium/cns11xx/econa_machdep.c index 159105333f03..e212a100c97f 100644 --- a/sys/arm/cavium/cns11xx/econa_machdep.c +++ b/sys/arm/cavium/cns11xx/econa_machdep.c @@ -275,7 +275,7 @@ initarm(struct arm_boot_params *abp) arm_devmap_bootstrap(l1pagetable, econa_devmap); cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); cninit(); @@ -297,7 +297,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 85826f0b4dd8..b5330021842f 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -412,9 +412,6 @@ void xscalec3_context_switch (void); #endif /* CPU_XSCALE_81342 */ -#define setttb cpu_setttb -#define drain_writebuf cpu_drain_writebuf - /* * Macros for manipulating CPU interrupts */ diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index e306a75a5b12..293696364a32 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* @@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index e033e1357b64..f8632e10ad37 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -353,7 +353,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); @@ -370,7 +370,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index 5cc8d46c0823..2bbb8350a577 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); @@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. From 1ef2c8adf6388662de306ad64df5252c02e3bfbd Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 3 Feb 2016 17:00:19 +0000 Subject: [PATCH 157/236] Handle a misaligned stack pointer exception from userspace. The exception still needs to be enabled, but this will help with testing. Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/trap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index 89d6d0c89f84..10e3f416c2a1 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -374,6 +374,10 @@ do_el0_sync(struct trapframe *frame) case EXCP_UNKNOWN: el0_excp_unknown(frame); break; + case EXCP_SP_ALIGN: + call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp); + userret(td, frame); + break; case EXCP_PC_ALIGN: call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr); userret(td, frame); From 3e3f3a4c0f055b92e0b78acd779955c92fedeb74 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Wed, 3 Feb 2016 20:24:21 +0000 Subject: [PATCH 158/236] Deduplicate distrib-dirs logic from r289086 in distribution. This does it correctly this time, rather than the incorrect version in r295167. Sponsored by: EMC / Isilon Storage Division --- Makefile.inc1 | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 222d7ec2b74f..ccd25d001d60 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1083,16 +1083,14 @@ redistribute: .MAKE .PHONY DISTRIBUTION=lib32 .endif -distrib-dirs: .MAKE .PHONY - ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ - ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} - -distribution: .MAKE .PHONY +distrib-dirs distribution: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} +.if make(distribution) ${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \ METALOG=${METALOG} installconfig +.endif # # buildkernel and installkernel From ba8e82fa42143956086d2cc9170c750bd601dd2c Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 3 Feb 2016 20:39:52 +0000 Subject: [PATCH 159/236] Fix inverse logic. If this is zone_pack, then we shouldn't free the cluster ourselves. Found by review. Since this code is !386 and !amd64 and is executed on error path, pretty sure no one ever executed it. --- sys/dev/cxgb/cxgb_sge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c index d70a94877fcd..2cfad262673b 100644 --- a/sys/dev/cxgb/cxgb_sge.c +++ b/sys/dev/cxgb/cxgb_sge.c @@ -738,7 +738,7 @@ refill_fl(adapter_t *sc, struct sge_fl *q, int n) cl, q->buf_size, refill_fl_cb, &cb_arg, 0); if (err != 0 || cb_arg.error) { - if (q->zone == zone_pack) + if (q->zone != zone_pack) uma_zfree(q->zone, cl); m_free(m); goto done; From 8f977b6c5c07cc8b9c845778b9b384d9e37482ee Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 3 Feb 2016 22:02:36 +0000 Subject: [PATCH 160/236] Move uma_dbg_alloc() and uma_dbg_free() into uma_core.c, which allows to make uma_dbg.h not depend on uma_int.h, which allows to uninclude uma_int.h from the mbuf(9) allocator. --- sys/kern/kern_mbuf.c | 1 - sys/vm/uma_core.c | 103 ++++++++++++++++++++++++++++++++++++++++++- sys/vm/uma_dbg.c | 97 ---------------------------------------- sys/vm/uma_dbg.h | 3 -- 4 files changed, 102 insertions(+), 102 deletions(-) diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index a864c946873c..779c62af32bd 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include /* diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 4600589bd06d..89ed213e82e6 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -275,6 +275,11 @@ void uma_print_stats(void); static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS); static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS); +#ifdef INVARIANTS +static void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item); +static void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item); +#endif + SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL); SYSCTL_PROC(_vm, OID_AUTO, zone_count, CTLFLAG_RD|CTLTYPE_INT, @@ -3607,6 +3612,102 @@ sysctl_handle_uma_zone_cur(SYSCTL_HANDLER_ARGS) return (sysctl_handle_int(oidp, &cur, 0, req)); } +#ifdef INVARIANTS +static uma_slab_t +uma_dbg_getslab(uma_zone_t zone, void *item) +{ + uma_slab_t slab; + uma_keg_t keg; + uint8_t *mem; + + mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); + if (zone->uz_flags & UMA_ZONE_VTOSLAB) { + slab = vtoslab((vm_offset_t)mem); + } else { + /* + * It is safe to return the slab here even though the + * zone is unlocked because the item's allocation state + * essentially holds a reference. + */ + ZONE_LOCK(zone); + keg = LIST_FIRST(&zone->uz_kegs)->kl_keg; + if (keg->uk_flags & UMA_ZONE_HASH) + slab = hash_sfind(&keg->uk_hash, mem); + else + slab = (uma_slab_t)(mem + keg->uk_pgoff); + ZONE_UNLOCK(zone); + } + + return (slab); +} + +/* + * Set up the slab's freei data such that uma_dbg_free can function. + * + */ +static void +uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) +{ + uma_keg_t keg; + int freei; + + if (zone_first_keg(zone) == NULL) + return; + if (slab == NULL) { + slab = uma_dbg_getslab(zone, item); + if (slab == NULL) + panic("uma: item %p did not belong to zone %s\n", + item, zone->uz_name); + } + keg = slab->us_keg; + freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; + + if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) + panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); + + return; +} + +/* + * Verifies freed addresses. Checks for alignment, valid slab membership + * and duplicate frees. + * + */ +static void +uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) +{ + uma_keg_t keg; + int freei; + + if (zone_first_keg(zone) == NULL) + return; + if (slab == NULL) { + slab = uma_dbg_getslab(zone, item); + if (slab == NULL) + panic("uma: Freed item %p did not belong to zone %s\n", + item, zone->uz_name); + } + keg = slab->us_keg; + freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; + + if (freei >= keg->uk_ipers) + panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + if (((freei * keg->uk_rsize) + slab->us_data) != item) + panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) + panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); +} +#endif /* INVARIANTS */ + #ifdef DDB DB_SHOW_COMMAND(uma, db_show_uma) { @@ -3664,4 +3765,4 @@ DB_SHOW_COMMAND(umacache, db_show_umacache) return; } } -#endif +#endif /* DDB */ diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c index 3fbd29b16dea..dcef5c9480cb 100644 --- a/sys/vm/uma_dbg.c +++ b/sys/vm/uma_dbg.c @@ -196,100 +196,3 @@ mtrash_fini(void *mem, int size) { (void)mtrash_ctor(mem, size, NULL, 0); } - -#ifdef INVARIANTS -static uma_slab_t -uma_dbg_getslab(uma_zone_t zone, void *item) -{ - uma_slab_t slab; - uma_keg_t keg; - uint8_t *mem; - - mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); - if (zone->uz_flags & UMA_ZONE_VTOSLAB) { - slab = vtoslab((vm_offset_t)mem); - } else { - /* - * It is safe to return the slab here even though the - * zone is unlocked because the item's allocation state - * essentially holds a reference. - */ - ZONE_LOCK(zone); - keg = LIST_FIRST(&zone->uz_kegs)->kl_keg; - if (keg->uk_flags & UMA_ZONE_HASH) - slab = hash_sfind(&keg->uk_hash, mem); - else - slab = (uma_slab_t)(mem + keg->uk_pgoff); - ZONE_UNLOCK(zone); - } - - return (slab); -} - -/* - * Set up the slab's freei data such that uma_dbg_free can function. - * - */ -void -uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) -{ - uma_keg_t keg; - int freei; - - if (zone_first_keg(zone) == NULL) - return; - if (slab == NULL) { - slab = uma_dbg_getslab(zone, item); - if (slab == NULL) - panic("uma: item %p did not belong to zone %s\n", - item, zone->uz_name); - } - keg = slab->us_keg; - freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; - - if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) - panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); - - return; -} - -/* - * Verifies freed addresses. Checks for alignment, valid slab membership - * and duplicate frees. - * - */ -void -uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) -{ - uma_keg_t keg; - int freei; - - if (zone_first_keg(zone) == NULL) - return; - if (slab == NULL) { - slab = uma_dbg_getslab(zone, item); - if (slab == NULL) - panic("uma: Freed item %p did not belong to zone %s\n", - item, zone->uz_name); - } - keg = slab->us_keg; - freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; - - if (freei >= keg->uk_ipers) - panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - if (((freei * keg->uk_rsize) + slab->us_data) != item) - panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) - panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); -} - -#endif /* INVARIANTS */ diff --git a/sys/vm/uma_dbg.h b/sys/vm/uma_dbg.h index 341cecbf8de3..e3c9df02f2d3 100644 --- a/sys/vm/uma_dbg.h +++ b/sys/vm/uma_dbg.h @@ -49,7 +49,4 @@ void mtrash_dtor(void *mem, int size, void *arg); int mtrash_init(void *mem, int size, int flags); void mtrash_fini(void *mem, int size); -void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item); -void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item); - #endif /* VM_UMA_DBG_H */ From 953ea03018f155940b6a4b4d34edf9d5107822fe Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 3 Feb 2016 23:30:17 +0000 Subject: [PATCH 161/236] Redo r292484. Embed task(9) into zone, so that uz_maxaction is called in a context that can sleep, allowing consumers of the KPI to run their drain routines without any extra measures. Discussed with: jtl --- sys/amd64/amd64/uma_machdep.c | 1 + sys/kern/kern_malloc.c | 1 + sys/kern/kern_mbuf.c | 92 ++++------------------------------- sys/vm/memguard.c | 1 + sys/vm/uma.h | 2 +- sys/vm/uma_core.c | 9 ++-- sys/vm/uma_dbg.c | 1 + sys/vm/uma_int.h | 2 +- sys/vm/vm_page.c | 1 + 9 files changed, 22 insertions(+), 88 deletions(-) diff --git a/sys/amd64/amd64/uma_machdep.c b/sys/amd64/amd64/uma_machdep.c index db566ae89d47..fc343cabe52f 100644 --- a/sys/amd64/amd64/uma_machdep.c +++ b/sys/amd64/amd64/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index e7c81d67e936..f7c67f2d7610 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 779c62af32bd..55964398b6a1 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -273,12 +273,6 @@ uma_zone_t zone_jumbo9; uma_zone_t zone_jumbo16; uma_zone_t zone_ext_refcnt; -/* - * Callout to assist us in freeing mbufs. - */ -static struct callout mb_reclaim_callout; -static struct mtx mb_reclaim_callout_mtx; - /* * Local prototypes. */ @@ -291,9 +285,8 @@ static void mb_dtor_pack(void *, int, void *); static int mb_zinit_pack(void *, int, int); static void mb_zfini_pack(void *, int); -static void mb_reclaim(void *); +static void mb_reclaim(uma_zone_t, int); static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int); -static void mb_maxaction(uma_zone_t); /* Ensure that MSIZE is a power of 2. */ CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); @@ -319,7 +312,7 @@ mbuf_init(void *dummy) if (nmbufs > 0) nmbufs = uma_zone_set_max(zone_mbuf, nmbufs); uma_zone_set_warning(zone_mbuf, "kern.ipc.nmbufs limit reached"); - uma_zone_set_maxaction(zone_mbuf, mb_maxaction); + uma_zone_set_maxaction(zone_mbuf, mb_reclaim); zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES, mb_ctor_clust, mb_dtor_clust, @@ -332,7 +325,7 @@ mbuf_init(void *dummy) if (nmbclusters > 0) nmbclusters = uma_zone_set_max(zone_clust, nmbclusters); uma_zone_set_warning(zone_clust, "kern.ipc.nmbclusters limit reached"); - uma_zone_set_maxaction(zone_clust, mb_maxaction); + uma_zone_set_maxaction(zone_clust, mb_reclaim); zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack, mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf); @@ -349,7 +342,7 @@ mbuf_init(void *dummy) if (nmbjumbop > 0) nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop); uma_zone_set_warning(zone_jumbop, "kern.ipc.nmbjumbop limit reached"); - uma_zone_set_maxaction(zone_jumbop, mb_maxaction); + uma_zone_set_maxaction(zone_jumbop, mb_reclaim); zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES, mb_ctor_clust, mb_dtor_clust, @@ -363,7 +356,7 @@ mbuf_init(void *dummy) if (nmbjumbo9 > 0) nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9); uma_zone_set_warning(zone_jumbo9, "kern.ipc.nmbjumbo9 limit reached"); - uma_zone_set_maxaction(zone_jumbo9, mb_maxaction); + uma_zone_set_maxaction(zone_jumbo9, mb_reclaim); zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES, mb_ctor_clust, mb_dtor_clust, @@ -377,20 +370,13 @@ mbuf_init(void *dummy) if (nmbjumbo16 > 0) nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16); uma_zone_set_warning(zone_jumbo16, "kern.ipc.nmbjumbo16 limit reached"); - uma_zone_set_maxaction(zone_jumbo16, mb_maxaction); + uma_zone_set_maxaction(zone_jumbo16, mb_reclaim); zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT); - /* uma_prealloc() goes here... */ - - /* Initialize the mb_reclaim() callout. */ - mtx_init(&mb_reclaim_callout_mtx, "mb_reclaim_callout_mtx", NULL, - MTX_DEF); - callout_init(&mb_reclaim_callout, 1); - /* * Hook event handler for low-memory situation, used to * drain protocols and push data back to the caches (UMA @@ -677,81 +663,23 @@ m_pkthdr_init(struct mbuf *m, int how) } /* - * This is the protocol drain routine. + * This is the protocol drain routine. Called by UMA whenever any of the + * mbuf zones is closed to its limit. * * No locks should be held when this is called. The drain routines have to * presently acquire some locks which raises the possibility of lock order * reversal. */ static void -mb_reclaim(void *junk) +mb_reclaim(uma_zone_t zone __unused, int pending __unused) { struct domain *dp; struct protosw *pr; - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, - "mb_reclaim()"); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, __func__); for (dp = domains; dp != NULL; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_drain != NULL) (*pr->pr_drain)(); } - -/* - * This is the function called by the mb_reclaim_callout, which is - * used when we hit the maximum for a zone. - * - * (See mb_maxaction() below.) - */ -static void -mb_reclaim_timer(void *junk __unused) -{ - - mtx_lock(&mb_reclaim_callout_mtx); - - /* - * Avoid running this function extra times by skipping this invocation - * if the callout has already been rescheduled. - */ - if (callout_pending(&mb_reclaim_callout) || - !callout_active(&mb_reclaim_callout)) { - mtx_unlock(&mb_reclaim_callout_mtx); - return; - } - mtx_unlock(&mb_reclaim_callout_mtx); - - mb_reclaim(NULL); - - mtx_lock(&mb_reclaim_callout_mtx); - callout_deactivate(&mb_reclaim_callout); - mtx_unlock(&mb_reclaim_callout_mtx); -} - -/* - * This function is called when we hit the maximum for a zone. - * - * At that point, we want to call the protocol drain routine to free up some - * mbufs. However, we will use the callout routines to schedule this to - * occur in another thread. (The thread calling this function holds the - * zone lock.) - */ -static void -mb_maxaction(uma_zone_t zone __unused) -{ - - /* - * If we can't immediately obtain the lock, either the callout - * is currently running, or another thread is scheduling the - * callout. - */ - if (!mtx_trylock(&mb_reclaim_callout_mtx)) - return; - - /* If not already scheduled/running, schedule the callout. */ - if (!callout_active(&mb_reclaim_callout)) { - callout_reset(&mb_reclaim_callout, 1, mb_reclaim_timer, NULL); - } - - mtx_unlock(&mb_reclaim_callout_mtx); -} diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c index d4efc2b7123e..fb70a4186c73 100644 --- a/sys/vm/memguard.c +++ b/sys/vm/memguard.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/vm/uma.h b/sys/vm/uma.h index d218e60886dc..21c61214315d 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -530,7 +530,7 @@ void uma_zone_set_warning(uma_zone_t zone, const char *warning); * Returns: * Nothing */ -typedef void (*uma_maxaction_t)(uma_zone_t); +typedef void (*uma_maxaction_t)(uma_zone_t, int); void uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t); /* diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 89ed213e82e6..0d45046e7e51 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -439,8 +440,9 @@ zone_log_warning(uma_zone_t zone) static inline void zone_maxaction(uma_zone_t zone) { - if (zone->uz_maxaction) - (*zone->uz_maxaction)(zone); + + if (zone->uz_maxaction.ta_func != NULL) + taskqueue_enqueue(taskqueue_thread, &zone->uz_maxaction); } static void @@ -1590,7 +1592,6 @@ zone_ctor(void *mem, int size, void *udata, int flags) zone->uz_flags = 0; zone->uz_warning = NULL; timevalclear(&zone->uz_ratecheck); - zone->uz_maxaction = NULL; keg = arg->keg; ZONE_LOCK_INIT(zone, (arg->flags & UMA_ZONE_MTXCLASS)); @@ -3027,7 +3028,7 @@ uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t maxaction) { ZONE_LOCK(zone); - zone->uz_maxaction = maxaction; + TASK_INIT(&zone->uz_maxaction, 0, (task_fn_t *)maxaction, zone); ZONE_UNLOCK(zone); } diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c index dcef5c9480cb..7bf06d35b4e2 100644 --- a/sys/vm/uma_dbg.c +++ b/sys/vm/uma_dbg.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index 5d7ecd331a7f..1b0d5d5dbf37 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -307,7 +307,7 @@ struct uma_zone { const char *uz_warning; /* Warning to print on failure */ struct timeval uz_ratecheck; /* Warnings rate-limiting */ - uma_maxaction_t uz_maxaction; /* Function to run when at limit */ + struct task uz_maxaction; /* Task to run when at limit */ /* * This HAS to be the last item because we adjust the zone size diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index d27eb2d4eaf0..b510696ed170 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include From 3cee84e03164f633467a8e2b0ea12df1c50bfa1a Mon Sep 17 00:00:00 2001 From: bdrewery Date: Wed, 3 Feb 2016 23:37:14 +0000 Subject: [PATCH 162/236] Don't let NLSLINKS contain itself. Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.nls.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/mk/bsd.nls.mk b/share/mk/bsd.nls.mk index c578361fdd53..d160a2bcf2d4 100644 --- a/share/mk/bsd.nls.mk +++ b/share/mk/bsd.nls.mk @@ -73,6 +73,9 @@ SYMLINKS+= ${NLSSYMLINKS} .for file in ${NLS} NLSNAME_${file:T}= ${file:T:R}/${NLSNAME}.cat .if defined(NLSLINKS_${file:R}) && !empty(NLSLINKS_${file:R}) +.if !empty(NLSLINKS_${file:R}:M${file:R}) +.error NLSLINKS_${file:R} contains itself: ${file:R} +.endif NLSLINKS+= ${file:R} .endif .for dst in ${NLSLINKS_${file:R}} From f053f5a5d6423c7e763945ddfc190f11a7a55efa Mon Sep 17 00:00:00 2001 From: bdrewery Date: Wed, 3 Feb 2016 23:37:24 +0000 Subject: [PATCH 163/236] Don't link /usr/share/nls/de_DE.UTF-8/tcsh.cat to itself. Sponsored by: EMC / Isilon Storage Division --- bin/csh/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/csh/Makefile b/bin/csh/Makefile index 18e266535e9a..deb63478727d 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -62,7 +62,7 @@ CATALOGS= et:et_EE.UTF-8 \ spanish:es_ES.UTF-8 \ ukrainian:uk_UA.UTF-8 -NLSLINKS_de_DE.UTF-8 = de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8 +NLSLINKS_de_DE.UTF-8 = de_AT.UTF-8 de_CH.UTF-8 NLSLINKS_fr_FR.UTF-8 = fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 NLSLINKS_it_IT.UTF-8 = it_CH.UTF-8 From c805a3354e5316470ff02dc5d57d943e3d3860c4 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 4 Feb 2016 00:23:21 +0000 Subject: [PATCH 164/236] Fix build. --- lib/libmemstat/memstat_uma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/libmemstat/memstat_uma.c b/lib/libmemstat/memstat_uma.c index 8e89585300b0..20cd5208fdd6 100644 --- a/lib/libmemstat/memstat_uma.c +++ b/lib/libmemstat/memstat_uma.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include From e6b730a42a3781472e318742288f25b698b5db01 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 4 Feb 2016 01:08:42 +0000 Subject: [PATCH 165/236] Stop hiding link install commands. This is no longer needed now that a .for loop is used rather than inline shell script. Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.incs.mk | 1 - share/mk/bsd.links.mk | 2 -- 2 files changed, 3 deletions(-) diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk index 8ea97ba14fc8..57e08ffcf768 100644 --- a/share/mk/bsd.incs.mk +++ b/share/mk/bsd.incs.mk @@ -80,7 +80,6 @@ _${group}INS: ${_${group}INCS} .if defined(INCSLINKS) && !empty(INCSLINKS) installincludes: .for s t in ${INCSLINKS} - @${ECHO} "$t -> $s" ; \ ${INSTALL_SYMLINK} $s ${DESTDIR}$t .endfor .endif diff --git a/share/mk/bsd.links.mk b/share/mk/bsd.links.mk index 4f8565c255f9..38ceb42289d5 100644 --- a/share/mk/bsd.links.mk +++ b/share/mk/bsd.links.mk @@ -8,10 +8,8 @@ afterinstall: _installlinks .ORDER: realinstall _installlinks _installlinks: .for s t in ${LINKS} - @${ECHO} "$t -> $s" ;\ ${INSTALL_LINK} ${DESTDIR}$s ${DESTDIR}$t .endfor .for s t in ${SYMLINKS} - @${ECHO} "$t -> $s" ;\ ${INSTALL_SYMLINK} $s ${DESTDIR}/$t .endfor From 95aca9386107e5e0bc09887d1a22176e40351228 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 4 Feb 2016 01:08:45 +0000 Subject: [PATCH 166/236] Fix cat files being installed to wrong place since r284685. Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.man.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk index d0992b630dfb..6be8e6476512 100644 --- a/share/mk/bsd.man.mk +++ b/share/mk/bsd.man.mk @@ -226,8 +226,8 @@ _maninstall: ${MAN} .endfor .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) .for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} - @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \ - t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \ + @l=${DESTDIR}${CATDIR}${_osect}${MANSUBDIR}/${_oname}; \ + t=${DESTDIR}${CATDIR}${_dsect}${MANSUBDIR}/${_dname}; \ ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \ rm -f $${t} $${t}${MCOMPRESS_EXT}; \ ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT} From 798fceb2c17744606d0117cac7d771a1e076f160 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 4 Feb 2016 01:08:48 +0000 Subject: [PATCH 167/236] MLINKS: Deduplicate some of the logic, simplify, and unhide install commands. Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.man.mk | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk index 6be8e6476512..5cfada030949 100644 --- a/share/mk/bsd.man.mk +++ b/share/mk/bsd.man.mk @@ -171,6 +171,17 @@ ${__target}: ${__page} .endif # ${MK_MANCOMPRESS} == "no" +.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS) +.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} +_MANLINKS+= ${MANDIR}${_osect}${MANSUBDIR}/${_oname} \ + ${MANDIR}${_dsect}${MANSUBDIR}/${_dname} +.if defined(MANBUILDCAT) && !empty(MANBUILDCAT) +_MANLINKS+= ${CATDIR}${_osect}${MANSUBDIR}/${_oname} \ + ${CATDIR}${_dsect}${MANSUBDIR}/${_dname} +.endif +.endfor +.endif + maninstall: _maninstall _maninstall: .if defined(MAN) && !empty(MAN) @@ -215,25 +226,10 @@ _maninstall: ${MAN} .endfor .endif # ${MK_MANCOMPRESS} == "no" .endif - -.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS) -.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} - @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \ - t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \ - ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \ - rm -f $${t} $${t}${MCOMPRESS_EXT}; \ - ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT} +.for l t in ${_MANLINKS} + rm -f ${DESTDIR}${t} ${DESTDIR}${t}${MCOMPRESS_EXT}; \ + ${INSTALL_LINK} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT} .endfor -.if defined(MANBUILDCAT) && !empty(MANBUILDCAT) -.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} - @l=${DESTDIR}${CATDIR}${_osect}${MANSUBDIR}/${_oname}; \ - t=${DESTDIR}${CATDIR}${_dsect}${MANSUBDIR}/${_dname}; \ - ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \ - rm -f $${t} $${t}${MCOMPRESS_EXT}; \ - ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT} -.endfor -.endif -.endif manlint: .if defined(MAN) && !empty(MAN) From c848707b796d017fa305da82177c3bf616e21322 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Thu, 4 Feb 2016 01:08:51 +0000 Subject: [PATCH 168/236] Fix style and remove excess / for installing SYMLINKS. Sponsored by: EMC / Isilon Storage Division --- share/mk/bsd.incs.mk | 2 +- share/mk/bsd.links.mk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk index 57e08ffcf768..0897e8d8ca35 100644 --- a/share/mk/bsd.incs.mk +++ b/share/mk/bsd.incs.mk @@ -80,7 +80,7 @@ _${group}INS: ${_${group}INCS} .if defined(INCSLINKS) && !empty(INCSLINKS) installincludes: .for s t in ${INCSLINKS} - ${INSTALL_SYMLINK} $s ${DESTDIR}$t + ${INSTALL_SYMLINK} ${s} ${DESTDIR}${t} .endfor .endif .endif # !target(installincludes) diff --git a/share/mk/bsd.links.mk b/share/mk/bsd.links.mk index 38ceb42289d5..9e24af86624f 100644 --- a/share/mk/bsd.links.mk +++ b/share/mk/bsd.links.mk @@ -8,8 +8,8 @@ afterinstall: _installlinks .ORDER: realinstall _installlinks _installlinks: .for s t in ${LINKS} - ${INSTALL_LINK} ${DESTDIR}$s ${DESTDIR}$t + ${INSTALL_LINK} ${DESTDIR}${s} ${DESTDIR}${t} .endfor .for s t in ${SYMLINKS} - ${INSTALL_SYMLINK} $s ${DESTDIR}/$t + ${INSTALL_SYMLINK} ${s} ${DESTDIR}${t} .endfor From e807599e3ffdfd1caaff4c43f3e2a3b7b6289440 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 4 Feb 2016 03:55:41 +0000 Subject: [PATCH 169/236] Fix build. --- sys/arm64/arm64/uma_machdep.c | 1 + sys/mips/mips/uma_machdep.c | 1 + sys/powerpc/powerpc/uma_machdep.c | 1 + sys/riscv/riscv/uma_machdep.c | 1 + 4 files changed, 4 insertions(+) diff --git a/sys/arm64/arm64/uma_machdep.c b/sys/arm64/arm64/uma_machdep.c index 9b9df5c68ed4..a9dae0f42573 100644 --- a/sys/arm64/arm64/uma_machdep.c +++ b/sys/arm64/arm64/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/mips/mips/uma_machdep.c b/sys/mips/mips/uma_machdep.c index b4006e1ead12..7014703b712a 100644 --- a/sys/mips/mips/uma_machdep.c +++ b/sys/mips/mips/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c index d5a458f37fa2..2e023965c95d 100644 --- a/sys/powerpc/powerpc/uma_machdep.c +++ b/sys/powerpc/powerpc/uma_machdep.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/riscv/riscv/uma_machdep.c b/sys/riscv/riscv/uma_machdep.c index ba480713fc75..b3f2d82be13c 100644 --- a/sys/riscv/riscv/uma_machdep.c +++ b/sys/riscv/riscv/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include From 9a7c585ab535448da4519e461a2216e335686144 Mon Sep 17 00:00:00 2001 From: mjg Date: Thu, 4 Feb 2016 04:22:18 +0000 Subject: [PATCH 170/236] fork: pass arguments to fork1 in a dedicated structure Suggested by: kib --- sys/compat/cloudabi/cloudabi_proc.c | 8 ++++- sys/compat/linux/linux_fork.c | 20 +++++++++--- sys/kern/init_main.c | 7 ++-- sys/kern/kern_fork.c | 50 ++++++++++++++++++++--------- sys/kern/kern_kthread.c | 8 +++-- sys/sys/proc.h | 12 +++++-- 6 files changed, 78 insertions(+), 27 deletions(-) diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c index d91733760ceb..7320af01e7fc 100644 --- a/sys/compat/cloudabi/cloudabi_proc.c +++ b/sys/compat/cloudabi/cloudabi_proc.c @@ -75,12 +75,18 @@ int cloudabi_sys_proc_fork(struct thread *td, struct cloudabi_sys_proc_fork_args *uap) { + struct fork_req fr; struct filecaps fcaps = {}; struct proc *p2; int error, fd; cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT); - error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; + fr.fr_procp = &p2; + fr.fr_pd_fd = &fd; + fr.fr_pd_fcaps = &fcaps; + error = fork1(td, &fr); if (error != 0) return (error); /* Return the file descriptor to the parent process. */ diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c index d0f73adefd31..c12f198fe79b 100644 --- a/sys/compat/linux/linux_fork.c +++ b/sys/compat/linux/linux_fork.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); int linux_fork(struct thread *td, struct linux_fork_args *args) { + struct fork_req fr; int error; struct proc *p2; struct thread *td2; @@ -73,8 +74,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args) printf(ARGS(fork, "")); #endif - if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0, - NULL)) != 0) + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; + fr.fr_procp = &p2; + if ((error = fork1(td, &fr)) != 0) return (error); td2 = FIRST_THREAD_IN_PROC(p2); @@ -97,6 +100,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args) int linux_vfork(struct thread *td, struct linux_vfork_args *args) { + struct fork_req fr; int error; struct proc *p2; struct thread *td2; @@ -106,8 +110,10 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) printf(ARGS(vfork, "")); #endif - if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED, - 0, &p2, NULL, 0, NULL)) != 0) + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED; + fr.fr_procp = &p2; + if ((error = fork1(td, &fr)) != 0) return (error); td2 = FIRST_THREAD_IN_PROC(p2); @@ -130,6 +136,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) static int linux_clone_proc(struct thread *td, struct linux_clone_args *args) { + struct fork_req fr; int error, ff = RFPROC | RFSTOPPED; struct proc *p2; struct thread *td2; @@ -170,7 +177,10 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args) if (args->flags & LINUX_CLONE_VFORK) ff |= RFPPWAIT; - error = fork1(td, ff, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = ff; + fr.fr_procp = &p2; + error = fork1(td, &fr); if (error) return (error); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 8d5580b6d046..d5f8f4ddbe31 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -828,12 +828,15 @@ start_init(void *dummy) static void create_init(const void *udata __unused) { + struct fork_req fr; struct ucred *newcred, *oldcred; struct thread *td; int error; - error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc, - NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; + fr.fr_procp = &initproc; + error = fork1(&thread0, &fr); if (error) panic("cannot fork init: %d\n", error); KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index e7d727619be0..d13a20c7cf46 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -101,10 +101,14 @@ struct fork_args { int sys_fork(struct thread *td, struct fork_args *uap) { + struct fork_req fr; int error; struct proc *p2; - error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC; + fr.fr_procp = &p2; + error = fork1(td, &fr); if (error == 0) { td->td_retval[0] = p2->p_pid; td->td_retval[1] = 0; @@ -118,16 +122,21 @@ sys_pdfork(td, uap) struct thread *td; struct pdfork_args *uap; { + struct fork_req fr; int error, fd; struct proc *p2; + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; + fr.fr_procp = &p2; + fr.fr_pd_fd = &fd; + fr.fr_pd_flags = uap->flags; /* * It is necessary to return fd by reference because 0 is a valid file * descriptor number, and the child needs to be able to distinguish * itself from the parent using the return value. */ - error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, - &fd, uap->flags, NULL); + error = fork1(td, &fr); if (error == 0) { td->td_retval[0] = p2->p_pid; td->td_retval[1] = 0; @@ -140,11 +149,14 @@ sys_pdfork(td, uap) int sys_vfork(struct thread *td, struct vfork_args *uap) { - int error, flags; + struct fork_req fr; + int error; struct proc *p2; - flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; - error = fork1(td, flags, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; + fr.fr_procp = &p2; + error = fork1(td, &fr); if (error == 0) { td->td_retval[0] = p2->p_pid; td->td_retval[1] = 0; @@ -155,6 +167,7 @@ sys_vfork(struct thread *td, struct vfork_args *uap) int sys_rfork(struct thread *td, struct rfork_args *uap) { + struct fork_req fr; struct proc *p2; int error; @@ -163,7 +176,10 @@ sys_rfork(struct thread *td, struct rfork_args *uap) return (EINVAL); AUDIT_ARG_FFLAGS(uap->flags); - error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = uap->flags; + fr.fr_procp = &p2; + error = fork1(td, &fr); if (error == 0) { td->td_retval[0] = p2 ? p2->p_pid : 0; td->td_retval[1] = 0; @@ -761,8 +777,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, } int -fork1(struct thread *td, int flags, int pages, struct proc **procp, - int *procdescp, int pdflags, struct filecaps *fcaps) +fork1(struct thread *td, struct fork_req *fr) { struct proc *p1, *newproc; struct thread *td2; @@ -772,6 +787,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, int error, nprocs_new, ok; static int curfail; static struct timeval lastfail; + int flags, pages; + + flags = fr->fr_flags; + pages = fr->fr_pages; /* Check for the undefined or unimplemented flags. */ if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0) @@ -795,7 +814,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, return (EINVAL); /* Must provide a place to put a procdesc if creating one. */ - if (procdescp == NULL) + if (fr->fr_pd_fd == NULL) return (EINVAL); } @@ -806,7 +825,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, * certain parts of a process from itself. */ if ((flags & RFPROC) == 0) { - *procp = NULL; + *fr->fr_procp = NULL; return (fork_norfproc(td, flags)); } @@ -845,7 +864,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, * later. */ if (flags & RFPROCDESC) { - error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps); + error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0, + fr->fr_pd_fcaps); if (error != 0) goto fail2; } @@ -933,12 +953,12 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, lim_cur(td, RLIMIT_NPROC)); } if (ok) { - do_fork(td, flags, newproc, td2, vm2, pdflags); + do_fork(td, flags, newproc, td2, vm2, fr->fr_pd_flags); /* * Return child proc pointer to parent. */ - *procp = newproc; + *fr->fr_procp = newproc; if (flags & RFPROCDESC) { procdesc_finit(newproc->p_procdesc, fp_procdesc); fdrop(fp_procdesc, td); @@ -962,7 +982,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, vmspace_free(vm2); uma_zfree(proc_zone, newproc); if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) { - fdclose(td, fp_procdesc, *procdescp); + fdclose(td, fp_procdesc, *fr->fr_pd_fd); fdrop(fp_procdesc, td); } atomic_add_int(&nprocs, -1); diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 2072dc726b08..9cca255fef91 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -80,6 +80,7 @@ int kproc_create(void (*func)(void *), void *arg, struct proc **newpp, int flags, int pages, const char *fmt, ...) { + struct fork_req fr; int error; va_list ap; struct thread *td; @@ -88,8 +89,11 @@ kproc_create(void (*func)(void *), void *arg, if (!proc0.p_stats) panic("kproc_create called too soon"); - error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, - pages, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFMEM | RFFDG | RFPROC | RFSTOPPED | flags; + fr.fr_pages = pages; + fr.fr_procp = &p2; + error = fork1(&thread0, &fr); if (error) return error; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index f2f4a9d17202..ac96566510ce 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -907,6 +907,15 @@ struct proc *pfind_locked(pid_t pid); struct pgrp *pgfind(pid_t); /* Find process group by id. */ struct proc *zpfind(pid_t); /* Find zombie process by id. */ +struct fork_req { + int fr_flags; + int fr_pages; + struct proc **fr_procp; + int *fr_pd_fd; + int fr_pd_flags; + struct filecaps *fr_pd_fcaps; +}; + /* * pget() flags. */ @@ -930,8 +939,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp, int enterthispgrp(struct proc *p, struct pgrp *pgrp); void faultin(struct proc *p); void fixjobc(struct proc *p, struct pgrp *pgrp, int entering); -int fork1(struct thread *, int, int, struct proc **, int *, int, - struct filecaps *); +int fork1(struct thread *, struct fork_req *); void fork_exit(void (*)(void *, struct trapframe *), void *, struct trapframe *); void fork_return(struct thread *, struct trapframe *); From 027c9d90e38cc5d801ef8365d78332bebdbbb32b Mon Sep 17 00:00:00 2001 From: mjg Date: Thu, 4 Feb 2016 04:25:30 +0000 Subject: [PATCH 171/236] fork: plug a use after free of the returned process fork1 required its callers to pass a pointer to struct proc * which would be set to the new process (if any). procdesc and racct manipulation also used said pointer. However, the process could have exited prior to do_fork return and be automatically reaped, thus making this a use-after-free. Fix the problem by letting callers indicate whether they want the pid or the struct proc, return the process in stopped state for the latter case. Reviewed by: kib --- sys/compat/cloudabi/cloudabi_proc.c | 2 - sys/kern/kern_fork.c | 142 +++++++++++++++------------- sys/kern/kern_racct.c | 3 +- sys/sys/proc.h | 1 + 4 files changed, 76 insertions(+), 72 deletions(-) diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c index 7320af01e7fc..8d0b6e76958a 100644 --- a/sys/compat/cloudabi/cloudabi_proc.c +++ b/sys/compat/cloudabi/cloudabi_proc.c @@ -77,13 +77,11 @@ cloudabi_sys_proc_fork(struct thread *td, { struct fork_req fr; struct filecaps fcaps = {}; - struct proc *p2; int error, fd; cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT); bzero(&fr, sizeof(fr)); fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; - fr.fr_procp = &p2; fr.fr_pd_fd = &fd; fr.fr_pd_fcaps = &fcaps; error = fork1(td, &fr); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d13a20c7cf46..baee954dc569 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -102,15 +102,14 @@ int sys_fork(struct thread *td, struct fork_args *uap) { struct fork_req fr; - int error; - struct proc *p2; + int error, pid; bzero(&fr, sizeof(fr)); fr.fr_flags = RFFDG | RFPROC; - fr.fr_procp = &p2; + fr.fr_pidp = &pid; error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -123,12 +122,11 @@ sys_pdfork(td, uap) struct pdfork_args *uap; { struct fork_req fr; - int error, fd; - struct proc *p2; + int error, fd, pid; bzero(&fr, sizeof(fr)); fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; - fr.fr_procp = &p2; + fr.fr_pidp = &pid; fr.fr_pd_fd = &fd; fr.fr_pd_flags = uap->flags; /* @@ -138,7 +136,7 @@ sys_pdfork(td, uap) */ error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; error = copyout(&fd, uap->fdp, sizeof(fd)); } @@ -150,15 +148,14 @@ int sys_vfork(struct thread *td, struct vfork_args *uap) { struct fork_req fr; - int error; - struct proc *p2; + int error, pid; bzero(&fr, sizeof(fr)); fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; - fr.fr_procp = &p2; + fr.fr_pidp = &pid; error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -168,8 +165,7 @@ int sys_rfork(struct thread *td, struct rfork_args *uap) { struct fork_req fr; - struct proc *p2; - int error; + int error, pid; /* Don't allow kernel-only flags. */ if ((uap->flags & RFKERNELONLY) != 0) @@ -178,10 +174,10 @@ sys_rfork(struct thread *td, struct rfork_args *uap) AUDIT_ARG_FFLAGS(uap->flags); bzero(&fr, sizeof(fr)); fr.fr_flags = uap->flags; - fr.fr_procp = &p2; + fr.fr_pidp = &pid; error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2 ? p2->p_pid : 0; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -382,11 +378,11 @@ fork_norfproc(struct thread *td, int flags) } static void -do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, - struct vmspace *vm2, int pdflags) +do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *td2, + struct vmspace *vm2, struct file *fp_procdesc) { struct proc *p1, *pptr; - int p2_held, trypid; + int trypid; struct filedesc *fd; struct filedesc_to_leader *fdtol; struct sigacts *newsigacts; @@ -394,10 +390,9 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, sx_assert(&proctree_lock, SX_SLOCKED); sx_assert(&allproc_lock, SX_XLOCKED); - p2_held = 0; p1 = td->td_proc; - trypid = fork_findpid(flags); + trypid = fork_findpid(fr->fr_flags); sx_sunlock(&proctree_lock); @@ -430,7 +425,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Malloc things while we don't hold any locks. */ - if (flags & RFSIGSHARE) + if (fr->fr_flags & RFSIGSHARE) newsigacts = NULL; else newsigacts = sigacts_alloc(); @@ -438,10 +433,10 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Copy filedesc. */ - if (flags & RFCFDG) { + if (fr->fr_flags & RFCFDG) { fd = fdinit(p1->p_fd, false); fdtol = NULL; - } else if (flags & RFFDG) { + } else if (fr->fr_flags & RFFDG) { fd = fdcopy(p1->p_fd); fdtol = NULL; } else { @@ -449,7 +444,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, if (p1->p_fdtol == NULL) p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL, p1->p_leader); - if ((flags & RFTHREAD) != 0) { + if ((fr->fr_flags & RFTHREAD) != 0) { /* * Shared file descriptor table, and shared * process leaders. @@ -517,16 +512,16 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, vm_domain_policy_localcopy(&p2->p_vm_dom_policy, &p1->p_vm_dom_policy); - if (flags & RFSIGSHARE) { + if (fr->fr_flags & RFSIGSHARE) { p2->p_sigacts = sigacts_hold(p1->p_sigacts); } else { sigacts_copy(newsigacts, p1->p_sigacts); p2->p_sigacts = newsigacts; } - if (flags & RFTSIGZMB) - p2->p_sigparent = RFTSIGNUM(flags); - else if (flags & RFLINUXTHPN) + if (fr->fr_flags & RFTSIGZMB) + p2->p_sigparent = RFTSIGNUM(fr->fr_flags); + else if (fr->fr_flags & RFLINUXTHPN) p2->p_sigparent = SIGUSR1; else p2->p_sigparent = SIGCHLD; @@ -559,7 +554,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Set up linkage for kernel based threading. */ - if ((flags & RFTHREAD) != 0) { + if ((fr->fr_flags & RFTHREAD) != 0) { mtx_lock(&ppeers_lock); p2->p_peers = p1->p_peers; p1->p_peers = p2; @@ -606,7 +601,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; SESS_UNLOCK(p1->p_session); - if (flags & RFPPWAIT) + if (fr->fr_flags & RFPPWAIT) p2->p_flag |= P_PPWAIT; p2->p_pgrp = p1->p_pgrp; @@ -640,7 +635,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * of init. This effectively disassociates the child from the * parent. */ - if ((flags & RFNOWAIT) != 0) { + if ((fr->fr_flags & RFNOWAIT) != 0) { pptr = p1->p_reaper; p2->p_reaper = pptr; } else { @@ -668,13 +663,13 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * Finish creating the child process. It will return via a different * execution path later. (ie: directly into user mode) */ - vm_forkproc(td, p2, td2, vm2, flags); + vm_forkproc(td, p2, td2, vm2, fr->fr_flags); - if (flags == (RFFDG | RFPROC)) { + if (fr->fr_flags == (RFFDG | RFPROC)) { PCPU_INC(cnt.v_forks); PCPU_ADD(cnt.v_forkpages, p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize); - } else if (flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) { + } else if (fr->fr_flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) { PCPU_INC(cnt.v_vforks); PCPU_ADD(cnt.v_vforkpages, p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize); @@ -693,14 +688,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * can happen that might cause that process to need the descriptor. * However, don't do this until after fork(2) can no longer fail. */ - if (flags & RFPROCDESC) - procdesc_new(p2, pdflags); + if (fr->fr_flags & RFPROCDESC) + procdesc_new(p2, fr->fr_pd_flags); /* * Both processes are set up, now check if any loadable modules want * to adjust anything. */ - EVENTHANDLER_INVOKE(process_fork, p1, p2, flags); + EVENTHANDLER_INVOKE(process_fork, p1, p2, fr->fr_flags); /* * Set the child start time and mark the process as being complete. @@ -719,9 +714,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * this only after p_state is PRS_NORMAL since the fasttrap module will * use pfind() later on. */ - if ((flags & RFMEM) == 0 && dtrace_fasttrap_fork) + if ((fr->fr_flags & RFMEM) == 0 && dtrace_fasttrap_fork) dtrace_fasttrap_fork(p1, p2); #endif + /* + * Hold the process so that it cannot exit after we make it runnable, + * but before we wait for the debugger. + */ + _PHOLD(p2); if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED | P_FOLLOWFORK)) { /* @@ -734,24 +734,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, td->td_dbgflags |= TDB_FORK; td->td_dbg_forked = p2->p_pid; td2->td_dbgflags |= TDB_STOPATFORK; - _PHOLD(p2); - p2_held = 1; } - if (flags & RFPPWAIT) { + if (fr->fr_flags & RFPPWAIT) { td->td_pflags |= TDP_RFPPWAIT; td->td_rfppwait_p = p2; } PROC_UNLOCK(p2); - if ((flags & RFSTOPPED) == 0) { - /* - * If RFSTOPPED not requested, make child runnable and - * add to run queue. - */ - thread_lock(td2); - TD_SET_CAN_RUN(td2); - sched_add(td2, SRQ_BORING); - thread_unlock(td2); - } /* * Now can be swapped. @@ -763,16 +751,36 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * Tell any interested parties about the new process. */ knote_fork(&p1->p_klist, p2->p_pid); - SDT_PROBE3(proc, , , create, p2, p1, flags); + SDT_PROBE3(proc, , , create, p2, p1, fr->fr_flags); + if (fr->fr_flags & RFPROCDESC) { + procdesc_finit(p2->p_procdesc, fp_procdesc); + fdrop(fp_procdesc, td); + } + + if ((fr->fr_flags & RFSTOPPED) == 0) { + /* + * If RFSTOPPED not requested, make child runnable and + * add to run queue. + */ + thread_lock(td2); + TD_SET_CAN_RUN(td2); + sched_add(td2, SRQ_BORING); + thread_unlock(td2); + if (fr->fr_pidp != NULL) + *fr->fr_pidp = p2->p_pid; + } else { + *fr->fr_procp = p2; + } + + PROC_LOCK(p2); /* * Wait until debugger is attached to child. */ - PROC_LOCK(p2); while ((td2->td_dbgflags & TDB_STOPATFORK) != 0) cv_wait(&p2->p_dbgwait, &p2->p_mtx); - if (p2_held) - _PRELE(p2); + _PRELE(p2); + racct_proc_fork_done(p2); PROC_UNLOCK(p2); } @@ -792,6 +800,11 @@ fork1(struct thread *td, struct fork_req *fr) flags = fr->fr_flags; pages = fr->fr_pages; + if ((flags & RFSTOPPED) != 0) + MPASS(fr->fr_procp != NULL && fr->fr_pidp == NULL); + else + MPASS(fr->fr_procp == NULL); + /* Check for the undefined or unimplemented flags. */ if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0) return (EINVAL); @@ -825,7 +838,10 @@ fork1(struct thread *td, struct fork_req *fr) * certain parts of a process from itself. */ if ((flags & RFPROC) == 0) { - *fr->fr_procp = NULL; + if (fr->fr_procp != NULL) + *fr->fr_procp = NULL; + else if (fr->fr_pidp != NULL) + *fr->fr_pidp = 0; return (fork_norfproc(td, flags)); } @@ -953,17 +969,7 @@ fork1(struct thread *td, struct fork_req *fr) lim_cur(td, RLIMIT_NPROC)); } if (ok) { - do_fork(td, flags, newproc, td2, vm2, fr->fr_pd_flags); - - /* - * Return child proc pointer to parent. - */ - *fr->fr_procp = newproc; - if (flags & RFPROCDESC) { - procdesc_finit(newproc->p_procdesc, fp_procdesc); - fdrop(fp_procdesc, td); - } - racct_proc_fork_done(newproc); + do_fork(td, fr, newproc, td2, vm2, fp_procdesc); return (0); } diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index 0c7c0c444382..ce7e2a4d92c8 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -957,16 +957,15 @@ void racct_proc_fork_done(struct proc *child) { + PROC_LOCK_ASSERT(child, MA_OWNED); #ifdef RCTL if (!racct_enable) return; - PROC_LOCK(child); mtx_lock(&racct_lock); rctl_enforce(child, RACCT_NPROC, 0); rctl_enforce(child, RACCT_NTHR, 0); mtx_unlock(&racct_lock); - PROC_UNLOCK(child); #endif } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index ac96566510ce..039fd394d34a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -910,6 +910,7 @@ struct proc *zpfind(pid_t); /* Find zombie process by id. */ struct fork_req { int fr_flags; int fr_pages; + int *fr_pidp; struct proc **fr_procp; int *fr_pd_fd; int fr_pd_flags; From 52d53d171566c2cd975d2db86a291e516d34d9fe Mon Sep 17 00:00:00 2001 From: ume Date: Thu, 4 Feb 2016 05:03:35 +0000 Subject: [PATCH 172/236] Make sure to enable aliases for SHIFT_JIS. MFC after: 3 days --- share/i18n/esdb/MISC/MISC.alias | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/share/i18n/esdb/MISC/MISC.alias b/share/i18n/esdb/MISC/MISC.alias index 90e2ccd6f126..6ffad5d45cf6 100644 --- a/share/i18n/esdb/MISC/MISC.alias +++ b/share/i18n/esdb/MISC/MISC.alias @@ -29,10 +29,10 @@ JISX0208:1990 x0208 JOHAB cp1361 -SHIFT_JIS csshiftjis -SHIFT_JIS ms_kanji -SHIFT_JIS sjis +Shift_JIS csshiftjis +Shift_JIS ms_kanji +Shift_JIS sjis -SHIFT_JIS-2004 shift_jisx0213 +Shift_JIS-2004 shift_jisx0213 TDS565 iso-ir-230 From 46763fd4ca8a37f836c9bf2333f9d687509278f3 Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 06:39:20 +0000 Subject: [PATCH 173/236] ARM: Remove unused symbols from genassym.c. --- sys/arm/arm/genassym.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index 31910b787903..4a60d9494331 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include ASSYM(KERNBASE, KERNBASE); -ASSYM(PCB_NOALIGNFLT, PCB_NOALIGNFLT); #if __ARM_ARCH >= 6 ASSYM(CPU_ASID_KERNEL,CPU_ASID_KERNEL); #endif @@ -67,7 +66,6 @@ ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); #if __ARM_ARCH < 6 ASSYM(PCB_DACR, offsetof(struct pcb, pcb_dacr)); #endif -ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir)); #if __ARM_ARCH < 6 ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec)); @@ -93,23 +91,15 @@ ASSYM(M_DATA, offsetof(struct mbuf, m_data)); ASSYM(M_NEXT, offsetof(struct mbuf, m_next)); ASSYM(IP_SRC, offsetof(struct ip, ip_src)); ASSYM(IP_DST, offsetof(struct ip, ip_dst)); -ASSYM(CF_SETTTB, offsetof(struct cpu_functions, cf_setttb)); -ASSYM(CF_CONTROL, offsetof(struct cpu_functions, cf_control)); ASSYM(CF_CONTEXT_SWITCH, offsetof(struct cpu_functions, cf_context_switch)); ASSYM(CF_DCACHE_WB_RANGE, offsetof(struct cpu_functions, cf_dcache_wb_range)); -ASSYM(CF_L2CACHE_WB_RANGE, offsetof(struct cpu_functions, cf_l2cache_wb_range)); ASSYM(CF_IDCACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_idcache_wbinv_all)); ASSYM(CF_L2CACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_l2cache_wbinv_all)); ASSYM(CF_TLB_FLUSHID_SE, offsetof(struct cpu_functions, cf_tlb_flushID_SE)); -ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap)); -ASSYM(V_SOFT, offsetof(struct vmmeter, v_soft)); -ASSYM(V_INTR, offsetof(struct vmmeter, v_intr)); - ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); ASSYM(TD_PROC, offsetof(struct thread, td_proc)); -ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); ASSYM(MD_TP, offsetof(struct mdthread, md_tp)); @@ -146,10 +136,6 @@ ASSYM(PMAP_INCLUDE_PTE_SYNC, 1); #endif ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); -ASSYM(P_TRACED, P_TRACED); -ASSYM(P_SIGEVENT, P_SIGEVENT); -ASSYM(P_PROFIL, P_PROFIL); -ASSYM(TRAPFRAMESIZE, sizeof(struct trapframe)); ASSYM(MAXCOMLEN, MAXCOMLEN); ASSYM(MAXCPU, MAXCPU); From ce2fb04a46c2cc3b31ab973bbde3bc7d5c609e5e Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 4 Feb 2016 10:49:34 +0000 Subject: [PATCH 174/236] Guard against runnable td2 exiting and than being reused for unrelated process when the parent sleeps waiting for the debugger attach on fork. Diagnosed and reviewed by: mjg Sponsored by: The FreeBSD Foundation --- sys/kern/kern_fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index baee954dc569..5bb14e8b4adb 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -777,7 +777,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * /* * Wait until debugger is attached to child. */ - while ((td2->td_dbgflags & TDB_STOPATFORK) != 0) + while (td2->td_proc == p2 && (td2->td_dbgflags & TDB_STOPATFORK) != 0) cv_wait(&p2->p_dbgwait, &p2->p_mtx); _PRELE(p2); racct_proc_fork_done(p2); From 30a404b9164af3ef3de2f8f38e0050f6b71fb1aa Mon Sep 17 00:00:00 2001 From: br Date: Thu, 4 Feb 2016 11:52:53 +0000 Subject: [PATCH 175/236] Fix build. --- sys/arm64/arm64/vm_machdep.c | 1 + sys/mips/mips/vm_machdep.c | 1 + sys/riscv/riscv/vm_machdep.c | 1 + 3 files changed, 3 insertions(+) diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c index 6794b1b411e2..3b6891496e68 100644 --- a/sys/arm64/arm64/vm_machdep.c +++ b/sys/arm64/arm64/vm_machdep.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c index f952eccbe777..03fc60e36ccc 100644 --- a/sys/mips/mips/vm_machdep.c +++ b/sys/mips/mips/vm_machdep.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index 62e466f9e19a..0f652501a67a 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include From 281991463be88ccea048efc7431bace6c07144f6 Mon Sep 17 00:00:00 2001 From: br Date: Thu, 4 Feb 2016 12:06:06 +0000 Subject: [PATCH 176/236] Fix build. --- sys/arm/arm/vm_machdep.c | 1 + sys/sparc64/sparc64/vm_machdep.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c index 6a70cbf403e0..601be0718d97 100644 --- a/sys/arm/arm/vm_machdep.c +++ b/sys/arm/arm/vm_machdep.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c index df8be0b4e0c2..9780406ae0f0 100644 --- a/sys/sparc64/sparc64/vm_machdep.c +++ b/sys/sparc64/sparc64/vm_machdep.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include From 444874ded476cb85cea4f20deced485f0aabf91c Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 12:11:18 +0000 Subject: [PATCH 177/236] ARM: Don't use ugly (and hidden) global variable, control register is readable at any time. --- sys/arm/arm/cpufunc.c | 9 --------- sys/arm/arm/identcpu.c | 4 ++-- sys/arm/include/cpufunc.h | 1 + 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 370bab7c53dc..a2b8180e56a5 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -88,8 +88,6 @@ u_int arm_cache_level; u_int arm_cache_type[14]; u_int arm_cache_loc; -int ctrl; - #ifdef CPU_ARM9 struct cpu_functions arm9_cpufuncs = { /* CPU functions */ @@ -889,7 +887,6 @@ arm9_setup(void) /* Set the control register */ cpu_control(cpuctrlmask, cpuctrl); - ctrl = cpuctrl; } #endif /* CPU_ARM9 */ @@ -928,7 +925,6 @@ arm10_setup(void) cpuctrl |= CPU_CONTROL_VECRELOC; /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* And again. */ @@ -1032,7 +1028,6 @@ arm11x6_setup(void) cp15_cpacr_set(0x0fffffff); /* Set the control register */ - ctrl = cpuctrl; cpu_control(~cpuctrl_wax, cpuctrl); tmp = cp15_actlr_get(); @@ -1074,7 +1069,6 @@ pj4bv7_setup(void) cpu_idcache_wbinv_all(); /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xFFFFFFFF, cpuctrl); /* And again. */ @@ -1120,7 +1114,6 @@ cortexa_setup(void) cpu_idcache_wbinv_all(); /* Set the control register */ - ctrl = cpuctrl; cpu_control(cpuctrlmask, cpuctrl); /* And again. */ @@ -1167,7 +1160,6 @@ fa526_setup(void) cpu_idcache_wbinv_all(); /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #endif /* CPU_FA526 */ @@ -1221,7 +1213,6 @@ xscale_setup(void) * Set the control register. Note that bits 6:3 must always * be set to 1. */ - ctrl = cpuctrl; /* cpu_control(cpuctrlmask, cpuctrl);*/ cpu_control(0xffffffff, cpuctrl); diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c index 6c5764c297ce..2b7fec4d05dc 100644 --- a/sys/arm/arm/identcpu.c +++ b/sys/arm/arm/identcpu.c @@ -321,7 +321,6 @@ print_enadis(int enadis, char *s) printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en"); } -extern int ctrl; enum cpu_class cpu_class = CPU_CLASS_NONE; u_int cpu_pfr(int num) @@ -388,9 +387,10 @@ void identify_arm_cpu(void) { u_int cpuid, reg, size, sets, ways; - u_int8_t type, linesize; + u_int8_t type, linesize, ctrl; int i; + ctrl = cpu_get_control(); cpuid = cpu_ident(); if (cpuid == 0) { diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index b5330021842f..afbcac834f13 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -202,6 +202,7 @@ u_int cpufunc_control (u_int clear, u_int bic); void cpu_domains (u_int domains); u_int cpu_faultstatus (void); u_int cpu_faultaddress (void); +u_int cpu_get_control (void); u_int cpu_pfr (int); #if defined(CPU_FA526) From a6a53aa0dc541d11f006058c210249628072c55e Mon Sep 17 00:00:00 2001 From: br Date: Thu, 4 Feb 2016 12:49:28 +0000 Subject: [PATCH 178/236] Reuse gp register for pcpu pointer. gp (global pointer) is used by compiler in userland only, so re-use it for pcpup in kernel, save it on stack on switching out to userland and load back on return to kernel. Discussed with: jhb, andrew, kib Sponsored by: DARPA, AFRL Sponsored by: HEIF5 Differential Revision: https://reviews.freebsd.org/D5178 --- sys/riscv/include/pcpu.h | 7 +++++-- sys/riscv/riscv/exception.S | 17 ++++++++++++----- sys/riscv/riscv/genassym.c | 1 + sys/riscv/riscv/machdep.c | 11 +++++------ sys/riscv/riscv/swtch.S | 23 ++++++++++++++--------- sys/riscv/riscv/vm_machdep.c | 2 +- 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h index c60a95428fe1..7dfe23d991bf 100644 --- a/sys/riscv/include/pcpu.h +++ b/sys/riscv/include/pcpu.h @@ -47,8 +47,11 @@ extern struct pcpu *pcpup; static inline struct pcpu * get_pcpu(void) { + struct pcpu *pcpu; - return (pcpup); + __asm __volatile("mv %0, gp" : "=&r"(pcpu)); + + return (pcpu); } static inline struct thread * @@ -56,7 +59,7 @@ get_curthread(void) { struct thread *td; - td = (struct thread *)*(uint64_t *)pcpup; + __asm __volatile("ld %0, 0(gp)" : "=&r"(td)); return (td); } diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index 07fcfc52787a..8bd9027313b3 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -41,12 +41,16 @@ __FBSDID("$FreeBSD$"); #include .macro save_registers el - addi sp, sp, -280 + addi sp, sp, -(TF_SIZE) sd ra, (TF_RA)(sp) - sd gp, (TF_GP)(sp) sd tp, (TF_TP)(sp) +.if \el == 0 /* We came from userspace. Load our pcpu */ + sd gp, (TF_GP)(sp) + ld gp, (TF_SIZE)(sp) +.endif + sd t0, (TF_T + 0 * 8)(sp) sd t1, (TF_T + 1 * 8)(sp) sd t2, (TF_T + 2 * 8)(sp) @@ -127,13 +131,16 @@ __FBSDID("$FreeBSD$"); csrw sepc, t0 .if \el == 0 - /* Load user sp */ + /* We go to userspace. Load user sp */ ld t0, (TF_SP)(sp) csrw sscratch, t0 + + /* And store our pcpu */ + sd gp, (TF_SIZE)(sp) + ld gp, (TF_GP)(sp) .endif ld ra, (TF_RA)(sp) - ld gp, (TF_GP)(sp) ld tp, (TF_TP)(sp) ld t0, (TF_T + 0 * 8)(sp) @@ -166,7 +173,7 @@ __FBSDID("$FreeBSD$"); ld a6, (TF_A + 6 * 8)(sp) ld a7, (TF_A + 7 * 8)(sp) - addi sp, sp, 280 + addi sp, sp, (TF_SIZE) .endm .macro do_ast diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c index f5c971d178a7..bf6c8fb4c851 100644 --- a/sys/riscv/riscv/genassym.c +++ b/sys/riscv/riscv/genassym.c @@ -85,6 +85,7 @@ ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); +ASSYM(TF_SIZE, sizeof(struct trapframe)); ASSYM(TF_RA, offsetof(struct trapframe, tf_ra)); ASSYM(TF_SP, offsetof(struct trapframe, tf_sp)); ASSYM(TF_GP, offsetof(struct trapframe, tf_gp)); diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 5f9bd1f283f2..79688e6f3009 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -256,7 +256,9 @@ ptrace_clear_single_step(struct thread *td) void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct trapframe *tf = td->td_frame; + struct trapframe *tf; + + tf = td->td_frame; memset(tf, 0, sizeof(struct trapframe)); @@ -563,6 +565,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) static void init_proc0(vm_offset_t kstack) { + pcpup = &__pcpu[0]; proc_linkup0(&proc0, &thread0); @@ -760,11 +763,7 @@ initriscv(struct riscv_bootparams *rvbp) pcpu_init(pcpup, 0, sizeof(struct pcpu)); /* Set the pcpu pointer */ -#if 0 - /* SMP TODO: try re-use gp for pcpu pointer */ - __asm __volatile( - "mv gp, %0" :: "r"(pcpup)); -#endif + __asm __volatile("mv gp, %0" :: "r"(pcpup)); PCPU_SET(curthread, &thread0); diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index 945fce354972..5e9b3c986238 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -74,8 +74,6 @@ ENTRY(cpu_throw) /* Load registers */ ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) - ld gp, (PCB_GP)(x13) - ld tp, (PCB_TP)(x13) /* s[0-11] */ ld s0, (PCB_S + 0 * 8)(x13) @@ -120,8 +118,6 @@ ENTRY(cpu_switch) /* Store the callee-saved registers */ sd ra, (PCB_RA)(x13) sd sp, (PCB_SP)(x13) - sd gp, (PCB_GP)(x13) - sd tp, (PCB_TP)(x13) /* We use these in fork_trampoline */ sd t0, (PCB_T + 0 * 8)(x13) @@ -176,8 +172,6 @@ ENTRY(cpu_switch) /* Restore the registers */ ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) - ld gp, (PCB_GP)(x13) - ld tp, (PCB_TP)(x13) /* We use these in fork_trampoline */ ld t0, (PCB_T + 0 * 8)(x13) @@ -254,12 +248,23 @@ ENTRY(fork_trampoline) ld a6, (TF_A + 6 * 8)(sp) ld a7, (TF_A + 7 * 8)(sp) + /* Load user ra and sp */ + ld tp, (TF_TP)(sp) + ld ra, (TF_RA)(sp) + + /* + * Store our pcpup on stack, we will load it back + * on kernel mode trap. + */ + sd gp, (TF_SIZE)(sp) + ld gp, (TF_GP)(sp) + /* Save kernel stack so we can use it doing a user trap */ + addi sp, sp, TF_SIZE csrw sscratch, sp - /* Load user ra and sp */ - ld ra, (TF_RA)(sp) - ld sp, (TF_SP)(sp) + /* Load user stack */ + ld sp, (TF_SP - TF_SIZE)(sp) eret END(fork_trampoline) diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index 0f652501a67a..fef626b9f2fa 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -218,7 +218,7 @@ cpu_thread_alloc(struct thread *td) td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE) - 1; td->td_frame = (struct trapframe *)STACKALIGN( - td->td_pcb - 1); + (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe)); } void From a235ff8242f112163b331a14d2ced14dd58250cf Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 13:32:29 +0000 Subject: [PATCH 179/236] ARM: RPI-B kernel was broken by r294740. Make it functional again. --- sys/arm/arm/debug_monitor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/arm/arm/debug_monitor.c b/sys/arm/arm/debug_monitor.c index e216e347597c..eaf88e9d1f07 100644 --- a/sys/arm/arm/debug_monitor.c +++ b/sys/arm/arm/debug_monitor.c @@ -845,8 +845,10 @@ dbg_arch_supported(void) { switch (dbg_model) { +#ifdef not_yet case ID_DFR0_CP_DEBUG_M_V6: case ID_DFR0_CP_DEBUG_M_V6_1: +#endif case ID_DFR0_CP_DEBUG_M_V7: case ID_DFR0_CP_DEBUG_M_V7_1: /* fall through */ return (TRUE); From 855ee55df38fa7caca48484dc2530a3e7e06affc Mon Sep 17 00:00:00 2001 From: skra Date: Thu, 4 Feb 2016 13:35:40 +0000 Subject: [PATCH 180/236] Small rearrangement of abort_handler(). (1) Move cnt.v_trap increment to the beginning. There is cnt.v_vm_faults counter in vm_fault(), so a number of hardware emulation aborts may be get roughly as difference. (2) Move kdb_reenter() up to not be ignored if pmap_fault() has failed. (3) Update comments. --- sys/arm/arm/trap-v6.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index adc29c6534e8..88aec53ab442 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -293,7 +293,10 @@ abort_handler(struct trapframe *tf, int prefetch) #ifdef INVARIANTS void *onfault; #endif + + PCPU_INC(cnt.v_trap); td = curthread; + fsr = (prefetch) ? cp15_ifsr_get(): cp15_dfsr_get(); #if __ARM_ARCH >= 7 far = (prefetch) ? cp15_ifar_get() : cp15_dfar_get(); @@ -334,24 +337,23 @@ abort_handler(struct trapframe *tf, int prefetch) * they are not from KVA space. Thus, no action is needed here. */ + /* + * (1) Handle access and R/W hardware emulation aborts. + * (2) Check that abort is not on pmap essential address ranges. + * There is no way how to fix it, so we don't even try. + */ rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode); if (rv == KERN_SUCCESS) return; - if (rv == KERN_INVALID_ADDRESS) - goto nogo; - /* - * Now, when we handled imprecise and debug aborts, the rest of - * aborts should be really related to mapping. - */ - - PCPU_INC(cnt.v_trap); - #ifdef KDB if (kdb_active) { kdb_reenter(); goto out; } #endif + if (rv == KERN_INVALID_ADDRESS) + goto nogo; + if (__predict_false((td->td_pflags & TDP_NOFAULTING) != 0)) { /* * Due to both processor errata and lazy TLB invalidation when @@ -417,6 +419,14 @@ abort_handler(struct trapframe *tf, int prefetch) goto out; } + /* + * At this point, we're dealing with one of the following aborts: + * + * FAULT_ICACHE - I-cache maintenance + * FAULT_TRAN_xx - Translation + * FAULT_PERM_xx - Permission + */ + /* * Don't pass faulting cache operation to vm_fault(). We don't want * to handle all vm stuff at this moment. @@ -435,16 +445,6 @@ abort_handler(struct trapframe *tf, int prefetch) goto out; } - /* - * At this point, we're dealing with one of the following aborts: - * - * FAULT_TRAN_xx - Translation - * FAULT_PERM_xx - Permission - * - * These are the main virtual memory-related faults signalled by - * the MMU. - */ - /* fusubailout is used by [fs]uswintr to avoid page faulting. */ if (__predict_false(pcb->pcb_onfault == fusubailout)) { tf->tf_r0 = EFAULT; From b512e43ef25c82d0955c88efbebd614817b95e26 Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 14:02:42 +0000 Subject: [PATCH 181/236] ARM: Set UNAL_ENABLE bit in SCTLR CP15 register. This bit is RAO/SBOP for ARMv7. For ARMv6, it controls ARMv5 compatible alignment support. This bit have no effect until unaligned access is enabled. --- sys/arm/arm/locore-v6.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index eda60146dd5b..b93af2c4b6b5 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -132,9 +132,9 @@ ASENTRY_NP(_start) bic r7, #CPU_CONTROL_DC_ENABLE bic r7, #CPU_CONTROL_MMU_ENABLE bic r7, #CPU_CONTROL_IC_ENABLE - bic r7, #CPU_CONTROL_UNAL_ENABLE bic r7, #CPU_CONTROL_BPRD_ENABLE bic r7, #CPU_CONTROL_SW_ENABLE + orr r7, #CPU_CONTROL_UNAL_ENABLE orr r7, #CPU_CONTROL_AFLT_ENABLE orr r7, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r7) @@ -456,9 +456,9 @@ ASENTRY_NP(mpentry) bic r0, #CPU_CONTROL_MMU_ENABLE bic r0, #CPU_CONTROL_DC_ENABLE bic r0, #CPU_CONTROL_IC_ENABLE - bic r0, #CPU_CONTROL_UNAL_ENABLE bic r0, #CPU_CONTROL_BPRD_ENABLE bic r0, #CPU_CONTROL_SW_ENABLE + orr r0, #CPU_CONTROL_UNAL_ENABLE orr r0, #CPU_CONTROL_AFLT_ENABLE orr r0, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r0) From 87f75655f47c981626c6195bef391c7b49efb7cf Mon Sep 17 00:00:00 2001 From: skra Date: Thu, 4 Feb 2016 14:15:24 +0000 Subject: [PATCH 182/236] Make VM_MEMATTR_xxx definitions independent on pmap internals for __ARM_ARCH >= 6. It's TEX class number now, so it still has some meaning. --- sys/arm/arm/pmap-v6.c | 129 ++++++++++++++++++++++++-------------- sys/arm/include/pmap-v6.h | 4 +- sys/arm/include/vm.h | 10 +-- 3 files changed, 89 insertions(+), 54 deletions(-) diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index d4ab9305b39d..95e4a5d5d2af 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -223,11 +223,13 @@ int pmap_debug_level = 1; /* * PTE2 descriptors creation macros. */ +#define PTE2_TEX_DEFAULT memattr_to_tex2(VM_MEMATTR_DEFAULT) + #define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, pt_memattr) #define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, pt_memattr) -#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL) -#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_NORMAL) +#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_TEX_DEFAULT) +#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_TEX_DEFAULT) #define PV_STATS #ifdef PV_STATS @@ -262,10 +264,6 @@ static uint32_t ttb_flags; static vm_memattr_t pt_memattr; ttb_entry_t pmap_kern_ttb; -/* XXX use converion function*/ -#define PTE2_ATTR_NORMAL VM_MEMATTR_DEFAULT -#define PTE1_ATTR_NORMAL ATTR_TO_L1(PTE2_ATTR_NORMAL) - struct pmap kernel_pmap_store; LIST_HEAD(pmaplist, pmap); static struct pmaplist allpmaps; @@ -399,6 +397,37 @@ static uint32_t tex_class[8] = { }; #undef TEX +static uint32_t tex_attr2[8] = { + PTE2_ATTR_WB_WA, /* 0 - VM_MEMATTR_WB_WA */ + PTE2_ATTR_NOCACHE, /* 1 - VM_MEMATTR_NOCACHE */ + PTE2_ATTR_DEVICE, /* 2 - VM_MEMATTR_DEVICE */ + PTE2_ATTR_SO, /* 3 - VM_MEMATTR_SO */ + PTE2_ATTR_WT, /* 4 - VM_MEMATTR_WRITE_THROUGH */ + 0, /* 5 - NOT USED YET */ + 0, /* 6 - NOT USED YET */ + 0 /* 7 - NOT USED YET */ +}; +CTASSERT(VM_MEMATTR_WB_WA == 0); +CTASSERT(VM_MEMATTR_NOCACHE == 1); +CTASSERT(VM_MEMATTR_DEVICE == 2); +CTASSERT(VM_MEMATTR_SO == 3); +CTASSERT(VM_MEMATTR_WRITE_THROUGH == 4); + +static inline uint32_t +memattr_to_tex2(vm_memattr_t ma) +{ + + KASSERT(ma < 5, ("%s: bad vm_memattr_t %d", __func__, ma)); + return (tex_attr2[(u_int)ma]); +} + +static inline uint32_t +page_tex2(vm_page_t m) +{ + + return (memattr_to_tex2(m->md.pat_mode)); +} + /* * Convert TEX definition entry to TTB flags. */ @@ -713,7 +742,7 @@ pmap_bootstrap_prepare(vm_paddr_t last) pt1_entry_t *pte1p; pt2_entry_t *pte2p; u_int i; - uint32_t actlr_mask, actlr_set; + uint32_t actlr_mask, actlr_set, l1_attr; /* * Now, we are going to make real kernel mapping. Note that we are @@ -776,10 +805,10 @@ pmap_bootstrap_prepare(vm_paddr_t last) pte1_store(pte1p++, PTE1_LINK(pa)); /* Make section mappings for kernel. */ + l1_attr = ATTR_TO_L1(PTE2_TEX_DEFAULT); pte1p = kern_pte1(KERNBASE); for (pa = KERNEL_V2P(KERNBASE); pa < last; pa += PTE1_SIZE) - pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, - ATTR_TO_L1(PTE2_ATTR_WB_WA))); + pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, l1_attr)); /* * Get free and aligned space for PT2MAP and make L1 page table links @@ -988,13 +1017,14 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, vm_prot_t prot, vm_memattr_t attr) { u_int num; - u_int l1_attr, l1_prot, l2_prot; + u_int l1_attr, l1_prot, l2_prot, l2_attr; pt1_entry_t *pte1p; pt2_entry_t *pte2p; l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR; + l2_attr = memattr_to_tex2(attr); l1_prot = ATTR_TO_L1(l2_prot); - l1_attr = ATTR_TO_L1(attr); + l1_attr = ATTR_TO_L1(l2_attr); /* Map all the pages. */ num = round_page(size); @@ -1007,7 +1037,7 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, num -= PTE1_SIZE; } else { pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, PTE2_KERN(pa, l2_prot, attr)); + pte2_store(pte2p, PTE2_KERN(pa, l2_prot, l2_attr)); va += PAGE_SIZE; pa += PAGE_SIZE; num -= PAGE_SIZE; @@ -1247,7 +1277,7 @@ PMAP_INLINE void pmap_kenter(vm_offset_t va, vm_paddr_t pa) { - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL); + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_TEX_DEFAULT); } /* @@ -1320,7 +1350,8 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) vm_offset_t va, sva; vm_paddr_t pte1_offset; pt1_entry_t npte1; - u_int l1prot,l2prot; + uint32_t l1prot, l2prot; + uint32_t l1attr, l2attr; PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x)," " prot = %d\n", __func__, *virt, start, end, end - start, prot)); @@ -1329,6 +1360,9 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX; l1prot = ATTR_TO_L1(l2prot); + l2attr = PTE2_TEX_DEFAULT; + l1attr = ATTR_TO_L1(l2attr); + va = *virt; /* * Does the physical address range's size and alignment permit at @@ -1351,13 +1385,12 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) if ((start & PTE1_OFFSET) == 0 && end - start >= PTE1_SIZE) { KASSERT((va & PTE1_OFFSET) == 0, ("%s: misaligned va %#x", __func__, va)); - npte1 = PTE1_KERN(start, l1prot, PTE1_ATTR_NORMAL); + npte1 = PTE1_KERN(start, l1prot, l1attr); pmap_kenter_pte1(va, npte1); va += PTE1_SIZE; start += PTE1_SIZE; } else { - pmap_kenter_prot_attr(va, start, l2prot, - PTE2_ATTR_NORMAL); + pmap_kenter_prot_attr(va, start, l2prot, l2attr); va += PAGE_SIZE; start += PAGE_SIZE; } @@ -1527,7 +1560,7 @@ pmap_page_init(vm_page_t m) TAILQ_INIT(&m->md.pv_list); pt2_wirecount_init(m); - m->md.pat_mode = PTE2_ATTR_NORMAL; + m->md.pat_mode = VM_MEMATTR_DEFAULT; } /* @@ -1561,8 +1594,7 @@ pmap_pt2pg_zero(vm_page_t m) mtx_lock(&sysmaps->lock); if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); - pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, - m->md.pat_mode)); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, page_tex2(m))); /* Even VM_ALLOC_ZERO request is only advisory. */ if ((m->flags & PG_ZERO) == 0) pagezero(sysmaps->CADDR2); @@ -1586,7 +1618,7 @@ pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m) pt2_entry_t *pte2p; /* Check page attributes. */ - if (pmap_page_get_memattr(m) != pt_memattr) + if (m->md.pat_mode != pt_memattr) pmap_page_set_memattr(m, pt_memattr); /* Zero page and init wire counts. */ @@ -1717,10 +1749,10 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) pa = VM_PAGE_TO_PHYS(m); pte2 = pte2_load(pte2p); if ((pte2_pa(pte2) != pa) || - (pte2_attr(pte2) != m->md.pat_mode)) { + (pte2_attr(pte2) != page_tex2(m))) { anychanged++; pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW, - m->md.pat_mode)); + page_tex2(m))); } pte2p++; } @@ -3770,7 +3802,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, /* * Now validate mapping with desired protection/wiring. */ - npte2 = PTE2(pa, PTE2_NM, m->md.pat_mode); + npte2 = PTE2(pa, PTE2_NM, page_tex2(m)); if (prot & VM_PROT_WRITE) { if (pte2_is_managed(npte2)) vm_page_aflag_set(m, PGA_WRITEABLE); @@ -3795,7 +3827,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, */ if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. Do it now, before the mapping is stored and made * valid for hardware table walk. If done later, there is a race * for other threads of current process in lazy loading case. @@ -3810,7 +3842,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, * (2) Now, we do it on a page basis. */ if ((prot & VM_PROT_EXECUTE) && pmap != kernel_pmap && - m->md.pat_mode == PTE2_ATTR_WB_WA && + m->md.pat_mode == VM_MEMATTR_WB_WA && (opa != pa || (opte2 & PTE2_NX))) cache_icache_sync_fresh(va, pa, PAGE_SIZE); @@ -4410,14 +4442,14 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, l2prot |= PTE2_U | PTE2_NG; if ((prot & VM_PROT_EXECUTE) == 0) l2prot |= PTE2_NX; - else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) { + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. QQQ: For more info, see comments in pmap_enter(). */ cache_icache_sync_fresh(va, pa, PAGE_SIZE); } - pte2_store(pte2p, PTE2(pa, l2prot, m->md.pat_mode)); + pte2_store(pte2p, PTE2(pa, l2prot, page_tex2(m))); return (mpt2pg); } @@ -4481,14 +4513,14 @@ pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) l1prot |= PTE1_U | PTE1_NG; if ((prot & VM_PROT_EXECUTE) == 0) l1prot |= PTE1_NX; - else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) { + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. QQQ: For more info, see comments in pmap_enter(). */ cache_icache_sync_fresh(va, pa, PTE1_SIZE); } - pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(m->md.pat_mode))); + pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(page_tex2(m)))); pmap_pte1_mappings++; CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va, @@ -4552,7 +4584,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, pt1_entry_t *pte1p; vm_paddr_t pa, pte2_pa; vm_page_t p; - int pat_mode; + vm_memattr_t pat_mode; u_int l1attr, l1prot; VM_OBJECT_ASSERT_WLOCKED(object); @@ -4598,7 +4630,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, * is done here, so readonly mapping must be done elsewhere. */ l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A; - l1attr = ATTR_TO_L1(pat_mode); + l1attr = ATTR_TO_L1(memattr_to_tex2(pat_mode)); PMAP_LOCK(pmap); for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) { pte1p = pmap_pte1(pmap, addr); @@ -5492,7 +5524,8 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP2) panic("%s: CMAP2 busy", __func__); - pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, + memattr_to_tex2(ma))); dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5583,7 +5616,7 @@ pmap_zero_page(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + page_tex2(m))); pagezero(sysmaps->CADDR2); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5608,7 +5641,7 @@ pmap_zero_page_area(vm_page_t m, int off, int size) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + page_tex2(m))); if (off == 0 && size == PAGE_SIZE) pagezero(sysmaps->CADDR2); else @@ -5633,7 +5666,7 @@ pmap_zero_page_idle(vm_page_t m) panic("%s: CMAP3 busy", __func__); sched_pin(); pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + page_tex2(m))); pagezero(CADDR3); pte2_clear(CMAP3); tlb_flush((vm_offset_t)CADDR3); @@ -5659,9 +5692,9 @@ pmap_copy_page(vm_page_t src, vm_page_t dst) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(src), - PTE2_AP_KR | PTE2_NM, src->md.pat_mode)); + PTE2_AP_KR | PTE2_NM, page_tex2(src))); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst), - PTE2_AP_KRW, dst->md.pat_mode)); + PTE2_AP_KRW, page_tex2(dst))); bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); pte2_clear(sysmaps->CMAP1); tlb_flush((vm_offset_t)sysmaps->CADDR1); @@ -5698,10 +5731,10 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], b_pg_offset = b_offset & PAGE_MASK; cnt = min(cnt, PAGE_SIZE - b_pg_offset); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg), - PTE2_AP_KR | PTE2_NM, a_pg->md.pat_mode)); + PTE2_AP_KR | PTE2_NM, page_tex2(a_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR1); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(b_pg), - PTE2_AP_KRW, b_pg->md.pat_mode)); + PTE2_AP_KRW, page_tex2(b_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR2); a_cp = sysmaps->CADDR1 + a_pg_offset; b_cp = sysmaps->CADDR2 + b_pg_offset; @@ -5731,7 +5764,7 @@ pmap_quick_enter_page(vm_page_t m) KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__)); pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - pmap_page_get_memattr(m))); + page_tex2(m))); return (qmap_addr); } @@ -5993,13 +6026,15 @@ void pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa) { vm_offset_t sva; + uint32_t l2attr; KASSERT((size & PAGE_MASK) == 0, ("%s: device mapping not page-sized", __func__)); sva = va; + l2attr = memattr_to_tex2(VM_MEMATTR_DEVICE); while (size != 0) { - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEVICE); + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, l2attr); va += PAGE_SIZE; pa += PAGE_SIZE; size -= PAGE_SIZE; @@ -6073,7 +6108,7 @@ cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, m->md.pat_mode); + pmap_dcache_wb_pou(pa, len, page_tex2(m)); } /* * I-cache is VIPT. Only way how to flush all virtual mappings @@ -6101,7 +6136,7 @@ pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, m->md.pat_mode); + pmap_dcache_wb_pou(pa, len, page_tex2(m)); } } /* @@ -6298,7 +6333,7 @@ pmap_zero_page_check(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + page_tex2(m))); end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE); for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++) if (*p != 0) diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index b380c29dded0..067897779a20 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -115,7 +115,7 @@ struct pv_chunk; struct md_page { TAILQ_HEAD(,pv_entry) pv_list; uint16_t pt2_wirecount[4]; - int pat_mode; + vm_memattr_t pat_mode; }; struct pmap { @@ -173,7 +173,7 @@ struct pv_chunk { struct pcb; extern ttb_entry_t pmap_kern_ttb; /* TTB for kernel pmap */ -#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) +#define pmap_page_get_memattr(m) ((m)->md.pat_mode) #define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0) /* diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 552460e9f9a9..eb670256f47c 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -34,11 +34,11 @@ #if __ARM_ARCH >= 6 #include -#define VM_MEMATTR_WB_WA ((vm_memattr_t)PTE2_ATTR_WB_WA) -#define VM_MEMATTR_NOCACHE ((vm_memattr_t)PTE2_ATTR_NOCACHE) -#define VM_MEMATTR_DEVICE ((vm_memattr_t)PTE2_ATTR_DEVICE) -#define VM_MEMATTR_SO ((vm_memattr_t)PTE2_ATTR_SO) -#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PTE2_ATTR_WT) +#define VM_MEMATTR_WB_WA ((vm_memattr_t)0) +#define VM_MEMATTR_NOCACHE ((vm_memattr_t)1) +#define VM_MEMATTR_DEVICE ((vm_memattr_t)2) +#define VM_MEMATTR_SO ((vm_memattr_t)3) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)4) #define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA #define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */ From 996520c667b5c94ff6e02725612083dc93269da3 Mon Sep 17 00:00:00 2001 From: br Date: Thu, 4 Feb 2016 14:30:46 +0000 Subject: [PATCH 183/236] Access pcpup using gp register. --- sys/riscv/include/asm.h | 4 +--- sys/riscv/riscv/exception.S | 4 +--- sys/riscv/riscv/swtch.S | 14 ++++---------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h index fb0c8442fc4f..adcc23aa9501 100644 --- a/sys/riscv/include/asm.h +++ b/sys/riscv/include/asm.h @@ -59,9 +59,7 @@ .set alias,sym #define SET_FAULT_HANDLER(handler, tmp) \ - la tmp, pcpup; \ - ld tmp, 0(tmp); \ - ld tmp, PC_CURTHREAD(tmp); \ + ld tmp, PC_CURTHREAD(gp); \ ld tmp, TD_PCB(tmp); /* Load the pcb */ \ sd handler, PCB_ONFAULT(tmp) /* Set the handler */ diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index 8bd9027313b3..814fcf67b9d8 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -182,9 +182,7 @@ __FBSDID("$FreeBSD$"); 1: csrci sstatus, SSTATUS_IE - la a1, pcpup - ld a1, 0(a1) - ld a1, PC_CURTHREAD(a1) + ld a1, PC_CURTHREAD(gp) lw a2, TD_FLAGS(a1) li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED) diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index 5e9b3c986238..c6336a968d15 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -46,14 +46,11 @@ __FBSDID("$FreeBSD$"); * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) - /* Load pcpu */ - la x14, pcpup - ld x14, 0(x14) /* Store the new curthread */ - sd a1, PC_CURTHREAD(x14) + sd a1, PC_CURTHREAD(gp) /* And the new pcb */ ld x13, TD_PCB(a1) - sd x13, PC_CURPCB(x14) + sd x13, PC_CURPCB(gp) sfence.vm @@ -103,14 +100,11 @@ END(cpu_throw) * x3 to x7, x16 and x17 are caller saved */ ENTRY(cpu_switch) - /* Load pcpu */ - la x14, pcpup - ld x14, 0(x14) /* Store the new curthread */ - sd a1, PC_CURTHREAD(x14) + sd a1, PC_CURTHREAD(gp) /* And the new pcb */ ld x13, TD_PCB(a1) - sd x13, PC_CURPCB(x14) + sd x13, PC_CURPCB(gp) /* Save the old context. */ ld x13, TD_PCB(a0) From d3b54cd6b114f5967773ce8d87f268875ca5d31a Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 14:32:48 +0000 Subject: [PATCH 184/236] ARM: For ARMv6/v7, code in locore.S initializes SCTLR and ACTRL registers. Don't duplicate this initialization in cpu_setup(). --- sys/arm/arm/cpufunc.c | 112 ------------------------------------------ 1 file changed, 112 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index a2b8180e56a5..139899139346 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -966,47 +966,12 @@ cpu_scc_setup_ccnt(void) void arm11x6_setup(void) { - int cpuctrl, cpuctrl_wax; uint32_t auxctrl, auxctrl_wax; uint32_t tmp, tmp2; - uint32_t sbz=0; uint32_t cpuid; cpuid = cpu_ident(); - cpuctrl = - CPU_CONTROL_MMU_ENABLE | - CPU_CONTROL_DC_ENABLE | - CPU_CONTROL_WBUF_ENABLE | - CPU_CONTROL_32BP_ENABLE | - CPU_CONTROL_32BD_ENABLE | - CPU_CONTROL_LABT_ENABLE | - CPU_CONTROL_SYST_ENABLE | - CPU_CONTROL_IC_ENABLE | - CPU_CONTROL_UNAL_ENABLE; - - /* - * "write as existing" bits - * inverse of this is mask - */ - cpuctrl_wax = - (3 << 30) | /* SBZ */ - (1 << 29) | /* FA */ - (1 << 28) | /* TR */ - (3 << 26) | /* SBZ */ - (3 << 19) | /* SBZ */ - (1 << 17); /* SBZ */ - - cpuctrl |= CPU_CONTROL_BPRD_ENABLE; - cpuctrl |= CPU_CONTROL_V6_EXTPAGE; - -#ifdef __ARMEB__ - cpuctrl |= CPU_CONTROL_BEND_ENABLE; -#endif - - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - auxctrl = 0; auxctrl_wax = ~0; @@ -1018,18 +983,6 @@ arm11x6_setup(void) auxctrl_wax = ~ARM1176_AUXCTL_PHD; } - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Now really make sure they are clean. */ - __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz)); - - /* Allow detection code to find the VFP if it's fitted. */ - cp15_cpacr_set(0x0fffffff); - - /* Set the control register */ - cpu_control(~cpuctrl_wax, cpuctrl); - tmp = cp15_actlr_get(); tmp2 = tmp; tmp &= auxctrl_wax; @@ -1037,9 +990,6 @@ arm11x6_setup(void) if (tmp != tmp2) cp15_actlr_set(tmp); - /* And again. */ - cpu_idcache_wbinv_all(); - cpu_scc_setup_ccnt(); } #endif /* CPU_ARM1176 */ @@ -1048,32 +998,8 @@ arm11x6_setup(void) void pj4bv7_setup(void) { - int cpuctrl; pj4b_config(); - - cpuctrl = CPU_CONTROL_MMU_ENABLE; -#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS - cpuctrl |= CPU_CONTROL_AFLT_ENABLE; -#endif - cpuctrl |= CPU_CONTROL_DC_ENABLE; - cpuctrl |= (0xf << 3); - cpuctrl |= CPU_CONTROL_BPRD_ENABLE; - cpuctrl |= CPU_CONTROL_IC_ENABLE; - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - cpuctrl |= (0x5 << 16) | (1 < 22); - cpuctrl |= CPU_CONTROL_V6_EXTPAGE; - - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Set the control register */ - cpu_control(0xFFFFFFFF, cpuctrl); - - /* And again. */ - cpu_idcache_wbinv_all(); - cpu_scc_setup_ccnt(); } #endif /* CPU_MV_PJ4B */ @@ -1083,44 +1009,6 @@ pj4bv7_setup(void) void cortexa_setup(void) { - int cpuctrl, cpuctrlmask; - - cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */ - CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */ - CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */ - CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */ - CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */ - CPU_CONTROL_VECRELOC; /* Vector relocation [13] */ - - cpuctrl = CPU_CONTROL_MMU_ENABLE | - CPU_CONTROL_IC_ENABLE | - CPU_CONTROL_DC_ENABLE | - CPU_CONTROL_BPRD_ENABLE; - -#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS - cpuctrl |= CPU_CONTROL_AFLT_ENABLE; -#endif - - /* Switch to big endian */ -#ifdef __ARMEB__ - cpuctrl |= CPU_CONTROL_BEND_ENABLE; -#endif - - /* Check if the vector page is at the high address (0xffff0000) */ - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Set the control register */ - cpu_control(cpuctrlmask, cpuctrl); - - /* And again. */ - cpu_idcache_wbinv_all(); -#if defined(SMP) && !defined(ARM_NEW_PMAP) - armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */ -#endif cpu_scc_setup_ccnt(); } From be3acaf3333f8339b4359538cd31ad24be8791f0 Mon Sep 17 00:00:00 2001 From: trasz Date: Thu, 4 Feb 2016 15:10:08 +0000 Subject: [PATCH 185/236] Reduce code duplication. MFC after: 1 month Sponsored by: The FreeBSD Foundation --- bin/dd/args.c | 82 +++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/bin/dd/args.c b/bin/dd/args.c index 2f197f8da505..21e4aa1cb089 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -360,6 +360,38 @@ c_conv(const void *a, const void *b) ((const struct conv *)b)->name)); } +static uintmax_t +postfix_to_mult(const char expr) +{ + uintmax_t mult; + + mult = 0; + switch (expr) { + case 'B': + case 'b': + mult = 512; + break; + case 'K': + case 'k': + mult = 1 << 10; + break; + case 'M': + case 'm': + mult = 1 << 20; + break; + case 'G': + case 'g': + mult = 1 << 30; + break; + case 'W': + case 'w': + mult = sizeof(int); + break; + } + + return (mult); +} + /* * Convert an expression of the following forms to a uintmax_t. * 1) A positive decimal number. @@ -386,31 +418,7 @@ get_num(const char *val) if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); - mult = 0; - switch (*expr) { - case 'B': - case 'b': - mult = 512; - break; - case 'K': - case 'k': - mult = 1 << 10; - break; - case 'M': - case 'm': - mult = 1 << 20; - break; - case 'G': - case 'g': - mult = 1 << 30; - break; - case 'W': - case 'w': - mult = sizeof(int); - break; - default: - ; - } + mult = postfix_to_mult(*expr); if (mult != 0) { prevnum = num; @@ -460,29 +468,7 @@ get_off_t(const char *val) if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); - mult = 0; - switch (*expr) { - case 'B': - case 'b': - mult = 512; - break; - case 'K': - case 'k': - mult = 1 << 10; - break; - case 'M': - case 'm': - mult = 1 << 20; - break; - case 'G': - case 'g': - mult = 1 << 30; - break; - case 'W': - case 'w': - mult = sizeof(int); - break; - } + mult = postfix_to_mult(*expr); if (mult != 0) { prevnum = num; From c73d67730ab2dedcdc1b171947392eecc94ba6dd Mon Sep 17 00:00:00 2001 From: trasz Date: Thu, 4 Feb 2016 15:21:01 +0000 Subject: [PATCH 186/236] Add 't' and 'p' postfixes to dd(1). MFC after: 1 month Sponsored by: The FreeBSD Foundation --- bin/dd/args.c | 8 ++++++++ bin/dd/dd.1 | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/bin/dd/args.c b/bin/dd/args.c index 21e4aa1cb089..1cbf3b374cf1 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -383,6 +383,14 @@ postfix_to_mult(const char expr) case 'g': mult = 1 << 30; break; + case 'T': + case 't': + mult = (uintmax_t)1 << 40; + break; + case 'P': + case 'p': + mult = (uintmax_t)1 << 50; + break; case 'W': case 'w': mult = sizeof(int); diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 index 0908642dd1cf..4047cdca57f5 100644 --- a/bin/dd/dd.1 +++ b/bin/dd/dd.1 @@ -32,7 +32,7 @@ .\" @(#)dd.1 8.2 (Berkeley) 1/13/94 .\" $FreeBSD$ .\" -.Dd August 28, 2014 +.Dd February 4, 2016 .Dt DD 1 .Os .Sh NAME @@ -332,10 +332,13 @@ If the number ends with a .Dq Li k , .Dq Li m , .Dq Li g , +.Dq Li t , +.Dq Li p , or .Dq Li w , the -number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G) +number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G), +1099511627776 (1T), 1125899906842624 (1P) or the number of bytes in an integer, respectively. Two or more numbers may be separated by an .Dq Li x From 55fda5017767c3c7da549cc9a384bc668e70e185 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 4 Feb 2016 16:32:21 +0000 Subject: [PATCH 187/236] Do not copy by field when converting struct oexport_args to struct export_args on mount update, bzero() is consistent with vfs_oexport_conv(). Make the code structure more explicit by using switch. Return EINVAL if export option layout (deduced from size) is unknown. Based on the submission by: bde Sponsored by: The FreeBSD Foundation --- sys/kern/vfs_mount.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 3ca995fea0d1..505da758ed4a 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -880,10 +880,10 @@ vfs_domount_update( struct vfsoptlist **optlist /* Options local to the filesystem. */ ) { - struct oexport_args oexport; struct export_args export; + void *bufp; struct mount *mp; - int error, export_error; + int error, export_error, len; uint64_t flag; ASSERT_VOP_ELOCKED(vp, __func__); @@ -951,23 +951,21 @@ vfs_domount_update( error = VFS_MOUNT(mp); export_error = 0; - if (error == 0) { - /* Process the export option. */ - if (vfs_copyopt(mp->mnt_optnew, "export", &export, - sizeof(export)) == 0) { - export_error = vfs_export(mp, &export); - } else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport, - sizeof(oexport)) == 0) { - export.ex_flags = oexport.ex_flags; - export.ex_root = oexport.ex_root; - export.ex_anon = oexport.ex_anon; - export.ex_addr = oexport.ex_addr; - export.ex_addrlen = oexport.ex_addrlen; - export.ex_mask = oexport.ex_mask; - export.ex_masklen = oexport.ex_masklen; - export.ex_indexfile = oexport.ex_indexfile; - export.ex_numsecflavors = 0; + /* Process the export option. */ + if (error == 0 && vfs_getopt(mp->mnt_optnew, "export", &bufp, + &len) == 0) { + /* Assume that there is only 1 ABI for each length. */ + switch (len) { + case (sizeof(struct oexport_args)): + bzero(&export, sizeof(export)); + /* FALLTHROUGH */ + case (sizeof(export)): + bcopy(bufp, &export, len); export_error = vfs_export(mp, &export); + break; + default: + export_error = EINVAL; + break; } } From 992d44365d2db42521c58f221c374be13f5c9e35 Mon Sep 17 00:00:00 2001 From: mmel Date: Thu, 4 Feb 2016 17:01:38 +0000 Subject: [PATCH 188/236] Replace broken implementation of fuswintr() and suswintr() by functions which return -1 as well as on tier 1 archs. Remove block_userspace_access used only in these implementations. (1) These functions may be called in interrupt context and pcb_onfault can be already set in this time. Thus, prior pcb_onfault must be saved and restored afterwards. (2) The check that an abort came either from nested interrupt or while in critical section or holding not sleepable lock must be avoided for this case. These functions are called only for profiling reason, so there will be only small gain by making the code more complex. --- sys/arm/arm/cpufunc_asm_xscale.S | 19 +----- sys/arm/arm/cpufunc_asm_xscale_c3.S | 20 +------ sys/arm/arm/elf_trampoline.c | 1 - sys/arm/arm/fusu.S | 91 +---------------------------- sys/arm/arm/trap-v6.c | 8 --- sys/arm/arm/trap.c | 9 --- 6 files changed, 6 insertions(+), 142 deletions(-) diff --git a/sys/arm/arm/cpufunc_asm_xscale.S b/sys/arm/arm/cpufunc_asm_xscale.S index 3031b8c150f9..8b9848ccb15f 100644 --- a/sys/arm/arm/cpufunc_asm_xscale.S +++ b/sys/arm/arm/cpufunc_asm_xscale.S @@ -80,9 +80,6 @@ __FBSDID("$FreeBSD$"); */ #define DCACHE_SIZE 0x00008000 -.Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - /* * CPWAIT -- Canonical method to wait for CP15 update. * From: Intel 80200 manual, section 2.3.3. @@ -137,11 +134,6 @@ ENTRY(xscale_setttb) mrs r3, cpsr orr r1, r3, #(PSR_I | PSR_F) msr cpsr_fsxc, r1 -#else - ldr r3, .Lblock_userspace_access - ldr r2, [r3] - orr r1, r2, #1 - str r1, [r3] #endif stmfd sp!, {r0-r3, lr} bl _C_LABEL(xscale_cache_cleanID) @@ -165,8 +157,6 @@ ENTRY(xscale_setttb) #ifdef CACHE_CLEAN_BLOCK_INTR msr cpsr_fsxc, r3 -#else - str r2, [r3] #endif RET END(xscale_setttb) @@ -273,14 +263,9 @@ _C_LABEL(xscale_minidata_clean_size): #define XSCALE_CACHE_CLEAN_UNBLOCK \ msr cpsr_fsxc, r3 #else -#define XSCALE_CACHE_CLEAN_BLOCK \ - ldr r3, .Lblock_userspace_access ; \ - ldr ip, [r3] ; \ - orr r0, ip, #1 ; \ - str r0, [r3] +#define XSCALE_CACHE_CLEAN_BLOCK -#define XSCALE_CACHE_CLEAN_UNBLOCK \ - str ip, [r3] +#define XSCALE_CACHE_CLEAN_UNBLOCK #endif /* CACHE_CLEAN_BLOCK_INTR */ #define XSCALE_CACHE_CLEAN_PROLOGUE \ diff --git a/sys/arm/arm/cpufunc_asm_xscale_c3.S b/sys/arm/arm/cpufunc_asm_xscale_c3.S index cb770a8b873a..4e2c99999cac 100644 --- a/sys/arm/arm/cpufunc_asm_xscale_c3.S +++ b/sys/arm/arm/cpufunc_asm_xscale_c3.S @@ -82,9 +82,6 @@ __FBSDID("$FreeBSD$"); */ #define DCACHE_SIZE 0x00008000 -.Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - /* * CPWAIT -- Canonical method to wait for CP15 update. * From: Intel 80200 manual, section 2.3.3. @@ -130,16 +127,8 @@ __FBSDID("$FreeBSD$"); msr cpsr_fsxc, r4 ; \ ldmfd sp!, {r4} #else -#define XSCALE_CACHE_CLEAN_BLOCK \ - stmfd sp!, {r4} ; \ - ldr r4, .Lblock_userspace_access ; \ - ldr ip, [r4] ; \ - orr r0, ip, #1 ; \ - str r0, [r4] - -#define XSCALE_CACHE_CLEAN_UNBLOCK \ - str ip, [r3] ; \ - ldmfd sp!, {r4} +#define XSCALE_CACHE_CLEAN_BLOCK +#define XSCALE_CACHE_CLEAN_UNBLOCK #endif /* CACHE_CLEAN_BLOCK_INTR */ @@ -352,11 +341,6 @@ ENTRY(xscalec3_setttb) mrs r3, cpsr orr r1, r3, #(PSR_I | PSR_F) msr cpsr_fsxc, r1 -#else - ldr r3, .Lblock_userspace_access - ldr r2, [r3] - orr r1, r2, #1 - str r1, [r3] #endif stmfd sp!, {r0-r3, lr} bl _C_LABEL(xscalec3_cache_cleanID) diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index e25a849c812b..22f0f44ae575 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -125,7 +125,6 @@ static int arm_dcache_l2_assoc; static int arm_dcache_l2_linesize; -int block_userspace_access = 0; extern int arm9_dcache_sets_inc; extern int arm9_dcache_sets_max; extern int arm9_dcache_index_max; diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S index 54d263c7984a..ba50e67f8656 100644 --- a/sys/arm/arm/fusu.S +++ b/sys/arm/arm/fusu.S @@ -183,51 +183,10 @@ END(fusword) */ ENTRY(fuswintr) - ldr r3, =(VM_MAXUSER_ADDRESS-1) - cmp r0, r3 - mvncs r0, #0 - RETc(cs) - - ldr r2, Lblock_userspace_access - ldr r2, [r2] - teq r2, #0 - mvnne r0, #0x00000000 - RETne - - GET_PCB(r2) - ldr r2, [r2] - -#ifdef DIAGNOSTIC - teq r2, #0x00000000 - beq .Lfusupcbfault -#endif - - adr r1, _C_LABEL(fusubailout) - str r1, [r2, #PCB_ONFAULT] - - ldrbt r3, [r0], #1 - ldrbt ip, [r0] -#ifdef __ARMEB__ - orr r0, ip, r3, asl #8 -#else - orr r0, r3, ip, asl #8 -#endif - - mov r1, #0x00000000 - str r1, [r2, #PCB_ONFAULT] + mov r0, #-1 RET END(fuswintr) -Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - - .data - .align 2 - .global _C_LABEL(block_userspace_access) -_C_LABEL(block_userspace_access): - .word 0 - .text - /* * fubyte(caddr_t uaddr); * Fetch a byte from the user's address space. @@ -268,20 +227,6 @@ END(fubyte) mvn r0, #0x00000000 RET -/* - * Handle faults from [fs]u*(). Clean up and return -1. This differs from - * fusufault() in that trap() will recognise it and return immediately rather - * than trying to page fault. - */ - -/* label must be global as fault.c references it */ - .global _C_LABEL(fusubailout) -_C_LABEL(fusubailout): - mov r0, #0x00000000 - str r0, [r2, #PCB_ONFAULT] - mvn r0, #0x00000000 - RET - #ifdef DIAGNOSTIC /* * Handle earlier faults from [fs]u*(), due to no pcb @@ -335,39 +280,7 @@ END(suword) */ ENTRY(suswintr) - ldr r3, =(VM_MAXUSER_ADDRESS-1) - cmp r0, r3 - mvncs r0, #0 - RETc(cs) - - ldr r2, Lblock_userspace_access - ldr r2, [r2] - teq r2, #0 - mvnne r0, #0x00000000 - RETne - - GET_PCB(r2) - ldr r2, [r2] - -#ifdef DIAGNOSTIC - teq r2, #0x00000000 - beq .Lfusupcbfault -#endif - - adr r3, _C_LABEL(fusubailout) - str r3, [r2, #PCB_ONFAULT] - -#ifdef __ARMEB__ - mov ip, r1, lsr #8 - strbt ip, [r0], #1 -#else - strbt r1, [r0], #1 - mov r1, r1, lsr #8 -#endif - strbt r1, [r0] - - mov r0, #0x00000000 - str r0, [r2, #PCB_ONFAULT] + mov r0, #-1 RET END(suswintr) diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 88aec53ab442..9c0799950d1b 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$"); #include #endif -extern char fusubailout[]; extern char cachebailout[]; #ifdef DEBUG @@ -445,13 +444,6 @@ abort_handler(struct trapframe *tf, int prefetch) goto out; } - /* fusubailout is used by [fs]uswintr to avoid page faulting. */ - if (__predict_false(pcb->pcb_onfault == fusubailout)) { - tf->tf_r0 = EFAULT; - tf->tf_pc = (register_t)pcb->pcb_onfault; - return; - } - va = trunc_page(far); if (va >= KERNBASE) { /* diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index e43ec8eb3eb2..eb4d68304b33 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -111,8 +111,6 @@ __FBSDID("$FreeBSD$"); #define ReadWord(a) (*((volatile unsigned int *)(a))) -extern char fusubailout[]; - #ifdef DEBUG int last_fault_code; /* For the benefit of pmap_fault_fixup() */ #endif @@ -255,13 +253,6 @@ abort_handler(struct trapframe *tf, int type) * the MMU. */ - /* fusubailout is used by [fs]uswintr to avoid page faulting */ - if (__predict_false(pcb->pcb_onfault == fusubailout)) { - tf->tf_r0 = EFAULT; - tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault; - return; - } - /* * Make sure the Program Counter is sane. We could fall foul of * someone executing Thumb code, in which case the PC might not From 1721d478e5d586aabc1829702996b4a44802fcad Mon Sep 17 00:00:00 2001 From: dteske Date: Thu, 4 Feb 2016 17:09:43 +0000 Subject: [PATCH 189/236] Fix grammar in error statement s/consider to migrate to jail.conf/consider migrating to jail.conf/ --- etc/rc.d/jail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/rc.d/jail b/etc/rc.d/jail index fa0bc46be6ee..b33f1b9a2c23 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -563,7 +563,7 @@ jail_warn() # To relieve confusion, show a warning message. case $_confwarn in 1) warn "Per-jail configuration via jail_* variables " \ - "is obsolete. Please consider to migrate to $jail_conf." + "is obsolete. Please consider migrating to $jail_conf." ;; esac } From 327df1a84adbc8d73c704c55a2b3ceaacb6cdd96 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 4 Feb 2016 17:22:15 +0000 Subject: [PATCH 190/236] Enable checking of the stack alignment. The stack should be aligned to a 16-byte value. With this the hardware will check if a memory access uses an incorrectly aligned stack pointer as the base address. Sponsored by: ABT Systems Ltd --- sys/arm64/arm64/locore.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 9909a42472d9..87abee18e483 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -628,11 +628,11 @@ tcr_early: sctlr_set: /* Bits to set */ .quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \ - SCTLR_I | SCTLR_SED | SCTLR_C | SCTLR_M) + SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | SCTLR_C | SCTLR_M) sctlr_clear: /* Bits to clear */ .quad (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | SCTLR_ITD | \ - SCTLR_THEE | SCTLR_CP15BEN | SCTLR_SA0 | SCTLR_SA | SCTLR_A) + SCTLR_THEE | SCTLR_CP15BEN | SCTLR_A) .globl abort abort: From a4232236fc1def9db170b2b0c3f27704b202f294 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 4 Feb 2016 17:43:56 +0000 Subject: [PATCH 191/236] Fix build of powerpc FPU emulator after changes in r295132 to restore the ABI of struct fpreg. The FPU emulator operates on the "raw" FPU state stored in the pcb rather than the "cooked" fpreg state used for ptrace() and cores. Reported by: bz --- sys/powerpc/fpu/fpu_emu.c | 42 +++++++++++++++++------------------ sys/powerpc/fpu/fpu_explode.c | 6 ++--- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c index 9056dca8aa23..011b9999db99 100644 --- a/sys/powerpc/fpu/fpu_emu.c +++ b/sys/powerpc/fpu/fpu_emu.c @@ -275,7 +275,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) vm_offset_t addr; int ra, rb, rc, rt, type, mask, fsr, cx, bf, setcr; unsigned int cond; - struct fpreg *fs; + struct fpu *fs; /* Setup work. */ fp = NULL; @@ -335,7 +335,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) if (ra != 0) addr += tf->fixreg[ra]; rt = instr.i_x.i_rt; - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; DPRINTF(FPE_INSN, ("fpu_execute: Store INT %x at %p\n", a[1], (void *)addr)); @@ -402,7 +402,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) DPRINTF(FPE_INSN, ("fpu_execute: Store DBL at %p\n", (void *)addr)); - if (copyout(&fs->fpreg[rt].fpr, (void *)addr, + if (copyout(&fs->fpr[rt].fpr, (void *)addr, size)) return (FAULT); } @@ -411,13 +411,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) FPU_EMU_EVCNT_INCR(fpload); DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n", (void *)addr)); - if (copyin((const void *)addr, &fs->fpreg[rt].fpr, + if (copyin((const void *)addr, &fs->fpr[rt].fpr, size)) return (FAULT); if (type != FTYPE_DBL) { fpu_explode(fe, fp = &fe->fe_f1, type, rt); fpu_implode(fe, fp, FTYPE_DBL, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); } } if (update) @@ -470,7 +470,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n")); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb); fpu_implode(fe, fp, FTYPE_SNG, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt); type = FTYPE_DBL; break; @@ -503,9 +503,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FNEG: FPU_EMU_EVCNT_INCR(fnegabs); DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a ^= (1U << 31); break; case OPC63_MCRFS: @@ -533,7 +533,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FMR: FPU_EMU_EVCNT_INCR(fmr); DPRINTF(FPE_INSN, ("fpu_execute: FMR\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); break; case OPC63_MTFSFI: @@ -550,23 +550,23 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FNABS: FPU_EMU_EVCNT_INCR(fnabs); DPRINTF(FPE_INSN, ("fpu_execute: FABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a |= (1U << 31); break; case OPC63_FABS: FPU_EMU_EVCNT_INCR(fabs); DPRINTF(FPE_INSN, ("fpu_execute: FABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a &= ~(1U << 31); break; case OPC63_MFFS: FPU_EMU_EVCNT_INCR(mffs); DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpscr, + memcpy(&fs->fpr[rt].fpr, &fs->fpscr, sizeof(fs->fpscr)); break; case OPC63_MTFSF: @@ -581,7 +581,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) if (rt & (1<fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; fe->fe_cx = mask & a[1]; fe->fe_fpscr = (fe->fe_fpscr&~mask) | (fe->fe_cx); @@ -648,12 +648,12 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63M_FSEL: FPU_EMU_EVCNT_INCR(fsel); DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n")); - a = (int *)&fe->fe_fpstate->fpreg[ra].fpr; + a = (int *)&fe->fe_fpstate->fpr[ra].fpr; if ((*a & 0x80000000) && (*a & 0x7fffffff)) /* fra < 0 */ rc = rb; DPRINTF(FPE_INSN, ("f%d => f%d\n", rc, rt)); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rc].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rc].fpr, sizeof(double)); break; case OPC59_FRES: @@ -662,7 +662,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) fpu_explode(fe, &fe->fe_f1, type, rb); fp = fpu_sqrt(fe); /* now we've gotta overwrite the dest reg */ - *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1; + *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1; fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt); fpu_div(fe); break; @@ -681,7 +681,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) fp = fpu_sqrt(fe); fe->fe_f2 = *fp; /* now we've gotta overwrite the dest reg */ - *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1; + *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1; fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt); fpu_div(fe); break; @@ -737,7 +737,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) /* If the instruction was single precision, round */ if (!(instr.i_any.i_opcd & 0x4)) { fpu_implode(fe, fp, FTYPE_SNG, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt); } } @@ -752,7 +752,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) * Otherwise set new current exceptions and accrue. */ if (fp) - fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt].fpr); + fpu_implode(fe, fp, type, (u_int *)&fs->fpr[rt].fpr); cx = fe->fe_cx; fsr = fe->fe_fpscr; if (cx != 0) { diff --git a/sys/powerpc/fpu/fpu_explode.c b/sys/powerpc/fpu/fpu_explode.c index 1ebd96eccdc4..84073a4edb26 100644 --- a/sys/powerpc/fpu/fpu_explode.c +++ b/sys/powerpc/fpu/fpu_explode.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -211,9 +211,9 @@ fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg) u_int s, *space; u_int64_t l, *xspace; - xspace = (u_int64_t *)&fe->fe_fpstate->fpreg[reg].fpr; + xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr; l = xspace[0]; - space = (u_int *)&fe->fe_fpstate->fpreg[reg].fpr; + space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr; s = space[0]; fp->fp_sign = s >> 31; fp->fp_sticky = 0; From 6c66e4feff3a0557cfef7a815c48885d2e8465e7 Mon Sep 17 00:00:00 2001 From: jgh Date: Thu, 4 Feb 2016 18:03:06 +0000 Subject: [PATCH 192/236] - connect(2) Clarify namelen PR: 206838 Submitted by: t@tobik.me Approved by: bcr (mentor) MFH: after 1 week Differential Revision: https://reviews.freebsd.org/D5194 --- lib/libc/sys/connect.2 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/libc/sys/connect.2 b/lib/libc/sys/connect.2 index e3e57831475a..80f440715b83 100644 --- a/lib/libc/sys/connect.2 +++ b/lib/libc/sys/connect.2 @@ -28,7 +28,7 @@ .\" @(#)connect.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 29, 2014 +.Dd February 4, 2016 .Dt CONNECT 2 .Os .Sh NAME @@ -58,6 +58,14 @@ another socket. The other socket is specified by .Fa name , which is an address in the communications space of the socket. +.Fa namelen +indicates the amount of space pointed to by +.Fa name , +in bytes; the +.Fa sa_len +member of +.Fa name +is ignored. Each communications space interprets the .Fa name argument in its own way. From ad65b26786a9160789d37051277ea5c34c98113b Mon Sep 17 00:00:00 2001 From: tuexen Date: Thu, 4 Feb 2016 18:08:50 +0000 Subject: [PATCH 193/236] In FreeBSD 10 and higher the driver announces SCTP checksum offloading support also for 82598, which doesn't support it. The legacy code has a check for it, which was missed when the code for dealing with CSUM_IP6_* was added. Add the same check for FreeBSD 10 and higher. Differential Revision: https://reviews.freebsd.org/D5192 --- sys/dev/ixgbe/if_ix.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index c6a50840d207..f0e218fab1ed 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -1017,6 +1017,7 @@ static void ixgbe_set_if_hwassist(struct adapter *adapter) { struct ifnet *ifp = adapter->ifp; + struct ixgbe_hw *hw = &adapter->hw; ifp->if_hwassist = 0; #if __FreeBSD_version >= 1000000 @@ -1024,18 +1025,21 @@ ixgbe_set_if_hwassist(struct adapter *adapter) ifp->if_hwassist |= CSUM_IP_TSO; if (ifp->if_capenable & IFCAP_TSO6) ifp->if_hwassist |= CSUM_IP6_TSO; - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | - CSUM_IP_SCTP); - if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) - ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP | - CSUM_IP6_SCTP); + if (ifp->if_capenable & IFCAP_TXCSUM) { + ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP); + if (hw->mac.type != ixgbe_mac_82598EB) + ifp->if_hwassist |= CSUM_IP_SCTP; + } + if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) { + ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP); + if (hw->mac.type != ixgbe_mac_82598EB) + ifp->if_hwassist |= CSUM_IP6_SCTP; + } #else if (ifp->if_capenable & IFCAP_TSO) ifp->if_hwassist |= CSUM_TSO; if (ifp->if_capenable & IFCAP_TXCSUM) { ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); - struct ixgbe_hw *hw = &adapter->hw; if (hw->mac.type != ixgbe_mac_82598EB) ifp->if_hwassist |= CSUM_SCTP; } From 90ae570ac2c2e37f4c958f0dc31bd40995034958 Mon Sep 17 00:00:00 2001 From: rpokala Date: Thu, 4 Feb 2016 19:53:54 +0000 Subject: [PATCH 194/236] Add defines for WRITE_UNCORRECTABLE ATA command, and improve command logging Add #defines for ATA_WRITE_UNCORRECTABLE48 and its features. Update the decoding in ATACAM to recognize the new values. Also improve command decoding for a few other commands (SMART, NOP, SET_FEATURES). Bring the decoding in ata(4) up to parity with ATACAM. Reviewed by: mav, imp MFC after: 1 month Sponsored by: Panasas, Inc. Differential Revision: https://reviews.freebsd.org/D5181 --- sys/cam/ata/ata_all.c | 60 ++++++++++++++++++------- sys/dev/ata/ata-all.c | 100 ++++++++++++++++++++++++++++++++++++++---- sys/sys/ata.h | 3 ++ 3 files changed, 138 insertions(+), 25 deletions(-) diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index d836e42d59d7..d5220e874c78 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -75,13 +75,18 @@ ata_op_string(struct ata_cmd *cmd) if (cmd->control & 0x04) return ("SOFT_RESET"); switch (cmd->command) { - case 0x00: return ("NOP"); + case 0x00: + switch (cmd->features) { + case 0x00: return ("NOP FLUSHQUEUE"); + case 0x01: return ("NOP AUTOPOLL"); + } + return ("NOP"); case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); case 0x06: switch (cmd->features) { - case 0x01: return ("DSM TRIM"); - } - return "DSM"; + case 0x01: return ("DSM TRIM"); + } + return "DSM"; case 0x08: return ("DEVICE_RESET"); case 0x20: return ("READ"); case 0x24: return ("READ48"); @@ -105,6 +110,12 @@ ata_op_string(struct ata_cmd *cmd) case 0x3f: return ("WRITE_LOG_EXT"); case 0x40: return ("READ_VERIFY"); case 0x42: return ("READ_VERIFY48"); + case 0x45: + switch (cmd->features) { + case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO"); + case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED"); + } + return "WRITE_UNCORRECTABLE48"; case 0x51: return ("CONFIGURE_STREAM"); case 0x60: return ("READ_FPDMA_QUEUED"); case 0x61: return ("WRITE_FPDMA_QUEUED"); @@ -128,7 +139,18 @@ ata_op_string(struct ata_cmd *cmd) case 0xa0: return ("PACKET"); case 0xa1: return ("ATAPI_IDENTIFY"); case 0xa2: return ("SERVICE"); - case 0xb0: return ("SMART"); + case 0xb0: + switch(cmd->features) { + case 0xd0: return ("SMART READ ATTR VALUES"); + case 0xd1: return ("SMART READ ATTR THRESHOLDS"); + case 0xd3: return ("SMART SAVE ATTR VALUES"); + case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE"); + case 0xd5: return ("SMART READ LOG DATA"); + case 0xd8: return ("SMART ENABLE OPERATION"); + case 0xd9: return ("SMART DISABLE OPERATION"); + case 0xda: return ("SMART RETURN STATUS"); + } + return ("SMART"); case 0xb1: return ("DEVICE CONFIGURATION"); case 0xc0: return ("CFA_ERASE"); case 0xc4: return ("READ_MUL"); @@ -158,18 +180,22 @@ ata_op_string(struct ata_cmd *cmd) case 0xed: return ("MEDIA_EJECT"); case 0xef: switch (cmd->features) { - case 0x03: return ("SETFEATURES SET TRANSFER MODE"); - case 0x02: return ("SETFEATURES ENABLE WCACHE"); - case 0x82: return ("SETFEATURES DISABLE WCACHE"); - case 0x06: return ("SETFEATURES ENABLE PUIS"); - case 0x86: return ("SETFEATURES DISABLE PUIS"); - case 0x07: return ("SETFEATURES SPIN-UP"); - case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); - case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); - case 0xaa: return ("SETFEATURES ENABLE RCACHE"); - case 0x55: return ("SETFEATURES DISABLE RCACHE"); - } - return "SETFEATURES"; + case 0x03: return ("SETFEATURES SET TRANSFER MODE"); + case 0x02: return ("SETFEATURES ENABLE WCACHE"); + case 0x82: return ("SETFEATURES DISABLE WCACHE"); + case 0x06: return ("SETFEATURES ENABLE PUIS"); + case 0x86: return ("SETFEATURES DISABLE PUIS"); + case 0x07: return ("SETFEATURES SPIN-UP"); + case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); + case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); + case 0xaa: return ("SETFEATURES ENABLE RCACHE"); + case 0x55: return ("SETFEATURES DISABLE RCACHE"); + case 0x5d: return ("SETFEATURES ENABLE RELIRQ"); + case 0xdd: return ("SETFEATURES DISABLE RELIRQ"); + case 0x5e: return ("SETFEATURES ENABLE SRVIRQ"); + case 0xde: return ("SETFEATURES DISABLE SRVIRQ"); + } + return "SETFEATURES"; case 0xf1: return ("SECURITY_SET_PASSWORD"); case 0xf2: return ("SECURITY_UNLOCK"); case 0xf3: return ("SECURITY_ERASE_PREPARE"); diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 118e38e30a19..8cefa9e09cd1 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -496,7 +496,18 @@ ata_cmd2str(struct ata_request *request) } } else { switch (request->u.ata.command) { - case 0x00: return ("NOP"); + case 0x00: + switch (request->u.ata.feature) { + case 0x00: return ("NOP FLUSHQUEUE"); + case 0x01: return ("NOP AUTOPOLL"); + } + return ("NOP"); + case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); + case 0x06: + switch (request->u.ata.feature) { + case 0x01: return ("DSM TRIM"); + } + return "DSM"; case 0x08: return ("DEVICE_RESET"); case 0x20: return ("READ"); case 0x24: return ("READ48"); @@ -504,18 +515,65 @@ ata_cmd2str(struct ata_request *request) case 0x26: return ("READ_DMA_QUEUED48"); case 0x27: return ("READ_NATIVE_MAX_ADDRESS48"); case 0x29: return ("READ_MUL48"); + case 0x2a: return ("READ_STREAM_DMA48"); + case 0x2b: return ("READ_STREAM48"); + case 0x2f: return ("READ_LOG_EXT"); case 0x30: return ("WRITE"); case 0x34: return ("WRITE48"); case 0x35: return ("WRITE_DMA48"); case 0x36: return ("WRITE_DMA_QUEUED48"); case 0x37: return ("SET_MAX_ADDRESS48"); case 0x39: return ("WRITE_MUL48"); + case 0x3a: return ("WRITE_STREAM_DMA48"); + case 0x3b: return ("WRITE_STREAM48"); + case 0x3d: return ("WRITE_DMA_FUA48"); + case 0x3e: return ("WRITE_DMA_QUEUED_FUA48"); + case 0x3f: return ("WRITE_LOG_EXT"); + case 0x40: return ("READ_VERIFY"); + case 0x42: return ("READ_VERIFY48"); + case 0x45: + switch (request->u.ata.feature) { + case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO"); + case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED"); + } + return "WRITE_UNCORRECTABLE48"; + case 0x51: return ("CONFIGURE_STREAM"); + case 0x60: return ("READ_FPDMA_QUEUED"); + case 0x61: return ("WRITE_FPDMA_QUEUED"); + case 0x63: return ("NCQ_NON_DATA"); + case 0x64: return ("SEND_FPDMA_QUEUED"); + case 0x65: return ("RECEIVE_FPDMA_QUEUED"); + case 0x67: + if (request->u.ata.feature == 0xec) + return ("SEP_ATTN IDENTIFY"); + switch (request->u.ata.lba) { + case 0x00: return ("SEP_ATTN READ BUFFER"); + case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS"); + case 0x80: return ("SEP_ATTN WRITE BUFFER"); + case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC"); + } + return ("SEP_ATTN"); case 0x70: return ("SEEK"); - case 0xa0: return ("PACKET_CMD"); + case 0x87: return ("CFA_TRANSLATE_SECTOR"); + case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC"); + case 0x92: return ("DOWNLOAD_MICROCODE"); + case 0xa0: return ("PACKET"); case 0xa1: return ("ATAPI_IDENTIFY"); case 0xa2: return ("SERVICE"); - case 0xb0: return ("SMART"); - case 0xc0: return ("CFA ERASE"); + case 0xb0: + switch(request->u.ata.feature) { + case 0xd0: return ("SMART READ ATTR VALUES"); + case 0xd1: return ("SMART READ ATTR THRESHOLDS"); + case 0xd3: return ("SMART SAVE ATTR VALUES"); + case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE"); + case 0xd5: return ("SMART READ LOG DATA"); + case 0xd8: return ("SMART ENABLE OPERATION"); + case 0xd9: return ("SMART DISABLE OPERATION"); + case 0xda: return ("SMART RETURN STATUS"); + } + return ("SMART"); + case 0xb1: return ("DEVICE CONFIGURATION"); + case 0xc0: return ("CFA_ERASE"); case 0xc4: return ("READ_MUL"); case 0xc5: return ("WRITE_MUL"); case 0xc6: return ("SET_MULTI"); @@ -523,22 +581,48 @@ ata_cmd2str(struct ata_request *request) case 0xc8: return ("READ_DMA"); case 0xca: return ("WRITE_DMA"); case 0xcc: return ("WRITE_DMA_QUEUED"); + case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE"); + case 0xce: return ("WRITE_MUL_FUA48"); + case 0xd1: return ("CHECK_MEDIA_CARD_TYPE"); + case 0xda: return ("GET_MEDIA_STATUS"); + case 0xde: return ("MEDIA_LOCK"); + case 0xdf: return ("MEDIA_UNLOCK"); + case 0xe0: return ("STANDBY_IMMEDIATE"); + case 0xe1: return ("IDLE_IMMEDIATE"); + case 0xe2: return ("STANDBY"); + case 0xe3: return ("IDLE"); + case 0xe4: return ("READ_BUFFER/PM"); + case 0xe5: return ("CHECK_POWER_MODE"); case 0xe6: return ("SLEEP"); case 0xe7: return ("FLUSHCACHE"); + case 0xe8: return ("WRITE_PM"); case 0xea: return ("FLUSHCACHE48"); case 0xec: return ("ATA_IDENTIFY"); + case 0xed: return ("MEDIA_EJECT"); case 0xef: switch (request->u.ata.feature) { case 0x03: return ("SETFEATURES SET TRANSFER MODE"); case 0x02: return ("SETFEATURES ENABLE WCACHE"); case 0x82: return ("SETFEATURES DISABLE WCACHE"); + case 0x06: return ("SETFEATURES ENABLE PUIS"); + case 0x86: return ("SETFEATURES DISABLE PUIS"); + case 0x07: return ("SETFEATURES SPIN-UP"); + case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); + case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); case 0xaa: return ("SETFEATURES ENABLE RCACHE"); case 0x55: return ("SETFEATURES DISABLE RCACHE"); + case 0x5d: return ("SETFEATURES ENABLE RELIRQ"); + case 0xdd: return ("SETFEATURES DISABLE RELIRQ"); + case 0x5e: return ("SETFEATURES ENABLE SRVIRQ"); + case 0xde: return ("SETFEATURES DISABLE SRVIRQ"); } - sprintf(buffer, "SETFEATURES 0x%02x", - request->u.ata.feature); - return (buffer); - case 0xf5: return ("SECURITY_FREE_LOCK"); + return "SETFEATURES"; + case 0xf1: return ("SECURITY_SET_PASSWORD"); + case 0xf2: return ("SECURITY_UNLOCK"); + case 0xf3: return ("SECURITY_ERASE_PREPARE"); + case 0xf4: return ("SECURITY_ERASE_UNIT"); + case 0xf5: return ("SECURITY_FREEZE_LOCK"); + case 0xf6: return ("SECURITY_DISABLE_PASSWORD"); case 0xf8: return ("READ_NATIVE_MAX_ADDRESS"); case 0xf9: return ("SET_MAX_ADDRESS"); } diff --git a/sys/sys/ata.h b/sys/sys/ata.h index 272b46a553d5..5df610e0da09 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -368,6 +368,9 @@ struct ata_params { #define ATA_WRITE_LOG_EXT 0x3f #define ATA_READ_VERIFY 0x40 #define ATA_READ_VERIFY48 0x42 +#define ATA_WRITE_UNCORRECTABLE48 0x45 /* write uncorrectable 48bit LBA */ +#define ATA_WU_PSEUDO 0x55 /* pseudo-uncorrectable error */ +#define ATA_WU_FLAGGED 0xaa /* flagged-uncorrectable error */ #define ATA_READ_LOG_DMA_EXT 0x47 /* read log DMA ext - PIO Data-In */ #define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */ #define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */ From 977f53633ffa1e668405525673a702136b3c640d Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 4 Feb 2016 20:55:49 +0000 Subject: [PATCH 195/236] When matching brand to the ELF binary by notes, try to find a brand with interpreter name exactly matching one wanted by the binary. If no such brand exists, return first brand which accepted the binary by note. The change fixes a regression after r292749, where e.g. our two ia32 compat brands, ia32_brand_info and ia32_brand_oinfo, only differ by the interpeter path and binary matches to a brand by linkage order. Then old binaries which require /usr/libexec/ld-elf.so.1 but matched against ia32_brand_info with interp_path /libexec/ld-elf.so.1, were considered requiring non-standard interpreter name, and magic to force ld-elf32.so.1 did not happen. Note that it might make sense to apply the same selection of brands for other matching criteria, SCO EI_OSABI and 3.x string. Reported and tested by: dwmalone Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/kern/imgact_elf.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 8a7a11a242d9..43d48000d140 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -258,7 +258,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, int interp_name_len, int32_t *osrel) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; - Elf_Brandinfo *bi; + Elf_Brandinfo *bi, *bi_m; boolean_t ret; int i; @@ -270,6 +270,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, */ /* Look for an ".note.ABI-tag" ELF section */ + bi_m = NULL; for (i = 0; i < MAX_BRANDS; i++) { bi = elf_brand_list[i]; if (bi == NULL) @@ -280,10 +281,28 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, /* Give brand a chance to veto check_note's guess */ if (ret && bi->header_supported) ret = bi->header_supported(imgp); + /* + * If note checker claimed the binary, but the + * interpreter path in the image does not + * match default one for the brand, try to + * search for other brands with the same + * interpreter. Either there is better brand + * with the right interpreter, or, failing + * this, we return first brand which accepted + * our note and, optionally, header. + */ + if (ret && bi_m == NULL && (strlen(bi->interp_path) + + 1 != interp_name_len || strncmp(interp, + bi->interp_path, interp_name_len) != 0)) { + bi_m = bi; + ret = 0; + } if (ret) return (bi); } } + if (bi_m != NULL) + return (bi_m); /* If the executable has a brand, search for it in the brand list. */ for (i = 0; i < MAX_BRANDS; i++) { From 143293cd0e96902ba910edb7b993a70502143f22 Mon Sep 17 00:00:00 2001 From: gnn Date: Thu, 4 Feb 2016 21:39:58 +0000 Subject: [PATCH 196/236] Summary: Remove discussion of fastforwarding. --- share/man/man4/inet.4 | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4 index a1d0a1cf82e3..0130eec842ff 100644 --- a/share/man/man4/inet.4 +++ b/share/man/man4/inet.4 @@ -164,33 +164,11 @@ MIB. In addition to the variables supported by the transport protocols (for which the respective manual pages may be consulted), the following general variables are defined: -.Bl -tag -width IPCTL_FASTFORWARDING +.Bl -tag -width IPCTL_ACCEPTSOURCEROUTE .It Dv IPCTL_FORWARDING .Pq ip.forwarding Boolean: enable/disable forwarding of IP packets. Defaults to off. -.It Dv IPCTL_FASTFORWARDING -.Pq ip.fastforwarding -Boolean: enable/disable the use of -.Tn fast IP forwarding -code. -Defaults to off. -When -.Tn fast IP forwarding -is enabled, IP packets are forwarded directly to the appropriate network -interface with direct processing to completion, which greatly improves -the throughput. -All packets for local IP addresses, non-unicast, or with IP options are -handled by the normal IP input processing path. -All features of the normal (slow) IP forwarding path are supported -including firewall (through -.Xr pfil 9 -hooks) checking, except -.Xr ipsec 4 -tunnel brokering. -The -.Tn IP fastforwarding -path does not generate ICMP redirect or source quench messages. .It Dv IPCTL_SENDREDIRECTS .Pq ip.redirect Boolean: enable/disable sending of ICMP redirects in response to From 8f5a4a0c37a15b8926c68a84deed6a9239093d32 Mon Sep 17 00:00:00 2001 From: gnn Date: Thu, 4 Feb 2016 21:46:37 +0000 Subject: [PATCH 197/236] Summary: Update the date --- share/man/man4/inet.4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4 index 0130eec842ff..07e7354e6083 100644 --- a/share/man/man4/inet.4 +++ b/share/man/man4/inet.4 @@ -28,7 +28,7 @@ .\" From: @(#)inet.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd April 7, 2015 +.Dd Feb 4, 2016 .Dt INET 4 .Os .Sh NAME From 1a98ff983495d0d6b92bcce40e94a080aa22bab7 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 4 Feb 2016 22:39:27 +0000 Subject: [PATCH 198/236] Provide a workaround for setting the correct endianness when doing CFI on a mips big-endian board. This is (hopefully! ish!) a temporary change until a slightly better way can be found to express this without a config option. Tested: * BUFFALO WZR-HP-G300NH 1stGen (by submitter) Submitted by: Mori Hiroki --- sys/conf/options | 1 + sys/dev/cfi/cfi_core.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/sys/conf/options b/sys/conf/options index c7cd58181e8b..f1b2af473ceb 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -918,6 +918,7 @@ VNET_DEBUG opt_global.h # Common Flash Interface (CFI) options CFI_SUPPORT_STRATAFLASH opt_cfi.h CFI_ARMEDANDDANGEROUS opt_cfi.h +CFI_HARDWAREBYTESWAP opt_cfi.h # Sound options SND_DEBUG opt_snd.h diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c index 5150b779f0e5..d292e1a4188b 100644 --- a/sys/dev/cfi/cfi_core.c +++ b/sys/dev/cfi/cfi_core.c @@ -99,11 +99,17 @@ cfi_read(struct cfi_softc *sc, u_int ofs) break; case 2: sval = bus_space_read_2(sc->sc_tag, sc->sc_handle, ofs); +#ifdef CFI_HARDWAREBYTESWAP + val = sval; +#else val = le16toh(sval); +#endif break; case 4: val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs); +#ifndef CFI_HARDWAREBYTESWAP val = le32toh(val); +#endif break; default: val = ~0; @@ -122,10 +128,19 @@ cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) bus_space_write_1(sc->sc_tag, sc->sc_handle, ofs, val); break; case 2: +#ifdef CFI_HARDWAREBYTESWAP + bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, val); +#else bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, htole16(val)); + +#endif break; case 4: +#ifdef CFI_HARDWAREBYTESWAP + bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, val); +#else bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, htole32(val)); +#endif break; } } From 3335a0f964ba16c7a46b893e3912aca5aca9e464 Mon Sep 17 00:00:00 2001 From: scottl Date: Thu, 4 Feb 2016 23:38:55 +0000 Subject: [PATCH 199/236] Add sysctls for dumping out the device mapping tables. I'm finding this useful for debugging device-target translation bugs. MFC after: 3 days Sponsored by: Netflix --- sys/dev/mps/mps.c | 8 ++++++ sys/dev/mps/mps_mapping.c | 59 +++++++++++++++++++++++++++++++++++++++ sys/dev/mps/mpsvar.h | 2 ++ 3 files changed, 69 insertions(+) diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 4080fc678fc1..5f183416e5ea 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1476,6 +1476,14 @@ mps_setup_sysctl(struct mps_softc *sc) OID_AUTO, "spinup_wait_time", CTLFLAG_RD, &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " "spinup after SATA ID error"); + + SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "mapping_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + mps_mapping_dump, "A", "Mapping Table Dump"); + + SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + mps_mapping_encl_dump, "A", "Enclosure Table Dump"); } int diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c index d96f33cdd919..351625be4817 100644 --- a/sys/dev/mps/mps_mapping.c +++ b/sys/dev/mps/mps_mapping.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2263,3 +2264,61 @@ mps_mapping_ir_config_change_event(struct mps_softc *sc, if (sc->pending_map_events) sc->pending_map_events--; } + +int +mps_mapping_dump(SYSCTL_HANDLER_ARGS) +{ + struct mps_softc *sc; + struct dev_mapping_table *mt_entry; + struct sbuf sbuf; + int i, error; + + sc = (struct mps_softc *)arg1; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + + sbuf_printf(&sbuf, "\nindex physical_id handle id\n"); + for (i = 0; i < sc->max_devices; i++) { + mt_entry = &sc->mapping_table[i]; + if (mt_entry->physical_id == 0) + continue; + sbuf_printf(&sbuf, "%4d %jx %04x %hd\n", + i, mt_entry->physical_id, mt_entry->dev_handle, + mt_entry->id); + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + return (error); +} + +int +mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS) +{ + struct mps_softc *sc; + struct enc_mapping_table *enc_entry; + struct sbuf sbuf; + int i, error; + + sc = (struct mps_softc *)arg1; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + + sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n"); + for (i = 0; i < sc->max_enclosures; i++) { + enc_entry = &sc->enclosure_table[i]; + if (enc_entry->enclosure_id == 0) + continue; + sbuf_printf(&sbuf, "%4d %jx %04x %d\n", + i, enc_entry->enclosure_id, enc_entry->enc_handle, + enc_entry->start_index); + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + return (error); +} diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index 96bb4e1cfa64..0cb51a0a3b19 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -756,6 +756,8 @@ void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *, Mpi2EventDataSasEnclDevStatusChange_t *event_data); void mps_mapping_ir_config_change_event(struct mps_softc *sc, Mpi2EventDataIrConfigChangeList_t *event_data); +int mps_mapping_dump(SYSCTL_HANDLER_ARGS); +int mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS); void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event); From 4b1b0d73e2df6a6716d3b447b0e18133218ee66b Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 03:46:53 +0000 Subject: [PATCH 200/236] hyperv/stor: Fix the NULL pointer dereference Reported by: Netapp Submitted by: Hongjiang Zhang Reviewed by: adrian, sephe, Dexuan Cui Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5097 --- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 098c8c9fda70..9683ad8f4ec4 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -1524,13 +1524,12 @@ static void storvsc_destroy_bounce_buffer(struct sglist *sgl) { struct hv_sgl_node *sgl_node = NULL; - - sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list); - LIST_REMOVE(sgl_node, link); - if (NULL == sgl_node) { + if (LIST_EMPTY(&g_hv_sgl_page_pool.in_use_sgl_list)) { printf("storvsc error: not enough in use sgl\n"); return; } + sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list); + LIST_REMOVE(sgl_node, link); sgl_node->sgl_data = sgl; LIST_INSERT_HEAD(&g_hv_sgl_page_pool.free_sgl_list, sgl_node, link); } @@ -1556,12 +1555,12 @@ storvsc_create_bounce_buffer(uint16_t seg_count, int write) struct hv_sgl_node *sgl_node = NULL; /* get struct sglist from free_sgl_list */ - sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); - LIST_REMOVE(sgl_node, link); - if (NULL == sgl_node) { + if (LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) { printf("storvsc error: not enough free sgl\n"); return NULL; } + sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); + LIST_REMOVE(sgl_node, link); bounce_sgl = sgl_node->sgl_data; LIST_INSERT_HEAD(&g_hv_sgl_page_pool.in_use_sgl_list, sgl_node, link); From 072319c51c99365ea0478266ce51c6192d07afa8 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 04:03:50 +0000 Subject: [PATCH 201/236] hyperv/hn: Avoid duplicate csum features settings - Record csum features in softc, so we don't need to duplicate the logic from attach path to ioctl path. - Protect if_capenable and if_hwassist changes by main lock. - Prefer turn on/off bits in if_hwassist explicitly instead of using XOR. Reviewed by: adrian, Hongjiang Zhang Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5085 --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 2 + sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 64 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index c19034043e38..de960cb1acd1 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1043,6 +1043,8 @@ typedef struct hn_softc { u_long hn_txdma_failed; u_long hn_tx_collapsed; u_long hn_tx_chimney; + + uint64_t hn_csum_assist; } hn_softc_t; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index ab88e367106d..2b752f55abaf 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -176,6 +176,14 @@ struct hn_txdesc { CSUM_IP_ISCSI|CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP| \ CSUM_IP6_TSO|CSUM_IP6_ISCSI) +/* + * Only enable UDP checksum offloading when it is on 2012R2 or + * later. UDP checksum offloading doesn't work on earlier + * Windows releases. + */ +#define HN_CSUM_ASSIST_WIN8 (CSUM_TCP) +#define HN_CSUM_ASSIST (CSUM_UDP | CSUM_TCP) + /* XXX move to netinet/tcp_lro.h */ #define HN_LRO_HIWAT_MAX 65535 #define HN_LRO_HIWAT_DEF HN_LRO_HIWAT_MAX @@ -444,15 +452,12 @@ netvsc_attach(device_t dev) ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO | IFCAP_LRO; - /* - * Only enable UDP checksum offloading when it is on 2012R2 or - * later. UDP checksum offloading doesn't work on earlier - * Windows releases. - */ + if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1) - ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_TSO; + sc->hn_csum_assist = HN_CSUM_ASSIST; else - ifp->if_hwassist = CSUM_TCP | CSUM_TSO; + sc->hn_csum_assist = HN_CSUM_ASSIST_WIN8; + ifp->if_hwassist = sc->hn_csum_assist | CSUM_TSO; error = hv_rf_on_device_add(device_ctx, &device_info); if (error) @@ -1506,47 +1511,40 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; break; case SIOCSIFCAP: + NV_LOCK(sc); + mask = ifr->ifr_reqcap ^ ifp->if_capenable; if (mask & IFCAP_TXCSUM) { - if (IFCAP_TXCSUM & ifp->if_capenable) { - ifp->if_capenable &= ~IFCAP_TXCSUM; - ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP); - } else { - ifp->if_capenable |= IFCAP_TXCSUM; - /* - * Only enable UDP checksum offloading on - * Windows Server 2012R2 or later releases. - */ - if (hv_vmbus_protocal_version >= - HV_VMBUS_VERSION_WIN8_1) { - ifp->if_hwassist |= - (CSUM_TCP | CSUM_UDP); - } else { - ifp->if_hwassist |= CSUM_TCP; - } - } + ifp->if_capenable ^= IFCAP_TXCSUM; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist |= sc->hn_csum_assist; + else + ifp->if_hwassist &= ~sc->hn_csum_assist; } - if (mask & IFCAP_RXCSUM) { - if (IFCAP_RXCSUM & ifp->if_capenable) { - ifp->if_capenable &= ~IFCAP_RXCSUM; - } else { - ifp->if_capenable |= IFCAP_RXCSUM; - } - } + if (mask & IFCAP_RXCSUM) + ifp->if_capenable ^= IFCAP_RXCSUM; + if (mask & IFCAP_LRO) ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_TSO4) { ifp->if_capenable ^= IFCAP_TSO4; - ifp->if_hwassist ^= CSUM_IP_TSO; + if (ifp->if_capenable & IFCAP_TSO4) + ifp->if_hwassist |= CSUM_IP_TSO; + else + ifp->if_hwassist &= ~CSUM_IP_TSO; } if (mask & IFCAP_TSO6) { ifp->if_capenable ^= IFCAP_TSO6; - ifp->if_hwassist ^= CSUM_IP6_TSO; + if (ifp->if_capenable & IFCAP_TSO6) + ifp->if_hwassist |= CSUM_IP6_TSO; + else + ifp->if_hwassist &= ~CSUM_IP6_TSO; } + NV_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: From f74912c36af597a5dfb50308315ee2d73390dac3 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 04:10:04 +0000 Subject: [PATCH 202/236] hyperv/hn: Reorganize TX csum offloading - For non-TSO offloading, we don't need to access mbuf to know which csum offloading is requested, we can just use the CSUM_{IP,TCP,UDP} in the csum_flags. - For TSO offloading, we still can depend on CSUM_{TSO4,TSO6} in the csum_flags to tell whether the TSO packet is an IPv4 TSO packet or an IPv6 TSO packet. This streamlines csum offloading handling (remove the two goto) and allows us the nuke the unnecessary get_transport_proto_type(). Reviewed by: adrian, Hongjiang Zhang Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5098 --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 3 +- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 210 +++++------------- 2 files changed, 60 insertions(+), 153 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index de960cb1acd1..31d023ac7ef0 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1015,6 +1015,7 @@ typedef struct hn_softc { bus_dma_tag_t hn_tx_rndis_dtag; int hn_tx_chimney_size; int hn_tx_chimney_max; + uint64_t hn_csum_assist; struct mtx hn_txlist_spin; struct hn_txdesc_list hn_txlist; @@ -1043,8 +1044,6 @@ typedef struct hn_softc { u_long hn_txdma_failed; u_long hn_tx_collapsed; u_long hn_tx_chimney; - - uint64_t hn_csum_assist; } hn_softc_t; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 2b752f55abaf..ccfb8c39a084 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -166,16 +166,6 @@ struct hn_txdesc { #define HN_TXD_FLAG_ONLIST 0x1 #define HN_TXD_FLAG_DMAMAP 0x2 -/* - * A unified flag for all outbound check sum flags is useful, - * and it helps avoiding unnecessary check sum calculation in - * network forwarding scenario. - */ -#define HV_CSUM_FOR_OUTBOUND \ - (CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP|CSUM_IP_TSO| \ - CSUM_IP_ISCSI|CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP| \ - CSUM_IP6_TSO|CSUM_IP6_ISCSI) - /* * Only enable UDP checksum offloading when it is on 2012R2 or * later. UDP checksum offloading doesn't work on earlier @@ -265,62 +255,6 @@ hn_set_lro_hiwat(struct hn_softc *sc, int hiwat) #endif } -/* - * NetVsc get message transport protocol type - */ -static uint32_t get_transport_proto_type(struct mbuf *m_head) -{ - uint32_t ret_val = TRANSPORT_TYPE_NOT_IP; - uint16_t ether_type = 0; - int ether_len = 0; - struct ether_vlan_header *eh; -#ifdef INET - struct ip *iph; -#endif -#ifdef INET6 - struct ip6_hdr *ip6; -#endif - - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { - ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; - ether_type = eh->evl_proto; - } else { - ether_len = ETHER_HDR_LEN; - ether_type = eh->evl_encap_proto; - } - - switch (ntohs(ether_type)) { -#ifdef INET6 - case ETHERTYPE_IPV6: - ip6 = (struct ip6_hdr *)(m_head->m_data + ether_len); - - if (IPPROTO_TCP == ip6->ip6_nxt) { - ret_val = TRANSPORT_TYPE_IPV6_TCP; - } else if (IPPROTO_UDP == ip6->ip6_nxt) { - ret_val = TRANSPORT_TYPE_IPV6_UDP; - } - break; -#endif -#ifdef INET - case ETHERTYPE_IP: - iph = (struct ip *)(m_head->m_data + ether_len); - - if (IPPROTO_TCP == iph->ip_p) { - ret_val = TRANSPORT_TYPE_IPV4_TCP; - } else if (IPPROTO_UDP == iph->ip_p) { - ret_val = TRANSPORT_TYPE_IPV4_UDP; - } - break; -#endif - default: - ret_val = TRANSPORT_TYPE_NOT_IP; - break; - } - - return (ret_val); -} - static int hn_ifmedia_upd(struct ifnet *ifp __unused) { @@ -783,16 +717,13 @@ hn_start_locked(struct ifnet *ifp, int len) hn_softc_t *sc = ifp->if_softc; struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); netvsc_dev *net_dev = sc->net_dev; - struct ether_vlan_header *eh; rndis_msg *rndis_mesg; rndis_packet *rndis_pkt; rndis_per_packet_info *rppi; ndis_8021q_info *rppi_vlan_info; rndis_tcp_ip_csum_info *csum_info; rndis_tcp_tso_info *tso_info; - int ether_len; uint32_t rndis_msg_size = 0; - uint32_t trans_proto_type; if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) @@ -872,101 +803,78 @@ hn_start_locked(struct ifnet *ifp, int len) m_head->m_pkthdr.ether_vtag & 0xfff; } - /* Only check the flags for outbound and ignore the ones for inbound */ - if (0 == (m_head->m_pkthdr.csum_flags & HV_CSUM_FOR_OUTBOUND)) { - goto pre_send; - } - - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { - ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; - } else { - ether_len = ETHER_HDR_LEN; - } - - trans_proto_type = get_transport_proto_type(m_head); - if (TRANSPORT_TYPE_NOT_IP == trans_proto_type) { - goto pre_send; - } - - /* - * TSO packet needless to setup the send side checksum - * offload. - */ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { - goto do_tso; - } + struct ether_vlan_header *eh; + int ether_len; - /* setup checksum offload */ - rndis_msg_size += RNDIS_CSUM_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, - tcpip_chksum_info); - csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi + - rppi->per_packet_info_offset); + eh = mtod(m_head, struct ether_vlan_header*); + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { + ether_len = ETHER_HDR_LEN + + ETHER_VLAN_ENCAP_LEN; + } else { + ether_len = ETHER_HDR_LEN; + } - if (trans_proto_type & (TYPE_IPV4 << 16)) { - csum_info->xmit.is_ipv4 = 1; - } else { - csum_info->xmit.is_ipv6 = 1; - } + rndis_msg_size += RNDIS_TSO_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, + tcp_large_send_info); - if (trans_proto_type & TYPE_TCP) { - csum_info->xmit.tcp_csum = 1; - csum_info->xmit.tcp_header_offset = 0; - } else if (trans_proto_type & TYPE_UDP) { - csum_info->xmit.udp_csum = 1; - } + tso_info = (rndis_tcp_tso_info *)((char *)rppi + + rppi->per_packet_info_offset); + tso_info->lso_v2_xmit.type = + RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; - goto pre_send; - -do_tso: - /* setup TCP segmentation offload */ - rndis_msg_size += RNDIS_TSO_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, - tcp_large_send_info); - - tso_info = (rndis_tcp_tso_info *)((char *)rppi + - rppi->per_packet_info_offset); - tso_info->lso_v2_xmit.type = - RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; - #ifdef INET - if (trans_proto_type & (TYPE_IPV4 << 16)) { - struct ip *ip = - (struct ip *)(m_head->m_data + ether_len); - unsigned long iph_len = ip->ip_hl << 2; - struct tcphdr *th = - (struct tcphdr *)((caddr_t)ip + iph_len); - - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; - ip->ip_len = 0; - ip->ip_sum = 0; - - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, - htons(IPPROTO_TCP)); - } + if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { + struct ip *ip = + (struct ip *)(m_head->m_data + ether_len); + unsigned long iph_len = ip->ip_hl << 2; + struct tcphdr *th = + (struct tcphdr *)((caddr_t)ip + iph_len); + + tso_info->lso_v2_xmit.ip_version = + RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; + ip->ip_len = 0; + ip->ip_sum = 0; + + th->th_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, htons(IPPROTO_TCP)); + } #endif #if defined(INET6) && defined(INET) - else + else #endif #ifdef INET6 - { - struct ip6_hdr *ip6 = - (struct ip6_hdr *)(m_head->m_data + ether_len); - struct tcphdr *th = (struct tcphdr *)(ip6 + 1); + { + struct ip6_hdr *ip6 = (struct ip6_hdr *) + (m_head->m_data + ether_len); + struct tcphdr *th = (struct tcphdr *)(ip6 + 1); - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6; - ip6->ip6_plen = 0; - th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); - } + tso_info->lso_v2_xmit.ip_version = + RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6; + ip6->ip6_plen = 0; + th->th_sum = + in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); + } #endif - tso_info->lso_v2_xmit.tcp_header_offset = 0; - tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; + tso_info->lso_v2_xmit.tcp_header_offset = 0; + tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; + } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) { + rndis_msg_size += RNDIS_CSUM_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, + tcpip_chksum_info); + csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi + + rppi->per_packet_info_offset); + + csum_info->xmit.is_ipv4 = 1; + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { + csum_info->xmit.tcp_csum = 1; + csum_info->xmit.tcp_header_offset = 0; + } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { + csum_info->xmit.udp_csum = 1; + } + } -pre_send: rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; packet->tot_data_buf_len = rndis_mesg->msg_len; From f8cf3cfcd0044ac1740e661a5bd94e2f10a684e8 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:01:02 +0000 Subject: [PATCH 203/236] hyperv/hn: Enable IP header checksum offloading So that: - TCP/IP stack will not do unnecessary IP header checksum for TSO packets. - Reduce guest load for non-TSO IP packets. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5099 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index ccfb8c39a084..b7bf1ef89710 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -172,7 +172,7 @@ struct hn_txdesc { * Windows releases. */ #define HN_CSUM_ASSIST_WIN8 (CSUM_TCP) -#define HN_CSUM_ASSIST (CSUM_UDP | CSUM_TCP) +#define HN_CSUM_ASSIST (CSUM_IP | CSUM_UDP | CSUM_TCP) /* XXX move to netinet/tcp_lro.h */ #define HN_LRO_HIWAT_MAX 65535 @@ -867,6 +867,9 @@ hn_start_locked(struct ifnet *ifp, int len) rppi->per_packet_info_offset); csum_info->xmit.is_ipv4 = 1; + if (m_head->m_pkthdr.csum_flags & CSUM_IP) + csum_info->xmit.ip_header_csum = 1; + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { csum_info->xmit.tcp_csum = 1; csum_info->xmit.tcp_header_offset = 0; From 25d1f76bed7e8e6f5df4963d9b9bb400cb494129 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:06:14 +0000 Subject: [PATCH 204/236] hyperv/hn: Enable UDP RXCSUM Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5102 --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 1 + sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 31d023ac7ef0..b9dcb8597107 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1036,6 +1036,7 @@ typedef struct hn_softc { u_long hn_csum_ip; u_long hn_csum_tcp; + u_long hn_csum_udp; u_long hn_csum_trusted; u_long hn_lro_tried; u_long hn_small_pkts; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index b7bf1ef89710..95abed8a4120 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -456,6 +456,8 @@ netvsc_attach(device_t dev) CTLFLAG_RW, &sc->hn_csum_ip, "RXCSUM IP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_tcp", CTLFLAG_RW, &sc->hn_csum_tcp, "RXCSUM TCP"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_udp", + CTLFLAG_RW, &sc->hn_csum_udp, "RXCSUM UDP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_trusted", CTLFLAG_RW, &sc->hn_csum_trusted, "# of TCP segements that we trust host's csum verification"); @@ -1156,7 +1158,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, m_new->m_pkthdr.rcvif = ifp; /* receive side checksum offload */ - if (NULL != csum_info) { + if (csum_info != NULL) { /* IP csum offload */ if (csum_info->receive.ip_csum_succeeded) { m_new->m_pkthdr.csum_flags |= @@ -1164,12 +1166,16 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, sc->hn_csum_ip++; } - /* TCP csum offload */ - if (csum_info->receive.tcp_csum_succeeded) { + /* TCP/UDP csum offload */ + if (csum_info->receive.tcp_csum_succeeded || + csum_info->receive.udp_csum_succeeded) { m_new->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); m_new->m_pkthdr.csum_data = 0xffff; - sc->hn_csum_tcp++; + if (csum_info->receive.tcp_csum_succeeded) + sc->hn_csum_tcp++; + else + sc->hn_csum_udp++; } if (csum_info->receive.ip_csum_succeeded && From 2f57b75e686fe630f9eb8d2bcee5eb9463002c1a Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:12:30 +0000 Subject: [PATCH 205/236] hyperv/hn: Add sysctls to trust host side UDP and IP csum verification Reviewed by: adrian, Hongjiang Zhang Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5103 --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 7 +- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 80 +++++++++++++++++-- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index b9dcb8597107..920ce7e8d577 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1031,8 +1031,8 @@ typedef struct hn_softc { struct lro_ctrl hn_lro; int hn_lro_hiwat; - /* Trust tcp segments verification on host side */ - int hn_trust_hosttcp; + /* Trust csum verification on host side */ + int hn_trust_hcsum; /* HN_TRUST_HCSUM_ */ u_long hn_csum_ip; u_long hn_csum_tcp; @@ -1047,6 +1047,9 @@ typedef struct hn_softc { u_long hn_tx_chimney; } hn_softc_t; +#define HN_TRUST_HCSUM_IP 0x0001 +#define HN_TRUST_HCSUM_TCP 0x0002 +#define HN_TRUST_HCSUM_UDP 0x0004 /* * Externs diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 95abed8a4120..fcaffdd0e5c0 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -210,6 +210,14 @@ int hv_promisc_mode = 0; /* normal mode by default */ static int hn_trust_hosttcp = 1; TUNABLE_INT("dev.hn.trust_hosttcp", &hn_trust_hosttcp); +/* Trust udp datagrams verification on host side. */ +static int hn_trust_hostudp = 1; +TUNABLE_INT("dev.hn.trust_hostudp", &hn_trust_hostudp); + +/* Trust ip packets verification on host side. */ +static int hn_trust_hostip = 1; +TUNABLE_INT("dev.hn.trust_hostip", &hn_trust_hostip); + #if __FreeBSD_version >= 1100045 /* Limit TSO burst size */ static int hn_tso_maxlen = 0; @@ -239,6 +247,7 @@ static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); #ifdef HN_LRO_HIWAT static int hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS); #endif +static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS); static int hn_check_iplen(const struct mbuf *, int); static int hn_create_tx_ring(struct hn_softc *sc); @@ -335,8 +344,13 @@ netvsc_attach(device_t dev) sc->hn_unit = unit; sc->hn_dev = dev; sc->hn_lro_hiwat = HN_LRO_HIWAT_DEF; - sc->hn_trust_hosttcp = hn_trust_hosttcp; sc->hn_direct_tx_size = hn_direct_tx_size; + if (hn_trust_hosttcp) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP; + if (hn_trust_hostudp) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP; + if (hn_trust_hostip) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; sc->hn_tx_taskq = taskqueue_create_fast("hn_tx", M_WAITOK, taskqueue_thread_enqueue, &sc->hn_tx_taskq); @@ -448,10 +462,21 @@ netvsc_attach(device_t dev) CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_lro_hiwat_sysctl, "I", "LRO high watermark"); #endif - SYSCTL_ADD_INT(ctx, child, OID_AUTO, "trust_hosttcp", - CTLFLAG_RW, &sc->hn_trust_hosttcp, 0, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hosttcp", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_TCP, + hn_trust_hcsum_sysctl, "I", "Trust tcp segement verification on host side, " "when csum info is missing"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostudp", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_UDP, + hn_trust_hcsum_sysctl, "I", + "Trust udp datagram verification on host side, " + "when csum info is missing"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostip", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_IP, + hn_trust_hcsum_sysctl, "I", + "Trust ip packet verification on host side, " + "when csum info is missing"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_ip", CTLFLAG_RW, &sc->hn_csum_ip, "RXCSUM IP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_tcp", @@ -460,7 +485,7 @@ netvsc_attach(device_t dev) CTLFLAG_RW, &sc->hn_csum_udp, "RXCSUM UDP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_trusted", CTLFLAG_RW, &sc->hn_csum_trusted, - "# of TCP segements that we trust host's csum verification"); + "# of packets that we trust host's csum verification"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "small_pkts", CTLFLAG_RW, &sc->hn_small_pkts, "# of small packets received"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "no_txdescs", @@ -503,6 +528,14 @@ netvsc_attach(device_t dev) CTLFLAG_RD, &hn_trust_hosttcp, 0, "Trust tcp segement verification on host side, " "when csum info is missing (global setting)"); + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostudp", + CTLFLAG_RD, &hn_trust_hostudp, 0, + "Trust udp datagram verification on host side, " + "when csum info is missing (global setting)"); + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostip", + CTLFLAG_RD, &hn_trust_hostip, 0, + "Trust ip packet verification on host side, " + "when csum info is missing (global setting)"); SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "tx_chimney_size", CTLFLAG_RD, &hn_tx_chimney_size, 0, "Chimney send packet size limit"); @@ -1206,7 +1239,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, pr = hn_check_iplen(m_new, hoff); if (pr == IPPROTO_TCP) { - if (sc->hn_trust_hosttcp) { + if (sc->hn_trust_hcsum & HN_TRUST_HCSUM_TCP) { sc->hn_csum_trusted++; m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID | @@ -1215,6 +1248,19 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, } /* Rely on SW csum verification though... */ do_lro = 1; + } else if (pr == IPPROTO_UDP) { + if (sc->hn_trust_hcsum & HN_TRUST_HCSUM_UDP) { + sc->hn_csum_trusted++; + m_new->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED | CSUM_IP_VALID | + CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + m_new->m_pkthdr.csum_data = 0xffff; + } + } else if (pr != IPPROTO_DONE && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_IP)) { + sc->hn_csum_trusted++; + m_new->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED | CSUM_IP_VALID); } } } @@ -1649,6 +1695,30 @@ hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS) } #endif /* HN_LRO_HIWAT */ +static int +hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct hn_softc *sc = arg1; + int hcsum = arg2; + int on, error; + + on = 0; + if (sc->hn_trust_hcsum & hcsum) + on = 1; + + error = sysctl_handle_int(oidp, &on, 0, req); + if (error || req->newptr == NULL) + return error; + + NV_LOCK(sc); + if (on) + sc->hn_trust_hcsum |= hcsum; + else + sc->hn_trust_hcsum &= ~hcsum; + NV_UNLOCK(sc); + return 0; +} + static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS) { From 0f6048195a8cbc8c5077108f37514f9c77145c4a Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:17:48 +0000 Subject: [PATCH 206/236] hyperv/hn: Obey IFCAP_RXCSUM configure Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5104 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index fcaffdd0e5c0..7f6e5d33eb91 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -1142,7 +1142,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, struct mbuf *m_new; struct ifnet *ifp; device_t dev = device_ctx->device; - int size, do_lro = 0; + int size, do_lro = 0, do_csum = 1; if (sc == NULL) { return (0); /* TODO: KYS how can this be! */ @@ -1190,18 +1190,21 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, } m_new->m_pkthdr.rcvif = ifp; + if (__predict_false((ifp->if_capenable & IFCAP_RXCSUM) == 0)) + do_csum = 0; + /* receive side checksum offload */ if (csum_info != NULL) { /* IP csum offload */ - if (csum_info->receive.ip_csum_succeeded) { + if (csum_info->receive.ip_csum_succeeded && do_csum) { m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID); sc->hn_csum_ip++; } /* TCP/UDP csum offload */ - if (csum_info->receive.tcp_csum_succeeded || - csum_info->receive.udp_csum_succeeded) { + if ((csum_info->receive.tcp_csum_succeeded || + csum_info->receive.udp_csum_succeeded) && do_csum) { m_new->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); m_new->m_pkthdr.csum_data = 0xffff; @@ -1239,7 +1242,8 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, pr = hn_check_iplen(m_new, hoff); if (pr == IPPROTO_TCP) { - if (sc->hn_trust_hcsum & HN_TRUST_HCSUM_TCP) { + if (do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_TCP)) { sc->hn_csum_trusted++; m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID | @@ -1249,14 +1253,15 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, /* Rely on SW csum verification though... */ do_lro = 1; } else if (pr == IPPROTO_UDP) { - if (sc->hn_trust_hcsum & HN_TRUST_HCSUM_UDP) { + if (do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_UDP)) { sc->hn_csum_trusted++; m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR); m_new->m_pkthdr.csum_data = 0xffff; } - } else if (pr != IPPROTO_DONE && + } else if (pr != IPPROTO_DONE && do_csum && (sc->hn_trust_hcsum & HN_TRUST_HCSUM_IP)) { sc->hn_csum_trusted++; m_new->m_pkthdr.csum_flags |= From 3ebbdfb23a21faaa68626895a808fcdce3cc5fce Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:25:11 +0000 Subject: [PATCH 207/236] hyperv/hn: Factor out hn_encap() from hn_start_locked() It will be shared w/ upcoming ifnet.if_transmit implementaion. No functional changes. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5158 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 434 +++++++++--------- 1 file changed, 220 insertions(+), 214 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 7f6e5d33eb91..69aa20a4ddc7 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -254,6 +254,7 @@ static int hn_create_tx_ring(struct hn_softc *sc); static void hn_destroy_tx_ring(struct hn_softc *sc); static void hn_start_taskfunc(void *xsc, int pending); static void hn_txeof_taskfunc(void *xsc, int pending); +static int hn_encap(struct hn_softc *, struct hn_txdesc *, struct mbuf **); static __inline void hn_set_lro_hiwat(struct hn_softc *sc, int hiwat) @@ -743,32 +744,236 @@ netvsc_channel_rollup(struct hv_device *device_ctx) hn_start_txeof(sc->hn_ifp); } +/* + * NOTE: + * This this function fails, then both txd and m_head0 will be freed + */ +static int +hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0) +{ + bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; + int error, nsegs, i; + struct mbuf *m_head = *m_head0; + netvsc_packet *packet; + rndis_msg *rndis_mesg; + rndis_packet *rndis_pkt; + rndis_per_packet_info *rppi; + uint32_t rndis_msg_size; + + packet = &txd->netvsc_pkt; + packet->is_data_pkt = TRUE; + packet->tot_data_buf_len = m_head->m_pkthdr.len; + + /* + * extension points to the area reserved for the + * rndis_filter_packet, which is placed just after + * the netvsc_packet (and rppi struct, if present; + * length is updated later). + */ + rndis_mesg = txd->rndis_msg; + /* XXX not necessary */ + memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); + rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; + + rndis_pkt = &rndis_mesg->msg.packet; + rndis_pkt->data_offset = sizeof(rndis_packet); + rndis_pkt->data_length = packet->tot_data_buf_len; + rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); + + rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); + + if (m_head->m_flags & M_VLANTAG) { + ndis_8021q_info *rppi_vlan_info; + + rndis_msg_size += RNDIS_VLAN_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE, + ieee_8021q_info); + + rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi + + rppi->per_packet_info_offset); + rppi_vlan_info->u1.s1.vlan_id = + m_head->m_pkthdr.ether_vtag & 0xfff; + } + + if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { + rndis_tcp_tso_info *tso_info; + struct ether_vlan_header *eh; + int ether_len; + + /* + * XXX need m_pullup and use mtodo + */ + eh = mtod(m_head, struct ether_vlan_header*); + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) + ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + else + ether_len = ETHER_HDR_LEN; + + rndis_msg_size += RNDIS_TSO_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, + tcp_large_send_info); + + tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi + + rppi->per_packet_info_offset); + tso_info->lso_v2_xmit.type = + RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; + +#ifdef INET + if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { + struct ip *ip = + (struct ip *)(m_head->m_data + ether_len); + unsigned long iph_len = ip->ip_hl << 2; + struct tcphdr *th = + (struct tcphdr *)((caddr_t)ip + iph_len); + + tso_info->lso_v2_xmit.ip_version = + RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; + ip->ip_len = 0; + ip->ip_sum = 0; + + th->th_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, htons(IPPROTO_TCP)); + } +#endif +#if defined(INET6) && defined(INET) + else +#endif +#ifdef INET6 + { + struct ip6_hdr *ip6 = (struct ip6_hdr *) + (m_head->m_data + ether_len); + struct tcphdr *th = (struct tcphdr *)(ip6 + 1); + + tso_info->lso_v2_xmit.ip_version = + RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6; + ip6->ip6_plen = 0; + th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); + } +#endif + tso_info->lso_v2_xmit.tcp_header_offset = 0; + tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; + } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) { + rndis_tcp_ip_csum_info *csum_info; + + rndis_msg_size += RNDIS_CSUM_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, + tcpip_chksum_info); + csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi + + rppi->per_packet_info_offset); + + csum_info->xmit.is_ipv4 = 1; + if (m_head->m_pkthdr.csum_flags & CSUM_IP) + csum_info->xmit.ip_header_csum = 1; + + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { + csum_info->xmit.tcp_csum = 1; + csum_info->xmit.tcp_header_offset = 0; + } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { + csum_info->xmit.udp_csum = 1; + } + } + + rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; + packet->tot_data_buf_len = rndis_mesg->msg_len; + + /* + * Chimney send, if the packet could fit into one chimney buffer. + */ + if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) { + netvsc_dev *net_dev = sc->net_dev; + uint32_t send_buf_section_idx; + + send_buf_section_idx = + hv_nv_get_next_send_section(net_dev); + if (send_buf_section_idx != + NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + uint8_t *dest = ((uint8_t *)net_dev->send_buf + + (send_buf_section_idx * + net_dev->send_section_size)); + + memcpy(dest, rndis_mesg, rndis_msg_size); + dest += rndis_msg_size; + m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); + + packet->send_buf_section_idx = send_buf_section_idx; + packet->send_buf_section_size = + packet->tot_data_buf_len; + packet->page_buf_count = 0; + sc->hn_tx_chimney++; + goto done; + } + } + + error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs); + if (error) { + int freed; + + /* + * This mbuf is not linked w/ the txd yet, so free it now. + */ + m_freem(m_head); + *m_head0 = NULL; + + freed = hn_txdesc_put(sc, txd); + KASSERT(freed != 0, + ("fail to free txd upon txdma error")); + + sc->hn_txdma_failed++; + if_inc_counter(sc->hn_ifp, IFCOUNTER_OERRORS, 1); + return error; + } + *m_head0 = m_head; + + packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS; + + /* send packet with page buffer */ + packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr); + packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK; + packet->page_buffers[0].length = rndis_msg_size; + + /* + * Fill the page buffers with mbuf info starting at index + * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. + */ + for (i = 0; i < nsegs; ++i) { + hv_vmbus_page_buffer *pb = &packet->page_buffers[ + i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; + + pb->pfn = atop(segs[i].ds_addr); + pb->offset = segs[i].ds_addr & PAGE_MASK; + pb->length = segs[i].ds_len; + } + + packet->send_buf_section_idx = + NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + packet->send_buf_section_size = 0; +done: + txd->m = m_head; + + /* Set the completion routine */ + packet->compl.send.on_send_completion = netvsc_xmit_completion; + packet->compl.send.send_completion_context = packet; + packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd; + + return 0; +} + /* * Start a transmit of one or more packets */ static int hn_start_locked(struct ifnet *ifp, int len) { - hn_softc_t *sc = ifp->if_softc; + struct hn_softc *sc = ifp->if_softc; struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); - netvsc_dev *net_dev = sc->net_dev; - rndis_msg *rndis_mesg; - rndis_packet *rndis_pkt; - rndis_per_packet_info *rppi; - ndis_8021q_info *rppi_vlan_info; - rndis_tcp_ip_csum_info *csum_info; - rndis_tcp_tso_info *tso_info; - uint32_t rndis_msg_size = 0; if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) return 0; while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { - bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; - int error, nsegs, i, send_failed = 0; + int error, send_failed = 0; struct hn_txdesc *txd; - netvsc_packet *packet; struct mbuf *m_head; IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); @@ -793,216 +998,17 @@ hn_start_locked(struct ifnet *ifp, int len) break; } - packet = &txd->netvsc_pkt; - packet->is_data_pkt = TRUE; - /* Initialize it from the mbuf */ - packet->tot_data_buf_len = m_head->m_pkthdr.len; - - /* - * extension points to the area reserved for the - * rndis_filter_packet, which is placed just after - * the netvsc_packet (and rppi struct, if present; - * length is updated later). - */ - rndis_mesg = txd->rndis_msg; - /* XXX not necessary */ - memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); - rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; - - rndis_pkt = &rndis_mesg->msg.packet; - rndis_pkt->data_offset = sizeof(rndis_packet); - rndis_pkt->data_length = packet->tot_data_buf_len; - rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); - - rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); - - /* - * If the Hyper-V infrastructure needs to embed a VLAN tag, - * initialize netvsc_packet and rppi struct values as needed. - */ - if (m_head->m_flags & M_VLANTAG) { - /* - * set up some additional fields so the Hyper-V infrastructure will stuff the VLAN tag - * into the frame. - */ - rndis_msg_size += RNDIS_VLAN_PPI_SIZE; - - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE, - ieee_8021q_info); - - /* VLAN info immediately follows rppi struct */ - rppi_vlan_info = (ndis_8021q_info *)((char*)rppi + - rppi->per_packet_info_offset); - /* FreeBSD does not support CFI or priority */ - rppi_vlan_info->u1.s1.vlan_id = - m_head->m_pkthdr.ether_vtag & 0xfff; - } - - if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { - struct ether_vlan_header *eh; - int ether_len; - - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { - ether_len = ETHER_HDR_LEN + - ETHER_VLAN_ENCAP_LEN; - } else { - ether_len = ETHER_HDR_LEN; - } - - rndis_msg_size += RNDIS_TSO_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, - tcp_large_send_info); - - tso_info = (rndis_tcp_tso_info *)((char *)rppi + - rppi->per_packet_info_offset); - tso_info->lso_v2_xmit.type = - RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; - -#ifdef INET - if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { - struct ip *ip = - (struct ip *)(m_head->m_data + ether_len); - unsigned long iph_len = ip->ip_hl << 2; - struct tcphdr *th = - (struct tcphdr *)((caddr_t)ip + iph_len); - - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; - ip->ip_len = 0; - ip->ip_sum = 0; - - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htons(IPPROTO_TCP)); - } -#endif -#if defined(INET6) && defined(INET) - else -#endif -#ifdef INET6 - { - struct ip6_hdr *ip6 = (struct ip6_hdr *) - (m_head->m_data + ether_len); - struct tcphdr *th = (struct tcphdr *)(ip6 + 1); - - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6; - ip6->ip6_plen = 0; - th->th_sum = - in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); - } -#endif - tso_info->lso_v2_xmit.tcp_header_offset = 0; - tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; - } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) { - rndis_msg_size += RNDIS_CSUM_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, - tcpip_chksum_info); - csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi + - rppi->per_packet_info_offset); - - csum_info->xmit.is_ipv4 = 1; - if (m_head->m_pkthdr.csum_flags & CSUM_IP) - csum_info->xmit.ip_header_csum = 1; - - if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { - csum_info->xmit.tcp_csum = 1; - csum_info->xmit.tcp_header_offset = 0; - } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { - csum_info->xmit.udp_csum = 1; - } - } - - rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; - packet->tot_data_buf_len = rndis_mesg->msg_len; - - /* send packet with send buffer */ - if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) { - uint32_t send_buf_section_idx; - - send_buf_section_idx = - hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { - uint8_t *dest = ((uint8_t *)net_dev->send_buf + - (send_buf_section_idx * - net_dev->send_section_size)); - - memcpy(dest, rndis_mesg, rndis_msg_size); - dest += rndis_msg_size; - - m_copydata(m_head, 0, m_head->m_pkthdr.len, - dest); - - packet->send_buf_section_idx = - send_buf_section_idx; - packet->send_buf_section_size = - packet->tot_data_buf_len; - packet->page_buf_count = 0; - sc->hn_tx_chimney++; - goto do_send; - } - } - - error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs); + error = hn_encap(sc, txd, &m_head); if (error) { - int freed; - - /* - * This mbuf is not linked w/ the txd yet, so free - * it now. - */ - m_freem(m_head); - freed = hn_txdesc_put(sc, txd); - KASSERT(freed != 0, - ("fail to free txd upon txdma error")); - - sc->hn_txdma_failed++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + /* Both txd and m_head are freed */ continue; } - - packet->page_buf_count = nsegs + - HV_RF_NUM_TX_RESERVED_PAGE_BUFS; - - /* send packet with page buffer */ - packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr); - packet->page_buffers[0].offset = - txd->rndis_msg_paddr & PAGE_MASK; - packet->page_buffers[0].length = rndis_msg_size; - - /* - * Fill the page buffers with mbuf info starting at index - * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. - */ - for (i = 0; i < nsegs; ++i) { - hv_vmbus_page_buffer *pb = &packet->page_buffers[ - i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; - - pb->pfn = atop(segs[i].ds_addr); - pb->offset = segs[i].ds_addr & PAGE_MASK; - pb->length = segs[i].ds_len; - } - - packet->send_buf_section_idx = - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; - packet->send_buf_section_size = 0; - -do_send: - txd->m = m_head; - - /* Set the completion routine */ - packet->compl.send.on_send_completion = netvsc_xmit_completion; - packet->compl.send.send_completion_context = packet; - packet->compl.send.send_completion_tid = - (uint64_t)(uintptr_t)txd; - again: /* * Make sure that txd is not freed before ETHER_BPF_MTAP. */ hn_txdesc_hold(txd); - error = hv_nv_on_send(device_ctx, packet); + error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt); if (!error) { ETHER_BPF_MTAP(ifp, m_head); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); From 3652c35a2d3ff5c1dd4988bb765c0007e0e950a6 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:31:31 +0000 Subject: [PATCH 208/236] hyperv/hn: Recover half of the chimney sending space We lost half of the chimney sending space, because we mis-used ffs() on a 64 bits mask, where ffsl() should be used. While I'm here: - Use system atomic operation instead. - Stringent chimney sending index assertion. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5159 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 31 ++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 8bf34a85c783..300704ff1059 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -136,15 +136,15 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev) int i; for (i = 0; i < bitsmap_words; i++) { - idx = ffs(~bitsmap[i]); + idx = ffsl(~bitsmap[i]); if (0 == idx) continue; idx--; - if (i * BITS_PER_LONG + idx >= net_dev->send_section_count) - return (ret); + KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count, + ("invalid i %d and idx %lu", i, idx)); - if (synch_test_and_set_bit(idx, &bitsmap[i])) + if (atomic_testandset_long(&bitsmap[i], idx)) continue; ret = i * BITS_PER_LONG + idx; @@ -789,8 +789,27 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, if (NULL != net_vsc_pkt) { if (net_vsc_pkt->send_buf_section_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { - synch_change_bit(net_vsc_pkt->send_buf_section_idx, - net_dev->send_section_bitsmap); + u_long mask; + int idx; + + idx = net_vsc_pkt->send_buf_section_idx / + BITS_PER_LONG; + KASSERT(idx < net_dev->bitsmap_words, + ("invalid section index %u", + net_vsc_pkt->send_buf_section_idx)); + mask = 1UL << + (net_vsc_pkt->send_buf_section_idx % + BITS_PER_LONG); + + KASSERT(net_dev->send_section_bitsmap[idx] & + mask, + ("index bitmap 0x%lx, section index %u, " + "bitmap idx %d, bitmask 0x%lx", + net_dev->send_section_bitsmap[idx], + net_vsc_pkt->send_buf_section_idx, + idx, mask)); + atomic_clear_long( + &net_dev->send_section_bitsmap[idx], mask); } /* Notify the layer above us */ From 20bba3d409e4485f894baa5adf473c71e506e05d Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:38:01 +0000 Subject: [PATCH 209/236] hyperv/hn: Increase LRO entry count to 128 by default hn(4) only has one RX ring currently, so default 8 LRO entries are too small. Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5166 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 69aa20a4ddc7..81a63f20cf57 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -132,6 +132,8 @@ __FBSDID("$FreeBSD$"); /* YYY should get it from the underlying channel */ #define HN_TX_DESC_CNT 512 +#define HN_LROENT_CNT_DEF 128 + #define HN_RNDIS_MSG_LEN \ (sizeof(rndis_msg) + \ RNDIS_VLAN_PPI_SIZE + \ @@ -232,6 +234,13 @@ TUNABLE_INT("dev.hn.tx_chimney_size", &hn_tx_chimney_size); static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF; TUNABLE_INT("dev.hn.direct_tx_size", &hn_direct_tx_size); +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 +static int hn_lro_entry_count = HN_LROENT_CNT_DEF; +TUNABLE_INT("dev.hn.lro_entry_count", &hn_lro_entry_count); +#endif +#endif + /* * Forward declarations */ @@ -334,6 +343,11 @@ netvsc_attach(device_t dev) int error; #if __FreeBSD_version >= 1100045 int tso_maxlen; +#endif +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + int lroent_cnt; +#endif #endif sc = device_get_softc(dev); @@ -417,9 +431,17 @@ netvsc_attach(device_t dev) } #if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + lroent_cnt = hn_lro_entry_count; + if (lroent_cnt < TCP_LRO_ENTRIES) + lroent_cnt = TCP_LRO_ENTRIES; + tcp_lro_init_args(&sc->hn_lro, ifp, lroent_cnt, 0); + device_printf(dev, "LRO: entry count %d\n", lroent_cnt); +#else tcp_lro_init(&sc->hn_lro); /* Driver private LRO settings */ sc->hn_lro.ifp = ifp; +#endif #ifdef HN_LRO_HIWAT sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat; #endif @@ -547,6 +569,12 @@ netvsc_attach(device_t dev) SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "direct_tx_size", CTLFLAG_RD, &hn_direct_tx_size, 0, "Size of the packet for direct transmission"); +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "lro_entry_count", + CTLFLAG_RD, &hn_lro_entry_count, 0, "LRO entry count"); +#endif +#endif } return (0); From 7430ccc0b2ffdfeff940e281d6587c8b43711180 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:44:31 +0000 Subject: [PATCH 210/236] hyperv/hn: Move LRO flush to the channel processing rollup This significantly increases LRO aggregation ratio when there are large amount of connections (improves reception performance a lot). Reviewed by: adrian Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5167 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 81a63f20cf57..907f3740211e 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -764,6 +764,15 @@ void netvsc_channel_rollup(struct hv_device *device_ctx) { struct hn_softc *sc = device_get_softc(device_ctx->device); +#if defined(INET) || defined(INET6) + struct lro_ctrl *lro = &sc->hn_lro; + struct lro_entry *queued; + + while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { + SLIST_REMOVE_HEAD(&lro->lro_active, next); + tcp_lro_flush(lro, queued); + } +#endif if (!sc->hn_txeof) return; @@ -1338,18 +1347,8 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, } void -netvsc_recv_rollup(struct hv_device *device_ctx) +netvsc_recv_rollup(struct hv_device *device_ctx __unused) { -#if defined(INET) || defined(INET6) - hn_softc_t *sc = device_get_softc(device_ctx->device); - struct lro_ctrl *lro = &sc->hn_lro; - struct lro_entry *queued; - - while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { - SLIST_REMOVE_HEAD(&lro->lro_active, next); - tcp_lro_flush(lro, queued); - } -#endif } /* From 43993ba1f9ee4bff5c7ee1666dde2f5fc919456b Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 05:50:53 +0000 Subject: [PATCH 211/236] hyperv/hn: Add an option to always do transmission scheduling It is off by default. This eases more experiment on hn(4). Reviewed by: adrian, Hongjiang Zhang Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5175 --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 1 + sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 920ce7e8d577..4f52e0d7c7f9 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1023,6 +1023,7 @@ typedef struct hn_softc { int hn_txdesc_avail; int hn_txeof; + int hn_sched_tx; int hn_direct_tx_size; struct taskqueue *hn_tx_taskq; struct task hn_start_task; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 907f3740211e..be43bf413302 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -534,6 +534,10 @@ netvsc_attach(device_t dev) SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size", CTLFLAG_RW, &sc->hn_direct_tx_size, 0, "Size of the packet for direct transmission"); + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sched_tx", + CTLFLAG_RW, &sc->hn_sched_tx, 0, + "Always schedule transmission " + "instead of doing direct transmission"); if (unit == 0) { struct sysctl_ctx_list *dc_ctx; @@ -1602,9 +1606,11 @@ hn_stop(hn_softc_t *sc) static void hn_start(struct ifnet *ifp) { - hn_softc_t *sc; + struct hn_softc *sc = ifp->if_softc; + + if (sc->hn_sched_tx) + goto do_sched; - sc = ifp->if_softc; if (NV_TRYLOCK(sc)) { int sched; @@ -1613,15 +1619,18 @@ hn_start(struct ifnet *ifp) if (!sched) return; } +do_sched: taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task); } static void hn_start_txeof(struct ifnet *ifp) { - hn_softc_t *sc; + struct hn_softc *sc = ifp->if_softc; + + if (sc->hn_sched_tx) + goto do_sched; - sc = ifp->if_softc; if (NV_TRYLOCK(sc)) { int sched; @@ -1633,6 +1642,7 @@ hn_start_txeof(struct ifnet *ifp) &sc->hn_start_task); } } else { +do_sched: /* * Release the OACTIVE earlier, with the hope, that * others could catch up. The task will clear the From 241c7a11bd40d303492821ebef545ea3ffbca849 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 07:09:58 +0000 Subject: [PATCH 212/236] hyperv: Use standard taskqueue instead of hv_work_queue HyperV code was ported from Linux. There is an implementation of work queue called hv_work_queue. In FreeBSD, taskqueue could be used for the same purpose. Convert all the consumer of hv_work_queue to use taskqueue, and remove work queue implementation. Submitted by: Jun Su Reviewed by: adrian, Hongjiang Zhang Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D4963 --- sys/dev/hyperv/include/hyperv.h | 33 +-- sys/dev/hyperv/utilities/hv_kvp.c | 35 +-- sys/dev/hyperv/utilities/hv_util.c | 58 ++--- sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 231 ++++++-------------- sys/dev/hyperv/vmbus/hv_connection.c | 7 - sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c | 22 +- sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 6 +- 7 files changed, 101 insertions(+), 291 deletions(-) diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 852e14ea5690..8e2ca57aa3ca 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -908,30 +908,6 @@ int hv_vmbus_channel_teardown_gpdal( struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary); -/* - * Work abstraction defines - */ -typedef struct hv_work_queue { - struct taskqueue* queue; - struct proc* proc; - struct sema* work_sema; -} hv_work_queue; - -typedef struct hv_work_item { - struct task work; - void (*callback)(void *); - void* context; - hv_work_queue* wq; -} hv_work_item; - -struct hv_work_queue* hv_work_queue_create(char* name); - -void hv_work_queue_close(struct hv_work_queue* wq); - -int hv_queue_work_item( - hv_work_queue* wq, - void (*callback)(void *), - void* context); /** * @brief Get physical address from virtual */ @@ -952,8 +928,8 @@ typedef struct hv_vmbus_service { hv_guid guid; /* Hyper-V GUID */ char *name; /* name of service */ boolean_t enabled; /* service enabled */ - hv_work_queue *work_queue; /* background work queue */ - + void* context; + struct task task; /* * function to initialize service */ @@ -963,6 +939,11 @@ typedef struct hv_vmbus_service { * function to process Hyper-V messages */ void (*callback)(void *); + + /* + * function to uninitilize service + */ + int (*uninit)(struct hv_vmbus_service *); } hv_vmbus_service; extern uint8_t* receive_buffer[]; diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index 58d565c44bfb..86e037ab7e79 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -98,7 +98,7 @@ static d_poll_t hv_kvp_dev_daemon_poll; static int hv_kvp_req_in_progress(void); static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *); static void hv_kvp_send_msg_to_daemon(void); -static void hv_kvp_process_request(void *context); +static void hv_kvp_process_request(void *context, int pending); /* hv_kvp character device structure */ static struct cdevsw hv_kvp_cdevsw = @@ -123,9 +123,6 @@ static struct selinfo hv_kvp_selinfo; */ static struct { - /* Pre-allocated work item for queue */ - hv_work_item work_item; - /* Unless specified the pending mutex should be * used to alter the values of the following paramters: * 1. req_in_progress @@ -642,7 +639,7 @@ hv_kvp_send_msg_to_daemon(void) * and interact with daemon */ static void -hv_kvp_process_request(void *context) +hv_kvp_process_request(void *context, int pending) { uint8_t *kvp_buf; hv_vmbus_channel *channel = context; @@ -756,23 +753,18 @@ hv_kvp_callback(void *context) uint64_t pending_cnt = 0; if (kvp_globals.register_done == false) { - kvp_globals.channelp = context; + TASK_INIT(&service_table[HV_KVP].task, 0, hv_kvp_process_request, context); } else { - mtx_lock(&kvp_globals.pending_mutex); kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1; pending_cnt = kvp_globals.pending_reqs; mtx_unlock(&kvp_globals.pending_mutex); if (pending_cnt == 1) { hv_kvp_log_info("%s: Queuing work item\n", __func__); - hv_queue_work_item( - service_table[HV_KVP].work_queue, - hv_kvp_process_request, - context - ); + taskqueue_enqueue(taskqueue_thread, &service_table[HV_KVP].task); } - } + } } @@ -977,26 +969,13 @@ int hv_kvp_init(hv_vmbus_service *srv) { int error = 0; - hv_work_queue *work_queue = NULL; - - memset(&kvp_globals, 0, sizeof(kvp_globals)); - work_queue = hv_work_queue_create("KVP Service"); - if (work_queue == NULL) { - hv_kvp_log_info("%s: Work queue alloc failed\n", __func__); - error = ENOMEM; - hv_kvp_log_error("%s: ENOMEM\n", __func__); - goto Finish; - } - srv->work_queue = work_queue; + memset(&kvp_globals, 0, sizeof(kvp_globals)); error = hv_kvp_dev_init(); mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex", - NULL, MTX_DEF); - kvp_globals.pending_reqs = 0; + NULL, MTX_DEF); - -Finish: return (error); } diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c index dc4b1e2537ba..38054ca566ba 100644 --- a/sys/dev/hyperv/utilities/hv_util.c +++ b/sys/dev/hyperv/utilities/hv_util.c @@ -52,6 +52,8 @@ static void hv_heartbeat_cb(void *context); static void hv_timesync_cb(void *context); static int hv_timesync_init(hv_vmbus_service *serv); +static int hv_timesync_uninit(hv_vmbus_service *serv); +static void hv_set_host_time(void *context, int pending); /* * Note: GUID codes below are predefined by the host hypervisor @@ -73,6 +75,7 @@ hv_vmbus_service service_table[] = { .enabled = TRUE, .init = hv_timesync_init, .callback = hv_timesync_cb, + .uninit = hv_timesync_uninit, }, /* Heartbeat Service */ @@ -111,10 +114,16 @@ struct hv_ictimesync_data { static int hv_timesync_init(hv_vmbus_service *serv) { + void *time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_WAITOK); + TASK_INIT(&serv->task, 1, hv_set_host_time, time_msg); + return (0); +} - serv->work_queue = hv_work_queue_create("Time Sync"); - if (serv->work_queue == NULL) - return (ENOMEM); +static int +hv_timesync_uninit(hv_vmbus_service *serv) +{ + taskqueue_drain(taskqueue_thread, &serv->task); + free(serv->task.ta_context, M_DEVBUF); return (0); } @@ -152,9 +161,9 @@ hv_negotiate_version( * Set host time based on time sync message from host */ static void -hv_set_host_time(void *context) +hv_set_host_time(void *context, int pending) { - time_sync_data* time_msg = (time_sync_data*) context; + time_sync_data* time_msg = (time_sync_data*) context; uint64_t hosttime = time_msg->data; struct timespec guest_ts, host_ts; uint64_t host_tns; @@ -166,7 +175,7 @@ hv_set_host_time(void *context) host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC); nanotime(&guest_ts); - + diff = (int64_t)host_ts.tv_sec - (int64_t)guest_ts.tv_sec; /* @@ -175,12 +184,7 @@ hv_set_host_time(void *context) if (diff > 5 || diff < -5) { error = kern_clock_settime(curthread, CLOCK_REALTIME, &host_ts); - } - - /* - * Free the hosttime that was allocated in hv_adj_guesttime() - */ - free(time_msg, M_DEVBUF); + } } /** @@ -197,23 +201,13 @@ hv_set_host_time(void *context) static inline void hv_adj_guesttime(uint64_t hosttime, uint8_t flags) { - time_sync_data* time_msg; + time_sync_data* time_msg = service_table[HV_TIME_SYNCH].task.ta_context; - time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_NOWAIT); - - if (time_msg == NULL) - return; - time_msg->data = hosttime; - if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) { - hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue, - hv_set_host_time, time_msg); - } else if ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0) { - hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue, - hv_set_host_time, time_msg); - } else { - free(time_msg, M_DEVBUF); + if (((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) || + ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0)) { + taskqueue_enqueue(taskqueue_thread, &service_table[HV_TIME_SYNCH].task); } } @@ -452,19 +446,14 @@ hv_util_detach(device_t dev) service = device_get_softc(dev); receive_buffer_offset = service - &service_table[0]; - if (service->work_queue != NULL) - hv_work_queue_close(service->work_queue); + if (service->uninit != NULL) + service->uninit(service); free(receive_buffer[receive_buffer_offset], M_DEVBUF); receive_buffer[receive_buffer_offset] = NULL; return (0); } -static void -hv_util_init(void) -{ -} - static int hv_util_modevent(module_t mod, int event, void *arg) { @@ -495,6 +484,3 @@ static devclass_t util_devclass; DRIVER_MODULE(hv_utils, vmbus, util_driver, util_devclass, hv_util_modevent, 0); MODULE_VERSION(hv_utils, 1); MODULE_DEPEND(hv_utils, vmbus, 1, 1, 1); - -SYSINIT(hv_util_initx, SI_SUB_KTHREAD_IDLE, SI_ORDER_MIDDLE + 1, - hv_util_init, NULL); diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index 93008aad857e..21f7d956d39c 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -36,8 +36,10 @@ */ static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr); +static void vmbus_channel_on_offer_internal(void* context); static void vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr); +static void vmbus_channel_on_offer_rescind_internal(void* context); static void vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr); @@ -49,41 +51,46 @@ static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr); hv_vmbus_channel_msg_table_entry g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = { { HV_CHANNEL_MESSAGE_INVALID, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_OFFER_CHANNEL, - 0, vmbus_channel_on_offer }, + vmbus_channel_on_offer }, { HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER, - 0, vmbus_channel_on_offer_rescind }, + vmbus_channel_on_offer_rescind }, { HV_CHANNEL_MESSAGE_REQUEST_OFFERS, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED, - 1, vmbus_channel_on_offers_delivered }, + vmbus_channel_on_offers_delivered }, { HV_CHANNEL_MESSAGE_OPEN_CHANNEL, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT, - 1, vmbus_channel_on_open_result }, + vmbus_channel_on_open_result }, { HV_CHANNEL_MESSAGE_CLOSE_CHANNEL, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGEL_GPADL_HEADER, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_BODY, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_CREATED, - 1, vmbus_channel_on_gpadl_created }, + vmbus_channel_on_gpadl_created }, { HV_CHANNEL_MESSAGE_GPADL_TEARDOWN, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_TORNDOWN, - 1, vmbus_channel_on_gpadl_torndown }, + vmbus_channel_on_gpadl_torndown }, { HV_CHANNEL_MESSAGE_REL_ID_RELEASED, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_INITIATED_CONTACT, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_VERSION_RESPONSE, - 1, vmbus_channel_on_version_response }, + vmbus_channel_on_version_response }, { HV_CHANNEL_MESSAGE_UNLOAD, - 0, NULL } + NULL } }; +typedef struct hv_work_item { + struct task work; + void (*callback)(void *); + void* context; +} hv_work_item; /** * Implementation of the work abstraction. @@ -93,120 +100,30 @@ work_item_callback(void *work, int pending) { struct hv_work_item *w = (struct hv_work_item *)work; - /* - * Serialize work execution. - */ - if (w->wq->work_sema != NULL) { - sema_wait(w->wq->work_sema); - } - w->callback(w->context); - if (w->wq->work_sema != NULL) { - sema_post(w->wq->work_sema); - } - free(w, M_DEVBUF); } -struct hv_work_queue* -hv_work_queue_create(char* name) -{ - static unsigned int qid = 0; - char qname[64]; - int pri; - struct hv_work_queue* wq; - - wq = malloc(sizeof(struct hv_work_queue), M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(wq != NULL, ("Error VMBUS: Failed to allocate work_queue\n")); - if (wq == NULL) - return (NULL); - - /* - * We use work abstraction to handle messages - * coming from the host and these are typically offers. - * Some FreeBsd drivers appear to have a concurrency issue - * where probe/attach needs to be serialized. We ensure that - * by having only one thread process work elements in a - * specific queue by serializing work execution. - * - */ - if (strcmp(name, "vmbusQ") == 0) { - pri = PI_DISK; - } else { /* control */ - pri = PI_NET; - /* - * Initialize semaphore for this queue by pointing - * to the globale semaphore used for synchronizing all - * control messages. - */ - wq->work_sema = &hv_vmbus_g_connection.control_sema; - } - - sprintf(qname, "hv_%s_%u", name, qid); - - /* - * Fixme: FreeBSD 8.2 has a different prototype for - * taskqueue_create(), and for certain other taskqueue functions. - * We need to research the implications of these changes. - * Fixme: Not sure when the changes were introduced. - */ - wq->queue = taskqueue_create(qname, M_NOWAIT, taskqueue_thread_enqueue, - &wq->queue - #if __FreeBSD_version < 800000 - , &wq->proc - #endif - ); - - if (wq->queue == NULL) { - free(wq, M_DEVBUF); - return (NULL); - } - - if (taskqueue_start_threads(&wq->queue, 1, pri, "%s taskq", qname)) { - taskqueue_free(wq->queue); - free(wq, M_DEVBUF); - return (NULL); - } - - qid++; - - return (wq); -} - -void -hv_work_queue_close(struct hv_work_queue *wq) -{ - /* - * KYS: Need to drain the taskqueue - * before we close the hv_work_queue. - */ - /*KYS: taskqueue_drain(wq->tq, ); */ - taskqueue_free(wq->queue); - free(wq, M_DEVBUF); -} - /** * @brief Create work item */ -int +static int hv_queue_work_item( - struct hv_work_queue *wq, void (*callback)(void *), void *context) { struct hv_work_item *w = malloc(sizeof(struct hv_work_item), - M_DEVBUF, M_NOWAIT | M_ZERO); + M_DEVBUF, M_NOWAIT); KASSERT(w != NULL, ("Error VMBUS: Failed to allocate WorkItem\n")); if (w == NULL) return (ENOMEM); w->callback = callback; w->context = context; - w->wq = wq; TASK_INIT(&w->work, 0, work_item_callback, w); - return (taskqueue_enqueue(wq->queue, &w->work)); + return (taskqueue_enqueue(taskqueue_thread, &w->work)); } @@ -221,10 +138,7 @@ hv_vmbus_allocate_channel(void) channel = (hv_vmbus_channel*) malloc( sizeof(hv_vmbus_channel), M_DEVBUF, - M_NOWAIT | M_ZERO); - KASSERT(channel != NULL, ("Error VMBUS: Failed to allocate channel!")); - if (channel == NULL) - return (NULL); + M_WAITOK | M_ZERO); mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF); mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF); @@ -234,16 +148,6 @@ hv_vmbus_allocate_channel(void) return (channel); } -/** - * @brief Release the vmbus channel object itself - */ -static inline void -ReleaseVmbusChannel(void *context) -{ - hv_vmbus_channel* channel = (hv_vmbus_channel*) context; - free(channel, M_DEVBUF); -} - /** * @brief Release the resources used by the vmbus channel object */ @@ -252,13 +156,8 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel) { mtx_destroy(&channel->sc_lock); mtx_destroy(&channel->inbound_lock); - /* - * We have to release the channel's workqueue/thread in - * the vmbus's workqueue/thread context - * ie we can't destroy ourselves - */ - hv_queue_work_item(hv_vmbus_g_connection.work_queue, - ReleaseVmbusChannel, (void *) channel); + + free(channel, M_DEVBUF); } /** @@ -456,7 +355,7 @@ static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) { hv_vmbus_channel_offer_channel* offer; - hv_vmbus_channel* new_channel; + hv_vmbus_channel_offer_channel* copied; offer = (hv_vmbus_channel_offer_channel*) hdr; @@ -466,10 +365,25 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) guidType = &offer->offer.interface_type; guidInstance = &offer->offer.interface_instance; + // copy offer data + copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT); + if (copied == NULL) { + printf("fail to allocate memory\n"); + return; + } + + memcpy(copied, hdr, sizeof(*copied)); + hv_queue_work_item(vmbus_channel_on_offer_internal, copied); +} + +static void +vmbus_channel_on_offer_internal(void* context) +{ + hv_vmbus_channel* new_channel; + + hv_vmbus_channel_offer_channel* offer = (hv_vmbus_channel_offer_channel*)context; /* Allocate the channel object and save this offer */ new_channel = hv_vmbus_allocate_channel(); - if (new_channel == NULL) - return; /* * By default we setup state to enable batched @@ -509,6 +423,8 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32; vmbus_channel_process_offer(new_channel); + + free(offer, M_DEVBUF); } /** @@ -526,13 +442,20 @@ vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr) rescind = (hv_vmbus_channel_rescind_offer*) hdr; channel = hv_vmbus_g_connection.channels[rescind->child_rel_id]; - if (channel == NULL) + if (channel == NULL) return; - hv_vmbus_child_device_unregister(channel->device); - mtx_lock(&hv_vmbus_g_connection.channel_lock); + hv_queue_work_item(vmbus_channel_on_offer_rescind_internal, channel); hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL; - mtx_unlock(&hv_vmbus_g_connection.channel_lock); +} + +static void +vmbus_channel_on_offer_rescind_internal(void *context) +{ + hv_vmbus_channel* channel; + + channel = (hv_vmbus_channel*)context; + hv_vmbus_child_device_unregister(channel->device); } /** @@ -708,35 +631,6 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr) } -/** - * @brief Handler for channel protocol messages. - * - * This is invoked in the vmbus worker thread context. - */ -void -hv_vmbus_on_channel_message(void *context) -{ - hv_vmbus_message* msg; - hv_vmbus_channel_msg_header* hdr; - int size; - - msg = (hv_vmbus_message*) context; - hdr = (hv_vmbus_channel_msg_header*) msg->u.payload; - size = msg->header.payload_size; - - if (hdr->message_type >= HV_CHANNEL_MESSAGE_COUNT) { - free(msg, M_DEVBUF); - return; - } - - if (g_channel_message_table[hdr->message_type].messageHandler) { - g_channel_message_table[hdr->message_type].messageHandler(hdr); - } - - /* Free the msg that was allocated in VmbusOnMsgDPC() */ - free(msg, M_DEVBUF); -} - /** * @brief Send a request to get all our pending offers. */ @@ -762,8 +656,7 @@ hv_vmbus_request_channel_offers(void) ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_msg_header)); - if (msg_info) - free(msg_info, M_DEVBUF); + free(msg_info, M_DEVBUF); return (ret); } diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c index 05b16120f303..c76028e21817 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -164,8 +164,6 @@ hv_vmbus_connect(void) { * Initialize the vmbus connection */ hv_vmbus_g_connection.connect_state = HV_CONNECTING; - hv_vmbus_g_connection.work_queue = hv_work_queue_create("vmbusQ"); - sema_init(&hv_vmbus_g_connection.control_sema, 1, "control_sema"); TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor); mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg", @@ -269,8 +267,6 @@ hv_vmbus_connect(void) { hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; - hv_work_queue_close(hv_vmbus_g_connection.work_queue); - sema_destroy(&hv_vmbus_g_connection.control_sema); mtx_destroy(&hv_vmbus_g_connection.channel_lock); mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); @@ -323,9 +319,6 @@ hv_vmbus_disconnect(void) { mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); - hv_work_queue_close(hv_vmbus_g_connection.work_queue); - sema_destroy(&hv_vmbus_g_connection.control_sema); - free(hv_vmbus_g_connection.channels, M_DEVBUF); hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c index 7eac11679290..cf69c38ac998 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -83,8 +83,6 @@ vmbus_msg_swintr(void *arg) hv_vmbus_channel_msg_table_entry *entry; hv_vmbus_channel_msg_type msg_type; hv_vmbus_message* msg; - hv_vmbus_message* copied; - static bool warned = false; cpu = (int)(long)arg; KASSERT(cpu <= mp_maxid, ("VMBUS: vmbus_msg_swintr: " @@ -100,31 +98,15 @@ vmbus_msg_swintr(void *arg) hdr = (hv_vmbus_channel_msg_header *)msg->u.payload; msg_type = hdr->message_type; - if (msg_type >= HV_CHANNEL_MESSAGE_COUNT && !warned) { - warned = true; + if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) { printf("VMBUS: unknown message type = %d\n", msg_type); goto handled; } entry = &g_channel_message_table[msg_type]; - if (entry->handler_no_sleep) + if (entry->messageHandler) entry->messageHandler(hdr); - else { - - copied = malloc(sizeof(hv_vmbus_message), - M_DEVBUF, M_NOWAIT); - KASSERT(copied != NULL, - ("Error VMBUS: malloc failed to allocate" - " hv_vmbus_message!")); - if (copied == NULL) - continue; - - memcpy(copied, msg, sizeof(hv_vmbus_message)); - hv_queue_work_item(hv_vmbus_g_connection.work_queue, - hv_vmbus_on_channel_message, - copied); - } handled: msg->header.message_type = HV_MESSAGE_TYPE_NONE; diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 538ab1e7222e..c1fdc40d1dae 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -362,10 +362,8 @@ typedef struct { /** * channel table for fast lookup through id. - */ + */ hv_vmbus_channel **channels; - hv_vmbus_handle work_queue; - struct sema control_sema; } hv_vmbus_connection; typedef union { @@ -632,7 +630,6 @@ typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg); typedef struct hv_vmbus_channel_msg_table_entry { hv_vmbus_channel_msg_type messageType; - bool handler_no_sleep; /* true: the handler doesn't sleep */ vmbus_msg_handler messageHandler; } hv_vmbus_channel_msg_table_entry; @@ -682,7 +679,6 @@ uint32_t hv_ring_buffer_read_end( hv_vmbus_channel* hv_vmbus_allocate_channel(void); void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); -void hv_vmbus_on_channel_message(void *context); int hv_vmbus_request_channel_offers(void); void hv_vmbus_release_unattached_channels(void); int hv_vmbus_init(void); From 9cc4c0881fabfdb6aa445c5bcb5bbb01f5b801f4 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 07:20:31 +0000 Subject: [PATCH 213/236] hyperv: Use WAITOK in the places where we can wait And convert rndis non-hot path spinlock to mutex. Submitted by: Jun Su Reviewed by: adrian, sephe Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5081 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 17 ++------ sys/dev/hyperv/netvsc/hv_rndis_filter.c | 24 +++++------ sys/dev/hyperv/vmbus/hv_connection.c | 44 ++++----------------- sys/dev/hyperv/vmbus/hv_hv.c | 6 +-- sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c | 14 +------ 5 files changed, 22 insertions(+), 83 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 300704ff1059..cd60b4969fd4 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -74,10 +74,7 @@ hv_nv_alloc_net_device(struct hv_device *device) netvsc_dev *net_dev; hn_softc_t *sc = device_get_softc(device->device); - net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO); - if (net_dev == NULL) { - return (NULL); - } + net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO); net_dev->dev = device; net_dev->destroy = FALSE; @@ -224,11 +221,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device) init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; net_dev->rx_sections = malloc(net_dev->rx_section_count * - sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT); - if (net_dev->rx_sections == NULL) { - ret = EINVAL; - goto cleanup; - } + sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK); memcpy(net_dev->rx_sections, init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections, net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section)); @@ -326,11 +319,7 @@ hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device) BITS_PER_LONG); net_dev->send_section_bitsmap = malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, - M_NOWAIT | M_ZERO); - if (NULL == net_dev->send_section_bitsmap) { - ret = ENOMEM; - goto cleanup; - } + M_WAITOK | M_ZERO); goto exit; diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index dfd0b4727938..9fb78eeeb406 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -135,12 +135,9 @@ hv_get_rndis_device(void) { rndis_device *device; - device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO); - if (device == NULL) { - return (NULL); - } + device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO); - mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE); + mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF); /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */ STAILQ_INIT(&device->myrequest_list); @@ -171,10 +168,7 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, rndis_msg *rndis_mesg; rndis_set_request *set; - request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO); - if (request == NULL) { - return (NULL); - } + request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO); sema_init(&request->wait_sema, 0, "rndis sema"); @@ -193,9 +187,9 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, set->request_id += 1; /* Add to the request list */ - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry); - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); return (request); } @@ -206,14 +200,14 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, static inline void hv_put_rndis_request(rndis_device *device, rndis_request *request) { - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); /* Fixme: Has O(n) performance */ /* * XXXKYS: Use Doubly linked lists. */ STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_, mylist_entry); - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); sema_destroy(&request->wait_sema); free(request, M_NETVSC); @@ -270,7 +264,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response) rndis_request *next_request; boolean_t found = FALSE; - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); request = STAILQ_FIRST(&device->myrequest_list); while (request != NULL) { /* @@ -285,7 +279,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response) next_request = STAILQ_NEXT(request, mylist_entry); request = next_request; } - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); if (found) { if (response->msg_len <= sizeof(rndis_msg)) { diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c index c76028e21817..2ea372f1a4c9 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -88,8 +88,7 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info, msg->monitor_page_1 = hv_get_phys_addr( hv_vmbus_g_connection.monitor_pages); - msg->monitor_page_2 = - hv_get_phys_addr( + msg->monitor_page_2 = hv_get_phys_addr( ((uint8_t *) hv_vmbus_g_connection.monitor_pages + PAGE_SIZE)); @@ -179,16 +178,9 @@ hv_vmbus_connect(void) { */ hv_vmbus_g_connection.interrupt_page = contigmalloc( PAGE_SIZE, M_DEVBUF, - M_NOWAIT | M_ZERO, 0UL, + M_WAITOK | M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); - KASSERT(hv_vmbus_g_connection.interrupt_page != NULL, - ("Error VMBUS: malloc failed to allocate Channel" - " Request Event message!")); - if (hv_vmbus_g_connection.interrupt_page == NULL) { - ret = ENOMEM; - goto cleanup; - } hv_vmbus_g_connection.recv_interrupt_page = hv_vmbus_g_connection.interrupt_page; @@ -204,28 +196,16 @@ hv_vmbus_connect(void) { hv_vmbus_g_connection.monitor_pages = contigmalloc( 2 * PAGE_SIZE, M_DEVBUF, - M_NOWAIT | M_ZERO, + M_WAITOK | M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); - KASSERT(hv_vmbus_g_connection.monitor_pages != NULL, - ("Error VMBUS: malloc failed to allocate Monitor Pages!")); - if (hv_vmbus_g_connection.monitor_pages == NULL) { - ret = ENOMEM; - goto cleanup; - } msg_info = (hv_vmbus_channel_msg_info*) malloc(sizeof(hv_vmbus_channel_msg_info) + sizeof(hv_vmbus_channel_initiate_contact), - M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(msg_info != NULL, - ("Error VMBUS: malloc failed for Initiate Contact message!")); - if (msg_info == NULL) { - ret = ENOMEM; - goto cleanup; - } + M_DEVBUF, M_WAITOK | M_ZERO); hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) * HV_CHANNEL_MAX_COUNT, @@ -301,19 +281,11 @@ hv_vmbus_connect(void) { int hv_vmbus_disconnect(void) { int ret = 0; - hv_vmbus_channel_unload* msg; + hv_vmbus_channel_unload msg; - msg = malloc(sizeof(hv_vmbus_channel_unload), - M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(msg != NULL, - ("Error VMBUS: malloc failed to allocate Channel Unload Msg!")); - if (msg == NULL) - return (ENOMEM); - - msg->message_type = HV_CHANNEL_MESSAGE_UNLOAD; - - ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_unload)); + msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD; + ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload)); contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF); @@ -322,8 +294,6 @@ hv_vmbus_disconnect(void) { free(hv_vmbus_g_connection.channels, M_DEVBUF); hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; - free(msg, M_DEVBUF); - return (ret); } diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c index ca5641f620bf..6afc2b8542bb 100644 --- a/sys/dev/hyperv/vmbus/hv_hv.c +++ b/sys/dev/hyperv/vmbus/hv_hv.c @@ -189,11 +189,7 @@ hv_vmbus_init(void) * See if the hypercall page is already set */ hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL); - virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(virt_addr != NULL, - ("Error VMBUS: malloc failed to allocate page during init!")); - if (virt_addr == NULL) - goto cleanup; + virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); hypercall_msr.u.enable = 1; hypercall_msr.u.guest_physical_address = diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c index cf69c38ac998..8a1e4126f13e 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -291,12 +291,7 @@ hv_vmbus_child_device_create( * Allocate the new child device */ child_dev = malloc(sizeof(hv_device), M_DEVBUF, - M_NOWAIT | M_ZERO); - KASSERT(child_dev != NULL, - ("Error VMBUS: malloc failed to allocate hv_device!")); - - if (child_dev == NULL) - return (NULL); + M_WAITOK | M_ZERO); child_dev->channel = channel; memcpy(&child_dev->class_id, &type, sizeof(hv_guid)); @@ -548,12 +543,7 @@ vmbus_bus_init(void) */ for(i = 0; i < 2; i++) { setup_args.page_buffers[2 * j + i] = - malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); - if (setup_args.page_buffers[2 * j + i] == NULL) { - KASSERT(setup_args.page_buffers[2 * j + i] != NULL, - ("Error VMBUS: malloc failed!")); - goto cleanup1; - } + malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); } } From 53270ee78850775ed6b7c609013336e470e9c5fc Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 5 Feb 2016 07:29:11 +0000 Subject: [PATCH 214/236] hyperv: Use malloc for page allocation. We will eventually convert them to use busdma. Submitted by: Jun Su Reviewed by: adrian, sephe, Dexuan Cui Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5087 --- sys/dev/hyperv/vmbus/hv_channel.c | 4 +--- sys/dev/hyperv/vmbus/hv_connection.c | 34 +++++++++++----------------- sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 3 ++- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 762ace4fe423..af7395b445f5 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -68,9 +68,7 @@ vmbus_channel_set_event(hv_vmbus_channel *channel) + ((channel->offer_msg.child_rel_id >> 5)))); monitor_page = (hv_vmbus_monitor_page *) - hv_vmbus_g_connection.monitor_pages; - - monitor_page++; /* Get the child to parent monitor page */ + hv_vmbus_g_connection.monitor_page_2; synch_set_bit(channel->monitor_bit, (uint32_t *)&monitor_page-> diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c index 2ea372f1a4c9..e60c55709fc0 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -86,11 +86,10 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info, hv_vmbus_g_connection.interrupt_page); msg->monitor_page_1 = hv_get_phys_addr( - hv_vmbus_g_connection.monitor_pages); + hv_vmbus_g_connection.monitor_page_1); msg->monitor_page_2 = hv_get_phys_addr( - ((uint8_t *) hv_vmbus_g_connection.monitor_pages - + PAGE_SIZE)); + hv_vmbus_g_connection.monitor_page_2); /** * Add to list before we send the request since we may receive the @@ -176,11 +175,9 @@ hv_vmbus_connect(void) { * Setup the vmbus event connection for channel interrupt abstraction * stuff */ - hv_vmbus_g_connection.interrupt_page = contigmalloc( + hv_vmbus_g_connection.interrupt_page = malloc( PAGE_SIZE, M_DEVBUF, - M_WAITOK | M_ZERO, 0UL, - BUS_SPACE_MAXADDR, - PAGE_SIZE, 0); + M_WAITOK | M_ZERO); hv_vmbus_g_connection.recv_interrupt_page = hv_vmbus_g_connection.interrupt_page; @@ -193,14 +190,14 @@ hv_vmbus_connect(void) { * Set up the monitor notification facility. The 1st page for * parent->child and the 2nd page for child->parent */ - hv_vmbus_g_connection.monitor_pages = contigmalloc( - 2 * PAGE_SIZE, - M_DEVBUF, - M_WAITOK | M_ZERO, - 0UL, - BUS_SPACE_MAXADDR, + hv_vmbus_g_connection.monitor_page_1 = malloc( PAGE_SIZE, - 0); + M_DEVBUF, + M_WAITOK | M_ZERO); + hv_vmbus_g_connection.monitor_page_2 = malloc( + PAGE_SIZE, + M_DEVBUF, + M_WAITOK | M_ZERO); msg_info = (hv_vmbus_channel_msg_info*) malloc(sizeof(hv_vmbus_channel_msg_info) + @@ -258,13 +255,8 @@ hv_vmbus_connect(void) { hv_vmbus_g_connection.interrupt_page = NULL; } - if (hv_vmbus_g_connection.monitor_pages != NULL) { - contigfree( - hv_vmbus_g_connection.monitor_pages, - 2 * PAGE_SIZE, - M_DEVBUF); - hv_vmbus_g_connection.monitor_pages = NULL; - } + free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF); + free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF); if (msg_info) { sema_destroy(&msg_info->wait_sema); diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index c1fdc40d1dae..5f6207217ecc 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -350,7 +350,8 @@ typedef struct { * notification and 2nd is child->parent * notification */ - void *monitor_pages; + void *monitor_page_1; + void *monitor_page_2; TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor; struct mtx channel_msg_lock; /** From 7589b2ecfc389751f478e6d2c0d3f89d12676cc7 Mon Sep 17 00:00:00 2001 From: mmel Date: Fri, 5 Feb 2016 09:46:24 +0000 Subject: [PATCH 215/236] ARM: Introduce new cpu-v4.h header and move all ARMv4 specific code from cpu-v6.h to it. Remove unneeded cpu-v6.h includes. --- sys/arm/arm/cpuinfo.c | 7 +- sys/arm/arm/genassym.c | 1 - sys/arm/arm/machdep.c | 1 - sys/arm/arm/pmap-v6.c | 1 - sys/arm/arm/sys_machdep.c | 2 +- sys/arm/arm/trap-v6.c | 1 - sys/arm/include/cpu-v4.h | 154 ++++++++++++++++++++++++++++++++++++++ sys/arm/include/cpu-v6.h | 72 +++++------------- sys/arm/include/cpu.h | 8 +- 9 files changed, 181 insertions(+), 66 deletions(-) create mode 100644 sys/arm/include/cpu-v4.h diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c index 5e96cae90775..b2d96a7b3ef1 100644 --- a/sys/arm/arm/cpuinfo.c +++ b/sys/arm/arm/cpuinfo.c @@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include -#include struct cpuinfo cpuinfo = { @@ -83,14 +83,16 @@ cpuinfo_init(void) /* CP15 c0,c0 regs 0-7 exist on all CPUs (although aliased with MIDR) */ cpuinfo.ctr = cp15_ctr_get(); cpuinfo.tcmtr = cp15_tcmtr_get(); +#if __ARM_ARCH >= 6 cpuinfo.tlbtr = cp15_tlbtr_get(); cpuinfo.mpidr = cp15_mpidr_get(); cpuinfo.revidr = cp15_revidr_get(); +#endif /* if CPU is not v7 cpu id scheme */ if (cpuinfo.architecture != 0xF) return; - +#if __ARM_ARCH >= 6 cpuinfo.id_pfr0 = cp15_id_pfr0_get(); cpuinfo.id_pfr1 = cp15_id_pfr1_get(); cpuinfo.id_dfr0 = cp15_id_dfr0_get(); @@ -144,6 +146,7 @@ cpuinfo_init(void) } cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1; cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1; +#endif } /* diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index 4a60d9494331..41497714619f 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index b4bfa6222c86..26109d4aa521 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -123,7 +123,6 @@ __FBSDID("$FreeBSD$"); #include #if __ARM_ARCH >= 6 -#include DB_SHOW_COMMAND(cp15, db_show_cp15) { diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 95e4a5d5d2af..23447d5839fe 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -141,7 +141,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #ifdef SMP diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c index efebda32262e..cad26ec42974 100644 --- a/sys/arm/arm/sys_machdep.c +++ b/sys/arm/arm/sys_machdep.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 9c0799950d1b..81a6ee428f6f 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/include/cpu-v4.h b/sys/arm/include/cpu-v4.h new file mode 100644 index 000000000000..503ed56a698a --- /dev/null +++ b/sys/arm/include/cpu-v4.h @@ -0,0 +1,154 @@ +/*- + * Copyright 2016 Svatopluk Kraus + * Copyright 2016 Michal Meloun + * 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_CPU_V4_H +#define MACHINE_CPU_V4_H + +/* There are no user serviceable parts here, they may change without notice */ +#ifndef _KERNEL +#error Only include this file in the kernel +#endif + +#include +#include +#include +#include +#include + +#if __ARM_ARCH >= 6 +#error Newer include this file for ARMv6 +#else + +#define CPU_ASID_KERNEL 0 + +/* + * Macros to generate CP15 (system control processor) read/write functions. + */ +#define _FX(s...) #s + +#define _RF0(fname, aname...) \ +static __inline register_t \ +fname(void) \ +{ \ + register_t reg; \ + __asm __volatile("mrc\t" _FX(aname): "=r" (reg)); \ + return(reg); \ +} + +#define _R64F0(fname, aname) \ +static __inline uint64_t \ +fname(void) \ +{ \ + uint64_t reg; \ + __asm __volatile("mrrc\t" _FX(aname): "=r" (reg)); \ + return(reg); \ +} + +#define _WF0(fname, aname...) \ +static __inline void \ +fname(void) \ +{ \ + __asm __volatile("mcr\t" _FX(aname)); \ +} + +#define _WF1(fname, aname...) \ +static __inline void \ +fname(register_t reg) \ +{ \ + __asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \ +} + + +/* + * Publicly accessible functions + */ + + +/* Various control registers */ + +_RF0(cp15_cpacr_get, CP15_CPACR(%0)) +_WF1(cp15_cpacr_set, CP15_CPACR(%0)) +_RF0(cp15_dfsr_get, CP15_DFSR(%0)) +_RF0(cp15_ttbr_get, CP15_TTBR0(%0)) +_RF0(cp15_dfar_get, CP15_DFAR(%0)) +/* XScale */ +_RF0(cp15_actlr_get, CP15_ACTLR(%0)) +_WF1(cp15_actlr_set, CP15_ACTLR(%0)) + +/*CPU id registers */ +_RF0(cp15_midr_get, CP15_MIDR(%0)) +_RF0(cp15_ctr_get, CP15_CTR(%0)) +_RF0(cp15_tcmtr_get, CP15_TCMTR(%0)) +_RF0(cp15_tlbtr_get, CP15_TLBTR(%0)) + +#undef _FX +#undef _RF0 +#undef _WF0 +#undef _WF1 + + +/* + * armv4/5 compatibility shims. + * + * These functions provide armv4 cache maintenance using the new armv6 names. + * Included here are just the functions actually used now in common code; it may + * be necessary to add things here over time. + * + * The callers of the dcache functions expect these routines to handle address + * and size values which are not aligned to cacheline boundaries; the armv4 and + * armv5 asm code handles that. + */ + +static __inline void +dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + cpu_dcache_inv_range(va, size); + cpu_l2cache_inv_range(va, size); +} + +static __inline void +dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + /* See armv6 code, above, for why we do L2 before L1 in this case. */ + cpu_l2cache_inv_range(va, size); + cpu_dcache_inv_range(va, size); +} + +static __inline void +dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + cpu_dcache_wb_range(va, size); + cpu_l2cache_wb_range(va, size); +} + +#endif /* _KERNEL */ + +#endif /* MACHINE_CPU_V4_H */ diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index bb8649ab30ba..40a7f400ba36 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -32,19 +32,33 @@ /* There are no user serviceable parts here, they may change without notice */ #ifndef _KERNEL #error Only include this file in the kernel -#else +#endif #include -#include "machine/atomic.h" -#include "machine/cpufunc.h" -#include "machine/cpuinfo.h" -#include "machine/sysreg.h" +#include +#include +#include +#include + +#if __ARM_ARCH < 6 +#error Only include this file for ARMv6 +#else + + #define CPU_ASID_KERNEL 0 vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t); vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t); +#ifdef DEV_PMU +#include +#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ +extern uint32_t ccnt_hi[MAXCPU]; +extern int pmu_attched; +#endif /* DEV_PMU */ + + /* * Macros to generate CP15 (system control processor) read/write functions. */ @@ -277,12 +291,6 @@ _W64F1(cp15_cnthp_cval_set, CP15_CNTHP_CVAL(%Q0, %R0)) #undef _WF0 #undef _WF1 -#if __ARM_ARCH >= 6 -/* - * Cache and TLB maintenance operations for armv6+ code. The #else block - * provides armv4/v5 implementations for a few of these used in common code. - */ - /* * TLB maintenance operations. */ @@ -577,48 +585,6 @@ cp15_ttbr_set(uint32_t reg) isb(); tlb_flush_all_ng_local(); } - -#else /* ! __ARM_ARCH >= 6 */ - -/* - * armv4/5 compatibility shims. - * - * These functions provide armv4 cache maintenance using the new armv6 names. - * Included here are just the functions actually used now in common code; it may - * be necessary to add things here over time. - * - * The callers of the dcache functions expect these routines to handle address - * and size values which are not aligned to cacheline boundaries; the armv4 and - * armv5 asm code handles that. - */ - -static __inline void -dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - cpu_dcache_inv_range(va, size); - cpu_l2cache_inv_range(va, size); -} - -static __inline void -dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - /* See armv6 code, above, for why we do L2 before L1 in this case. */ - cpu_l2cache_inv_range(va, size); - cpu_dcache_inv_range(va, size); -} - -static __inline void -dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - cpu_dcache_wb_range(va, size); - cpu_l2cache_wb_range(va, size); -} - -#endif /* __ARM_ARCH >= 6 */ - #endif /* _KERNEL */ #endif /* !MACHINE_CPU_V6_H */ diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h index 782471e725d3..0d79e68dc2b8 100644 --- a/sys/arm/include/cpu.h +++ b/sys/arm/include/cpu.h @@ -14,12 +14,8 @@ void swi_vm(void *); #ifdef _KERNEL #if __ARM_ARCH >= 6 #include -#ifdef DEV_PMU -#include -#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ -extern uint32_t ccnt_hi[MAXCPU]; -extern int pmu_attched; -#endif /* DEV_PMU */ +#else +#include #endif /* __ARM_ARCH >= 6 */ static __inline uint64_t From c0682f3da4d309573d6b42105f0f4f77766122e7 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 5 Feb 2016 10:40:01 +0000 Subject: [PATCH 216/236] Follow up r295257 and convert also pt_memattr. This did not break anything as both VM_MEMATTR_WB_WA and PTE2_ATTR_WB_WA are zero. Correct also type of pmap_dcache_wb_pou() last argument. --- sys/arm/arm/pmap-v6.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 23447d5839fe..cc4d3b29e453 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -3,8 +3,8 @@ * Copyright (c) 1994 John S. Dyson * Copyright (c) 1994 David Greenman * Copyright (c) 2005-2010 Alan L. Cox - * Copyright (c) 2014 Svatopluk Kraus - * Copyright (c) 2014 Michal Meloun + * Copyright (c) 2014-2016 Svatopluk Kraus + * Copyright (c) 2014-2016 Michal Meloun * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -223,9 +223,10 @@ int pmap_debug_level = 1; * PTE2 descriptors creation macros. */ #define PTE2_TEX_DEFAULT memattr_to_tex2(VM_MEMATTR_DEFAULT) +#define PTE2_TEX_PT memattr_to_tex2(pt_memattr) -#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, pt_memattr) -#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, pt_memattr) +#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_TEX_PT) +#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, PTE2_TEX_PT) #define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_TEX_DEFAULT) #define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_TEX_DEFAULT) @@ -6071,7 +6072,7 @@ pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb) * The range must be within a single page. */ static void -pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma) +pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, uint32_t attr) { struct sysmaps *sysmaps; @@ -6083,7 +6084,7 @@ pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma) mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP3) panic("%s: CMAP3 busy", __func__); - pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); + pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, attr)); dcache_wb_pou((vm_offset_t)sysmaps->CADDR3 + (pa & PAGE_MASK), size); pte2_clear(sysmaps->CMAP3); tlb_flush((vm_offset_t)sysmaps->CADDR3); From f58eb974cee99ed66fc09089b6d118039edfc098 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 5 Feb 2016 11:28:35 +0000 Subject: [PATCH 217/236] Follow up r295257 and replace bad reference to TEX in defines, variables and functions. This stuff is named properly now. Thus, the VM_MEMATTR_xxx is an index to PTE2 attribute table. Pointy hat to: skra --- sys/arm/arm/pmap-v6.c | 73 ++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index cc4d3b29e453..525280c6d822 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -222,14 +222,14 @@ int pmap_debug_level = 1; /* * PTE2 descriptors creation macros. */ -#define PTE2_TEX_DEFAULT memattr_to_tex2(VM_MEMATTR_DEFAULT) -#define PTE2_TEX_PT memattr_to_tex2(pt_memattr) +#define PTE2_ATTR_DEFAULT vm_memattr_to_pte2(VM_MEMATTR_DEFAULT) +#define PTE2_ATTR_PT vm_memattr_to_pte2(pt_memattr) -#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_TEX_PT) -#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, PTE2_TEX_PT) +#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_PT) +#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, PTE2_ATTR_PT) -#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_TEX_DEFAULT) -#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_TEX_DEFAULT) +#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT) +#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_DEFAULT) #define PV_STATS #ifdef PV_STATS @@ -397,7 +397,7 @@ static uint32_t tex_class[8] = { }; #undef TEX -static uint32_t tex_attr2[8] = { +static uint32_t pte2_attr_tab[8] = { PTE2_ATTR_WB_WA, /* 0 - VM_MEMATTR_WB_WA */ PTE2_ATTR_NOCACHE, /* 1 - VM_MEMATTR_NOCACHE */ PTE2_ATTR_DEVICE, /* 2 - VM_MEMATTR_DEVICE */ @@ -414,18 +414,18 @@ CTASSERT(VM_MEMATTR_SO == 3); CTASSERT(VM_MEMATTR_WRITE_THROUGH == 4); static inline uint32_t -memattr_to_tex2(vm_memattr_t ma) +vm_memattr_to_pte2(vm_memattr_t ma) { - KASSERT(ma < 5, ("%s: bad vm_memattr_t %d", __func__, ma)); - return (tex_attr2[(u_int)ma]); + KASSERT((u_int)ma < 5, ("%s: bad vm_memattr_t %d", __func__, ma)); + return (pte2_attr_tab[(u_int)ma]); } static inline uint32_t -page_tex2(vm_page_t m) +vm_page_pte2_attr(vm_page_t m) { - return (memattr_to_tex2(m->md.pat_mode)); + return (vm_memattr_to_pte2(m->md.pat_mode)); } /* @@ -805,7 +805,7 @@ pmap_bootstrap_prepare(vm_paddr_t last) pte1_store(pte1p++, PTE1_LINK(pa)); /* Make section mappings for kernel. */ - l1_attr = ATTR_TO_L1(PTE2_TEX_DEFAULT); + l1_attr = ATTR_TO_L1(PTE2_ATTR_DEFAULT); pte1p = kern_pte1(KERNBASE); for (pa = KERNEL_V2P(KERNBASE); pa < last; pa += PTE1_SIZE) pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, l1_attr)); @@ -1022,7 +1022,7 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, pt2_entry_t *pte2p; l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR; - l2_attr = memattr_to_tex2(attr); + l2_attr = vm_memattr_to_pte2(attr); l1_prot = ATTR_TO_L1(l2_prot); l1_attr = ATTR_TO_L1(l2_attr); @@ -1277,7 +1277,7 @@ PMAP_INLINE void pmap_kenter(vm_offset_t va, vm_paddr_t pa) { - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_TEX_DEFAULT); + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT); } /* @@ -1360,7 +1360,7 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX; l1prot = ATTR_TO_L1(l2prot); - l2attr = PTE2_TEX_DEFAULT; + l2attr = PTE2_ATTR_DEFAULT; l1attr = ATTR_TO_L1(l2attr); va = *virt; @@ -1594,7 +1594,8 @@ pmap_pt2pg_zero(vm_page_t m) mtx_lock(&sysmaps->lock); if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); - pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, page_tex2(m))); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, + vm_page_pte2_attr(m))); /* Even VM_ALLOC_ZERO request is only advisory. */ if ((m->flags & PG_ZERO) == 0) pagezero(sysmaps->CADDR2); @@ -1749,10 +1750,10 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) pa = VM_PAGE_TO_PHYS(m); pte2 = pte2_load(pte2p); if ((pte2_pa(pte2) != pa) || - (pte2_attr(pte2) != page_tex2(m))) { + (pte2_attr(pte2) != vm_page_pte2_attr(m))) { anychanged++; pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); } pte2p++; } @@ -3802,7 +3803,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, /* * Now validate mapping with desired protection/wiring. */ - npte2 = PTE2(pa, PTE2_NM, page_tex2(m)); + npte2 = PTE2(pa, PTE2_NM, vm_page_pte2_attr(m)); if (prot & VM_PROT_WRITE) { if (pte2_is_managed(npte2)) vm_page_aflag_set(m, PGA_WRITEABLE); @@ -4449,7 +4450,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, */ cache_icache_sync_fresh(va, pa, PAGE_SIZE); } - pte2_store(pte2p, PTE2(pa, l2prot, page_tex2(m))); + pte2_store(pte2p, PTE2(pa, l2prot, vm_page_pte2_attr(m))); return (mpt2pg); } @@ -4520,7 +4521,7 @@ pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) */ cache_icache_sync_fresh(va, pa, PTE1_SIZE); } - pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(page_tex2(m)))); + pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(vm_page_pte2_attr(m)))); pmap_pte1_mappings++; CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va, @@ -4630,7 +4631,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, * is done here, so readonly mapping must be done elsewhere. */ l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A; - l1attr = ATTR_TO_L1(memattr_to_tex2(pat_mode)); + l1attr = ATTR_TO_L1(vm_memattr_to_pte2(pat_mode)); PMAP_LOCK(pmap); for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) { pte1p = pmap_pte1(pmap, addr); @@ -5525,7 +5526,7 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) if (*sysmaps->CMAP2) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, - memattr_to_tex2(ma))); + vm_memattr_to_pte2(ma))); dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5616,7 +5617,7 @@ pmap_zero_page(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); pagezero(sysmaps->CADDR2); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5641,7 +5642,7 @@ pmap_zero_page_area(vm_page_t m, int off, int size) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); if (off == 0 && size == PAGE_SIZE) pagezero(sysmaps->CADDR2); else @@ -5666,7 +5667,7 @@ pmap_zero_page_idle(vm_page_t m) panic("%s: CMAP3 busy", __func__); sched_pin(); pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); pagezero(CADDR3); pte2_clear(CMAP3); tlb_flush((vm_offset_t)CADDR3); @@ -5692,9 +5693,9 @@ pmap_copy_page(vm_page_t src, vm_page_t dst) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(src), - PTE2_AP_KR | PTE2_NM, page_tex2(src))); + PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(src))); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst), - PTE2_AP_KRW, page_tex2(dst))); + PTE2_AP_KRW, vm_page_pte2_attr(dst))); bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); pte2_clear(sysmaps->CMAP1); tlb_flush((vm_offset_t)sysmaps->CADDR1); @@ -5731,10 +5732,10 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], b_pg_offset = b_offset & PAGE_MASK; cnt = min(cnt, PAGE_SIZE - b_pg_offset); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg), - PTE2_AP_KR | PTE2_NM, page_tex2(a_pg))); + PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(a_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR1); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(b_pg), - PTE2_AP_KRW, page_tex2(b_pg))); + PTE2_AP_KRW, vm_page_pte2_attr(b_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR2); a_cp = sysmaps->CADDR1 + a_pg_offset; b_cp = sysmaps->CADDR2 + b_pg_offset; @@ -5764,7 +5765,7 @@ pmap_quick_enter_page(vm_page_t m) KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__)); pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); return (qmap_addr); } @@ -6032,7 +6033,7 @@ pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa) ("%s: device mapping not page-sized", __func__)); sva = va; - l2attr = memattr_to_tex2(VM_MEMATTR_DEVICE); + l2attr = vm_memattr_to_pte2(VM_MEMATTR_DEVICE); while (size != 0) { pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, l2attr); va += PAGE_SIZE; @@ -6108,7 +6109,7 @@ cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, page_tex2(m)); + pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m)); } /* * I-cache is VIPT. Only way how to flush all virtual mappings @@ -6136,7 +6137,7 @@ pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, page_tex2(m)); + pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m)); } } /* @@ -6333,7 +6334,7 @@ pmap_zero_page_check(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - page_tex2(m))); + vm_page_pte2_attr(m))); end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE); for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++) if (*p != 0) From fd38ead294ac15adc73d80d72d44517a82502ac2 Mon Sep 17 00:00:00 2001 From: mmel Date: Fri, 5 Feb 2016 14:57:41 +0000 Subject: [PATCH 218/236] ARM: Use new ARMv6 naming conventions for cache and TLB functions in all but ARMv4 specific files. Expand ARMv6 compatibility stubs in cpu-v4.h. Use physical address in L2 cache functions if ARM_L2_PIPT is defined. --- sys/arm/allwinner/a20/a20_mp.c | 4 +-- sys/arm/altera/socfpga/socfpga_mp.c | 4 +-- sys/arm/amlogic/aml8726/aml8726_mp.c | 3 +- sys/arm/arm/db_interface.c | 10 +++--- sys/arm/arm/dump_machdep.c | 3 +- sys/arm/arm/fiq.c | 2 +- sys/arm/arm/machdep.c | 9 ++--- sys/arm/arm/minidump_machdep.c | 7 ++-- sys/arm/arm/mp_machdep.c | 8 ++--- sys/arm/arm/sys_machdep.c | 7 +++- sys/arm/broadcom/bcm2835/bcm2836_mp.c | 4 +-- sys/arm/freescale/imx/imx6_mp.c | 3 +- sys/arm/include/cpu-v4.h | 34 ++++++++++++++++++- sys/arm/include/cpu-v6.h | 3 +- sys/arm/include/cpufunc.h | 6 ++++ sys/arm/include/kdb.h | 6 ++-- sys/arm/mv/armada38x/pmsu.c | 5 +-- sys/arm/mv/armadaxp/armadaxp_mp.c | 3 +- sys/arm/rockchip/rk30xx_mp.c | 4 +-- sys/arm/samsung/exynos/exynos5_mp.c | 4 +-- sys/arm/ti/omap4/omap4_mp.c | 5 +-- sys/arm/xilinx/zy7_mp.c | 4 +-- .../interface/vchiq_arm/vchiq_2835_arm.c | 5 ++- 23 files changed, 92 insertions(+), 51 deletions(-) diff --git a/sys/arm/allwinner/a20/a20_mp.c b/sys/arm/allwinner/a20/a20_mp.c index 27cbb3d32280..ba9ce9af0b35 100644 --- a/sys/arm/allwinner/a20/a20_mp.c +++ b/sys/arm/allwinner/a20/a20_mp.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -101,8 +102,7 @@ platform_mp_start_ap(void) &cpucfg) != 0) panic("Couldn't map the CPUCFG\n"); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, pmap_kextract((vm_offset_t)mpentry)); diff --git a/sys/arm/altera/socfpga/socfpga_mp.c b/sys/arm/altera/socfpga/socfpga_mp.c index 46977f6f4804..e057eb3d706a 100644 --- a/sys/arm/altera/socfpga/socfpga_mp.c +++ b/sys/arm/altera/socfpga/socfpga_mp.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -162,8 +163,7 @@ platform_mp_start_ap(void) bus_space_write_region_4(fdtbus_bs_tag, ram, 0, (uint32_t *)&socfpga_trampoline, 8); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Put CPU1 out from reset */ bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0); diff --git a/sys/arm/amlogic/aml8726/aml8726_mp.c b/sys/arm/amlogic/aml8726/aml8726_mp.c index 779a793e3008..c5081350df09 100644 --- a/sys/arm/amlogic/aml8726/aml8726_mp.c +++ b/sys/arm/amlogic/aml8726/aml8726_mp.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -485,7 +486,7 @@ platform_mp_start_ap(void) value |= AML_SCU_CONTROL_ENABLE; SCU_WRITE_4(AML_SCU_CONTROL_REG, value); SCU_BARRIER(AML_SCU_CONTROL_REG); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Set the boot address and power on each AP. */ paddr = pmap_kextract((vm_offset_t)mpentry); diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c index 613dc08149cc..bc49dc6e49c0 100644 --- a/sys/arm/arm/db_interface.c +++ b/sys/arm/arm/db_interface.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include +#include #include #include #include /* just for boothowto */ @@ -53,9 +54,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include -#include #include #include @@ -63,7 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include + static int nil = 0; @@ -245,11 +246,10 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) } /* make sure the caches and memory are in sync */ - cpu_icache_sync_range(addr, size); + icache_sync(addr, size); /* In case the current page tables have been modified ... */ - cpu_tlb_flushID(); - cpu_cpwait(); + tlb_flush_all(); return (0); } diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c index e87d3e7c835d..2c11141c4b0e 100644 --- a/sys/arm/arm/dump_machdep.c +++ b/sys/arm/arm/dump_machdep.c @@ -59,8 +59,7 @@ dumpsys_wbinv_all(void) * have already been stopped, and their flush/invalidate was done as * part of stopping. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); #ifdef __XSCALE__ xscale_cache_clean_minidata(); #endif diff --git a/sys/arm/arm/fiq.c b/sys/arm/arm/fiq.c index 94231dea22c8..f475a303d3c4 100644 --- a/sys/arm/arm/fiq.c +++ b/sys/arm/arm/fiq.c @@ -81,8 +81,8 @@ fiq_installhandler(void *func, size_t size) #if !defined(__ARM_FIQ_INDIRECT) vector_page_setprot(VM_PROT_READ); - cpu_icache_sync_range((vm_offset_t) fiqvector, size); #endif + icache_sync((vm_offset_t) fiqvector, size); } /* diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 26109d4aa521..4e7cb70c84bb 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -396,7 +396,7 @@ arm_vector_init(vm_offset_t va, int which) } /* Now sync the vectors. */ - cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); + icache_sync(va, (ARM_NVEC * 2) * sizeof(u_int)); vector_page = va; @@ -478,12 +478,7 @@ void cpu_flush_dcache(void *ptr, size_t len) { - cpu_dcache_wb_range((uintptr_t)ptr, len); -#ifdef ARM_L2_PIPT - cpu_l2cache_wb_range((uintptr_t)vtophys(ptr), len); -#else - cpu_l2cache_wb_range((uintptr_t)ptr, len); -#endif + dcache_wb_poc((vm_offset_t)ptr, (vm_paddr_t)vtophys(ptr), len); } /* Get current clock frequency for the given cpu id. */ diff --git a/sys/arm/arm/minidump_machdep.c b/sys/arm/arm/minidump_machdep.c index a351fb76095c..2eb4bfd01f86 100644 --- a/sys/arm/arm/minidump_machdep.c +++ b/sys/arm/arm/minidump_machdep.c @@ -45,11 +45,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include -#include #include -#include +#include CTASSERT(sizeof(struct kerneldumpheader) == 512); @@ -203,8 +203,7 @@ minidumpsys(struct dumperinfo *di) * by time we get to here, all that remains is to flush the L1 for the * current CPU, then the L2. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); counter = 0; /* Walk page table pages, set bits in vm_page_dump */ diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 6cedd46e2bb5..8643860792d5 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -123,9 +123,7 @@ cpu_mp_start(void) dpcpu[i] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Initialize boot code and start up processors */ platform_mp_start_ap(); @@ -283,7 +281,7 @@ ipi_stop(void *dummy __unused) * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); @@ -381,7 +379,7 @@ ipi_handler(void *arg) * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c index cad26ec42974..b893a9028561 100644 --- a/sys/arm/arm/sys_machdep.c +++ b/sys/arm/arm/sys_machdep.c @@ -153,8 +153,13 @@ arm32_drain_writebuf(struct thread *td, void *args) { /* No args. */ - td->td_retval[0] = 0; +#if __ARM_ARCH < 6 cpu_drain_writebuf(); +#else + dsb(); + cpu_l2cache_drain_writebuf(); +#endif + td->td_retval[0] = 0; return (0); } diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c index 93cc0d862d86..d6c84cbd1244 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c +++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -123,8 +124,7 @@ platform_mp_start_ap(void) BSWR4(MBOX3CLR_CORE(i), 0xffffffff); } wmb(); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* boot secondary CPUs */ for (i = 1; i < mp_ncpus; i++) { diff --git a/sys/arm/freescale/imx/imx6_mp.c b/sys/arm/freescale/imx/imx6_mp.c index 3208f676e6ff..7aa9aab708d1 100644 --- a/sys/arm/freescale/imx/imx6_mp.c +++ b/sys/arm/freescale/imx/imx6_mp.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -149,7 +150,7 @@ platform_mp_start_ap(void) val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, val | SCU_CONTROL_ENABLE); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* * For each AP core, set the entry point address and argument registers, diff --git a/sys/arm/include/cpu-v4.h b/sys/arm/include/cpu-v4.h index 503ed56a698a..0d66dee42bc3 100644 --- a/sys/arm/include/cpu-v4.h +++ b/sys/arm/include/cpu-v4.h @@ -41,7 +41,7 @@ #include #if __ARM_ARCH >= 6 -#error Newer include this file for ARMv6 +#error Never include this file for ARMv6 #else #define CPU_ASID_KERNEL 0 @@ -124,12 +124,29 @@ _RF0(cp15_tlbtr_get, CP15_TLBTR(%0)) * armv5 asm code handles that. */ +static __inline void +tlb_flush_all(void) +{ + cpu_tlb_flushID(); + cpu_cpwait(); +} + +static __inline void +icache_sync(vm_offset_t va, vm_size_t size) +{ + cpu_icache_sync_range(va, size); +} + static __inline void dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) { cpu_dcache_inv_range(va, size); +#ifdef ARM_L2_PIPT + cpu_l2cache_inv_range(pa, size); +#else cpu_l2cache_inv_range(va, size); +#endif } static __inline void @@ -137,7 +154,11 @@ dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size) { /* See armv6 code, above, for why we do L2 before L1 in this case. */ +#ifdef ARM_L2_PIPT + cpu_l2cache_inv_range(pa, size); +#else cpu_l2cache_inv_range(va, size); +#endif cpu_dcache_inv_range(va, size); } @@ -146,7 +167,18 @@ dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) { cpu_dcache_wb_range(va, size); +#ifdef ARM_L2_PIPT + cpu_l2cache_wb_range(pa, size); +#else cpu_l2cache_wb_range(va, size); +#endif +} + +static __inline void +dcache_wbinv_poc_all(void) +{ + cpu_idcache_wbinv_all(); + cpu_l2cache_wbinv_all(); } #endif /* _KERNEL */ diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index 40a7f400ba36..e537c10b4d4e 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -44,10 +44,9 @@ #error Only include this file for ARMv6 #else - - #define CPU_ASID_KERNEL 0 +void dcache_wbinv_poc_all(void); /* !!! NOT SMP coherent function !!! */ vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t); vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t); diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index afbcac834f13..eb445b49abcf 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -161,9 +161,12 @@ struct cpu_functions { extern struct cpu_functions cpufuncs; extern u_int cputype; +#if __ARM_ARCH < 6 #define cpu_cpwait() cpufuncs.cf_cpwait() +#endif #define cpu_control(c, e) cpufuncs.cf_control(c, e) +#if __ARM_ARCH < 6 #define cpu_setttb(t) cpufuncs.cf_setttb(t) #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() @@ -181,13 +184,16 @@ extern u_int cputype; #define cpu_idcache_inv_all() cpufuncs.cf_idcache_inv_all() #define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all() #define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s)) +#endif #define cpu_l2cache_wbinv_all() cpufuncs.cf_l2cache_wbinv_all() #define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s)) #define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s)) #define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s)) #define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf() +#if __ARM_ARCH < 6 #define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() +#endif #define cpu_sleep(m) cpufuncs.cf_sleep(m) #define cpu_setup() cpufuncs.cf_setup() diff --git a/sys/arm/include/kdb.h b/sys/arm/include/kdb.h index fb50c78ef94e..c7968ab6e8b2 100644 --- a/sys/arm/include/kdb.h +++ b/sys/arm/include/kdb.h @@ -29,10 +29,10 @@ #ifndef _MACHINE_KDB_H_ #define _MACHINE_KDB_H_ +#include +#include #include #include -#include -#include #define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] @@ -56,7 +56,7 @@ static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { - cpu_icache_sync_range((vm_offset_t)addr, size); + icache_sync((vm_offset_t)addr, size); } static __inline void diff --git a/sys/arm/mv/armada38x/pmsu.c b/sys/arm/mv/armada38x/pmsu.c index a84ede02a4a3..110278b4f181 100644 --- a/sys/arm/mv/armada38x/pmsu.c +++ b/sys/arm/mv/armada38x/pmsu.c @@ -36,10 +36,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include @@ -143,8 +145,7 @@ pmsu_boot_secondary_cpu(void) bus_space_write_4(fdtbus_bs_tag, vaddr, PMSU_BOOT_ADDR_REDIRECT_OFFSET(1), pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, vaddr, MV_PMSU_REGS_LEN); diff --git a/sys/arm/mv/armadaxp/armadaxp_mp.c b/sys/arm/mv/armadaxp/armadaxp_mp.c index 4ccf7e3ef360..52f35084a4bd 100644 --- a/sys/arm/mv/armadaxp/armadaxp_mp.c +++ b/sys/arm/mv/armadaxp/armadaxp_mp.c @@ -40,6 +40,7 @@ #include +#include #include #include #include @@ -174,7 +175,7 @@ platform_mp_start_ap(void) bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT, pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0); diff --git a/sys/arm/rockchip/rk30xx_mp.c b/sys/arm/rockchip/rk30xx_mp.c index 38b6b41e13c7..5de2eff14757 100644 --- a/sys/arm/rockchip/rk30xx_mp.c +++ b/sys/arm/rockchip/rk30xx_mp.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -171,8 +172,7 @@ platform_mp_start_ap(void) bus_space_write_region_4(fdtbus_bs_tag, imem, 0, (uint32_t *)&rk30xx_boot2, 8); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Start all cores */ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); diff --git a/sys/arm/samsung/exynos/exynos5_mp.c b/sys/arm/samsung/exynos/exynos5_mp.c index 8eb0d29fcedd..44b2844ce254 100644 --- a/sys/arm/samsung/exynos/exynos5_mp.c +++ b/sys/arm/samsung/exynos/exynos5_mp.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -135,8 +136,7 @@ platform_mp_start_ap(void) bus_space_write_4(fdtbus_bs_tag, sysram, 0x0, pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, sysram, 0x100); diff --git a/sys/arm/ti/omap4/omap4_mp.c b/sys/arm/ti/omap4/omap4_mp.c index 1a095ab6444c..6cea1cc697d2 100644 --- a/sys/arm/ti/omap4/omap4_mp.c +++ b/sys/arm/ti/omap4/omap4_mp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -72,8 +73,8 @@ platform_mp_start_ap(void) /* Enable the SCU */ *(volatile unsigned int *)scu_addr |= 1; //*(volatile unsigned int *)(scu_addr + 0x30) |= 1; - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); + ti_smc0(0x200, 0xfffffdff, MODIFY_AUX_CORE_0); ti_smc0(pmap_kextract((vm_offset_t)mpentry), 0, WRITE_AUX_CORE_1); armv7_sev(); diff --git a/sys/arm/xilinx/zy7_mp.c b/sys/arm/xilinx/zy7_mp.c index f71740ce395c..74528ef870b2 100644 --- a/sys/arm/xilinx/zy7_mp.c +++ b/sys/arm/xilinx/zy7_mp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -104,8 +105,7 @@ platform_mp_start_ap(void) * magic location, 0xfffffff0, isn't in the SCU's filtering range so it * needs a write-back too. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Wake up CPU1. */ armv7_sev(); diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c index 753e8e510631..e325f6ed777a 100644 --- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c +++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -411,6 +412,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, int run, addridx, actual_pages; int err; vm_paddr_t pagelist_phys; + vm_paddr_t pa; offset = (vm_offset_t)buf & (PAGE_SIZE - 1); num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; @@ -533,7 +535,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, (fragments - g_fragments_base)/g_fragment_size; } - cpu_dcache_wbinv_range((vm_offset_t)buf, count); + pa = pmap_extract(PCPU_GET(curpmap), (vm_offset_t)buf); + dcache_wbinv_poc((vm_offset_t)buf, pa, count); bus_dmamap_sync(bi->pagelist_dma_tag, bi->pagelist_dma_map, BUS_DMASYNC_PREWRITE); From 277002da84c3e33d12853e5396d1cddb7389b400 Mon Sep 17 00:00:00 2001 From: smh Date: Fri, 5 Feb 2016 15:35:33 +0000 Subject: [PATCH 219/236] Fix EFI multi device boot support Fix EFI boot support when presented with multiple valid boot partitions across multiple devices. It now prefers to boot from partitions that are present on the underlying device that the boot1 image was loaded from. This means that it will boot from the partitions on device the user chose from EFI boot menu in preference to those on other devices. Also fixed is the recovery from a failed attempt to boot, from a seemingly valid partition, by continuing to trying all other available partitions no matter what the error. boot1 now use * to signify a partition what was accepted from the preferred device and + otherwise. Finally some error messages where improved and DPRINTF's with slowed boot to aid debugging. ZFS will still be preferred over UFS when both are available on the boot device. Reviewed by: imp MFC after: 1 week Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D5108 --- sys/boot/efi/boot1/boot1.c | 560 ++++++++++++++++++++++++------- sys/boot/efi/boot1/boot_module.h | 13 +- sys/boot/efi/boot1/ufs_module.c | 55 ++- sys/boot/efi/boot1/zfs_module.c | 59 ++-- sys/boot/efi/include/efidevp.h | 13 +- 5 files changed, 518 insertions(+), 182 deletions(-) diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index c326c79d77ad..1161b0a1e58a 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -50,9 +50,6 @@ static const boot_module_t *boot_modules[] = void putchar(int c); EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); -static void try_load(const boot_module_t* mod); -static EFI_STATUS probe_handle(EFI_HANDLE h); - EFI_SYSTEM_TABLE *systab; EFI_BOOT_SERVICES *bs; static EFI_HANDLE *image; @@ -85,20 +82,300 @@ Free(void *buf, const char *file __unused, int line __unused) } /* - * This function only returns if it fails to load the kernel. If it - * succeeds, it simply boots the kernel. + * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match, + * FALSE otherwise. */ -void -try_load(const boot_module_t *mod) +static BOOLEAN +nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) { - size_t bufsize, cmdsize; - void *buf; + int len; + + if (imgpath == NULL || imgpath->Type != devpath->Type || + imgpath->SubType != devpath->SubType) + return (FALSE); + + len = DevicePathNodeLength(imgpath); + if (len != DevicePathNodeLength(devpath)) + return (FALSE); + + return (memcmp(imgpath, devpath, (size_t)len) == 0); +} + +/* + * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes + * in imgpath and devpath match up to their respect occurances of a media + * node, FALSE otherwise. + */ +static BOOLEAN +device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + + if (imgpath == NULL) + return (FALSE); + + while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) { + if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) && + IsDevicePathType(devpath, MEDIA_DEVICE_PATH)) + return (TRUE); + + if (!nodes_match(imgpath, devpath)) + return (FALSE); + + imgpath = NextDevicePathNode(imgpath); + devpath = NextDevicePathNode(devpath); + } + + return (FALSE); +} + +/* + * devpath_last returns the last non-path end node in devpath. + */ +static EFI_DEVICE_PATH * +devpath_last(EFI_DEVICE_PATH *devpath) +{ + + while (!IsDevicePathEnd(NextDevicePathNode(devpath))) + devpath = NextDevicePathNode(devpath); + + return (devpath); +} + +/* + * devpath_node_str is a basic output method for a devpath node which + * only understands a subset of the available sub types. + * + * If we switch to UEFI 2.x then we should update it to use: + * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. + */ +static int +devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + + switch (devpath->Type) { + case MESSAGING_DEVICE_PATH: + switch (devpath->SubType) { + case MSG_ATAPI_DP: { + ATAPI_DEVICE_PATH *atapi; + + atapi = (ATAPI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "ata(%s,%s,0x%x)", + (atapi->PrimarySecondary == 1) ? "Sec" : "Pri", + (atapi->SlaveMaster == 1) ? "Slave" : "Master", + atapi->Lun); + } + case MSG_USB_DP: { + USB_DEVICE_PATH *usb; + + usb = (USB_DEVICE_PATH *)devpath; + return snprintf(buf, size, "usb(0x%02x,0x%02x)", + usb->ParentPortNumber, usb->InterfaceNumber); + } + case MSG_SCSI_DP: { + SCSI_DEVICE_PATH *scsi; + + scsi = (SCSI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "scsi(0x%02x,0x%02x)", + scsi->Pun, scsi->Lun); + } + case MSG_SATA_DP: { + SATA_DEVICE_PATH *sata; + + sata = (SATA_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)", + sata->HBAPortNumber, sata->PortMultiplierPortNumber, + sata->Lun); + } + default: + return snprintf(buf, size, "msg(0x%02x)", + devpath->SubType); + } + break; + case HARDWARE_DEVICE_PATH: + switch (devpath->SubType) { + case HW_PCI_DP: { + PCI_DEVICE_PATH *pci; + + pci = (PCI_DEVICE_PATH *)devpath; + return snprintf(buf, size, "pci(0x%02x,0x%02x)", + pci->Device, pci->Function); + } + default: + return snprintf(buf, size, "hw(0x%02x)", + devpath->SubType); + } + break; + case ACPI_DEVICE_PATH: { + ACPI_HID_DEVICE_PATH *acpi; + + acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath; + if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM(acpi->HID)) { + case 0x0a03: + return snprintf(buf, size, "pciroot(0x%x)", + acpi->UID); + case 0x0a08: + return snprintf(buf, size, "pcieroot(0x%x)", + acpi->UID); + case 0x0604: + return snprintf(buf, size, "floppy(0x%x)", + acpi->UID); + case 0x0301: + return snprintf(buf, size, "keyboard(0x%x)", + acpi->UID); + case 0x0501: + return snprintf(buf, size, "serial(0x%x)", + acpi->UID); + case 0x0401: + return snprintf(buf, size, "parallelport(0x%x)", + acpi->UID); + default: + return snprintf(buf, size, "acpi(pnp%04x,0x%x)", + EISA_ID_TO_NUM(acpi->HID), acpi->UID); + } + } + + return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID, + acpi->UID); + } + case MEDIA_DEVICE_PATH: + switch (devpath->SubType) { + case MEDIA_CDROM_DP: { + CDROM_DEVICE_PATH *cdrom; + + cdrom = (CDROM_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "cdrom(%x)", + cdrom->BootEntry); + } + case MEDIA_HARDDRIVE_DP: { + HARDDRIVE_DEVICE_PATH *hd; + + hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "hd(%x)", + hd->PartitionNumber); + } + default: + return snprintf(buf, size, "media(0x%02x)", + devpath->SubType); + } + case BBS_DEVICE_PATH: + return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType); + case END_DEVICE_PATH_TYPE: + return (0); + } + + return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type, + devpath->SubType); +} + +/* + * devpath_strlcat appends a text description of devpath to buf but not more + * than size - 1 characters followed by NUL-terminator. + */ +int +devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + size_t len, used; + const char *sep; + + sep = ""; + used = 0; + while (!IsDevicePathEnd(devpath)) { + len = snprintf(buf, size - used, "%s", sep); + used += len; + if (used > size) + return (used); + buf += len; + + len = devpath_node_str(buf, size - used, devpath); + used += len; + if (used > size) + return (used); + buf += len; + devpath = NextDevicePathNode(devpath); + sep = ":"; + } + + return (used); +} + +/* + * devpath_str is convenience method which returns the text description of + * devpath using a static buffer, so it isn't thread safe! + */ +char * +devpath_str(EFI_DEVICE_PATH *devpath) +{ + static char buf[256]; + + devpath_strlcat(buf, sizeof(buf), devpath); + + return buf; +} + +/* + * load_loader attempts to load the loader image data. + * + * It tries each module and its respective devices, identified by mod->probe, + * in order until a successful load occurs at which point it returns EFI_SUCCESS + * and EFI_NOT_FOUND otherwise. + * + * Only devices which have preferred matching the preferred parameter are tried. + */ +static EFI_STATUS +load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, + size_t *bufsize, BOOLEAN preferred) +{ + UINTN i; + dev_info_t *dev; + const boot_module_t *mod; + + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + mod = boot_modules[i]; + for (dev = mod->devices(); dev != NULL; dev = dev->next) { + if (dev->preferred != preferred) + continue; + + if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == + EFI_SUCCESS) { + *devinfop = dev; + *modp = mod; + return (EFI_SUCCESS); + } + } + } + + return (EFI_NOT_FOUND); +} + +/* + * try_boot only returns if it fails to load the loader. If it succeeds + * it simply boots, otherwise it returns the status of last EFI call. + */ +static EFI_STATUS +try_boot() +{ + size_t bufsize, loadersize, cmdsize; + void *buf, *loaderbuf; char *cmd; dev_info_t *dev; + const boot_module_t *mod; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); + if (status != EFI_SUCCESS) { + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, + FALSE); + if (status != EFI_SUCCESS) { + printf("Failed to load '%s'\n", PATH_LOADER_EFI); + return (status); + } + } + /* * Read in and parse the command line from /boot.config or /boot/config, * if present. We'll pass it the next stage via a simple ASCII @@ -111,67 +388,183 @@ try_load(const boot_module_t *mod) */ cmd = NULL; cmdsize = 0; - status = mod->load(PATH_DOTCONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize); if (status == EFI_NOT_FOUND) - status = mod->load(PATH_CONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_CONFIG, dev, &buf, &bufsize); if (status == EFI_SUCCESS) { cmdsize = bufsize + 1; cmd = malloc(cmdsize); - if (cmd == NULL) { - free(buf); - return; - } + if (cmd == NULL) + goto errout; memcpy(cmd, buf, bufsize); cmd[bufsize] = '\0'; free(buf); + buf = NULL; } - status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize); - if (status == EFI_NOT_FOUND) - return; - - if (status != EFI_SUCCESS) { - printf("%s failed to load %s (%lu)\n", mod->name, - PATH_LOADER_EFI, EFI_ERROR_CODE(status)); - return; - } - - if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize, - &loaderhandle)) != EFI_SUCCESS) { + if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath), + loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) { printf("Failed to load image provided by %s, size: %zu, (%lu)\n", mod->name, bufsize, EFI_ERROR_CODE(status)); - return; + goto errout; } - if (cmd != NULL) - printf(" command args: %s\n", cmd); - if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image)) != EFI_SUCCESS) { printf("Failed to query LoadedImage provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - return; + goto errout; } + if (cmd != NULL) + printf(" command args: %s\n", cmd); + loaded_image->DeviceHandle = dev->devhandle; loaded_image->LoadOptionsSize = cmdsize; loaded_image->LoadOptions = cmd; + DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF(".\n"); + if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != EFI_SUCCESS) { printf("Failed to start image provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - free(cmd); loaded_image->LoadOptionsSize = 0; loaded_image->LoadOptions = NULL; - return; } + +errout: + if (cmd != NULL) + free(cmd); + if (buf != NULL) + free(buf); + if (loaderbuf != NULL) + free(loaderbuf); + + return (status); +} + +/* + * probe_handle determines if the passed handle represents a logical partition + * if it does it uses each module in order to probe it and if successful it + * returns EFI_SUCCESS. + */ +static EFI_STATUS +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred) +{ + dev_info_t *devinfo; + EFI_BLOCK_IO *blkio; + EFI_DEVICE_PATH *devpath; + EFI_STATUS status; + UINTN i; + + /* Figure out if we're dealing with an actual partition. */ + status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + DPRINTF("probing: %s\n", devpath_str(devpath)); + + status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + if (!blkio->Media->LogicalPartition) + return (EFI_UNSUPPORTED); + + *preferred = device_paths_match(imgpath, devpath); + + /* Run through each module, see if it can load this partition */ + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + + if ((status = bs->AllocatePool(EfiLoaderData, + sizeof(*devinfo), (void **)&devinfo)) != + EFI_SUCCESS) { + DPRINTF("\nFailed to allocate devinfo (%lu)\n", + EFI_ERROR_CODE(status)); + continue; + } + devinfo->dev = blkio; + devinfo->devpath = devpath; + devinfo->devhandle = h; + devinfo->devdata = NULL; + devinfo->preferred = *preferred; + devinfo->next = NULL; + + status = boot_modules[i]->probe(devinfo); + if (status == EFI_SUCCESS) + return (EFI_SUCCESS); + (void)bs->FreePool(devinfo); + } + + return (EFI_UNSUPPORTED); +} + +/* + * probe_handle_status calls probe_handle and outputs the returned status + * of the call. + */ +static void +probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) +{ + EFI_STATUS status; + BOOLEAN preferred; + + status = probe_handle(h, imgpath, &preferred); + + DPRINTF("probe: "); + switch (status) { + case EFI_UNSUPPORTED: + printf("."); + DPRINTF(" not supported\n"); + break; + case EFI_SUCCESS: + if (preferred) { + printf("%c", '*'); + DPRINTF(" supported (preferred)\n"); + } else { + printf("%c", '+'); + DPRINTF(" supported\n"); + } + break; + default: + printf("x"); + DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); + break; + } + DSTALL(500000); } EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) { EFI_HANDLE *handles; + EFI_LOADED_IMAGE *img; + EFI_DEVICE_PATH *imgpath; EFI_STATUS status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; @@ -254,20 +647,22 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) /* Scan all partitions, probing with all modules. */ nhandles = hsize / sizeof(*handles); printf(" Probing %zu block devices...", nhandles); - for (i = 0; i < nhandles; i++) { - status = probe_handle(handles[i]); - switch (status) { - case EFI_UNSUPPORTED: - printf("."); - break; - case EFI_SUCCESS: - printf("+"); - break; - default: - printf("x"); - break; - } + DPRINTF("\n"); + + /* Determine the devpath of our image so we can prefer it. */ + status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); + imgpath = NULL; + if (status == EFI_SUCCESS) { + status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, + (void **)&imgpath); + if (status != EFI_SUCCESS) + DPRINTF("Failed to get image DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath)); } + + for (i = 0; i < nhandles; i++) + probe_handle_status(handles[i], imgpath); printf(" done\n"); /* Status summary. */ @@ -278,78 +673,15 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) } } - /* Select a partition to boot by trying each module in order. */ - for (i = 0; i < NUM_BOOT_MODULES; i++) - if (boot_modules[i] != NULL) - try_load(boot_modules[i]); + try_boot(); /* If we get here, we're out of luck... */ panic("No bootable partitions found!"); } -static EFI_STATUS -probe_handle(EFI_HANDLE h) -{ - dev_info_t *devinfo; - EFI_BLOCK_IO *blkio; - EFI_DEVICE_PATH *devpath; - EFI_STATUS status; - UINTN i; - - /* Figure out if we're dealing with an actual partition. */ - status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query DevicePath (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - while (!IsDevicePathEnd(NextDevicePathNode(devpath))) - devpath = NextDevicePathNode(devpath); - - status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - if (!blkio->Media->LogicalPartition) - return (EFI_UNSUPPORTED); - - /* Run through each module, see if it can load this partition */ - for (i = 0; i < NUM_BOOT_MODULES; i++) { - if (boot_modules[i] == NULL) - continue; - - if ((status = bs->AllocatePool(EfiLoaderData, - sizeof(*devinfo), (void **)&devinfo)) != - EFI_SUCCESS) { - DPRINTF("\nFailed to allocate devinfo (%lu)\n", - EFI_ERROR_CODE(status)); - continue; - } - devinfo->dev = blkio; - devinfo->devpath = devpath; - devinfo->devhandle = h; - devinfo->devdata = NULL; - devinfo->next = NULL; - - status = boot_modules[i]->probe(devinfo); - if (status == EFI_SUCCESS) - return (EFI_SUCCESS); - (void)bs->FreePool(devinfo); - } - - return (EFI_UNSUPPORTED); -} - +/* + * add_device adds a device to the passed devinfo list. + */ void add_device(dev_info_t **devinfop, dev_info_t *devinfo) { diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h index 2c158f6dd821..296d5a67a10b 100644 --- a/sys/boot/efi/boot1/boot_module.h +++ b/sys/boot/efi/boot1/boot_module.h @@ -36,9 +36,11 @@ #include #ifdef EFI_DEBUG -#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#define DPRINTF(fmt, args...) printf(fmt, ##args) +#define DSTALL(d) bs->Stall(d) #else #define DPRINTF(fmt, ...) {} +#define DSTALL(d) {} #endif /* EFI device info */ @@ -48,6 +50,7 @@ typedef struct dev_info EFI_DEVICE_PATH *devpath; EFI_HANDLE *devhandle; void *devdata; + BOOLEAN preferred; struct dev_info *next; } dev_info_t; @@ -75,19 +78,21 @@ typedef struct boot_module_t /* * load should select the best out of a set of devices that probe - * indicated were loadable and load it. + * indicated were loadable and load the specified file. * * Return codes: * EFI_SUCCESS = The module can handle the device. * EFI_NOT_FOUND = The module can not handle the device. * Other = The module encountered an error. */ - EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo, + EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo, void **buf, size_t *bufsize); /* status outputs information about the probed devices. */ void (*status)(); + /* valid devices as found by probe. */ + dev_info_t *(*devices)(); } boot_module_t; /* Standard boot modules. */ @@ -107,4 +112,6 @@ extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); extern EFI_SYSTEM_TABLE *systab; extern EFI_BOOT_SERVICES *bs; +extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath); +extern char *devpath_str(EFI_DEVICE_PATH *devpath); #endif diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c index 07c7152f342c..63087ea22fa7 100644 --- a/sys/boot/efi/boot1/ufs_module.c +++ b/sys/boot/efi/boot1/ufs_module.c @@ -93,7 +93,7 @@ probe(dev_info_t* dev) } static EFI_STATUS -try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) { ufs_ino_t ino; EFI_STATUS status; @@ -101,59 +101,46 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) ssize_t read; void *buf; - if (init_dev(dev) < 0) - return (EFI_UNSUPPORTED); + DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath)); - if ((ino = lookup(loader_path)) == 0) + if (init_dev(dev) < 0) { + DPRINTF("Failed to init device\n"); + return (EFI_UNSUPPORTED); + } + + if ((ino = lookup(filepath)) == 0) { + DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); return (EFI_NOT_FOUND); + } if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { - printf("Failed to read size of '%s' ino: %d\n", loader_path, - ino); + printf("Failed to read size of '%s' ino: %d\n", filepath, ino); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate read buffer (%lu)\n", - EFI_ERROR_CODE(status)); + printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", + size, filepath, EFI_ERROR_CODE(status)); return (status); } read = fsread(ino, buf, size); if ((size_t)read != size) { - printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read, + printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, size); (void)bs->FreePool(buf); return (EFI_INVALID_PARAMETER); } + DPRINTF("Load complete\n"); + *bufp = buf; *bufsize = size; return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **buf, - size_t *bufsize) -{ - dev_info_t *dev; - EFI_STATUS status; - - for (dev = devices; dev != NULL; dev = dev->next) { - status = try_load(dev, loader_path, buf, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = dev; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -176,10 +163,18 @@ status() } } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t ufs_module = { .name = "UFS", .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c index 96eec332f16a..4e2c5c4681c1 100644 --- a/sys/boot/efi/boot1/zfs_module.c +++ b/sys/boot/efi/boot1/zfs_module.c @@ -91,7 +91,7 @@ probe(dev_info_t *dev) } static EFI_STATUS -try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) { spa_t *spa; struct zfsmount zfsmount; @@ -102,32 +102,41 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs EFI_STATUS status; spa = devinfo->devdata; - if (zfs_spa_init(spa) != 0) { - /* Init failed, don't report this loudly. */ + + DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name, + devpath_str(devinfo->devpath)); + + if ((err = zfs_spa_init(spa)) != 0) { + DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if (zfs_mount(spa, 0, &zfsmount) != 0) { - /* Mount failed, don't report this loudly. */ + if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) { + DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) { + if (err == ENOENT) { + DPRINTF("Failed to find '%s' on pool '%s' (%d)\n", + filepath, spa->spa_name, err); + return (EFI_NOT_FOUND); + } + printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate load buffer for pool %s (%lu)\n", - spa->spa_name, EFI_ERROR_CODE(status)); + printf("Failed to allocate load buffer %zu for pool '%s' for '%s' " + "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status)); return (EFI_INVALID_PARAMETER); } @@ -144,26 +153,6 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **bufp, - size_t *bufsize) -{ - dev_info_t *devinfo; - EFI_STATUS status; - - for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) { - status = try_load(devinfo, loader_path, bufp, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = devinfo; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -189,11 +178,19 @@ init() zfs_init(); } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t zfs_module = { .name = "ZFS", .init = init, .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/include/efidevp.h b/sys/boot/efi/include/efidevp.h index f0f49efc3fff..dda79de7af13 100644 --- a/sys/boot/efi/include/efidevp.h +++ b/sys/boot/efi/include/efidevp.h @@ -40,9 +40,7 @@ typedef struct _EFI_DEVICE_PATH { #define EFI_DP_TYPE_MASK 0x7F #define EFI_DP_TYPE_UNPACKED 0x80 -//#define END_DEVICE_PATH_TYPE 0xff #define END_DEVICE_PATH_TYPE 0x7f -//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 @@ -56,8 +54,8 @@ typedef struct _EFI_DEVICE_PATH { #define DevicePathSubType(a) ( (a)->SubType ) #define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) #define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) -//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) -#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathType(a, t) ( DevicePathType(a) == t ) +#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE) #define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) #define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) #define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) @@ -285,6 +283,13 @@ typedef struct _UART_DEVICE_PATH { #define DEVICE_PATH_MESSAGING_VT_UTF8 \ { 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} } +#define MSG_SATA_DP 0x12 +typedef struct _SATA_DEVICE_PATH { + EFI_DEVICE_PATH Header; + UINT16 HBAPortNumber; + UINT16 PortMultiplierPortNumber; + UINT16 Lun; +} SATA_DEVICE_PATH; #define MEDIA_DEVICE_PATH 0x04 From a718ec05809255deb93481e75282825de5dc21b5 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 5 Feb 2016 15:38:28 +0000 Subject: [PATCH 220/236] Implement kdb_cpu_sync_icache on arm64. Sponsored by: ABT Systems Ltd --- sys/arm64/include/kdb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/arm64/include/kdb.h b/sys/arm64/include/kdb.h index e4f4f70a4a71..2f7306ef669b 100644 --- a/sys/arm64/include/kdb.h +++ b/sys/arm64/include/kdb.h @@ -43,6 +43,8 @@ void kdb_cpu_set_singlestep(void); static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { + + cpu_icache_sync_range((vm_offset_t)addr, size); } static __inline void From 9accef3f0f76cde9f02a5d55f391aa02355ddc2b Mon Sep 17 00:00:00 2001 From: erj Date: Fri, 5 Feb 2016 17:14:37 +0000 Subject: [PATCH 221/236] Update em(4) to 7.6.1; update igb(4) to 2.5.3. Major changes: - Add i219/i219(2) hardware support. (Found on Skylake generation and newer chipsets.) - Further to the last Skylake support diff, this one also includes support for the Lewisburg chipset (i219(3)). - Add a workaround to an igb hardware errata. All 1G server products need to have IPv6 extension header parsing turned off. This should be listed in the specification updates for current 1G server products, e.g. for i350 it's errata #37 in this document: http://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ethernet-controller-i350-spec-update.pdf - Avoton (i354) PHY errata workaround added And a bunch of minor fixes, as well as #defines for things that the current em(4)/igb(4) drivers don't implement. Differential Revision: https://reviews.freebsd.org/D3162 Reviewed by: sbruno, marius, gnn Approved by: gnn MFC after: 2 weeks Sponsored by: Intel Corporation --- sys/dev/e1000/e1000_80003es2lan.c | 33 +- sys/dev/e1000/e1000_82540.c | 10 +- sys/dev/e1000/e1000_82541.c | 7 +- sys/dev/e1000/e1000_82542.c | 4 +- sys/dev/e1000/e1000_82543.c | 4 +- sys/dev/e1000/e1000_82571.h | 5 +- sys/dev/e1000/e1000_82575.c | 169 +++++- sys/dev/e1000/e1000_82575.h | 5 +- sys/dev/e1000/e1000_api.c | 8 + sys/dev/e1000/e1000_defines.h | 11 +- sys/dev/e1000/e1000_hw.h | 8 +- sys/dev/e1000/e1000_i210.c | 30 + sys/dev/e1000/e1000_ich8lan.c | 952 +++++++++++++++++++++++++++--- sys/dev/e1000/e1000_ich8lan.h | 30 +- sys/dev/e1000/e1000_mac.h | 2 - sys/dev/e1000/e1000_mbx.c | 36 +- sys/dev/e1000/e1000_nvm.h | 2 - sys/dev/e1000/e1000_osdep.h | 25 +- sys/dev/e1000/e1000_phy.c | 10 +- sys/dev/e1000/e1000_regs.h | 9 + sys/dev/e1000/if_em.c | 166 +++++- sys/dev/e1000/if_em.h | 3 + sys/dev/e1000/if_igb.c | 14 +- 23 files changed, 1348 insertions(+), 195 deletions(-) diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c index b948bb4e3198..e7c42d5386eb 100644 --- a/sys/dev/e1000/e1000_80003es2lan.c +++ b/sys/dev/e1000/e1000_80003es2lan.c @@ -851,11 +851,17 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) e1000_release_phy_80003es2lan(hw); /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + DEBUGOUT("Error disabling far-end loopback\n"); + } else + DEBUGOUT("Error disabling far-end loopback\n"); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) @@ -911,11 +917,18 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) return ret_val; /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + ret_val = + e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + &kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + DEBUGOUT("Error disabling far-end loopback\n"); + } else + DEBUGOUT("Error disabling far-end loopback\n"); /* Set the transmit descriptor write-back policy */ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c index 68f92c619afe..2d03b8ff8e3f 100644 --- a/sys/dev/e1000/e1000_82540.c +++ b/sys/dev/e1000/e1000_82540.c @@ -66,7 +66,7 @@ static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw); static s32 e1000_init_phy_params_82540(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; @@ -329,7 +329,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 txdctl, ctrl_ext; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_82540"); @@ -411,7 +411,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 data; DEBUGFUNC("e1000_setup_copper_link_82540"); @@ -498,7 +498,7 @@ static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw) **/ static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_adjust_serdes_amplitude_82540"); @@ -528,7 +528,7 @@ static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw) **/ static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 default_page = 0; u16 phy_data; diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c index 59615556fa32..55d51087b7b3 100644 --- a/sys/dev/e1000/e1000_82541.c +++ b/sys/dev/e1000/e1000_82541.c @@ -85,7 +85,7 @@ static const u16 e1000_igp_cable_length_table[] = { static s32 e1000_init_phy_params_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_init_phy_params_82541"); @@ -295,7 +295,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) { - u32 ledctl, ctrl, icr, manc; + u32 ledctl, ctrl, manc; DEBUGFUNC("e1000_reset_hw_82541"); @@ -317,6 +317,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) /* Must reset the Phy before resetting the MAC */ if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); + E1000_WRITE_FLUSH(hw); msec_delay(5); } @@ -359,7 +360,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); /* Clear any pending interrupt events. */ - icr = E1000_READ_REG(hw, E1000_ICR); + E1000_READ_REG(hw, E1000_ICR); return E1000_SUCCESS; } diff --git a/sys/dev/e1000/e1000_82542.c b/sys/dev/e1000/e1000_82542.c index b2d676eca8c5..4cca9b2b2c61 100644 --- a/sys/dev/e1000/e1000_82542.c +++ b/sys/dev/e1000/e1000_82542.c @@ -317,7 +317,7 @@ static s32 e1000_init_hw_82542(struct e1000_hw *hw) static s32 e1000_setup_link_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_setup_link_82542"); @@ -565,7 +565,7 @@ static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw) * * Reads the device MAC address from the EEPROM and stores the value. **/ -static s32 e1000_read_mac_addr_82542(struct e1000_hw *hw) +s32 e1000_read_mac_addr_82542(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 offset, nvm_data, i; diff --git a/sys/dev/e1000/e1000_82543.c b/sys/dev/e1000/e1000_82543.c index b9a53bd6081c..474387d2cb75 100644 --- a/sys/dev/e1000/e1000_82543.c +++ b/sys/dev/e1000/e1000_82543.c @@ -900,7 +900,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) { - u32 ctrl, icr; + u32 ctrl; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82543"); @@ -942,7 +942,7 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) /* Masking off and clearing any pending interrupts */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - icr = E1000_READ_REG(hw, E1000_ICR); + E1000_READ_REG(hw, E1000_ICR); return ret_val; } diff --git a/sys/dev/e1000/e1000_82571.h b/sys/dev/e1000/e1000_82571.h index 1d7718eda12c..8e5ca56ae88c 100644 --- a/sys/dev/e1000/e1000_82571.h +++ b/sys/dev/e1000/e1000_82571.h @@ -50,9 +50,10 @@ #define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAC_MASK_82574 0x01F00000 -#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ +#define E1000_IVAR_INT_ALLOC_VALID 0x8 -#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */ +/* Manageability Operation Mode mask */ +#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 #define E1000_BASE1000T_STATUS 10 #define E1000_IDLE_ERROR_COUNT_MASK 0xFF diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index 10653f8824c8..38770a327b16 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -278,6 +278,11 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) if (ret_val) goto out; } + if (phy->id == M88E1543_E_PHY_ID) { + ret_val = e1000_initialize_M88E1543_phy(hw); + if (ret_val) + goto out; + } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: @@ -1235,7 +1240,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) DEBUGFUNC("e1000_check_for_link_media_swap"); - /* Check the copper medium. */ + /* Check for copper. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; @@ -1247,7 +1252,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_COPPER; - /* Check the other medium. */ + /* Check for other. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); if (ret_val) return ret_val; @@ -1256,11 +1261,6 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (ret_val) return ret_val; - /* reset page to 0 */ - ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); - if (ret_val) - return ret_val; - if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_OTHER; @@ -1268,8 +1268,20 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (port && (hw->dev_spec._82575.media_port != port)) { hw->dev_spec._82575.media_port = port; hw->dev_spec._82575.media_changed = TRUE; + } + + if (port == E1000_MEDIA_PORT_COPPER) { + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + e1000_check_for_link_82575(hw); } else { - ret_val = e1000_check_for_link_82575(hw); + e1000_check_for_link_82575(hw); + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; } return E1000_SUCCESS; @@ -2136,7 +2148,13 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; - DEBUGFUNC("e1000_rx_fifo_workaround_82575"); + DEBUGFUNC("e1000_rx_fifo_flush_82575"); + + /* disable IPv6 options as per hardware errata */ + rfctl = E1000_READ_REG(hw, E1000_RFCTL); + rfctl |= E1000_RFCTL_IPV6_EX_DIS; + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); + if (hw->mac.type != e1000_82575 || !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; @@ -2164,7 +2182,6 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ - rfctl = E1000_READ_REG(hw, E1000_RFCTL); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = E1000_READ_REG(hw, E1000_RLPML); @@ -2806,7 +2823,7 @@ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY * @hw: pointer to the HW structure * - * Initialize Marverl 1512 to work correctly with Avoton. + * Initialize Marvell 1512 to work correctly with Avoton. **/ s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) { @@ -2891,14 +2908,115 @@ s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) return ret_val; } +/** + * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY + * @hw: pointer to the HW structure + * + * Initialize Marvell 1543 to work correctly with Avoton. + **/ +s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_initialize_M88E1543_phy"); + + /* Check if this is correct PHY. */ + if (phy->id != M88E1543_E_PHY_ID) + goto out; + + /* Switch to PHY page 0xFF. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); + if (ret_val) + goto out; + + /* Switch to PHY page 0xFB. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D); + if (ret_val) + goto out; + + /* Switch to PHY page 0x12. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); + if (ret_val) + goto out; + + /* Change mode to SGMII-to-Copper */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); + if (ret_val) + goto out; + + /* Switch to PHY page 1. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1); + if (ret_val) + goto out; + + /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140); + if (ret_val) + goto out; + + /* Return the PHY to page 0. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); + if (ret_val) + goto out; + + ret_val = phy->ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error committing the PHY changes\n"); + return ret_val; + } + + msec_delay(1000); +out: + return ret_val; +} + /** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i350(struct e1000_hw *hw) +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) { u32 ipcnfg, eeer; @@ -2914,7 +3032,16 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) if (!(hw->dev_spec._82575.eee_disable)) { u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); - ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); + if (adv100M) + ipcnfg |= E1000_IPCNFG_EEE_100M_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; + + if (adv1G) + ipcnfg |= E1000_IPCNFG_EEE_1G_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; + eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); @@ -2938,11 +3065,13 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) /** * e1000_set_eee_i354 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE legacy mode based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i354(struct e1000_hw *hw) +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; @@ -2984,8 +3113,16 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw) if (ret_val) goto out; - phy_data |= E1000_EEE_ADV_100_SUPPORTED | - E1000_EEE_ADV_1000_SUPPORTED; + if (adv100M) + phy_data |= E1000_EEE_ADV_100_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; + + if (adv1G) + phy_data |= E1000_EEE_ADV_1000_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; + ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index 503fdce305d6..45fe132e4a40 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -495,10 +495,11 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); -s32 e1000_set_eee_i350(struct e1000_hw *); -s32 e1000_set_eee_i354(struct e1000_hw *); +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M); +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M); s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *); s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw); +s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw); /* I2C SDA and SCL timing parameters for standard mode */ #define E1000_I2C_T_HD_STA 4 diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 5db22db16f0d..28379cc572d3 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -299,6 +299,13 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_I218_V3: mac->type = e1000_pch_lpt; break; + case E1000_DEV_ID_PCH_SPT_I219_LM: + case E1000_DEV_ID_PCH_SPT_I219_V: + case E1000_DEV_ID_PCH_SPT_I219_LM2: + case E1000_DEV_ID_PCH_SPT_I219_V2: + case E1000_DEV_ID_PCH_LBG_I219_LM3: + mac->type = e1000_pch_spt; + break; case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: @@ -449,6 +456,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: e1000_init_function_pointers_ich8lan(hw); break; case e1000_82575: diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index 9472ca4c4d4d..e33fe0fb7982 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -197,6 +197,8 @@ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ +#define E1000_RCTL_RDMTS_HEX 0x00010000 +#define E1000_RCTL_RDMTS1_HEX E1000_RCTL_RDMTS_HEX #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ @@ -753,6 +755,12 @@ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ +/* HH Time Sync */ +#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ +#define E1000_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ +#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */ +#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ + #define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 @@ -849,6 +857,7 @@ #define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ #define E1000_M88E1543_EEE_CTRL_1 0x0 #define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ +#define E1000_M88E1543_FIBER_CTRL 0x0 /* Fiber Control Register */ #define E1000_EEE_ADV_DEV_I354 7 #define E1000_EEE_ADV_ADDR_I354 60 #define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ @@ -1020,9 +1029,7 @@ /* NVM Addressing bits based on type 0=small, 1=large */ #define E1000_EECD_ADDR_BITS 0x00000400 #define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */ -#ifndef E1000_NVM_GRANT_ATTEMPTS #define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ -#endif #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ #define E1000_EECD_SIZE_EX_SHIFT 11 diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 8ae4b202fd1e..1792e14ef38a 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -137,6 +137,11 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_I218_V2 0x15A1 #define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ #define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */ #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -222,6 +227,7 @@ enum e1000_mac_type { e1000_pchlan, e1000_pch2lan, e1000_pch_lpt, + e1000_pch_spt, e1000_82575, e1000_82576, e1000_82580, @@ -805,7 +811,7 @@ struct e1000_mac_info { enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; - u32 max_frame_size; + u32 max_frame_size; }; struct e1000_phy_info { diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c index 563f11a1d27e..cd8d7c7e1f56 100644 --- a/sys/dev/e1000/e1000_i210.c +++ b/sys/dev/e1000/e1000_i210.c @@ -882,6 +882,35 @@ static s32 e1000_pll_workaround_i210(struct e1000_hw *hw) return ret_val; } +/** + * e1000_get_cfg_done_i210 - Read config done bit + * @hw: pointer to the HW structure + * + * Read the management control register for the config done bit for + * completion status. NOTE: silicon which is EEPROM-less will fail trying + * to read the config done bit, so an error is *ONLY* logged and returns + * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon + * would not be able to be reset or change link. + **/ +static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw) +{ + s32 timeout = PHY_CFG_TIMEOUT; + u32 mask = E1000_NVM_CFG_DONE_PORT_0; + + DEBUGFUNC("e1000_get_cfg_done_i210"); + + while (timeout) { + if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask) + break; + msec_delay(1); + timeout--; + } + if (!timeout) + DEBUGOUT("MNG configuration cycle has not completed.\n"); + + return E1000_SUCCESS; +} + /** * e1000_init_hw_i210 - Init hw for I210/I211 * @hw: pointer to the HW structure @@ -899,6 +928,7 @@ s32 e1000_init_hw_i210(struct e1000_hw *hw) if (ret_val != E1000_SUCCESS) return ret_val; } + hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210; ret_val = e1000_init_hw_82575(hw); return ret_val; } diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index 75fcade3703b..9b9a090422e9 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -92,10 +92,13 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active); static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data); static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); +static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw); static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data); static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); @@ -123,6 +126,14 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 *data); static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 *data); +static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data); +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 *data); +static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, + u32 offset, u32 data); +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword); static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, @@ -232,16 +243,21 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) if (ret_val) return FALSE; out: - if (hw->mac.type == e1000_pch_lpt) { - /* Unforce SMBus mode in PHY */ - hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { + /* Only unforce SMBus if ME is not active */ + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + /* Unforce SMBus mode in PHY */ + hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); + phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; + hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); - /* Unforce SMBus mode in MAC */ - mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + /* Unforce SMBus mode in MAC */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + } } return TRUE; @@ -328,6 +344,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) */ switch (hw->mac.type) { case e1000_pch_lpt: + case e1000_pch_spt: if (e1000_phy_is_accessible_pchlan(hw)) break; @@ -475,6 +492,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) /* fall-through */ case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ @@ -617,37 +635,58 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 gfpreg, sector_base_addr, sector_end_addr; u16 i; + u32 nvm_size; DEBUGFUNC("e1000_init_nvm_params_ich8lan"); - /* Can't read flash registers if the register set isn't mapped. */ nvm->type = e1000_nvm_flash_sw; - if (!hw->flash_address) { - DEBUGOUT("ERROR: Flash registers not mapped\n"); - return -E1000_ERR_CONFIG; + + if (hw->mac.type == e1000_pch_spt) { + /* in SPT, gfpreg doesn't exist. NVM size is taken from the + * STRAP register. This is because in SPT the GbE Flash region + * is no longer accessed through the flash registers. Instead, + * the mechanism has changed, and the Flash region access + * registers are now implemented in GbE memory space. + */ + nvm->flash_base_addr = 0; + nvm_size = + (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1) + * NVM_SIZE_MULTIPLIER; + nvm->flash_bank_size = nvm_size / 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); + /* Set the base address for flash register access */ + hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR; + } else { + /* Can't read flash registers if register set isn't mapped. */ + if (!hw->flash_address) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return -E1000_ERR_CONFIG; + } + + gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); + + /* sector_X_addr is a "sector"-aligned address (4096 bytes) + * Add 1 to sector_end_addr since this sector is included in + * the overall size. + */ + sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; + sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; + + /* flash_base_addr is byte-aligned */ + nvm->flash_base_addr = sector_base_addr + << FLASH_SECTOR_ADDR_SHIFT; + + /* find total size of the NVM, then cut in half since the total + * size represents two separate NVM banks. + */ + nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) + << FLASH_SECTOR_ADDR_SHIFT); + nvm->flash_bank_size /= 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); } - gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); - - /* sector_X_addr is a "sector"-aligned address (4096 bytes) - * Add 1 to sector_end_addr since this sector is included in - * the overall size. - */ - sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; - sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; - - /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; - - /* find total size of the NVM, then cut in half since the total - * size represents two separate NVM banks. - */ - nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) - << FLASH_SECTOR_ADDR_SHIFT); - nvm->flash_bank_size /= 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - nvm->word_size = E1000_SHADOW_RAM_WORDS; /* Clear shadow ram */ @@ -662,8 +701,13 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_ich8lan; nvm->ops.release = e1000_release_nvm_ich8lan; - nvm->ops.read = e1000_read_nvm_ich8lan; - nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + if (hw->mac.type == e1000_pch_spt) { + nvm->ops.read = e1000_read_nvm_spt; + nvm->ops.update = e1000_update_nvm_checksum_spt; + } else { + nvm->ops.read = e1000_read_nvm_ich8lan; + nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + } nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; nvm->ops.write = e1000_write_nvm_ich8lan; @@ -681,9 +725,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) - u16 pci_cfg; -#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ DEBUGFUNC("e1000_init_mac_params_ich8lan"); @@ -752,15 +793,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) mac->ops.rar_set = e1000_rar_set_pch2lan; /* fall-through */ case e1000_pch_lpt: + case e1000_pch_spt: /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; + /* fall-through */ case e1000_pchlan: -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) - /* save PCH revision_id */ - e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg); - hw->revision_id = (u8)(pci_cfg &= 0x000F); -#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; /* ID LED init */ @@ -777,7 +815,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) break; } - if (mac->type == e1000_pch_lpt) { + if ((mac->type == e1000_pch_lpt) || + (mac->type == e1000_pch_spt)) { mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch_lpt; mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt; @@ -1007,8 +1046,9 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) /* clear FEXTNVM6 bit 8 on link down or 10/100 */ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; - if (!link || ((status & E1000_STATUS_SPEED_100) && - (status & E1000_STATUS_FD))) + if ((hw->phy.revision > 5) || !link || + ((status & E1000_STATUS_SPEED_100) && + (status & E1000_STATUS_FD))) goto update_fextnvm6; ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, ®); @@ -1221,6 +1261,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) u32 mac_reg; s32 ret_val = E1000_SUCCESS; u16 phy_reg; + u16 oem_reg = 0; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || @@ -1276,6 +1317,25 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable + * LPLU and disable Gig speed when entering ULP + */ + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) { + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS, + &oem_reg); + if (ret_val) + goto release; + + phy_reg = oem_reg; + phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS; + + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + phy_reg); + + if (ret_val) + goto release; + } + /* Set Inband ULP Exit, Reset to SMBus mode and * Disable SMBus Release on PERST# in PHY */ @@ -1287,10 +1347,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) if (to_sx) { if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC) phy_reg |= I218_ULP_CONFIG1_WOL_HOST; + else + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT; } else { phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; + phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; } e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); @@ -1302,6 +1367,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) /* Commit ULP changes in PHY by starting auto ULP configuration */ phy_reg |= I218_ULP_CONFIG1_START; e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) && + to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + oem_reg); + if (ret_val) + goto release; + } + release: hw->phy.ops.release(hw); out: @@ -1352,10 +1426,10 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); } - /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ + /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */ while (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_ULP_CFG_DONE) { - if (i++ == 10) { + if (i++ == 30) { ret_val = -E1000_ERR_PHY; goto out; } @@ -1429,6 +1503,8 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) I218_ULP_CONFIG1_RESET_TO_SMBUS | I218_ULP_CONFIG1_WOL_HOST | I218_ULP_CONFIG1_INBAND_EXIT | + I218_ULP_CONFIG1_EN_ULP_LANPHYPC | + I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST | I218_ULP_CONFIG1_DISABLE_SMB_PERST); e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); @@ -1467,7 +1543,8 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; + s32 ret_val, tipg_reg = 0; + u16 emi_addr, emi_val = 0; bool link; u16 phy_reg; @@ -1500,33 +1577,117 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * the IPG and reduce Rx latency in the PHY. */ if (((hw->mac.type == e1000_pch2lan) || - (hw->mac.type == e1000_pch_lpt)) && link) { - u32 reg; - reg = E1000_READ_REG(hw, E1000_STATUS); - if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { - u16 emi_addr; + (hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) && link) { + u16 speed, duplex; - reg = E1000_READ_REG(hw, E1000_TIPG); - reg &= ~E1000_TIPG_IPGT_MASK; - reg |= 0xFF; - E1000_WRITE_REG(hw, E1000_TIPG, reg); + e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex); + tipg_reg = E1000_READ_REG(hw, E1000_TIPG); + tipg_reg &= ~E1000_TIPG_IPGT_MASK; + if (duplex == HALF_DUPLEX && speed == SPEED_10) { + tipg_reg |= 0xFF; /* Reduce Rx latency in analog PHY */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pch2lan) - emi_addr = I82579_RX_CONFIG; - else - emi_addr = I217_RX_CONFIG; - ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); - - hw->phy.ops.release(hw); - - if (ret_val) - return ret_val; + emi_val = 0; + } else if (hw->mac.type == e1000_pch_spt && + duplex == FULL_DUPLEX && speed != SPEED_1000) { + tipg_reg |= 0xC; + emi_val = 1; + } else { + /* Roll back the default values */ + tipg_reg |= 0x08; + emi_val = 1; } + + E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + if (hw->mac.type == e1000_pch2lan) + emi_addr = I82579_RX_CONFIG; + else + emi_addr = I217_RX_CONFIG; + ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val); + + if (hw->mac.type == e1000_pch_lpt || + hw->mac.type == e1000_pch_spt) { + u16 phy_reg; + + hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG, + &phy_reg); + phy_reg &= ~I217_PLL_CLOCK_GATE_MASK; + if (speed == SPEED_100 || speed == SPEED_10) + phy_reg |= 0x3E8; + else + phy_reg |= 0xFA; + hw->phy.ops.write_reg_locked(hw, + I217_PLL_CLOCK_GATE_REG, + phy_reg); + } + hw->phy.ops.release(hw); + + if (ret_val) + return ret_val; + + if (hw->mac.type == e1000_pch_spt) { + u16 data; + u16 ptr_gap; + + if (speed == SPEED_1000) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.read_reg_locked(hw, + PHY_REG(776, 20), + &data); + if (ret_val) { + hw->phy.ops.release(hw); + return ret_val; + } + + ptr_gap = (data & (0x3FF << 2)) >> 2; + if (ptr_gap < 0x18) { + data &= ~(0x3FF << 2); + data |= (0x18 << 2); + ret_val = + hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), data); + } + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + } else { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), + 0xC023); + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + + } + } + } + + /* I217 Packet Loss issue: + * ensure that FEXTNVM4 Beacon Duration is set correctly + * on power up. + * Set the Beacon Duration for I217 to 8 usec + */ + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { + u32 mac_reg; + + mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg); } /* Work-around I218 hang issue */ @@ -1538,7 +1699,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; } - if (hw->mac.type == e1000_pch_lpt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { /* Set platform power management values for * Latency Tolerance Reporting (LTR) * Optimized Buffer Flush/Fill (OBFF) @@ -1551,6 +1713,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) /* Clear link partner's EEE ability */ hw->dev_spec.ich8lan.eee_lp_ability = 0; + /* FEXTNVM6 K1-off workaround */ + if (hw->mac.type == e1000_pch_spt) { + u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG); + u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); + + if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) + fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; + else + fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; + + E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6); + } + if (!link) return E1000_SUCCESS; /* No link detected */ @@ -1644,6 +1819,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: hw->phy.ops.init_params = e1000_init_phy_params_pchlan; break; default: @@ -2026,7 +2202,7 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) continue; } blocked = FALSE; - } while (blocked && (i++ < 10)); + } while (blocked && (i++ < 30)); return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } @@ -2107,6 +2283,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: @@ -3216,12 +3393,47 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) struct e1000_nvm_info *nvm = &hw->nvm; u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; + u32 nvm_dword = 0; u8 sig_byte = 0; s32 ret_val; DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan"); switch (hw->mac.type) { + case e1000_pch_spt: + bank1_offset = nvm->flash_bank_size; + act_offset = E1000_ICH_NVM_SIG_WORD; + + /* set bank to 0 in case flash read fails */ + *bank = 0; + + /* Check bank 0 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 0; + return E1000_SUCCESS; + } + + /* Check bank 1 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset + + bank1_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 1; + return E1000_SUCCESS; + } + + DEBUGOUT("ERROR: No valid NVM bank present\n"); + return -E1000_ERR_NVM; case e1000_ich8lan: case e1000_ich9lan: eecd = E1000_READ_REG(hw, E1000_EECD); @@ -3268,6 +3480,99 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) } } +/** + * e1000_read_nvm_spt - NVM access for SPT + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the word(s) to read. + * @words: Size of data to read in words. + * @data: pointer to the word(s) to read at offset. + * + * Reads a word(s) from the NVM + **/ +static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 act_offset; + s32 ret_val = E1000_SUCCESS; + u32 bank = 0; + u32 dword = 0; + u16 offset_to_read; + u16 i; + + DEBUGFUNC("e1000_read_nvm_spt"); + + if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + nvm->ops.acquire(hw); + + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) { + DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); + bank = 0; + } + + act_offset = (bank) ? nvm->flash_bank_size : 0; + act_offset += offset; + + ret_val = E1000_SUCCESS; + + for (i = 0; i < words; i += 2) { + if (words - i == 1) { + if (dev_spec->shadow_ram[offset+i].modified) { + data[i] = dev_spec->shadow_ram[offset+i].value; + } else { + offset_to_read = act_offset + i - + ((act_offset + i) % 2); + ret_val = + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); + if (ret_val) + break; + if ((act_offset + i) % 2 == 0) + data[i] = (u16)(dword & 0xFFFF); + else + data[i] = (u16)((dword >> 16) & 0xFFFF); + } + } else { + offset_to_read = act_offset + i; + if (!(dev_spec->shadow_ram[offset+i].modified) || + !(dev_spec->shadow_ram[offset+i+1].modified)) { + ret_val = + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); + if (ret_val) + break; + } + if (dev_spec->shadow_ram[offset+i].modified) + data[i] = dev_spec->shadow_ram[offset+i].value; + else + data[i] = (u16) (dword & 0xFFFF); + if (dev_spec->shadow_ram[offset+i].modified) + data[i+1] = + dev_spec->shadow_ram[offset+i+1].value; + else + data[i+1] = (u16) (dword >> 16 & 0xFFFF); + } + } + + nvm->ops.release(hw); + +out: + if (ret_val) + DEBUGOUT1("NVM read error: %d\n", ret_val); + + return ret_val; +} + /** * e1000_read_nvm_ich8lan - Read word(s) from the NVM * @hw: pointer to the HW structure @@ -3355,7 +3660,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) /* Clear FCERR and DAEL in hw status by writing 1 */ hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or @@ -3371,7 +3680,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * Begin by setting Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, + hsfsts.regval); ret_val = E1000_SUCCESS; } else { s32 i; @@ -3393,8 +3707,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, - hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, + hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access\n"); } @@ -3419,10 +3737,17 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) DEBUGFUNC("e1000_flash_cycle_ich8lan"); /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* wait till FDONE bit is set to 1 */ do { @@ -3438,6 +3763,29 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) return -E1000_ERR_NVM; } +/** + * e1000_read_flash_dword_ich8lan - Read dword from flash + * @hw: pointer to the HW structure + * @offset: offset to data location + * @data: pointer to the location for storing the data + * + * Reads the flash dword at offset into data. Offset is converted + * to bytes before read. + **/ +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data) +{ + DEBUGFUNC("e1000_read_flash_dword_ich8lan"); + + if (!data) + return -E1000_ERR_NVM; + + /* Must convert word offset into bytes. */ + offset <<= 1; + + return e1000_read_flash_data32_ich8lan(hw, offset, data); +} + /** * e1000_read_flash_word_ich8lan - Read word from flash * @hw: pointer to the HW structure @@ -3475,7 +3823,13 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val; u16 word = 0; - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); + /* In SPT, only 32 bits access is supported, + * so this function should not be called. + */ + if (hw->mac.type == e1000_pch_spt) + return -E1000_ERR_NVM; + else + ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); if (ret_val) return ret_val; @@ -3561,6 +3915,83 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } +/** + * e1000_read_flash_data32_ich8lan - Read dword from NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the dword to read. + * @data: Pointer to the dword to store the value read. + * + * Reads a byte or word from the NVM using the flash access registers. + **/ +static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + + DEBUGFUNC("e1000_read_flash_data_ich8lan"); + + if (offset > ICH_FLASH_LINEAR_ADDR_MASK || + hw->mac.type != e1000_pch_spt) + return -E1000_ERR_NVM; + flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr); + + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + (u32)hsflctl.regval << 16); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_READ_COMMAND_TIMEOUT); + + /* Check if FCERR is set to 1, if set to 1, clear it + * and try the whole sequence a few more times, else + * read in (shift in) the Flash Data0, the order is + * least significant byte first msb to lsb + */ + if (ret_val == E1000_SUCCESS) { + *data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); + break; + } else { + /* If we've gotten here, then things are probably + * completely hosed, but if the error condition is + * detected, it won't hurt to give it another try... + * ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr) { + /* Repeat for some time before giving up. */ + continue; + } else if (!hsfsts.hsf_status.flcdone) { + DEBUGOUT("Timeout error - flash cycle did not complete.\n"); + break; + } + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + + return ret_val; +} /** * e1000_write_nvm_ich8lan - Write word(s) to the NVM @@ -3598,6 +4029,175 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, return E1000_SUCCESS; } +/** + * e1000_update_nvm_checksum_spt - Update the checksum for NVM + * @hw: pointer to the HW structure + * + * The NVM checksum is updated by calling the generic update_nvm_checksum, + * which writes the checksum to the shadow ram. The changes in the shadow + * ram are then committed to the EEPROM by processing each bank at a time + * checking for the modified bit and writing only the pending changes. + * After a successful commit, the shadow ram is cleared and is ready for + * future writes. + **/ +static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 i, act_offset, new_bank_offset, old_bank_offset, bank; + s32 ret_val; + u32 dword = 0; + + DEBUGFUNC("e1000_update_nvm_checksum_spt"); + + ret_val = e1000_update_nvm_checksum_generic(hw); + if (ret_val) + goto out; + + if (nvm->type != e1000_nvm_flash_sw) + goto out; + + nvm->ops.acquire(hw); + + /* We're writing to the opposite bank so if we're on bank 1, + * write to bank 0 etc. We also need to erase the segment that + * is going to be written + */ + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) { + DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); + bank = 0; + } + + if (bank == 0) { + new_bank_offset = nvm->flash_bank_size; + old_bank_offset = 0; + ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); + if (ret_val) + goto release; + } else { + old_bank_offset = nvm->flash_bank_size; + new_bank_offset = 0; + ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); + if (ret_val) + goto release; + } + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) { + /* Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM + */ + ret_val = e1000_read_flash_dword_ich8lan(hw, + i + old_bank_offset, + &dword); + + if (dev_spec->shadow_ram[i].modified) { + dword &= 0xffff0000; + dword |= (dev_spec->shadow_ram[i].value & 0xffff); + } + if (dev_spec->shadow_ram[i + 1].modified) { + dword &= 0x0000ffff; + dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff) + << 16); + } + if (ret_val) + break; + + /* If the word is 0x13, then make sure the signature bits + * (15:14) are 11b until the commit has completed. + * This will allow us to write 10b which indicates the + * signature is valid. We want to do this after the write + * has completed so that we don't mark the segment valid + * while the write is still in progress + */ + if (i == E1000_ICH_NVM_SIG_WORD - 1) + dword |= E1000_ICH_NVM_SIG_MASK << 16; + + /* Convert offset to bytes. */ + act_offset = (i + new_bank_offset) << 1; + + usec_delay(100); + + /* Write the data to the new bank. Offset in words*/ + act_offset = i + new_bank_offset; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, + dword); + if (ret_val) + break; + } + + /* Don't bother writing the segment valid bits if sector + * programming failed. + */ + if (ret_val) { + DEBUGOUT("Flash commit failed.\n"); + goto release; + } + + /* Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b + */ + act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; + + /*offset in words but we read dword*/ + --act_offset; + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); + + if (ret_val) + goto release; + + dword &= 0xBFFFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); + + if (ret_val) + goto release; + + /* And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase + */ + act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; + + /* offset in words but we read dword*/ + act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1; + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); + + if (ret_val) + goto release; + + dword &= 0x00FFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); + + if (ret_val) + goto release; + + /* Great! Everything worked, we can now clear the cached entries. */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + dev_spec->shadow_ram[i].modified = FALSE; + dev_spec->shadow_ram[i].value = 0xFFFF; + } + +release: + nvm->ops.release(hw); + + /* Reload the EEPROM, or else modifications will not appear + * until after the next adapter reset. + */ + if (!ret_val) { + nvm->ops.reload(hw); + msec_delay(10); + } + +out: + if (ret_val) + DEBUGOUT1("NVM update error: %d\n", ret_val); + + return ret_val; +} + /** * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM * @hw: pointer to the HW structure @@ -3775,6 +4375,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) */ switch (hw->mac.type) { case e1000_pch_lpt: + case e1000_pch_spt: word = NVM_COMPAT; valid_csum_mask = NVM_COMPAT_VALID_CSUM; break; @@ -3822,8 +4423,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, DEBUGFUNC("e1000_write_ich8_data"); - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; + if (hw->mac.type == e1000_pch_spt) { + if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } else { + if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); @@ -3834,12 +4440,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = + E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = + E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + /* In SPT, This register is in Lan memory space, + * not flash. Therefore, only 32 bit access is + * supported + */ + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); @@ -3877,6 +4500,94 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } +/** +* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM +* @hw: pointer to the HW structure +* @offset: The offset (in bytes) of the dwords to read. +* @data: The 4 bytes to write to the NVM. +* +* Writes one/two/four bytes to the NVM using the flash access registers. +**/ +static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + s32 ret_val; + u8 count = 0; + + DEBUGFUNC("e1000_write_flash_data32_ich8lan"); + + if (hw->mac.type == e1000_pch_spt) { + if (offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } + flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr); + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS) + >> 16; + else + hsflctl.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); + + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + + /* In SPT, This register is in Lan memory space, + * not flash. Therefore, only 32 bit access is + * supported + */ + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data); + + /* check if FCERR is set to 1 , if set to 1, clear it + * and try the whole sequence a few more times else done + */ + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_WRITE_COMMAND_TIMEOUT); + + if (ret_val == E1000_SUCCESS) + break; + + /* If we're here, then things are most likely + * completely hosed, but if the error condition + * is detected, it won't hurt to give it another + * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + + if (hsfsts.hsf_status.flcerr) + /* Repeat for some time before giving up. */ + continue; + if (!hsfsts.hsf_status.flcdone) { + DEBUGOUT("Timeout error - flash cycle did not complete.\n"); + break; + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + + return ret_val; +} /** * e1000_write_flash_byte_ich8lan - Write a single byte to NVM @@ -3896,7 +4607,42 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, return e1000_write_flash_data_ich8lan(hw, offset, 1, word); } +/** +* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM +* @hw: pointer to the HW structure +* @offset: The offset of the word to write. +* @dword: The dword to write to the NVM. +* +* Writes a single dword to the NVM using the flash access registers. +* Goes through a retry algorithm before giving up. +**/ +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword) +{ + s32 ret_val; + u16 program_retries; + DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan"); + + /* Must convert word offset into bytes. */ + offset <<= 1; + + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + + if (!ret_val) + return ret_val; + for (program_retries = 0; program_retries < 100; program_retries++) { + DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset); + usec_delay(100); + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + if (ret_val == E1000_SUCCESS) + break; + } + if (program_retries == 100) + return -E1000_ERR_NVM; + + return E1000_SUCCESS; +} /** * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM @@ -4006,12 +4752,22 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) /* Write a value 11 (block Erase) in Flash * Cycle field in hw flash control */ - hsflctl.regval = - E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = + E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = + E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, - hsflctl.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); /* Write the last 24 bits of an index within the * block into Flash Linear address field in Flash @@ -4444,7 +5200,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_RFCTL, reg); /* Enable ECC on Lynxpoint */ - if (hw->mac.type == e1000_pch_lpt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { reg = E1000_READ_REG(hw, E1000_PBECCSTS); reg |= E1000_PBECCSTS_ECC_ENABLE; E1000_WRITE_REG(hw, E1000_PBECCSTS, reg); @@ -4876,7 +5633,8 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) || (device_id == E1000_DEV_ID_PCH_I218_LM3) || - (device_id == E1000_DEV_ID_PCH_I218_V3)) { + (device_id == E1000_DEV_ID_PCH_I218_V3) || + (hw->mac.type == e1000_pch_spt)) { u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); E1000_WRITE_REG(hw, E1000_FEXTNVM6, @@ -4992,18 +5750,18 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) * the PHY. * On i217, setup Intel Rapid Start Technology. **/ -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_resume_workarounds_pchlan"); if (hw->mac.type < e1000_pch2lan) - return; + return E1000_SUCCESS; ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) { DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val); - return; + return ret_val; } /* For i217 Intel Rapid Start Technology support when the system @@ -5017,7 +5775,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) { DEBUGOUT("Failed to setup iRST\n"); - return; + return ret_val; } /* Clear Auto Enable LPI after link up */ @@ -5051,7 +5809,9 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) if (ret_val) DEBUGOUT1("Error %d in resume workarounds\n", ret_val); hw->phy.ops.release(hw); + return ret_val; } + return E1000_SUCCESS; } /** diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index 9cb79c0b0c99..edc1dd14ccc9 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -107,9 +107,23 @@ #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 - +#define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000 +/* bit for disabling packet buffer read */ +#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000 +#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004 #define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 +#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800 +#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000 +#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200 +#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000 +/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */ +#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000 + +#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/ +#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/ +#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ +#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29) #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -171,6 +185,8 @@ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +#define K1_ENTRY_LATENCY 0 +#define K1_MIN_TIME 1 /* SMBus Control Phy Register */ #define CV_SMB_CTRL PHY_REG(769, 23) @@ -184,6 +200,10 @@ #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ +/* enable ULP even if when phy powered down via lanphypc */ +#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400 +/* disable clear of sticky ULP on PERST */ +#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800 #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ /* SMBus Address Phy Register */ @@ -222,6 +242,9 @@ #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define HV_PM_CTRL_K1_ENABLE 0x4000 +#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) +#define I217_PLL_CLOCK_GATE_MASK 0x07FF + #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* Inband Control */ @@ -302,15 +325,12 @@ #define E1000_SVCR_OFF_TIMER_SHIFT 16 #define E1000_SVT_OFF_HWM_MASK 0x0000001F -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) -#define E1000_PCI_REVISION_ID_REG 0x08 -#endif /* defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) */ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw); s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h index 1daed9bc9472..ef9789bbb537 100644 --- a/sys/dev/e1000/e1000_mac.h +++ b/sys/dev/e1000/e1000_mac.h @@ -36,9 +36,7 @@ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); -#ifndef E1000_REMOVED #define E1000_REMOVED(a) (0) -#endif /* E1000_REMOVED */ void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c index d9fb9acdce17..1de19a4df77c 100644 --- a/sys/dev/e1000/e1000_mbx.c +++ b/sys/dev/e1000/e1000_mbx.c @@ -426,15 +426,21 @@ static s32 e1000_check_for_rst_vf(struct e1000_hw *hw, static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_MBX; + int count = 10; DEBUGFUNC("e1000_obtain_mbx_lock_vf"); - /* Take ownership of the buffer */ - E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); + do { + /* Take ownership of the buffer */ + E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); - /* reserve mailbox for vf use */ - if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) - ret_val = E1000_SUCCESS; + /* reserve mailbox for vf use */ + if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) { + ret_val = E1000_SUCCESS; + break; + } + usec_delay(1000); + } while (count-- > 0); return ret_val; } @@ -639,18 +645,26 @@ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; u32 p2v_mailbox; + int count = 10; DEBUGFUNC("e1000_obtain_mbx_lock_pf"); - /* Take ownership of the buffer */ - E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + do { + /* Take ownership of the buffer */ + E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), + E1000_P2VMAILBOX_PFU); - /* reserve mailbox for vf use */ - p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); - if (p2v_mailbox & E1000_P2VMAILBOX_PFU) - ret_val = E1000_SUCCESS; + /* reserve mailbox for pf use */ + p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); + if (p2v_mailbox & E1000_P2VMAILBOX_PFU) { + ret_val = E1000_SUCCESS; + break; + } + usec_delay(1000); + } while (count-- > 0); return ret_val; + } /** diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h index 31f2180a0b6b..64a4083eb209 100644 --- a/sys/dev/e1000/e1000_nvm.h +++ b/sys/dev/e1000/e1000_nvm.h @@ -35,12 +35,10 @@ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ -#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW) struct e1000_pba { u16 word[2]; u16 *pba_block; }; -#endif void e1000_init_nvm_ops_generic(struct e1000_hw *hw); diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h index fc46f48df6cc..c0bf4182ec62 100644 --- a/sys/dev/e1000/e1000_osdep.h +++ b/sys/dev/e1000/e1000_osdep.h @@ -60,24 +60,24 @@ #define ASSERT(x) if(!(x)) panic("EM: x") #define usec_delay(x) DELAY(x) -#define usec_delay_irq(x) DELAY(x) +#define usec_delay_irq(x) usec_delay(x) #define msec_delay(x) DELAY(1000*(x)) #define msec_delay_irq(x) DELAY(1000*(x)) -#define DEBUGFUNC(F) DEBUGOUT(F); -#define DEBUGOUT(S) do {} while (0) -#define DEBUGOUT1(S,A) do {} while (0) -#define DEBUGOUT2(S,A,B) do {} while (0) -#define DEBUGOUT3(S,A,B,C) do {} while (0) -#define DEBUGOUT7(S,A,B,C,D,E,F,G) do {} while (0) +/* Enable/disable debugging statements in shared code */ +#define DBG 0 + +#define DEBUGOUT(...) \ + do { if (DBG) printf(__VA_ARGS__); } while (0) +#define DEBUGOUT1(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT2(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT3(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT7(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGFUNC(F) DEBUGOUT(F "\n") #define STATIC static #define FALSE 0 #define TRUE 1 -#ifndef __bool_true_false_are_defined -#define false FALSE -#define true TRUE -#endif #define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ #define PCI_COMMAND_REGISTER PCIR_COMMAND @@ -99,9 +99,6 @@ typedef int64_t s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; -#ifndef __bool_true_false_are_defined -typedef boolean_t bool; -#endif #define __le16 u16 #define __le32 u32 diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index 0c8ccd2ba627..b2bec3e5fe6b 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -1827,9 +1827,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) phy_data); if (ret_val) return ret_val; - } - DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + } ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) @@ -3429,14 +3429,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set) { s32 ret_val; - u16 reg, page; + u16 reg = BM_PHY_REG_NUM(offset); + u16 page = BM_PHY_REG_PAGE(offset); u16 phy_reg = 0; DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); - reg = BM_PHY_REG_NUM(offset); - page = BM_PHY_REG_PAGE(offset); - /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ if ((hw->mac.type == e1000_pchlan) && (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 7c81a8988243..37d701722da1 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -65,6 +65,9 @@ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ +#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */ +#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */ +#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ @@ -107,7 +110,9 @@ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ +#define E1000_IOSFPC 0x00F28 /* TX corrupted data */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ +#define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */ #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ @@ -588,6 +593,10 @@ #define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ #define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ +#define E1000_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */ +#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */ +#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */ +#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ #define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index b6c98b160e25..1f6746c5cdae 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -95,15 +95,10 @@ #include "e1000_82571.h" #include "if_em.h" -/********************************************************************* - * Set this to one to display debug statistics - *********************************************************************/ -int em_display_debug_stats = 0; - /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.4.2"; +char em_driver_version[] = "7.6.1-k"; /********************************************************************* * PCI Device ID Table @@ -191,6 +186,13 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_I218_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_I218_LM3, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_I218_V3, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM2, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LBG_I219_LM3, + PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -238,6 +240,7 @@ static void em_free_pci_resources(struct adapter *); static void em_local_timer(void *); static void em_reset(struct adapter *); static int em_setup_interface(device_t, struct adapter *); +static void em_flush_desc_rings(struct adapter *); static void em_setup_transmit_structures(struct adapter *); static void em_initialize_transmit_unit(struct adapter *); @@ -577,10 +580,25 @@ em_attach(device_t dev) adapter->osdep.flash_bus_space_handle = rman_get_bushandle(adapter->flash); } + /* + ** In the new SPT device flash is not a + ** seperate BAR, rather it is also in BAR0, + ** so use the same tag and an offset handle for the + ** FLASH read/write macros in the shared code. + */ + else if (hw->mac.type == e1000_pch_spt) { + adapter->osdep.flash_bus_space_tag = + adapter->osdep.mem_bus_space_tag; + adapter->osdep.flash_bus_space_handle = + adapter->osdep.mem_bus_space_handle + + E1000_FLASH_BASE_ADDR; + } /* Do Shared Code initialization */ - if (e1000_setup_init_funcs(hw, TRUE)) { - device_printf(dev, "Setup of Shared code failed\n"); + error = e1000_setup_init_funcs(hw, TRUE); + if (error) { + device_printf(dev, "Setup of Shared code failed, error %d\n", + error); error = ENXIO; goto err_pci; } @@ -1170,6 +1188,7 @@ em_ioctl(if_t ifp, u_long command, caddr_t data) case e1000_ich10lan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: case e1000_82574: case e1000_82583: case e1000_80003es2lan: /* 9K Jumbo Frame size */ @@ -2359,6 +2378,8 @@ em_update_link_status(struct adapter *adapter) switch (hw->phy.media_type) { case e1000_media_type_copper: if (hw->mac.get_link_status) { + if (hw->mac.type == e1000_pch_spt) + msec_delay(50); /* Do the work to read phy */ e1000_check_for_link(hw); link_check = !hw->mac.get_link_status; @@ -2450,6 +2471,10 @@ em_stop(void *arg) EM_TX_UNLOCK(txr); } + /* I219 needs some special flushing to avoid hangs */ + if (adapter->hw.mac.type == e1000_pch_spt) + em_flush_desc_rings(adapter); + e1000_reset_hw(&adapter->hw); E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); @@ -2869,6 +2894,116 @@ em_setup_msix(struct adapter *adapter) } +/* +** The 3 following flush routines are used as a workaround in the +** I219 client parts and only for them. +** +** em_flush_tx_ring - remove all descriptors from the tx_ring +** +** We want to clear all pending descriptors from the TX ring. +** zeroing happens when the HW reads the regs. We assign the ring itself as +** the data of the next descriptor. We don't care about the data we are about +** to reset the HW. +*/ +static void +em_flush_tx_ring(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct tx_ring *txr = adapter->tx_rings; + struct e1000_tx_desc *txd; + u32 tctl, txd_lower = E1000_TXD_CMD_IFCS; + u16 size = 512; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); + + txd = &txr->tx_base[txr->next_avail_desc++]; + if (txr->next_avail_desc == adapter->num_tx_desc) + txr->next_avail_desc = 0; + + /* Just use the ring as a dummy buffer addr */ + txd->buffer_addr = txr->txdma.dma_paddr; + txd->lower.data = htole32(txd_lower | size); + txd->upper.data = 0; + + /* flush descriptors to memory before notifying the HW */ + wmb(); + + E1000_WRITE_REG(hw, E1000_TDT(0), txr->next_avail_desc); + mb(); + usec_delay(250); +} + +/* +** em_flush_rx_ring - remove all descriptors from the rx_ring +** +** Mark all descriptors in the RX ring as consumed and disable the rx ring +*/ +static void +em_flush_rx_ring(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl, rxdctl; + + rctl = E1000_READ_REG(hw, E1000_RCTL); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); + /* zero the lower 14 bits (prefetch and host thresholds) */ + rxdctl &= 0xffffc000; + /* + * update thresholds: prefetch threshold to 31, host threshold to 1 + * and make sure the granularity is "descriptors" and not "cache lines" + */ + rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC); + E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl); + + /* momentarily enable the RX ring for the changes to take effect */ + E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); +} + +/* +** em_flush_desc_rings - remove all descriptors from the descriptor rings +** +** In i219, the descriptor rings must be emptied before resetting the HW +** or before changing the device state to D3 during runtime (runtime PM). +** +** Failure to do this will cause the HW to enter a unit hang state which can +** only be released by PCI reset on the device +** +*/ +static void +em_flush_desc_rings(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + device_t dev = adapter->dev; + u16 hang_state; + u32 fext_nvm11, tdlen; + + /* First, disable MULR fix in FEXTNVM11 */ + fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11); + fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; + E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11); + + /* do nothing if we're not in faulty state, or if the queue is empty */ + tdlen = E1000_READ_REG(hw, E1000_TDLEN(0)); + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen) + return; + em_flush_tx_ring(adapter); + + /* recheck, maybe the fault is caused by the rx ring */ + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (hang_state & FLUSH_DESC_REQUIRED) + em_flush_rx_ring(adapter); +} + + /********************************************************************* * * Initialize the hardware to a configuration @@ -2930,6 +3065,7 @@ em_reset(struct adapter *adapter) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: pba = E1000_PBA_26K; break; default: @@ -2988,6 +3124,7 @@ em_reset(struct adapter *adapter) break; case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; hw->fc.pause_time = 0x0650; @@ -3012,6 +3149,10 @@ em_reset(struct adapter *adapter) break; } + /* I219 needs some special flushing to avoid hangs */ + if (hw->mac.type == e1000_pch_spt) + em_flush_desc_rings(adapter); + /* Issue a global reset */ e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); @@ -3608,6 +3749,15 @@ em_initialize_transmit_unit(struct adapter *adapter) /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); + if (hw->mac.type == e1000_pch_spt) { + u32 reg; + reg = E1000_READ_REG(hw, E1000_IOSFPC); + reg |= E1000_RCTL_RDMTS_HEX; + E1000_WRITE_REG(hw, E1000_IOSFPC, reg); + reg = E1000_READ_REG(hw, E1000_TARC(0)); + reg |= E1000_TARC0_CB_MULTIQ_3_REQ; + E1000_WRITE_REG(hw, E1000_TARC(0), reg); + } } diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 362df49442a7..3b280b33401c 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -218,6 +218,9 @@ #define EM_TX_HUNG 0x80000000 #define EM_TX_MAXTRIES 10 +#define PCICFG_DESC_RING_STATUS 0xe4 +#define FLUSH_DESC_REQUIRED 0x100 + /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 5be7836cb8f8..c84dfc2be007 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -47,7 +47,7 @@ /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "2.5.2"; +char igb_driver_version[] = "2.5.3-k"; /********************************************************************* @@ -551,9 +551,9 @@ igb_attach(device_t dev) "Disable Energy Efficient Ethernet"); if (adapter->hw.phy.media_type == e1000_media_type_copper) { if (adapter->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&adapter->hw); + e1000_set_eee_i354(&adapter->hw, TRUE, TRUE); else - e1000_set_eee_i350(&adapter->hw); + e1000_set_eee_i350(&adapter->hw, TRUE, TRUE); } } @@ -1277,6 +1277,9 @@ igb_init_locked(struct adapter *adapter) if (ifp->if_capenable & IFCAP_TSO) ifp->if_hwassist |= CSUM_TSO; + /* Clear bad data from Rx FIFOs */ + e1000_rx_fifo_flush_82575(&adapter->hw); + /* Configure for OS presence */ igb_init_manageability(adapter); @@ -1304,7 +1307,6 @@ igb_init_locked(struct adapter *adapter) return; } igb_initialize_receive_units(adapter); - e1000_rx_fifo_flush_82575(&adapter->hw); /* Enable VLAN support */ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) @@ -1341,9 +1343,9 @@ igb_init_locked(struct adapter *adapter) /* Set Energy Efficient Ethernet */ if (adapter->hw.phy.media_type == e1000_media_type_copper) { if (adapter->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&adapter->hw); + e1000_set_eee_i354(&adapter->hw, TRUE, TRUE); else - e1000_set_eee_i350(&adapter->hw); + e1000_set_eee_i350(&adapter->hw, TRUE, TRUE); } } From c212e48d5be4c79d408a59189b0eddbaed1585bc Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 5 Feb 2016 17:28:11 +0000 Subject: [PATCH 222/236] Add error check to not leak logs with syntax errors in case of failed `zpool history`. MFC after: 1 month --- etc/periodic/daily/800.scrub-zfs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs index 359be13b227a..b7a009d2c1e9 100755 --- a/etc/periodic/daily/800.scrub-zfs +++ b/etc/periodic/daily/800.scrub-zfs @@ -63,6 +63,11 @@ case "$daily_scrub_zfs_enable" in _last_scrub=$(zpool history ${pool} | \ sed -ne '2s/ .*$//p') fi + if [ -z "${_last_scrub}" ]; then + echo " skipping scrubbing of pool '${pool}':" + echo " can't get last scrubbing date" + continue + fi # Now minus last scrub (both in seconds) converted to days. _scrub_diff=$(expr -e \( $(date +%s) - \ From d6ed13470ae8ba961478892aefbc84081c8ece1b Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 5 Feb 2016 18:17:37 +0000 Subject: [PATCH 223/236] Update script for modern `zpool status` output. --- etc/periodic/daily/800.scrub-zfs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs index b7a009d2c1e9..64eac99c38a1 100755 --- a/etc/periodic/daily/800.scrub-zfs +++ b/etc/periodic/daily/800.scrub-zfs @@ -78,11 +78,14 @@ case "$daily_scrub_zfs_enable" in continue fi - _status="$(zpool status ${pool} | grep scrub:)" + _status="$(zpool status ${pool} | grep scan:)" case "${_status}" in *"scrub in progress"*) echo " scrubbing of pool '${pool}' already in progress, skipping:" ;; + *"resilver in progress"*) + echo " resilvering of pool '${pool}' is in progress, skipping:" + ;; *"none requested"*) echo " starting first scrub (since reboot) of pool '${pool}':" zpool scrub ${pool} From f611a6573503c119077126cc01f2444b3cd0db13 Mon Sep 17 00:00:00 2001 From: markj Date: Fri, 5 Feb 2016 19:35:53 +0000 Subject: [PATCH 224/236] Plug a vm_page leak introduced in r292373. Reported by: vangyzen --- sys/vm/sg_pager.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c index 84bfa49f11a4..2cccb7ea1598 100644 --- a/sys/vm/sg_pager.c +++ b/sys/vm/sg_pager.c @@ -189,6 +189,9 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, VM_OBJECT_WLOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q); vm_page_replace_checked(page, object, offset, m[0]); + vm_page_lock(m[0]); + vm_page_free(m[0]); + vm_page_unlock(m[0]); m[0] = page; page->valid = VM_PAGE_BITS_ALL; From 21434c7a701096dfe0b99fcfe37d637fae83cb2b Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 5 Feb 2016 20:38:09 +0000 Subject: [PATCH 225/236] Rename aiocblist to kaiocb and use consistent variable names. Typically list is used for a structure that holds a list head in FreeBSD, not for members of a list. As such, rename 'struct aiocblist' to 'struct kaiocb' (the kernel version of 'struct aiocb'). While here, use more consistent variable names for AIO control blocks: - Use 'job' instead of 'aiocbe', 'cb', 'cbe', or 'iocb' for kernel job objects. - Use 'jobn' instead of 'cbn' for use with TAILQ_FOREACH_SAFE(). - Use 'sjob' and 'sjobn' instead of 'scb' and 'scbn' for fsync jobs. - Use 'ujob' instead of 'aiocbp', 'job', 'uaiocb', or 'uuaiocb' to hold a user pointer to a 'struct aiocb'. - Use 'ujobp' instead of 'aiocbp' for a user pointer to a 'struct aiocb *'. Reviewed by: kib Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D5125 --- sys/kern/vfs_aio.c | 644 ++++++++++++++++++++++---------------------- sys/sys/event.h | 2 +- sys/sys/socketvar.h | 2 +- 3 files changed, 324 insertions(+), 324 deletions(-) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 14a66c3bb7d7..5b2083c65312 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -196,7 +196,7 @@ typedef struct oaiocb { } oaiocb_t; /* - * Below is a key of locks used to protect each member of struct aiocblist + * Below is a key of locks used to protect each member of struct kaiocb * aioliojob and kaioinfo and any backends. * * * - need not protected @@ -219,10 +219,10 @@ typedef struct oaiocb { * daemons. */ -struct aiocblist { - TAILQ_ENTRY(aiocblist) list; /* (b) internal list of for backend */ - TAILQ_ENTRY(aiocblist) plist; /* (a) list of jobs for each backend */ - TAILQ_ENTRY(aiocblist) allist; /* (a) list of all jobs in proc */ +struct kaiocb { + TAILQ_ENTRY(kaiocb) list; /* (b) internal list of for backend */ + TAILQ_ENTRY(kaiocb) plist; /* (a) list of jobs for each backend */ + TAILQ_ENTRY(kaiocb) allist; /* (a) list of all jobs in proc */ int jobflags; /* (a) job flags */ int jobstate; /* (b) job state */ int inputcharge; /* (*) input blockes */ @@ -235,7 +235,7 @@ struct aiocblist { struct ucred *cred; /* (*) active credential when created */ struct file *fd_file; /* (*) pointer to file structure */ struct aioliojob *lio; /* (*) optional lio job */ - struct aiocb *uuaiocb; /* (*) pointer in userspace of aiocb */ + struct aiocb *ujob; /* (*) pointer in userspace of aiocb */ struct knlist klist; /* (a) list of knotes */ struct aiocb uaiocb; /* (*) kernel I/O control block */ ksiginfo_t ksi; /* (a) realtime signal info */ @@ -244,10 +244,10 @@ struct aiocblist { }; /* jobflags */ -#define AIOCBLIST_DONE 0x01 -#define AIOCBLIST_BUFDONE 0x02 -#define AIOCBLIST_RUNDOWN 0x04 -#define AIOCBLIST_CHECKSYNC 0x08 +#define KAIOCB_DONE 0x01 +#define KAIOCB_BUFDONE 0x02 +#define KAIOCB_RUNDOWN 0x04 +#define KAIOCB_CHECKSYNC 0x08 /* * AIO process info @@ -289,12 +289,12 @@ struct kaioinfo { int kaio_count; /* (a) size of AIO queue */ int kaio_ballowed_count; /* (*) maximum number of buffers */ int kaio_buffer_count; /* (a) number of physio buffers */ - TAILQ_HEAD(,aiocblist) kaio_all; /* (a) all AIOs in a process */ - TAILQ_HEAD(,aiocblist) kaio_done; /* (a) done queue for process */ + TAILQ_HEAD(,kaiocb) kaio_all; /* (a) all AIOs in a process */ + TAILQ_HEAD(,kaiocb) kaio_done; /* (a) done queue for process */ TAILQ_HEAD(,aioliojob) kaio_liojoblist; /* (a) list of lio jobs */ - TAILQ_HEAD(,aiocblist) kaio_jobqueue; /* (a) job queue for process */ - TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* (a) buffer job queue */ - TAILQ_HEAD(,aiocblist) kaio_syncqueue; /* (a) queue for aio_fsync */ + TAILQ_HEAD(,kaiocb) kaio_jobqueue; /* (a) job queue for process */ + TAILQ_HEAD(,kaiocb) kaio_bufqueue; /* (a) buffer job queue */ + TAILQ_HEAD(,kaiocb) kaio_syncqueue; /* (a) queue for aio_fsync */ struct task kaio_task; /* (*) task to kick aio processes */ }; @@ -323,28 +323,28 @@ struct aiocb_ops { static TAILQ_HEAD(,aioproc) aio_freeproc; /* (c) Idle daemons */ static struct sema aio_newproc_sem; static struct mtx aio_job_mtx; -static TAILQ_HEAD(,aiocblist) aio_jobs; /* (c) Async job list */ +static TAILQ_HEAD(,kaiocb) aio_jobs; /* (c) Async job list */ static struct unrhdr *aiod_unr; void aio_init_aioinfo(struct proc *p); static int aio_onceonly(void); -static int aio_free_entry(struct aiocblist *aiocbe); -static void aio_process_rw(struct aiocblist *aiocbe); -static void aio_process_sync(struct aiocblist *aiocbe); -static void aio_process_mlock(struct aiocblist *aiocbe); +static int aio_free_entry(struct kaiocb *job); +static void aio_process_rw(struct kaiocb *job); +static void aio_process_sync(struct kaiocb *job); +static void aio_process_mlock(struct kaiocb *job); static int aio_newproc(int *); -int aio_aqueue(struct thread *td, struct aiocb *job, +int aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lio, int type, struct aiocb_ops *ops); static void aio_physwakeup(struct bio *bp); static void aio_proc_rundown(void *arg, struct proc *p); static void aio_proc_rundown_exec(void *arg, struct proc *p, struct image_params *imgp); -static int aio_qphysio(struct proc *p, struct aiocblist *iocb); +static int aio_qphysio(struct proc *p, struct kaiocb *job); static void aio_daemon(void *param); static void aio_swake_cb(struct socket *, struct sockbuf *); static int aio_unload(void); -static void aio_bio_done_notify(struct proc *userp, - struct aiocblist *aiocbe, int type); +static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job, + int type); #define DONE_BUF 1 #define DONE_QUEUE 2 static int aio_kick(struct proc *userp); @@ -488,7 +488,7 @@ aio_onceonly(void) NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiop_zone = uma_zcreate("AIOP", sizeof(struct aioproc), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - aiocb_zone = uma_zcreate("AIOCB", sizeof(struct aiocblist), NULL, NULL, + aiocb_zone = uma_zcreate("AIOCB", sizeof(struct kaiocb), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiol_zone = uma_zcreate("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t) , NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); @@ -625,29 +625,29 @@ aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi) * restart the queue scan. */ static int -aio_free_entry(struct aiocblist *aiocbe) +aio_free_entry(struct kaiocb *job) { struct kaioinfo *ki; struct aioliojob *lj; struct proc *p; - p = aiocbe->userproc; + p = job->userproc; MPASS(curproc == p); ki = p->p_aioinfo; MPASS(ki != NULL); AIO_LOCK_ASSERT(ki, MA_OWNED); - MPASS(aiocbe->jobstate == JOBST_JOBFINISHED); + MPASS(job->jobstate == JOBST_JOBFINISHED); atomic_subtract_int(&num_queue_count, 1); ki->kaio_count--; MPASS(ki->kaio_count >= 0); - TAILQ_REMOVE(&ki->kaio_done, aiocbe, plist); - TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist); + TAILQ_REMOVE(&ki->kaio_done, job, plist); + TAILQ_REMOVE(&ki->kaio_all, job, allist); - lj = aiocbe->lio; + lj = job->lio; if (lj) { lj->lioj_count--; lj->lioj_finished_count--; @@ -663,14 +663,14 @@ aio_free_entry(struct aiocblist *aiocbe) } } - /* aiocbe is going away, we need to destroy any knotes */ - knlist_delete(&aiocbe->klist, curthread, 1); + /* job is going away, we need to destroy any knotes */ + knlist_delete(&job->klist, curthread, 1); PROC_LOCK(p); - sigqueue_take(&aiocbe->ksi); + sigqueue_take(&job->ksi); PROC_UNLOCK(p); - MPASS(aiocbe->bp == NULL); - aiocbe->jobstate = JOBST_NULL; + MPASS(job->bp == NULL); + job->jobstate = JOBST_NULL; AIO_UNLOCK(ki); /* @@ -682,7 +682,7 @@ aio_free_entry(struct aiocblist *aiocbe) * another process. * * Currently, all the callers of this function call it to remove - * an aiocblist from the current process' job list either via a + * a kaiocb from the current process' job list either via a * syscall or due to the current process calling exit() or * execve(). Thus, we know that p == curproc. We also know that * curthread can't exit since we are curthread. @@ -693,10 +693,10 @@ aio_free_entry(struct aiocblist *aiocbe) * at open time, but this is already true of file descriptors in * a multithreaded process. */ - if (aiocbe->fd_file) - fdrop(aiocbe->fd_file, curthread); - crfree(aiocbe->cred); - uma_zfree(aiocb_zone, aiocbe); + if (job->fd_file) + fdrop(job->fd_file, curthread); + crfree(job->cred); + uma_zfree(aiocb_zone, job); AIO_LOCK(ki); return (0); @@ -717,7 +717,7 @@ aio_proc_rundown(void *arg, struct proc *p) { struct kaioinfo *ki; struct aioliojob *lj; - struct aiocblist *cbe, *cbn; + struct kaiocb *job, *jobn; struct file *fp; struct socket *so; int remove; @@ -737,30 +737,30 @@ aio_proc_rundown(void *arg, struct proc *p) * Try to cancel all pending requests. This code simulates * aio_cancel on all pending I/O requests. */ - TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { + TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) { remove = 0; mtx_lock(&aio_job_mtx); - if (cbe->jobstate == JOBST_JOBQGLOBAL) { - TAILQ_REMOVE(&aio_jobs, cbe, list); + if (job->jobstate == JOBST_JOBQGLOBAL) { + TAILQ_REMOVE(&aio_jobs, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSOCK) { - fp = cbe->fd_file; + } else if (job->jobstate == JOBST_JOBQSOCK) { + fp = job->fd_file; MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; - TAILQ_REMOVE(&so->so_aiojobq, cbe, list); + TAILQ_REMOVE(&so->so_aiojobq, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSYNC) { - TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); + } else if (job->jobstate == JOBST_JOBQSYNC) { + TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { - cbe->jobstate = JOBST_JOBFINISHED; - cbe->uaiocb._aiocb_private.status = -1; - cbe->uaiocb._aiocb_private.error = ECANCELED; - TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); - aio_bio_done_notify(p, cbe, DONE_QUEUE); + job->jobstate = JOBST_JOBFINISHED; + job->uaiocb._aiocb_private.status = -1; + job->uaiocb._aiocb_private.error = ECANCELED; + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + aio_bio_done_notify(p, job, DONE_QUEUE); } } @@ -773,8 +773,8 @@ aio_proc_rundown(void *arg, struct proc *p) } /* Free all completed I/O requests. */ - while ((cbe = TAILQ_FIRST(&ki->kaio_done)) != NULL) - aio_free_entry(cbe); + while ((job = TAILQ_FIRST(&ki->kaio_done)) != NULL) + aio_free_entry(job); while ((lj = TAILQ_FIRST(&ki->kaio_liojoblist)) != NULL) { if (lj->lioj_count == 0) { @@ -799,27 +799,27 @@ aio_proc_rundown(void *arg, struct proc *p) /* * Select a job to run (called by an AIO daemon). */ -static struct aiocblist * +static struct kaiocb * aio_selectjob(struct aioproc *aiop) { - struct aiocblist *aiocbe; + struct kaiocb *job; struct kaioinfo *ki; struct proc *userp; mtx_assert(&aio_job_mtx, MA_OWNED); - TAILQ_FOREACH(aiocbe, &aio_jobs, list) { - userp = aiocbe->userproc; + TAILQ_FOREACH(job, &aio_jobs, list) { + userp = job->userproc; ki = userp->p_aioinfo; if (ki->kaio_active_count < ki->kaio_maxactive_count) { - TAILQ_REMOVE(&aio_jobs, aiocbe, list); + TAILQ_REMOVE(&aio_jobs, job, list); /* Account for currently active jobs. */ ki->kaio_active_count++; - aiocbe->jobstate = JOBST_JOBRUNNING; + job->jobstate = JOBST_JOBRUNNING; break; } } - return (aiocbe); + return (job); } /* @@ -857,7 +857,7 @@ aio_fsync_vnode(struct thread *td, struct vnode *vp) * XXX I don't think it works well for socket, pipe, and fifo. */ static void -aio_process_rw(struct aiocblist *aiocbe) +aio_process_rw(struct kaiocb *job) { struct ucred *td_savedcred; struct thread *td; @@ -871,15 +871,15 @@ aio_process_rw(struct aiocblist *aiocbe) int oublock_st, oublock_end; int inblock_st, inblock_end; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_READ || - aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_READ || + job->uaiocb.aio_lio_opcode == LIO_WRITE, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); td = curthread; td_savedcred = td->td_ucred; - td->td_ucred = aiocbe->cred; - cb = &aiocbe->uaiocb; - fp = aiocbe->fd_file; + td->td_ucred = job->cred; + cb = &job->uaiocb; + fp = job->fd_file; aiov.iov_base = (void *)(uintptr_t)cb->aio_buf; aiov.iov_len = cb->aio_nbytes; @@ -913,8 +913,8 @@ aio_process_rw(struct aiocblist *aiocbe) inblock_end = td->td_ru.ru_inblock; oublock_end = td->td_ru.ru_oublock; - aiocbe->inputcharge = inblock_end - inblock_st; - aiocbe->outputcharge = oublock_end - oublock_st; + job->inputcharge = inblock_end - inblock_st; + job->outputcharge = oublock_end - oublock_st; if ((error) && (auio.uio_resid != cnt)) { if (error == ERESTART || error == EINTR || error == EWOULDBLOCK) @@ -927,9 +927,9 @@ aio_process_rw(struct aiocblist *aiocbe) sigpipe = 0; } if (sigpipe) { - PROC_LOCK(aiocbe->userproc); - kern_psignal(aiocbe->userproc, SIGPIPE); - PROC_UNLOCK(aiocbe->userproc); + PROC_LOCK(job->userproc); + kern_psignal(job->userproc, SIGPIPE); + PROC_UNLOCK(job->userproc); } } } @@ -941,18 +941,18 @@ aio_process_rw(struct aiocblist *aiocbe) } static void -aio_process_sync(struct aiocblist *aiocbe) +aio_process_sync(struct kaiocb *job) { struct thread *td = curthread; struct ucred *td_savedcred = td->td_ucred; - struct aiocb *cb = &aiocbe->uaiocb; - struct file *fp = aiocbe->fd_file; + struct aiocb *cb = &job->uaiocb; + struct file *fp = job->fd_file; int error = 0; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_SYNC, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); - td->td_ucred = aiocbe->cred; + td->td_ucred = job->cred; if (fp->f_vnode != NULL) error = aio_fsync_vnode(td, fp->f_vnode); cb->_aiocb_private.error = error; @@ -961,31 +961,31 @@ aio_process_sync(struct aiocblist *aiocbe) } static void -aio_process_mlock(struct aiocblist *aiocbe) +aio_process_mlock(struct kaiocb *job) { - struct aiocb *cb = &aiocbe->uaiocb; + struct aiocb *cb = &job->uaiocb; int error; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_MLOCK, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_MLOCK, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); - error = vm_mlock(aiocbe->userproc, aiocbe->cred, + error = vm_mlock(job->userproc, job->cred, __DEVOLATILE(void *, cb->aio_buf), cb->aio_nbytes); cb->_aiocb_private.error = error; cb->_aiocb_private.status = 0; } static void -aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) +aio_bio_done_notify(struct proc *userp, struct kaiocb *job, int type) { struct aioliojob *lj; struct kaioinfo *ki; - struct aiocblist *scb, *scbn; + struct kaiocb *sjob, *sjobn; int lj_done; ki = userp->p_aioinfo; AIO_LOCK_ASSERT(ki, MA_OWNED); - lj = aiocbe->lio; + lj = job->lio; lj_done = 0; if (lj) { lj->lioj_finished_count++; @@ -993,21 +993,21 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) lj_done = 1; } if (type == DONE_QUEUE) { - aiocbe->jobflags |= AIOCBLIST_DONE; + job->jobflags |= KAIOCB_DONE; } else { - aiocbe->jobflags |= AIOCBLIST_BUFDONE; + job->jobflags |= KAIOCB_BUFDONE; } - TAILQ_INSERT_TAIL(&ki->kaio_done, aiocbe, plist); - aiocbe->jobstate = JOBST_JOBFINISHED; + TAILQ_INSERT_TAIL(&ki->kaio_done, job, plist); + job->jobstate = JOBST_JOBFINISHED; if (ki->kaio_flags & KAIO_RUNDOWN) goto notification_done; - if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || - aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) - aio_sendsig(userp, &aiocbe->uaiocb.aio_sigevent, &aiocbe->ksi); + if (job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || + job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) + aio_sendsig(userp, &job->uaiocb.aio_sigevent, &job->ksi); - KNOTE_LOCKED(&aiocbe->klist, 1); + KNOTE_LOCKED(&job->klist, 1); if (lj_done) { if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) { @@ -1024,16 +1024,16 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) } notification_done: - if (aiocbe->jobflags & AIOCBLIST_CHECKSYNC) { - TAILQ_FOREACH_SAFE(scb, &ki->kaio_syncqueue, list, scbn) { - if (aiocbe->fd_file == scb->fd_file && - aiocbe->seqno < scb->seqno) { - if (--scb->pending == 0) { + if (job->jobflags & KAIOCB_CHECKSYNC) { + TAILQ_FOREACH_SAFE(sjob, &ki->kaio_syncqueue, list, sjobn) { + if (job->fd_file == sjob->fd_file && + job->seqno < sjob->seqno) { + if (--sjob->pending == 0) { mtx_lock(&aio_job_mtx); - scb->jobstate = JOBST_JOBQGLOBAL; - TAILQ_REMOVE(&ki->kaio_syncqueue, scb, + sjob->jobstate = JOBST_JOBQGLOBAL; + TAILQ_REMOVE(&ki->kaio_syncqueue, sjob, list); - TAILQ_INSERT_TAIL(&aio_jobs, scb, list); + TAILQ_INSERT_TAIL(&aio_jobs, sjob, list); aio_kick_nowait(userp); mtx_unlock(&aio_job_mtx); } @@ -1047,10 +1047,10 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) } static void -aio_switch_vmspace(struct aiocblist *aiocbe) +aio_switch_vmspace(struct kaiocb *job) { - vmspace_switch_aio(aiocbe->userproc->p_vmspace); + vmspace_switch_aio(job->userproc->p_vmspace); } /* @@ -1060,7 +1060,7 @@ aio_switch_vmspace(struct aiocblist *aiocbe) static void aio_daemon(void *_id) { - struct aiocblist *aiocbe; + struct kaiocb *job; struct aioproc *aiop; struct kaioinfo *ki; struct proc *p, *userp; @@ -1105,28 +1105,28 @@ aio_daemon(void *_id) /* * Check for jobs. */ - while ((aiocbe = aio_selectjob(aiop)) != NULL) { + while ((job = aio_selectjob(aiop)) != NULL) { mtx_unlock(&aio_job_mtx); - userp = aiocbe->userproc; + userp = job->userproc; /* * Connect to process address space for user program. */ - aio_switch_vmspace(aiocbe); + aio_switch_vmspace(job); ki = userp->p_aioinfo; /* Do the I/O function. */ - switch(aiocbe->uaiocb.aio_lio_opcode) { + switch(job->uaiocb.aio_lio_opcode) { case LIO_READ: case LIO_WRITE: - aio_process_rw(aiocbe); + aio_process_rw(job); break; case LIO_SYNC: - aio_process_sync(aiocbe); + aio_process_sync(job); break; case LIO_MLOCK: - aio_process_mlock(aiocbe); + aio_process_mlock(job); break; } @@ -1136,8 +1136,8 @@ aio_daemon(void *_id) mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); - TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist); - aio_bio_done_notify(userp, aiocbe, DONE_QUEUE); + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + aio_bio_done_notify(userp, job, DONE_QUEUE); AIO_UNLOCK(ki); mtx_lock(&aio_job_mtx); @@ -1226,7 +1226,7 @@ aio_newproc(int *start) * duration of this call. */ static int -aio_qphysio(struct proc *p, struct aiocblist *aiocbe) +aio_qphysio(struct proc *p, struct kaiocb *job) { struct aiocb *cb; struct file *fp; @@ -1240,8 +1240,8 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) int error, ref, unmap, poff; vm_prot_t prot; - cb = &aiocbe->uaiocb; - fp = aiocbe->fd_file; + cb = &job->uaiocb; + fp = job->fd_file; if (fp == NULL || fp->f_type != DTYPE_VNODE) return (-1); @@ -1286,9 +1286,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) goto unref; } } - aiocbe->bp = bp = g_alloc_bio(); + job->bp = bp = g_alloc_bio(); if (!unmap) { - aiocbe->pbuf = pbuf = (struct buf *)getpbuf(NULL); + job->pbuf = pbuf = (struct buf *)getpbuf(NULL); BUF_KERNPROC(pbuf); } @@ -1296,12 +1296,12 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) ki->kaio_count++; if (!unmap) ki->kaio_buffer_count++; - lj = aiocbe->lio; + lj = job->lio; if (lj) lj->lioj_count++; - TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, aiocbe, plist); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); - aiocbe->jobstate = JOBST_JOBQBUF; + TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, job, plist); + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); + job->jobstate = JOBST_JOBQBUF; cb->_aiocb_private.status = cb->aio_nbytes; AIO_UNLOCK(ki); @@ -1312,25 +1312,25 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) bp->bio_offset = cb->aio_offset; bp->bio_cmd = cb->aio_lio_opcode == LIO_WRITE ? BIO_WRITE : BIO_READ; bp->bio_dev = dev; - bp->bio_caller1 = (void *)aiocbe; + bp->bio_caller1 = (void *)job; prot = VM_PROT_READ; if (cb->aio_lio_opcode == LIO_READ) prot |= VM_PROT_WRITE; /* Less backwards than it looks */ - if ((aiocbe->npages = vm_fault_quick_hold_pages( + if ((job->npages = vm_fault_quick_hold_pages( &curproc->p_vmspace->vm_map, - (vm_offset_t)bp->bio_data, bp->bio_length, prot, aiocbe->pages, - sizeof(aiocbe->pages)/sizeof(aiocbe->pages[0]))) < 0) { + (vm_offset_t)bp->bio_data, bp->bio_length, prot, job->pages, + sizeof(job->pages)/sizeof(job->pages[0]))) < 0) { error = EFAULT; goto doerror; } if (!unmap) { pmap_qenter((vm_offset_t)pbuf->b_data, - aiocbe->pages, aiocbe->npages); + job->pages, job->npages); bp->bio_data = pbuf->b_data + poff; } else { - bp->bio_ma = aiocbe->pages; - bp->bio_ma_n = aiocbe->npages; + bp->bio_ma = job->pages; + bp->bio_ma_n = job->npages; bp->bio_ma_offset = poff; bp->bio_data = unmapped_buf; bp->bio_flags |= BIO_UNMAPPED; @@ -1347,9 +1347,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) doerror: AIO_LOCK(ki); - aiocbe->jobstate = JOBST_NULL; - TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist); - TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist); + job->jobstate = JOBST_NULL; + TAILQ_REMOVE(&ki->kaio_bufqueue, job, plist); + TAILQ_REMOVE(&ki->kaio_all, job, allist); ki->kaio_count--; if (!unmap) ki->kaio_buffer_count--; @@ -1358,10 +1358,10 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) AIO_UNLOCK(ki); if (pbuf) { relpbuf(pbuf, NULL); - aiocbe->pbuf = NULL; + job->pbuf = NULL; } g_destroy_bio(bp); - aiocbe->bp = NULL; + job->bp = NULL; unref: dev_relthread(dev, ref); return (error); @@ -1373,7 +1373,7 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) static void aio_swake_cb(struct socket *so, struct sockbuf *sb) { - struct aiocblist *cb, *cbn; + struct kaiocb *job, *jobn; int opcode; SOCKBUF_LOCK_ASSERT(sb); @@ -1384,18 +1384,18 @@ aio_swake_cb(struct socket *so, struct sockbuf *sb) sb->sb_flags &= ~SB_AIO; mtx_lock(&aio_job_mtx); - TAILQ_FOREACH_SAFE(cb, &so->so_aiojobq, list, cbn) { - if (opcode == cb->uaiocb.aio_lio_opcode) { - if (cb->jobstate != JOBST_JOBQSOCK) + TAILQ_FOREACH_SAFE(job, &so->so_aiojobq, list, jobn) { + if (opcode == job->uaiocb.aio_lio_opcode) { + if (job->jobstate != JOBST_JOBQSOCK) panic("invalid queue value"); /* XXX * We don't have actual sockets backend yet, * so we simply move the requests to the generic * file I/O backend. */ - TAILQ_REMOVE(&so->so_aiojobq, cb, list); - TAILQ_INSERT_TAIL(&aio_jobs, cb, list); - aio_kick_nowait(cb->userproc); + TAILQ_REMOVE(&so->so_aiojobq, job, list); + TAILQ_INSERT_TAIL(&aio_jobs, job, list); + aio_kick_nowait(job->userproc); } } mtx_unlock(&aio_job_mtx); @@ -1515,14 +1515,14 @@ static struct aiocb_ops aiocb_ops_osigevent = { * technique is done in this code. */ int -aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, +aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, int type, struct aiocb_ops *ops) { struct proc *p = td->td_proc; cap_rights_t rights; struct file *fp; struct socket *so; - struct aiocblist *aiocbe, *cb; + struct kaiocb *job, *job2; struct kaioinfo *ki; struct kevent kev; struct sockbuf *sb; @@ -1537,57 +1537,57 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, ki = p->p_aioinfo; - ops->store_status(job, -1); - ops->store_error(job, 0); - ops->store_kernelinfo(job, -1); + ops->store_status(ujob, -1); + ops->store_error(ujob, 0); + ops->store_kernelinfo(ujob, -1); if (num_queue_count >= max_queue_count || ki->kaio_count >= ki->kaio_qallowed_count) { - ops->store_error(job, EAGAIN); + ops->store_error(ujob, EAGAIN); return (EAGAIN); } - aiocbe = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); - knlist_init_mtx(&aiocbe->klist, AIO_MTX(ki)); + job = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); + knlist_init_mtx(&job->klist, AIO_MTX(ki)); - error = ops->copyin(job, &aiocbe->uaiocb); + error = ops->copyin(ujob, &job->uaiocb); if (error) { - ops->store_error(job, error); - uma_zfree(aiocb_zone, aiocbe); + ops->store_error(ujob, error); + uma_zfree(aiocb_zone, job); return (error); } /* XXX: aio_nbytes is later casted to signed types. */ - if (aiocbe->uaiocb.aio_nbytes > INT_MAX) { - uma_zfree(aiocb_zone, aiocbe); + if (job->uaiocb.aio_nbytes > INT_MAX) { + uma_zfree(aiocb_zone, job); return (EINVAL); } - if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) { - ops->store_error(job, EINVAL); - uma_zfree(aiocb_zone, aiocbe); + if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) { + ops->store_error(ujob, EINVAL); + uma_zfree(aiocb_zone, job); return (EINVAL); } - if ((aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || - aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) && - !_SIG_VALID(aiocbe->uaiocb.aio_sigevent.sigev_signo)) { - uma_zfree(aiocb_zone, aiocbe); + if ((job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || + job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) && + !_SIG_VALID(job->uaiocb.aio_sigevent.sigev_signo)) { + uma_zfree(aiocb_zone, job); return (EINVAL); } - ksiginfo_init(&aiocbe->ksi); + ksiginfo_init(&job->ksi); /* Save userspace address of the job info. */ - aiocbe->uuaiocb = job; + job->ujob = ujob; /* Get the opcode. */ if (type != LIO_NOP) - aiocbe->uaiocb.aio_lio_opcode = type; - opcode = aiocbe->uaiocb.aio_lio_opcode; + job->uaiocb.aio_lio_opcode = type; + opcode = job->uaiocb.aio_lio_opcode; /* * Validate the opcode and fetch the file object for the specified @@ -1597,7 +1597,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, * retrieve a file descriptor without knowing what the capabiltity * should be. */ - fd = aiocbe->uaiocb.aio_fildes; + fd = job->uaiocb.aio_fildes; switch (opcode) { case LIO_WRITE: error = fget_write(td, fd, @@ -1620,8 +1620,8 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, error = EINVAL; } if (error) { - uma_zfree(aiocb_zone, aiocbe); - ops->store_error(job, error); + uma_zfree(aiocb_zone, job); + ops->store_error(ujob, error); return (error); } @@ -1630,60 +1630,60 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, goto aqueue_fail; } - if (opcode != LIO_SYNC && aiocbe->uaiocb.aio_offset == -1LL) { + if (opcode != LIO_SYNC && job->uaiocb.aio_offset == -1LL) { error = EINVAL; goto aqueue_fail; } - aiocbe->fd_file = fp; + job->fd_file = fp; mtx_lock(&aio_job_mtx); jid = jobrefid++; - aiocbe->seqno = jobseqno++; + job->seqno = jobseqno++; mtx_unlock(&aio_job_mtx); - error = ops->store_kernelinfo(job, jid); + error = ops->store_kernelinfo(ujob, jid); if (error) { error = EINVAL; goto aqueue_fail; } - aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid; + job->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid; if (opcode == LIO_NOP) { fdrop(fp, td); - uma_zfree(aiocb_zone, aiocbe); + uma_zfree(aiocb_zone, job); return (0); } - if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT) + if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT) goto no_kqueue; - evflags = aiocbe->uaiocb.aio_sigevent.sigev_notify_kevent_flags; + evflags = job->uaiocb.aio_sigevent.sigev_notify_kevent_flags; if ((evflags & ~(EV_CLEAR | EV_DISPATCH | EV_ONESHOT)) != 0) { error = EINVAL; goto aqueue_fail; } - kqfd = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue; - kev.ident = (uintptr_t)aiocbe->uuaiocb; + kqfd = job->uaiocb.aio_sigevent.sigev_notify_kqueue; + kev.ident = (uintptr_t)job->ujob; kev.filter = EVFILT_AIO; kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1 | evflags; - kev.data = (intptr_t)aiocbe; - kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sival_ptr; + kev.data = (intptr_t)job; + kev.udata = job->uaiocb.aio_sigevent.sigev_value.sival_ptr; error = kqfd_register(kqfd, &kev, td, 1); aqueue_fail: if (error) { if (fp) fdrop(fp, td); - uma_zfree(aiocb_zone, aiocbe); - ops->store_error(job, error); + uma_zfree(aiocb_zone, job); + ops->store_error(ujob, error); goto done; } no_kqueue: - ops->store_error(job, EINPROGRESS); - aiocbe->uaiocb._aiocb_private.error = EINPROGRESS; - aiocbe->userproc = p; - aiocbe->cred = crhold(td->td_ucred); - aiocbe->jobflags = 0; - aiocbe->lio = lj; + ops->store_error(ujob, EINPROGRESS); + job->uaiocb._aiocb_private.error = EINPROGRESS; + job->userproc = p; + job->cred = crhold(td->td_ucred); + job->jobflags = 0; + job->lio = lj; if (opcode == LIO_SYNC) goto queueit; @@ -1695,7 +1695,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, * socket is ready to be read or written (based on the requested * operation). * - * If it is not ready for io, then queue the aiocbe on the + * If it is not ready for io, then queue the job on the * socket, and set the flags so we get a call when sbnotify() * happens. * @@ -1710,13 +1710,13 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, sb->sb_flags |= SB_AIO; mtx_lock(&aio_job_mtx); - TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list); + TAILQ_INSERT_TAIL(&so->so_aiojobq, job, list); mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); - TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); - aiocbe->jobstate = JOBST_JOBQSOCK; + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); + TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist); + job->jobstate = JOBST_JOBQSOCK; ki->kaio_count++; if (lj) lj->lioj_count++; @@ -1729,12 +1729,12 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, SOCKBUF_UNLOCK(sb); } - if ((error = aio_qphysio(p, aiocbe)) == 0) + if ((error = aio_qphysio(p, job)) == 0) goto done; #if 0 if (error > 0) { - aiocbe->uaiocb._aiocb_private.error = error; - ops->store_error(job, error); + job->uaiocb._aiocb_private.error = error; + ops->store_error(ujob, error); goto done; } #endif @@ -1745,35 +1745,35 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, ki->kaio_count++; if (lj) lj->lioj_count++; - TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); + TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist); + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); if (opcode == LIO_SYNC) { - TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) { - if (cb->fd_file == aiocbe->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < aiocbe->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - aiocbe->pending++; + TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { + if (job2->fd_file == job->fd_file && + job2->uaiocb.aio_lio_opcode != LIO_SYNC && + job2->seqno < job->seqno) { + job2->jobflags |= KAIOCB_CHECKSYNC; + job->pending++; } } - TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) { - if (cb->fd_file == aiocbe->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < aiocbe->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - aiocbe->pending++; + TAILQ_FOREACH(job2, &ki->kaio_bufqueue, plist) { + if (job2->fd_file == job->fd_file && + job2->uaiocb.aio_lio_opcode != LIO_SYNC && + job2->seqno < job->seqno) { + job2->jobflags |= KAIOCB_CHECKSYNC; + job->pending++; } } - if (aiocbe->pending != 0) { - TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQSYNC; + if (job->pending != 0) { + TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); + job->jobstate = JOBST_JOBQSYNC; AIO_UNLOCK(ki); goto done; } } mtx_lock(&aio_job_mtx); - TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQGLOBAL; + TAILQ_INSERT_TAIL(&aio_jobs, job, list); + job->jobstate = JOBST_JOBQGLOBAL; aio_kick_nowait(p); mtx_unlock(&aio_job_mtx); AIO_UNLOCK(ki); @@ -1848,10 +1848,10 @@ aio_kick_helper(void *context, int pending) * released. */ static int -kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops) +kern_aio_return(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocblist *cb; + struct kaiocb *job; struct kaioinfo *ki; int status, error; @@ -1859,26 +1859,26 @@ kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops) if (ki == NULL) return (EINVAL); AIO_LOCK(ki); - TAILQ_FOREACH(cb, &ki->kaio_done, plist) { - if (cb->uuaiocb == uaiocb) + TAILQ_FOREACH(job, &ki->kaio_done, plist) { + if (job->ujob == ujob) break; } - if (cb != NULL) { - MPASS(cb->jobstate == JOBST_JOBFINISHED); - status = cb->uaiocb._aiocb_private.status; - error = cb->uaiocb._aiocb_private.error; + if (job != NULL) { + MPASS(job->jobstate == JOBST_JOBFINISHED); + status = job->uaiocb._aiocb_private.status; + error = job->uaiocb._aiocb_private.error; td->td_retval[0] = status; - if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { - td->td_ru.ru_oublock += cb->outputcharge; - cb->outputcharge = 0; - } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { - td->td_ru.ru_inblock += cb->inputcharge; - cb->inputcharge = 0; + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) { + td->td_ru.ru_oublock += job->outputcharge; + job->outputcharge = 0; + } else if (job->uaiocb.aio_lio_opcode == LIO_READ) { + td->td_ru.ru_inblock += job->inputcharge; + job->inputcharge = 0; } - aio_free_entry(cb); + aio_free_entry(job); AIO_UNLOCK(ki); - ops->store_error(uaiocb, error); - ops->store_status(uaiocb, status); + ops->store_error(ujob, error); + ops->store_status(ujob, status); } else { error = EINVAL; AIO_UNLOCK(ki); @@ -1903,7 +1903,7 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist, struct proc *p = td->td_proc; struct timeval atv; struct kaioinfo *ki; - struct aiocblist *cb, *cbfirst; + struct kaiocb *firstjob, *job; int error, i, timo; timo = 0; @@ -1926,20 +1926,20 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist, AIO_LOCK(ki); for (;;) { - cbfirst = NULL; + firstjob = NULL; error = 0; - TAILQ_FOREACH(cb, &ki->kaio_all, allist) { + TAILQ_FOREACH(job, &ki->kaio_all, allist) { for (i = 0; i < njoblist; i++) { - if (cb->uuaiocb == ujoblist[i]) { - if (cbfirst == NULL) - cbfirst = cb; - if (cb->jobstate == JOBST_JOBFINISHED) + if (job->ujob == ujoblist[i]) { + if (firstjob == NULL) + firstjob = job; + if (job->jobstate == JOBST_JOBFINISHED) goto RETURN; } } } /* All tasks were finished. */ - if (cbfirst == NULL) + if (firstjob == NULL) break; ki->kaio_flags |= KAIO_WAKEUP; @@ -1990,7 +1990,7 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) { struct proc *p = td->td_proc; struct kaioinfo *ki; - struct aiocblist *cbe, *cbn; + struct kaiocb *job, *jobn; struct file *fp; struct socket *so; cap_rights_t rights; @@ -2019,32 +2019,32 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) } AIO_LOCK(ki); - TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { - if ((uap->fd == cbe->uaiocb.aio_fildes) && + TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) { + if ((uap->fd == job->uaiocb.aio_fildes) && ((uap->aiocbp == NULL) || - (uap->aiocbp == cbe->uuaiocb))) { + (uap->aiocbp == job->ujob))) { remove = 0; mtx_lock(&aio_job_mtx); - if (cbe->jobstate == JOBST_JOBQGLOBAL) { - TAILQ_REMOVE(&aio_jobs, cbe, list); + if (job->jobstate == JOBST_JOBQGLOBAL) { + TAILQ_REMOVE(&aio_jobs, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSOCK) { + } else if (job->jobstate == JOBST_JOBQSOCK) { MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; - TAILQ_REMOVE(&so->so_aiojobq, cbe, list); + TAILQ_REMOVE(&so->so_aiojobq, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSYNC) { - TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); + } else if (job->jobstate == JOBST_JOBQSYNC) { + TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { - TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); - cbe->uaiocb._aiocb_private.status = -1; - cbe->uaiocb._aiocb_private.error = ECANCELED; - aio_bio_done_notify(p, cbe, DONE_QUEUE); + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + job->uaiocb._aiocb_private.status = -1; + job->uaiocb._aiocb_private.error = ECANCELED; + aio_bio_done_notify(p, job, DONE_QUEUE); cancelled++; } else { notcancelled++; @@ -2086,10 +2086,10 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) * a userland subroutine. */ static int -kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) +kern_aio_error(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocblist *cb; + struct kaiocb *job; struct kaioinfo *ki; int status; @@ -2100,11 +2100,11 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) } AIO_LOCK(ki); - TAILQ_FOREACH(cb, &ki->kaio_all, allist) { - if (cb->uuaiocb == aiocbp) { - if (cb->jobstate == JOBST_JOBFINISHED) + TAILQ_FOREACH(job, &ki->kaio_all, allist) { + if (job->ujob == ujob) { + if (job->jobstate == JOBST_JOBFINISHED) td->td_retval[0] = - cb->uaiocb._aiocb_private.error; + job->uaiocb._aiocb_private.error; else td->td_retval[0] = EINPROGRESS; AIO_UNLOCK(ki); @@ -2116,9 +2116,9 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) /* * Hack for failure of aio_aqueue. */ - status = ops->fetch_status(aiocbp); + status = ops->fetch_status(ujob); if (status == -1) { - td->td_retval[0] = ops->fetch_error(aiocbp); + td->td_retval[0] = ops->fetch_error(ujob); return (0); } @@ -2178,7 +2178,7 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocb *iocb; + struct aiocb *job; struct kaioinfo *ki; struct aioliojob *lj; struct kevent kev; @@ -2254,9 +2254,9 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list, */ nerror = 0; for (i = 0; i < nent; i++) { - iocb = acb_list[i]; - if (iocb != NULL) { - error = aio_aqueue(td, iocb, lj, LIO_NOP, ops); + job = acb_list[i]; + if (job != NULL) { + error = aio_aqueue(td, job, lj, LIO_NOP, ops); if (error != 0) nerror++; } @@ -2379,37 +2379,37 @@ sys_lio_listio(struct thread *td, struct lio_listio_args *uap) static void aio_physwakeup(struct bio *bp) { - struct aiocblist *aiocbe = (struct aiocblist *)bp->bio_caller1; + struct kaiocb *job = (struct kaiocb *)bp->bio_caller1; struct proc *userp; struct kaioinfo *ki; int nblks; /* Release mapping into kernel space. */ - if (aiocbe->pbuf) { - pmap_qremove((vm_offset_t)aiocbe->pbuf->b_data, aiocbe->npages); - relpbuf(aiocbe->pbuf, NULL); - aiocbe->pbuf = NULL; + if (job->pbuf) { + pmap_qremove((vm_offset_t)job->pbuf->b_data, job->npages); + relpbuf(job->pbuf, NULL); + job->pbuf = NULL; atomic_subtract_int(&num_buf_aio, 1); } - vm_page_unhold_pages(aiocbe->pages, aiocbe->npages); + vm_page_unhold_pages(job->pages, job->npages); - bp = aiocbe->bp; - aiocbe->bp = NULL; - userp = aiocbe->userproc; + bp = job->bp; + job->bp = NULL; + userp = job->userproc; ki = userp->p_aioinfo; AIO_LOCK(ki); - aiocbe->uaiocb._aiocb_private.status -= bp->bio_resid; - aiocbe->uaiocb._aiocb_private.error = 0; + job->uaiocb._aiocb_private.status -= bp->bio_resid; + job->uaiocb._aiocb_private.error = 0; if (bp->bio_flags & BIO_ERROR) - aiocbe->uaiocb._aiocb_private.error = bp->bio_error; - nblks = btodb(aiocbe->uaiocb.aio_nbytes); - if (aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE) - aiocbe->outputcharge += nblks; + job->uaiocb._aiocb_private.error = bp->bio_error; + nblks = btodb(job->uaiocb.aio_nbytes); + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) + job->outputcharge += nblks; else - aiocbe->inputcharge += nblks; - TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, aiocbe, plist); + job->inputcharge += nblks; + TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, job, plist); ki->kaio_buffer_count--; - aio_bio_done_notify(userp, aiocbe, DONE_BUF); + aio_bio_done_notify(userp, job, DONE_BUF); AIO_UNLOCK(ki); g_destroy_bio(bp); @@ -2417,17 +2417,17 @@ aio_physwakeup(struct bio *bp) /* syscall - wait for the next completion of an aio request */ static int -kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, +kern_aio_waitcomplete(struct thread *td, struct aiocb **ujobp, struct timespec *ts, struct aiocb_ops *ops) { struct proc *p = td->td_proc; struct timeval atv; struct kaioinfo *ki; - struct aiocblist *cb; - struct aiocb *uuaiocb; + struct kaiocb *job; + struct aiocb *ujob; int error, status, timo; - ops->store_aiocb(aiocbp, NULL); + ops->store_aiocb(ujobp, NULL); if (ts == NULL) { timo = 0; @@ -2448,9 +2448,9 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, ki = p->p_aioinfo; error = 0; - cb = NULL; + job = NULL; AIO_LOCK(ki); - while ((cb = TAILQ_FIRST(&ki->kaio_done)) == NULL) { + while ((job = TAILQ_FIRST(&ki->kaio_done)) == NULL) { if (timo == -1) { error = EWOULDBLOCK; break; @@ -2464,24 +2464,24 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, break; } - if (cb != NULL) { - MPASS(cb->jobstate == JOBST_JOBFINISHED); - uuaiocb = cb->uuaiocb; - status = cb->uaiocb._aiocb_private.status; - error = cb->uaiocb._aiocb_private.error; + if (job != NULL) { + MPASS(job->jobstate == JOBST_JOBFINISHED); + ujob = job->ujob; + status = job->uaiocb._aiocb_private.status; + error = job->uaiocb._aiocb_private.error; td->td_retval[0] = status; - if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { - td->td_ru.ru_oublock += cb->outputcharge; - cb->outputcharge = 0; - } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { - td->td_ru.ru_inblock += cb->inputcharge; - cb->inputcharge = 0; + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) { + td->td_ru.ru_oublock += job->outputcharge; + job->outputcharge = 0; + } else if (job->uaiocb.aio_lio_opcode == LIO_READ) { + td->td_ru.ru_inblock += job->inputcharge; + job->inputcharge = 0; } - aio_free_entry(cb); + aio_free_entry(job); AIO_UNLOCK(ki); - ops->store_aiocb(aiocbp, uuaiocb); - ops->store_error(uuaiocb, error); - ops->store_status(uuaiocb, status); + ops->store_aiocb(ujobp, ujob); + ops->store_error(ujob, error); + ops->store_status(ujob, status); } else AIO_UNLOCK(ki); @@ -2507,7 +2507,7 @@ sys_aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) } static int -kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp, +kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; @@ -2518,7 +2518,7 @@ kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp, ki = p->p_aioinfo; if (ki == NULL) aio_init_aioinfo(p); - return (aio_aqueue(td, aiocbp, NULL, LIO_SYNC, ops)); + return (aio_aqueue(td, ujob, NULL, LIO_SYNC, ops)); } int @@ -2532,19 +2532,19 @@ sys_aio_fsync(struct thread *td, struct aio_fsync_args *uap) static int filt_aioattach(struct knote *kn) { - struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; + struct kaiocb *job = (struct kaiocb *)kn->kn_sdata; /* - * The aiocbe pointer must be validated before using it, so + * The job pointer must be validated before using it, so * registration is restricted to the kernel; the user cannot * set EV_FLAG1. */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); - kn->kn_ptr.p_aio = aiocbe; + kn->kn_ptr.p_aio = job; kn->kn_flags &= ~EV_FLAG1; - knlist_add(&aiocbe->klist, kn, 0); + knlist_add(&job->klist, kn, 0); return (0); } @@ -2567,10 +2567,10 @@ filt_aiodetach(struct knote *kn) static int filt_aio(struct knote *kn, long hint) { - struct aiocblist *aiocbe = kn->kn_ptr.p_aio; + struct kaiocb *job = kn->kn_ptr.p_aio; - kn->kn_data = aiocbe->uaiocb._aiocb_private.error; - if (aiocbe->jobstate != JOBST_JOBFINISHED) + kn->kn_data = job->uaiocb._aiocb_private.error; + if (job->jobstate != JOBST_JOBFINISHED) return (0); kn->kn_flags |= EV_EOF; return (1); diff --git a/sys/sys/event.h b/sys/sys/event.h index 35aad99899e3..7897c818cb0e 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -222,7 +222,7 @@ struct knote { union { struct file *p_fp; /* file data pointer */ struct proc *p_proc; /* proc pointer */ - struct aiocblist *p_aio; /* AIO job pointer */ + struct kaiocb *p_aio; /* AIO job pointer */ struct aioliojob *p_lio; /* LIO job pointer */ sbintime_t *p_nexttime; /* next timer event fires at */ void *p_v; /* generic other pointer */ diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 55a7950cebb7..f101849eb92d 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -104,7 +104,7 @@ struct socket { struct sigio *so_sigio; /* [sg] information for async I/O or out of band data (SIGURG) */ u_long so_oobmark; /* (c) chars to oob mark */ - TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */ + TAILQ_HEAD(, kaiocb) so_aiojobq; /* AIO ops waiting on socket */ struct sockbuf so_rcv, so_snd; From 860ed9e53f6883401334547dea3fcede88e39d50 Mon Sep 17 00:00:00 2001 From: emaste Date: Fri, 5 Feb 2016 20:54:51 +0000 Subject: [PATCH 226/236] readelf: avoid accidental fallthrough in RISC-V relocations This would have printed an unknown RISC-V relocation type as a SPARC relocation. CID: 1331398 Obtained from: ELF Tool Chain r3283 Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/readelf/readelf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 6902024725af..7e9343e30d08 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1452,6 +1452,7 @@ r_type(unsigned int mach, unsigned int type) case 43: return "R_RISCV_ALIGN"; case 44: return "R_RISCV_RVC_BRANCH"; case 45: return "R_RISCV_RVC_JUMP"; + default: return ""; } case EM_SPARC: case EM_SPARCV9: From e76c56eec876ba994cae09d2d465992d9be5d093 Mon Sep 17 00:00:00 2001 From: emaste Date: Fri, 5 Feb 2016 20:56:11 +0000 Subject: [PATCH 227/236] readelf: report value of unknown relocation types Obtained from: ELF Tool Chain r3387 Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/readelf/readelf.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 7e9343e30d08..c2779ba16c4e 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1053,8 +1053,9 @@ static struct { static const char * r_type(unsigned int mach, unsigned int type) { + static char s_type[32]; + switch(mach) { - case EM_NONE: return ""; case EM_386: case EM_IAMCU: switch(type) { @@ -1089,8 +1090,8 @@ r_type(unsigned int mach, unsigned int type) case 35: return "R_386_TLS_DTPMOD32"; case 36: return "R_386_TLS_DTPOFF32"; case 37: return "R_386_TLS_TPOFF32"; - default: return ""; } + break; case EM_AARCH64: switch(type) { case 0: return "R_AARCH64_NONE"; @@ -1154,8 +1155,8 @@ r_type(unsigned int mach, unsigned int type) case 1030: return "R_AARCH64_TLS_TPREL64"; case 1031: return "R_AARCH64_TLSDESC"; case 1032: return "R_AARCH64_IRELATIVE"; - default: return ""; } + break; case EM_ARM: switch(type) { case 0: return "R_ARM_NONE"; @@ -1206,8 +1207,8 @@ r_type(unsigned int mach, unsigned int type) case 253: return "R_ARM_RABS32"; case 254: return "R_ARM_RPC24"; case 255: return "R_ARM_RBASE"; - default: return ""; } + break; case EM_IA_64: switch(type) { case 0: return "R_IA_64_NONE"; @@ -1290,8 +1291,8 @@ r_type(unsigned int mach, unsigned int type) case 182: return "R_IA_64_DTPREL64MSB"; case 183: return "R_IA_64_DTPREL64LSB"; case 186: return "R_IA_64_LTOFF_DTPREL22"; - default: return ""; } + break; case EM_MIPS: switch(type) { case 0: return "R_MIPS_NONE"; @@ -1324,9 +1325,8 @@ r_type(unsigned int mach, unsigned int type) case 48: return "R_MIPS_TLS_TPREL64"; case 49: return "R_MIPS_TLS_TPREL_HI16"; case 50: return "R_MIPS_TLS_TPREL_LO16"; - - default: return ""; } + break; case EM_PPC: switch(type) { case 0: return "R_PPC_NONE"; @@ -1406,8 +1406,8 @@ r_type(unsigned int mach, unsigned int type) case 114: return "R_PPC_EMB_RELST_HA"; case 115: return "R_PPC_EMB_BIT_FLD"; case 116: return "R_PPC_EMB_RELSDA"; - default: return ""; } + break; case EM_RISCV: switch(type) { case 0: return "R_RISCV_NONE"; @@ -1452,8 +1452,8 @@ r_type(unsigned int mach, unsigned int type) case 43: return "R_RISCV_ALIGN"; case 44: return "R_RISCV_RVC_BRANCH"; case 45: return "R_RISCV_RVC_JUMP"; - default: return ""; } + break; case EM_SPARC: case EM_SPARCV9: switch(type) { @@ -1537,8 +1537,8 @@ r_type(unsigned int mach, unsigned int type) case 77: return "R_SPARC_TLS_DTPOFF64"; case 78: return "R_SPARC_TLS_TPOFF32"; case 79: return "R_SPARC_TLS_TPOFF64"; - default: return ""; } + break; case EM_X86_64: switch(type) { case 0: return "R_X86_64_NONE"; @@ -1579,10 +1579,12 @@ r_type(unsigned int mach, unsigned int type) case 35: return "R_X86_64_TLSDESC_CALL"; case 36: return "R_X86_64_TLSDESC"; case 37: return "R_X86_64_IRELATIVE"; - default: return ""; } - default: return ""; + break; } + + snprintf(s_type, sizeof(s_type), "", type); + return (s_type); } static const char * From 752d332a4b9c16a487f568188302b49395f489b5 Mon Sep 17 00:00:00 2001 From: emaste Date: Fri, 5 Feb 2016 20:57:21 +0000 Subject: [PATCH 228/236] readelf: decode AArch64 TLS descriptor relocations From ELF for the ARM(R) 64-bit Architecture, table 4-19. Obtained from: ELF Tool Chain r3386 Sponsored by: The FreeBSD Foundation --- contrib/elftoolchain/readelf/readelf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index c2779ba16c4e..a0170234fb07 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1146,6 +1146,16 @@ r_type(unsigned int mach, unsigned int type) case 311: return "R_AARCH64_ADR_GOT_PAGE"; case 312: return "R_AARCH64_LD64_GOT_LO12_NC"; case 313: return "R_AARCH64_LD64_GOTPAGE_LO15"; + case 560: return "R_AARCH64_TLSDESC_LD_PREL19"; + case 561: return "R_AARCH64_TLSDESC_ADR_PREL21"; + case 562: return "R_AARCH64_TLSDESC_ADR_PAGE21"; + case 563: return "R_AARCH64_TLSDESC_LD64_LO12"; + case 564: return "R_AARCH64_TLSDESC_ADD_LO12"; + case 565: return "R_AARCH64_TLSDESC_OFF_G1"; + case 566: return "R_AARCH64_TLSDESC_OFF_G0_NC"; + case 567: return "R_AARCH64_TLSDESC_LDR"; + case 568: return "R_AARCH64_TLSDESC_ADD"; + case 569: return "R_AARCH64_TLSDESC_CALL"; case 1024: return "R_AARCH64_COPY"; case 1025: return "R_AARCH64_GLOB_DAT"; case 1026: return "R_AARCH64_JUMP_SLOT"; From e7ca06fef133f827bef89f564ac7e91b6d423ee7 Mon Sep 17 00:00:00 2001 From: glebius Date: Fri, 5 Feb 2016 21:57:50 +0000 Subject: [PATCH 229/236] Provide a future release as an example, instead of a historical one. --- usr.sbin/freebsd-update/freebsd-update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh index cce2af574f61..feb8db6a6b3c 100644 --- a/usr.sbin/freebsd-update/freebsd-update.sh +++ b/usr.sbin/freebsd-update/freebsd-update.sh @@ -45,7 +45,7 @@ Options: (default: /etc/freebsd-update.conf) -F -- Force a fetch operation to proceed -k KEY -- Trust an RSA key with SHA256 hash of KEY - -r release -- Target for upgrade (e.g., 6.2-RELEASE) + -r release -- Target for upgrade (e.g., 11.1-RELEASE) -s server -- Server from which to fetch updates (default: update.FreeBSD.org) -t address -- Mail output of cron command, if any, to address From ebde2e6348e8c51b90136123557364880f072efb Mon Sep 17 00:00:00 2001 From: ngie Date: Fri, 5 Feb 2016 23:50:15 +0000 Subject: [PATCH 230/236] Require /bin/getfacl and /bin/setfacl when running the acl tests For cases where these utilities aren't installed, the tests would fail today in a non-intuitive manner on sub-testcase #3 in each of the test scripts MFC after: 1 week Reviewed by: markj Sponsored by: EMC / Isilon Storage Division --- tests/sys/acl/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/sys/acl/Makefile b/tests/sys/acl/Makefile index 298b0a27c91d..3f40bb2eb5d2 100644 --- a/tests/sys/acl/Makefile +++ b/tests/sys/acl/Makefile @@ -22,8 +22,14 @@ TAP_TESTS_SH+= 04 TEST_METADATA.$t+= required_user="root" .endfor +_ACL_PROGS= /bin/getfacl /bin/setfacl + .for t in 01 03 04 -TEST_METADATA.$t+= required_programs="/sbin/zpool" +TEST_METADATA.$t+= required_programs="/sbin/zpool ${_ACL_PROGS}" +.endfor + +.for t in 00 02 +TEST_METADATA.$t+= required_programs="${_ACL_PROGS}" .endfor .include From 0e082dce884fa04860090796745506c7bbcfadca Mon Sep 17 00:00:00 2001 From: dteske Date: Sat, 6 Feb 2016 02:16:48 +0000 Subject: [PATCH 231/236] Allow rc_conf_files to be redefined in rc.conf(5) With this change, it's possible to redefine rc_conf_files (e.g., sysrc rc_conf_files+=/etc/rc.conf.other) and have the boot process pick up settings in extra files. The sysrc(8) tool can be used to query/enumerate/find/manage extra files configured in this manner. Relnotes: yes --- etc/defaults/rc.conf | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index a674acb97532..f8ca47fbf917 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -716,5 +716,17 @@ if [ -z "${source_rc_confs_defined}" ]; then ;; esac done + for i in ${rc_conf_files}; do + case ${sourced_files} in + *:$i:*) + ;; + *) + sourced_files="${sourced_files}:$i:" + if [ -r $i ]; then + . $i + fi + ;; + esac + done } fi From d6e962f26838a991c43b1f03ba2051ebb6eb8e3a Mon Sep 17 00:00:00 2001 From: dteske Date: Sat, 6 Feb 2016 02:32:13 +0000 Subject: [PATCH 232/236] Add comment to explain functionality of code Thanks to: rpokala --- etc/defaults/rc.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index f8ca47fbf917..5e412914a284 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -716,6 +716,7 @@ if [ -z "${source_rc_confs_defined}" ]; then ;; esac done + # Re-do process to pick up [possibly] redined $rc_conf_files for i in ${rc_conf_files}; do case ${sourced_files} in *:$i:*) From 4bbbf067b6deab87d1277c494cd3381f2e946d20 Mon Sep 17 00:00:00 2001 From: dteske Date: Sat, 6 Feb 2016 02:35:52 +0000 Subject: [PATCH 233/236] Fix typo in a comment; s/redined/redefined/ Thanks to: rpokala --- etc/defaults/rc.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 5e412914a284..69b6d0f77bd0 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -716,7 +716,7 @@ if [ -z "${source_rc_confs_defined}" ]; then ;; esac done - # Re-do process to pick up [possibly] redined $rc_conf_files + # Re-do process to pick up [possibly] redefined $rc_conf_files for i in ${rc_conf_files}; do case ${sourced_files} in *:$i:*) From 226a73a2862dc1daac539ae5c5c774fde539b95d Mon Sep 17 00:00:00 2001 From: ngie Date: Sat, 6 Feb 2016 04:13:20 +0000 Subject: [PATCH 234/236] Use basenames for getfacl, setfacl, and zpool to work around the fact that Jenkins hardcodes image sizes to 2GB with the FreeBSD_HEAD job This is to stop the unnecessary failure emails because we've gone over the 2GB limit MFC after: 1 week X-MFC with: r295341 Sponsored by: EMC / Isilon Storage Division --- tests/sys/acl/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sys/acl/Makefile b/tests/sys/acl/Makefile index 3f40bb2eb5d2..d101088dcd3f 100644 --- a/tests/sys/acl/Makefile +++ b/tests/sys/acl/Makefile @@ -22,10 +22,10 @@ TAP_TESTS_SH+= 04 TEST_METADATA.$t+= required_user="root" .endfor -_ACL_PROGS= /bin/getfacl /bin/setfacl +_ACL_PROGS= getfacl setfacl .for t in 01 03 04 -TEST_METADATA.$t+= required_programs="/sbin/zpool ${_ACL_PROGS}" +TEST_METADATA.$t+= required_programs="zpool ${_ACL_PROGS}" .endfor .for t in 00 02 From 8d5e31f3ba87dc161a50367594ff6db3941b9a0d Mon Sep 17 00:00:00 2001 From: mjg Date: Sat, 6 Feb 2016 09:01:03 +0000 Subject: [PATCH 235/236] fork: ansify sys_pdfork No functional changes. --- sys/kern/kern_fork.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 5bb14e8b4adb..9abe08c037c5 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -117,9 +117,7 @@ sys_fork(struct thread *td, struct fork_args *uap) /* ARGUSED */ int -sys_pdfork(td, uap) - struct thread *td; - struct pdfork_args *uap; +sys_pdfork(struct thread *td, struct pdfork_args *uap) { struct fork_req fr; int error, fd, pid; From 1cb81502033e8887257dd52c0b57721abdd24839 Mon Sep 17 00:00:00 2001 From: mmel Date: Sat, 6 Feb 2016 11:16:15 +0000 Subject: [PATCH 236/236] ARM: Rename remaining ARMv4 specific function in DTrace code. I missed it in r295319. Pointed by: tuexen --- sys/cddl/dev/fbt/arm/fbt_isa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/dev/fbt/arm/fbt_isa.c b/sys/cddl/dev/fbt/arm/fbt_isa.c index 0e948dd90979..2e0e5a5eae10 100644 --- a/sys/cddl/dev/fbt/arm/fbt_isa.c +++ b/sys/cddl/dev/fbt/arm/fbt_isa.c @@ -83,7 +83,7 @@ fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) { *fbt->fbtp_patchpoint = val; - cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val)); + icache_sync((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val)); } int