diff --git a/Makefile b/Makefile index acb061bf8a74..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 @@ -328,7 +329,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 +340,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 # diff --git a/Makefile.inc1 b/Makefile.inc1 index ad3e0fe24072..87de0621acb6 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 @@ -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 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/bin/csh/Makefile b/bin/csh/Makefile index 51ef3dd9c306..deb63478727d 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 +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 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 *); diff --git a/bin/dd/args.c b/bin/dd/args.c index 2f197f8da505..1cbf3b374cf1 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -360,6 +360,46 @@ 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 '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); + break; + } + + return (mult); +} + /* * Convert an expression of the following forms to a uintmax_t. * 1) A positive decimal number. @@ -386,31 +426,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 +476,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; 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 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; 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. 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 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); } 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; diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 6902024725af..a0170234fb07 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"; @@ -1145,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"; @@ -1154,8 +1165,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 +1217,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 +1301,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 +1335,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 +1416,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"; @@ -1453,6 +1463,7 @@ r_type(unsigned int mach, unsigned int type) case 44: return "R_RISCV_RVC_BRANCH"; case 45: return "R_RISCV_RVC_JUMP"; } + break; case EM_SPARC: case EM_SPARCV9: switch(type) { @@ -1536,8 +1547,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"; @@ -1578,10 +1589,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 * 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/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 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" 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 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 - 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 diff --git a/crypto/openssl/ACKNOWLEDGMENTS b/crypto/openssl/ACKNOWLEDGMENTS index 59c6f01f97f6..d21dccbb79cf 100644 --- a/crypto/openssl/ACKNOWLEDGMENTS +++ b/crypto/openssl/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/crypto/openssl/CHANGES b/crypto/openssl/CHANGES index 5e9225b57cd9..18693f70efe9 100644 --- a/crypto/openssl/CHANGES +++ b/crypto/openssl/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/crypto/openssl/Configure b/crypto/openssl/Configure index ac86cd6cf6a2..4a715dc43732 100755 --- a/crypto/openssl/Configure +++ b/crypto/openssl/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/crypto/openssl/LICENSE b/crypto/openssl/LICENSE index e47d101f1025..fb03713dd111 100644 --- a/crypto/openssl/LICENSE +++ b/crypto/openssl/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/crypto/openssl/Makefile b/crypto/openssl/Makefile index e2bbb475c7df..ee04c02cc1ca 100644 --- a/crypto/openssl/Makefile +++ b/crypto/openssl/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/crypto/openssl/Makefile.org b/crypto/openssl/Makefile.org index f16770d69b22..15c1c9f54428 100644 --- a/crypto/openssl/Makefile.org +++ b/crypto/openssl/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/crypto/openssl/NEWS b/crypto/openssl/NEWS index e1c78f834f08..06c77025e999 100644 --- a/crypto/openssl/NEWS +++ b/crypto/openssl/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/crypto/openssl/README b/crypto/openssl/README index 49c4c9f147c3..1e9869daee00 100644 --- a/crypto/openssl/README +++ b/crypto/openssl/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/crypto/openssl/apps/engine.c b/crypto/openssl/apps/engine.c index 460ec60cb14c..f54631b50d81 100644 --- a/crypto/openssl/apps/engine.c +++ b/crypto/openssl/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/crypto/openssl/apps/ocsp.c b/crypto/openssl/apps/ocsp.c index 6ed255d4b563..5da51df5148c 100644 --- a/crypto/openssl/apps/ocsp.c +++ b/crypto/openssl/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/crypto/openssl/apps/pkcs12.c b/crypto/openssl/apps/pkcs12.c index e41b445a50b0..cbb75b7d5fe4 100644 --- a/crypto/openssl/apps/pkcs12.c +++ b/crypto/openssl/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/crypto/openssl/apps/pkeyutl.c b/crypto/openssl/apps/pkeyutl.c index aaa90740ad4d..c8d513b44ac4 100644 --- a/crypto/openssl/apps/pkeyutl.c +++ b/crypto/openssl/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/crypto/openssl/apps/s_client.c b/crypto/openssl/apps/s_client.c index f80711fd5e58..caf76d35dc5a 100644 --- a/crypto/openssl/apps/s_client.c +++ b/crypto/openssl/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/crypto/openssl/apps/s_server.c b/crypto/openssl/apps/s_server.c index f19532b75fab..65cbaaf6eb9b 100644 --- a/crypto/openssl/apps/s_server.c +++ b/crypto/openssl/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/crypto/openssl/apps/speed.c b/crypto/openssl/apps/speed.c index 3697b71ec18b..95adcc19cc15 100644 --- a/crypto/openssl/apps/speed.c +++ b/crypto/openssl/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/crypto/openssl/apps/x509.c b/crypto/openssl/apps/x509.c index 864a60dda2e7..7c215bced001 100644 --- a/crypto/openssl/apps/x509.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes.h b/crypto/openssl/crypto/aes/aes.h index 87bf60f6f2bf..faa66c49148f 100644 --- a/crypto/openssl/crypto/aes/aes.h +++ b/crypto/openssl/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/openssl/crypto/aes/aes_cbc.c b/crypto/openssl/crypto/aes/aes_cbc.c index e39231f17cb8..805d0e260a6f 100644 --- a/crypto/openssl/crypto/aes/aes_cbc.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_cfb.c b/crypto/openssl/crypto/aes/aes_cfb.c index 1c79ce2dbaa1..1225000963ea 100644 --- a/crypto/openssl/crypto/aes/aes_cfb.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_core.c b/crypto/openssl/crypto/aes/aes_core.c index 2ddb0860d78a..7019b5d7aa3a 100644 --- a/crypto/openssl/crypto/aes/aes_core.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_ctr.c b/crypto/openssl/crypto/aes/aes_ctr.c index 3ee382299881..9e760c4b12ad 100644 --- a/crypto/openssl/crypto/aes/aes_ctr.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_ecb.c b/crypto/openssl/crypto/aes/aes_ecb.c index 2e0d20ca224e..52151a5c70f4 100644 --- a/crypto/openssl/crypto/aes/aes_ecb.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_ige.c b/crypto/openssl/crypto/aes/aes_ige.c index cf31c9bba44a..8f2b7706472a 100644 --- a/crypto/openssl/crypto/aes/aes_ige.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_locl.h b/crypto/openssl/crypto/aes/aes_locl.h index fabfd02ac095..7acd74ec1603 100644 --- a/crypto/openssl/crypto/aes/aes_locl.h +++ b/crypto/openssl/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/openssl/crypto/aes/aes_misc.c b/crypto/openssl/crypto/aes/aes_misc.c index ab948ad85eb4..fafad4d6f57a 100644 --- a/crypto/openssl/crypto/aes/aes_misc.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_ofb.c b/crypto/openssl/crypto/aes/aes_ofb.c index e6153f99ba70..64a08caaec6d 100644 --- a/crypto/openssl/crypto/aes/aes_ofb.c +++ b/crypto/openssl/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/openssl/crypto/aes/aes_x86core.c b/crypto/openssl/crypto/aes/aes_x86core.c index c869ed719852..b5dd6976772a 100644 --- a/crypto/openssl/crypto/aes/aes_x86core.c +++ b/crypto/openssl/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/openssl/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl index 5a100fa8983b..d7ad7882c4ee 100755 --- a/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl index c803cdebc112..8c84260856e1 100755 --- a/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl index bfe29268c781..72f44ecf6253 100755 --- a/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/bio/bio.h b/crypto/openssl/crypto/bio/bio.h index f78796b069f5..6e2293bc66da 100644 --- a/crypto/openssl/crypto/bio/bio.h +++ b/crypto/openssl/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/openssl/crypto/bio/bss_bio.c b/crypto/openssl/crypto/bio/bss_bio.c index d629a37a5a1d..4d8727f8f890 100644 --- a/crypto/openssl/crypto/bio/bss_bio.c +++ b/crypto/openssl/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/openssl/crypto/bio/bss_conn.c b/crypto/openssl/crypto/bio/bss_conn.c index 42d0afffbc6c..7d15ad29dcd7 100644 --- a/crypto/openssl/crypto/bio/bss_conn.c +++ b/crypto/openssl/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/openssl/crypto/bio/bss_dgram.c b/crypto/openssl/crypto/bio/bss_dgram.c index 7fcd831da06b..bdd7bf88ea0e 100644 --- a/crypto/openssl/crypto/bio/bss_dgram.c +++ b/crypto/openssl/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/openssl/crypto/bn/asm/rsaz-x86_64.pl b/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl index 12b571c282dc..091cdc2069da 100755 --- a/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/bn/asm/x86_64-mont.pl b/crypto/openssl/crypto/bn/asm/x86_64-mont.pl index 725833d022e2..e82e451388c7 100755 --- a/crypto/openssl/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/openssl/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/openssl/crypto/bn/asm/x86_64-mont5.pl b/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl index 64e668f140c2..292409c4ffb8 100755 --- a/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/openssl/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/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c index 50cf3231b07b..6d30d1e0fff5 100644 --- a/crypto/openssl/crypto/bn/bn_exp.c +++ b/crypto/openssl/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/openssl/crypto/bn/exptest.c b/crypto/openssl/crypto/bn/exptest.c index 8b3a4bae4328..ac611c2e2614 100644 --- a/crypto/openssl/crypto/bn/exptest.c +++ b/crypto/openssl/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/openssl/crypto/camellia/camellia.c b/crypto/openssl/crypto/camellia/camellia.c index b4a6766c623c..719fa61cf627 100644 --- a/crypto/openssl/crypto/camellia/camellia.c +++ b/crypto/openssl/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/openssl/crypto/camellia/camellia.h b/crypto/openssl/crypto/camellia/camellia.h index 9be7c0fd9996..45e8d25b1dd5 100644 --- a/crypto/openssl/crypto/camellia/camellia.h +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_cbc.c b/crypto/openssl/crypto/camellia/cmll_cbc.c index a4907ca05f78..4017e00d9272 100644 --- a/crypto/openssl/crypto/camellia/cmll_cbc.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_cfb.c b/crypto/openssl/crypto/camellia/cmll_cfb.c index 59b85225c35e..78f2ae4566b1 100644 --- a/crypto/openssl/crypto/camellia/cmll_cfb.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_ctr.c b/crypto/openssl/crypto/camellia/cmll_ctr.c index b8f523d44648..95e26621b7d8 100644 --- a/crypto/openssl/crypto/camellia/cmll_ctr.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_ecb.c b/crypto/openssl/crypto/camellia/cmll_ecb.c index 16f1af86ac38..b030791b275c 100644 --- a/crypto/openssl/crypto/camellia/cmll_ecb.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_locl.h b/crypto/openssl/crypto/camellia/cmll_locl.h index 4e4707b6213e..2bd79b8c4eb3 100644 --- a/crypto/openssl/crypto/camellia/cmll_locl.h +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_misc.c b/crypto/openssl/crypto/camellia/cmll_misc.c index cbd250227bec..694d2fac8f1f 100644 --- a/crypto/openssl/crypto/camellia/cmll_misc.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_ofb.c b/crypto/openssl/crypto/camellia/cmll_ofb.c index 46c3ae2af737..85eb8921568f 100644 --- a/crypto/openssl/crypto/camellia/cmll_ofb.c +++ b/crypto/openssl/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/openssl/crypto/camellia/cmll_utl.c b/crypto/openssl/crypto/camellia/cmll_utl.c index d19ee19317ce..d5eb6b4d68b1 100644 --- a/crypto/openssl/crypto/camellia/cmll_utl.c +++ b/crypto/openssl/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/openssl/crypto/des/des_old.c b/crypto/openssl/crypto/des/des_old.c index 54b0968e663b..c5c5a00f00c1 100644 --- a/crypto/openssl/crypto/des/des_old.c +++ b/crypto/openssl/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/openssl/crypto/des/des_old.h b/crypto/openssl/crypto/des/des_old.h index f1e1e2cb09cf..ee7607a2415f 100644 --- a/crypto/openssl/crypto/des/des_old.h +++ b/crypto/openssl/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/openssl/crypto/des/des_old2.c b/crypto/openssl/crypto/des/des_old2.c index f7d28a671355..247ff8dcf85f 100644 --- a/crypto/openssl/crypto/des/des_old2.c +++ b/crypto/openssl/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/openssl/crypto/dh/dh.h b/crypto/openssl/crypto/dh/dh.h index b17767328183..5498a9dc1060 100644 --- a/crypto/openssl/crypto/dh/dh.h +++ b/crypto/openssl/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/openssl/crypto/dh/dh_check.c b/crypto/openssl/crypto/dh/dh_check.c index 347467c6a433..5adedc0d264e 100644 --- a/crypto/openssl/crypto/dh/dh_check.c +++ b/crypto/openssl/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/openssl/crypto/dh/dhtest.c b/crypto/openssl/crypto/dh/dhtest.c index 6fe8ff4c0c49..c5d3d87ea549 100644 --- a/crypto/openssl/crypto/dh/dhtest.c +++ b/crypto/openssl/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/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c index f0ec8faa84cc..efc4f1b6aeba 100644 --- a/crypto/openssl/crypto/dsa/dsa_ossl.c +++ b/crypto/openssl/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/openssl/crypto/dso/dso.h b/crypto/openssl/crypto/dso/dso.h index 7c4a1dc4a620..c9013f5cea8b 100644 --- a/crypto/openssl/crypto/dso/dso.h +++ b/crypto/openssl/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/openssl/crypto/dso/dso_dl.c b/crypto/openssl/crypto/dso/dso_dl.c index 0087ac54afe1..ceedf66e8856 100644 --- a/crypto/openssl/crypto/dso/dso_dl.c +++ b/crypto/openssl/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/openssl/crypto/dso/dso_dlfcn.c b/crypto/openssl/crypto/dso/dso_dlfcn.c index f629f0380d8c..78df723ffbae 100644 --- a/crypto/openssl/crypto/dso/dso_dlfcn.c +++ b/crypto/openssl/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/openssl/crypto/dso/dso_lib.c b/crypto/openssl/crypto/dso/dso_lib.c index 09b8eafccacc..3312450eae67 100644 --- a/crypto/openssl/crypto/dso/dso_lib.c +++ b/crypto/openssl/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/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl index 648c969be621..e6acfd59f0d4 100755 --- a/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/ec/ec2_smpl.c b/crypto/openssl/crypto/ec/ec2_smpl.c index 077c7fc8dda5..5b27b91fcc94 100644 --- a/crypto/openssl/crypto/ec/ec2_smpl.c +++ b/crypto/openssl/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/openssl/crypto/ec/ec_key.c b/crypto/openssl/crypto/ec/ec_key.c index c784b6fd30a3..bc94ab5661ff 100644 --- a/crypto/openssl/crypto/ec/ec_key.c +++ b/crypto/openssl/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/openssl/crypto/ec/ecp_nistz256_table.c b/crypto/openssl/crypto/ec/ecp_nistz256_table.c index 216d024e0120..2f0797db6b9b 100644 --- a/crypto/openssl/crypto/ec/ecp_nistz256_table.c +++ b/crypto/openssl/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/openssl/crypto/ec/ectest.c b/crypto/openssl/crypto/ec/ectest.c index fede530bc139..efab0b07b1d2 100644 --- a/crypto/openssl/crypto/ec/ectest.c +++ b/crypto/openssl/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/openssl/crypto/engine/eng_all.c b/crypto/openssl/crypto/engine/eng_all.c index 195a3a95542a..48ad0d26b41e 100644 --- a/crypto/openssl/crypto/engine/eng_all.c +++ b/crypto/openssl/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/openssl/crypto/evp/e_camellia.c b/crypto/openssl/crypto/evp/e_camellia.c index f9c84013675d..f273f9c9475a 100644 --- a/crypto/openssl/crypto/evp/e_camellia.c +++ b/crypto/openssl/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/openssl/crypto/evp/e_old.c b/crypto/openssl/crypto/evp/e_old.c index c93f5a548163..a23d143b7fae 100644 --- a/crypto/openssl/crypto/evp/e_old.c +++ b/crypto/openssl/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/openssl/crypto/evp/e_seed.c b/crypto/openssl/crypto/evp/e_seed.c index c948a8f3914f..7249d1b1eecb 100644 --- a/crypto/openssl/crypto/evp/e_seed.c +++ b/crypto/openssl/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/openssl/crypto/mem_clr.c b/crypto/openssl/crypto/mem_clr.c index 1a06636d0ce8..ab85344eef38 100644 --- a/crypto/openssl/crypto/mem_clr.c +++ b/crypto/openssl/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/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl index 4be25571ea28..bd6bf72fe487 100755 --- a/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/modes/asm/ghash-x86_64.pl b/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl index 0bcb6d4e028b..4ff2d39aa7b2 100755 --- a/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/o_dir.c b/crypto/openssl/crypto/o_dir.c index 26242444c885..f9dbed871127 100644 --- a/crypto/openssl/crypto/o_dir.c +++ b/crypto/openssl/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/openssl/crypto/o_dir.h b/crypto/openssl/crypto/o_dir.h index d55431194ef2..bf45a14d02ec 100644 --- a/crypto/openssl/crypto/o_dir.h +++ b/crypto/openssl/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/openssl/crypto/o_dir_test.c b/crypto/openssl/crypto/o_dir_test.c index 7cdbbbc403e7..60436b72ce37 100644 --- a/crypto/openssl/crypto/o_dir_test.c +++ b/crypto/openssl/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/openssl/crypto/o_str.c b/crypto/openssl/crypto/o_str.c index 4e2d096704f0..7e61cde85a27 100644 --- a/crypto/openssl/crypto/o_str.c +++ b/crypto/openssl/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/openssl/crypto/o_str.h b/crypto/openssl/crypto/o_str.h index 5313528ed926..fa512eb39784 100644 --- a/crypto/openssl/crypto/o_str.h +++ b/crypto/openssl/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/openssl/crypto/o_time.c b/crypto/openssl/crypto/o_time.c index 58413fe97d09..635dae184d2f 100644 --- a/crypto/openssl/crypto/o_time.c +++ b/crypto/openssl/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/openssl/crypto/o_time.h b/crypto/openssl/crypto/o_time.h index a83a3d247d41..f192c6dccf37 100644 --- a/crypto/openssl/crypto/o_time.h +++ b/crypto/openssl/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/openssl/crypto/opensslv.h b/crypto/openssl/crypto/opensslv.h index 5b9d7183719b..b315d5ef97ee 100644 --- a/crypto/openssl/crypto/opensslv.h +++ b/crypto/openssl/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-freebsd 3 Dec 2015" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2f-freebsd 28 Jan 2016" # endif # define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/openssl/crypto/rc4/rc4_utl.c b/crypto/openssl/crypto/rc4/rc4_utl.c index 7c6a15f1c71f..cbd4a24e4b4d 100644 --- a/crypto/openssl/crypto/rc4/rc4_utl.c +++ b/crypto/openssl/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/openssl/crypto/rsa/rsa_chk.c b/crypto/openssl/crypto/rsa/rsa_chk.c index f4383860b58b..607faa00171e 100644 --- a/crypto/openssl/crypto/rsa/rsa_chk.c +++ b/crypto/openssl/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/openssl/crypto/rsa/rsa_sign.c b/crypto/openssl/crypto/rsa/rsa_sign.c index 82ca8324dfbc..ed63a1d8b0e3 100644 --- a/crypto/openssl/crypto/rsa/rsa_sign.c +++ b/crypto/openssl/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/openssl/crypto/seed/seed_cbc.c b/crypto/openssl/crypto/seed/seed_cbc.c index 33e6887740e9..ee1115b4c113 100644 --- a/crypto/openssl/crypto/seed/seed_cbc.c +++ b/crypto/openssl/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/openssl/crypto/seed/seed_cfb.c b/crypto/openssl/crypto/seed/seed_cfb.c index 3437d7b4e111..b6a5648b35fd 100644 --- a/crypto/openssl/crypto/seed/seed_cfb.c +++ b/crypto/openssl/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/openssl/crypto/seed/seed_ecb.c b/crypto/openssl/crypto/seed/seed_ecb.c index 937a31b42a87..9363d5508044 100644 --- a/crypto/openssl/crypto/seed/seed_ecb.c +++ b/crypto/openssl/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/openssl/crypto/seed/seed_ofb.c b/crypto/openssl/crypto/seed/seed_ofb.c index 6974302ce80f..48b71224c52c 100644 --- a/crypto/openssl/crypto/seed/seed_ofb.c +++ b/crypto/openssl/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/openssl/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl index f856bb888b0e..a8d8708d4b75 100755 --- a/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/sha/asm/sha1-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl index 9a6acc347d33..5f375fc6886b 100755 --- a/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl index 3d37ae31ad3e..9770286b9596 100755 --- a/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/sha/asm/sha512-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl index 58665667f149..78e445f3fe4a 100755 --- a/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/openssl/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/openssl/crypto/sha/sha1test.c b/crypto/openssl/crypto/sha/sha1test.c index 0052a95c7dd4..551a348df37f 100644 --- a/crypto/openssl/crypto/sha/sha1test.c +++ b/crypto/openssl/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/openssl/crypto/store/store.h b/crypto/openssl/crypto/store/store.h index 834334104907..ce3709d9f00b 100644 --- a/crypto/openssl/crypto/store/store.h +++ b/crypto/openssl/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/openssl/crypto/store/str_lib.c b/crypto/openssl/crypto/store/str_lib.c index 227b797b5949..e3d5da938868 100644 --- a/crypto/openssl/crypto/store/str_lib.c +++ b/crypto/openssl/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/openssl/crypto/store/str_locl.h b/crypto/openssl/crypto/store/str_locl.h index ac55784df0aa..c0b40f0db674 100644 --- a/crypto/openssl/crypto/store/str_locl.h +++ b/crypto/openssl/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/openssl/crypto/store/str_mem.c b/crypto/openssl/crypto/store/str_mem.c index 8edd0eb41b12..6eee5bba2922 100644 --- a/crypto/openssl/crypto/store/str_mem.c +++ b/crypto/openssl/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/openssl/crypto/store/str_meth.c b/crypto/openssl/crypto/store/str_meth.c index d83a6de0fc47..c83fbc565aac 100644 --- a/crypto/openssl/crypto/store/str_meth.c +++ b/crypto/openssl/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/openssl/crypto/ts/ts_rsp_verify.c b/crypto/openssl/crypto/ts/ts_rsp_verify.c index da8991173ced..29aa5a497e89 100644 --- a/crypto/openssl/crypto/ts/ts_rsp_verify.c +++ b/crypto/openssl/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/openssl/crypto/ui/ui.h b/crypto/openssl/crypto/ui/ui.h index b917edab3a7a..0dc16330b870 100644 --- a/crypto/openssl/crypto/ui/ui.h +++ b/crypto/openssl/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/openssl/crypto/ui/ui_compat.c b/crypto/openssl/crypto/ui/ui_compat.c index 0ca5284f91c0..e79d54eea682 100644 --- a/crypto/openssl/crypto/ui/ui_compat.c +++ b/crypto/openssl/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/openssl/crypto/ui/ui_compat.h b/crypto/openssl/crypto/ui/ui_compat.h index 42fb9ff6500f..bf541542c041 100644 --- a/crypto/openssl/crypto/ui/ui_compat.h +++ b/crypto/openssl/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/openssl/crypto/ui/ui_lib.c b/crypto/openssl/crypto/ui/ui_lib.c index 5ddd7317e52b..2f580352ce8f 100644 --- a/crypto/openssl/crypto/ui/ui_lib.c +++ b/crypto/openssl/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/openssl/crypto/ui/ui_locl.h b/crypto/openssl/crypto/ui/ui_locl.h index 0d919cd7b1cc..bebc13abfc52 100644 --- a/crypto/openssl/crypto/ui/ui_locl.h +++ b/crypto/openssl/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/openssl/crypto/ui/ui_openssl.c b/crypto/openssl/crypto/ui/ui_openssl.c index 5d66276418fc..9ab259b8f605 100644 --- a/crypto/openssl/crypto/ui/ui_openssl.c +++ b/crypto/openssl/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/openssl/crypto/ui/ui_util.c b/crypto/openssl/crypto/ui/ui_util.c index f65f80d71de6..0f290115d0f8 100644 --- a/crypto/openssl/crypto/ui/ui_util.c +++ b/crypto/openssl/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/openssl/crypto/x509/x509_vfy.c b/crypto/openssl/crypto/x509/x509_vfy.c index ab94948f0135..0429767032fd 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.c +++ b/crypto/openssl/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/openssl/crypto/x509/x509_vfy.h b/crypto/openssl/crypto/x509/x509_vfy.h index bd8613c62ba4..2663e1c0a362 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.h +++ b/crypto/openssl/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/openssl/crypto/x509/x509_vpm.c b/crypto/openssl/crypto/x509/x509_vpm.c index 592a8a5f6a5c..1ac15a881a10 100644 --- a/crypto/openssl/crypto/x509/x509_vpm.c +++ b/crypto/openssl/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/openssl/crypto/x509v3/v3_pci.c b/crypto/openssl/crypto/x509v3/v3_pci.c index 48ac0959cb10..34cad53cb5f0 100644 --- a/crypto/openssl/crypto/x509v3/v3_pci.c +++ b/crypto/openssl/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/openssl/crypto/x509v3/v3_pcia.c b/crypto/openssl/crypto/x509v3/v3_pcia.c index 43fd362aeda0..e53c82e8dc79 100644 --- a/crypto/openssl/crypto/x509v3/v3_pcia.c +++ b/crypto/openssl/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/openssl/crypto/x509v3/v3_utl.c b/crypto/openssl/crypto/x509v3/v3_utl.c index 4d1ecc58bf94..43b9cb9c5861 100644 --- a/crypto/openssl/crypto/x509v3/v3_utl.c +++ b/crypto/openssl/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/openssl/crypto/x509v3/v3nametest.c b/crypto/openssl/crypto/x509v3/v3nametest.c index 7b5c1c8e5127..ac5c9ff432d9 100644 --- a/crypto/openssl/crypto/x509v3/v3nametest.c +++ b/crypto/openssl/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/crypto/openssl/doc/apps/s_time.pod b/crypto/openssl/doc/apps/s_time.pod index 5a38aa2e0394..9082d876feeb 100644 --- a/crypto/openssl/doc/apps/s_time.pod +++ b/crypto/openssl/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/crypto/openssl/doc/crypto/BIO_s_connect.pod b/crypto/openssl/doc/crypto/BIO_s_connect.pod index 18ece4c91f66..345a468a5d74 100644 --- a/crypto/openssl/doc/crypto/BIO_s_connect.pod +++ b/crypto/openssl/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/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod b/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod index 493cca481940..3e3a4fa90c0e 100644 --- a/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod +++ b/crypto/openssl/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/crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod new file mode 100644 index 000000000000..b8147baecf98 --- /dev/null +++ b/crypto/openssl/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/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod index b754c16a86e6..234fbc845002 100644 --- a/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod +++ b/crypto/openssl/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/crypto/openssl/engines/e_chil.c b/crypto/openssl/engines/e_chil.c index 72d14fe383a4..5dfab5134527 100644 --- a/crypto/openssl/engines/e_chil.c +++ b/crypto/openssl/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/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index c2c8d57e9d9c..d1fc716d5c5c 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/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/crypto/openssl/ssl/kssl.c b/crypto/openssl/ssl/kssl.c index cf585679dccc..f2839bdcd7f5 100644 --- a/crypto/openssl/ssl/kssl.c +++ b/crypto/openssl/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/crypto/openssl/ssl/kssl.h b/crypto/openssl/ssl/kssl.h index 9a5767280150..ae8a51f472da 100644 --- a/crypto/openssl/ssl/kssl.h +++ b/crypto/openssl/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/crypto/openssl/ssl/kssl_lcl.h b/crypto/openssl/ssl/kssl_lcl.h index 46dcef22d16c..8e6a6d69e949 100644 --- a/crypto/openssl/ssl/kssl_lcl.h +++ b/crypto/openssl/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/crypto/openssl/ssl/s2_srvr.c b/crypto/openssl/ssl/s2_srvr.c index 4289272b73d3..07e9df82820a 100644 --- a/crypto/openssl/ssl/s2_srvr.c +++ b/crypto/openssl/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/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index bc5254c81160..04cc9f54a92d 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/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/crypto/openssl/ssl/s3_lib.c b/crypto/openssl/ssl/s3_lib.c index 64793d6af34f..f846cb5b7b01 100644 --- a/crypto/openssl/ssl/s3_lib.c +++ b/crypto/openssl/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/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index ee83105b75bf..ab28702ee972 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/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/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index afec1f5bf29f..ae8c92575e03 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/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/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index 6d1366f2a59d..dd3b2afd1ea6 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/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/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c index f2071db93702..2744be8ad8ce 100644 --- a/crypto/openssl/ssl/ssl_lib.c +++ b/crypto/openssl/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/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index 68390d310809..b18299834384 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/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/crypto/openssl/ssl/t1_enc.c b/crypto/openssl/ssl/t1_enc.c index f46544b4d713..514fcb3e4e74 100644 --- a/crypto/openssl/ssl/t1_enc.c +++ b/crypto/openssl/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/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c index 3176d1e3baba..d9ba99d73584 100644 --- a/crypto/openssl/ssl/t1_lib.c +++ b/crypto/openssl/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/crypto/openssl/util/domd b/crypto/openssl/util/domd index 6a628c7f96c2..95bb1b06e257 100755 --- a/crypto/openssl/util/domd +++ b/crypto/openssl/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/crypto/openssl/util/pl/VC-32.pl b/crypto/openssl/util/pl/VC-32.pl index 284fe0381ed9..0f5547f056c2 100644 --- a/crypto/openssl/util/pl/VC-32.pl +++ b/crypto/openssl/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/crypto/openssl/util/pod2mantest b/crypto/openssl/util/pod2mantest new file mode 100755 index 000000000000..384e683df4cc --- /dev/null +++ b/crypto/openssl/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" diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index a674acb97532..69b6d0f77bd0 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -716,5 +716,18 @@ if [ -z "${source_rc_confs_defined}" ]; then ;; esac done + # Re-do process to pick up [possibly] redefined $rc_conf_files + 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 diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs index 359be13b227a..64eac99c38a1 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) - \ @@ -73,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} 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 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 } 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) 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); 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/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; } } 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/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. 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/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/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/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 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/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 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) { 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); } 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/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]; } 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; 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); diff --git a/secure/lib/libcrypto/Makefile.inc b/secure/lib/libcrypto/Makefile.inc index 2eb862f20423..7b1401ff3975 100644 --- a/secure/lib/libcrypto/Makefile.inc +++ b/secure/lib/libcrypto/Makefile.inc @@ -3,8 +3,8 @@ .include # OpenSSL version used for manual page generation -OPENSSL_VER= 1.0.2e -OPENSSL_DATE= 2015-12-03 +OPENSSL_VER= 1.0.2f +OPENSSL_DATE= 2016-01-28 LCRYPTO_SRC= ${.CURDIR}/../../../crypto/openssl LCRYPTO_DOC= ${LCRYPTO_SRC}/doc diff --git a/secure/lib/libcrypto/man/ASN1_OBJECT_new.3 b/secure/lib/libcrypto/man/ASN1_OBJECT_new.3 index 67e7e4857231..0d7709d27aec 100644 --- a/secure/lib/libcrypto/man/ASN1_OBJECT_new.3 +++ b/secure/lib/libcrypto/man/ASN1_OBJECT_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_OBJECT_new 3" -.TH ASN1_OBJECT_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_OBJECT_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ASN1_STRING_length.3 b/secure/lib/libcrypto/man/ASN1_STRING_length.3 index e2eb45ccea14..5ab4b086e883 100644 --- a/secure/lib/libcrypto/man/ASN1_STRING_length.3 +++ b/secure/lib/libcrypto/man/ASN1_STRING_length.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_STRING_length 3" -.TH ASN1_STRING_length 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_STRING_length 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ASN1_STRING_new.3 b/secure/lib/libcrypto/man/ASN1_STRING_new.3 index f0c2c0a96116..1c0ca345906c 100644 --- a/secure/lib/libcrypto/man/ASN1_STRING_new.3 +++ b/secure/lib/libcrypto/man/ASN1_STRING_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_STRING_new 3" -.TH ASN1_STRING_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_STRING_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3 b/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3 index cc97d99616a2..0ef8712f8fff 100644 --- a/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3 +++ b/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_STRING_print_ex 3" -.TH ASN1_STRING_print_ex 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_STRING_print_ex 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ASN1_TIME_set.3 b/secure/lib/libcrypto/man/ASN1_TIME_set.3 index a7339697cb18..6cb1b1b47b8e 100644 --- a/secure/lib/libcrypto/man/ASN1_TIME_set.3 +++ b/secure/lib/libcrypto/man/ASN1_TIME_set.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_TIME_set 3" -.TH ASN1_TIME_set 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_TIME_set 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ASN1_generate_nconf.3 b/secure/lib/libcrypto/man/ASN1_generate_nconf.3 index 37f279d6ce0a..1300cacf5c0b 100644 --- a/secure/lib/libcrypto/man/ASN1_generate_nconf.3 +++ b/secure/lib/libcrypto/man/ASN1_generate_nconf.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1_generate_nconf 3" -.TH ASN1_generate_nconf 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1_generate_nconf 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_ctrl.3 b/secure/lib/libcrypto/man/BIO_ctrl.3 index 784d3072fa33..8fc642ab1bfd 100644 --- a/secure/lib/libcrypto/man/BIO_ctrl.3 +++ b/secure/lib/libcrypto/man/BIO_ctrl.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_ctrl 3" -.TH BIO_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_base64.3 b/secure/lib/libcrypto/man/BIO_f_base64.3 index fb804bd7c20d..7922ffbd261a 100644 --- a/secure/lib/libcrypto/man/BIO_f_base64.3 +++ b/secure/lib/libcrypto/man/BIO_f_base64.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_base64 3" -.TH BIO_f_base64 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_base64 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_buffer.3 b/secure/lib/libcrypto/man/BIO_f_buffer.3 index ace920f2a07a..65bf13c9f752 100644 --- a/secure/lib/libcrypto/man/BIO_f_buffer.3 +++ b/secure/lib/libcrypto/man/BIO_f_buffer.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_buffer 3" -.TH BIO_f_buffer 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_buffer 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_cipher.3 b/secure/lib/libcrypto/man/BIO_f_cipher.3 index 46aa9aaeb492..44c7a36ebf2e 100644 --- a/secure/lib/libcrypto/man/BIO_f_cipher.3 +++ b/secure/lib/libcrypto/man/BIO_f_cipher.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_cipher 3" -.TH BIO_f_cipher 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_cipher 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_md.3 b/secure/lib/libcrypto/man/BIO_f_md.3 index 39688fb4f76b..89d648a79755 100644 --- a/secure/lib/libcrypto/man/BIO_f_md.3 +++ b/secure/lib/libcrypto/man/BIO_f_md.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_md 3" -.TH BIO_f_md 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_md 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_null.3 b/secure/lib/libcrypto/man/BIO_f_null.3 index 6fbb01072534..31c56d02308b 100644 --- a/secure/lib/libcrypto/man/BIO_f_null.3 +++ b/secure/lib/libcrypto/man/BIO_f_null.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_null 3" -.TH BIO_f_null 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_null 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_f_ssl.3 b/secure/lib/libcrypto/man/BIO_f_ssl.3 index 6bed4fedf900..b8dec88a6749 100644 --- a/secure/lib/libcrypto/man/BIO_f_ssl.3 +++ b/secure/lib/libcrypto/man/BIO_f_ssl.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_f_ssl 3" -.TH BIO_f_ssl 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_f_ssl 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_find_type.3 b/secure/lib/libcrypto/man/BIO_find_type.3 index 0ad3bb452a62..ea022e660c2e 100644 --- a/secure/lib/libcrypto/man/BIO_find_type.3 +++ b/secure/lib/libcrypto/man/BIO_find_type.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_find_type 3" -.TH BIO_find_type 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_find_type 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_new.3 b/secure/lib/libcrypto/man/BIO_new.3 index dc11b3038fca..80f390692af3 100644 --- a/secure/lib/libcrypto/man/BIO_new.3 +++ b/secure/lib/libcrypto/man/BIO_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_new 3" -.TH BIO_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_new_CMS.3 b/secure/lib/libcrypto/man/BIO_new_CMS.3 index 2b4c7a30433c..7841215a9db3 100644 --- a/secure/lib/libcrypto/man/BIO_new_CMS.3 +++ b/secure/lib/libcrypto/man/BIO_new_CMS.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_new_CMS 3" -.TH BIO_new_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_new_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_push.3 b/secure/lib/libcrypto/man/BIO_push.3 index d9e132aaef39..3dc3a90cfa24 100644 --- a/secure/lib/libcrypto/man/BIO_push.3 +++ b/secure/lib/libcrypto/man/BIO_push.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_push 3" -.TH BIO_push 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_push 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_read.3 b/secure/lib/libcrypto/man/BIO_read.3 index 54a99745abb7..5e621b3e1b5e 100644 --- a/secure/lib/libcrypto/man/BIO_read.3 +++ b/secure/lib/libcrypto/man/BIO_read.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_read 3" -.TH BIO_read 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_read 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_accept.3 b/secure/lib/libcrypto/man/BIO_s_accept.3 index 8dfb1271b7fc..d454bf9c3781 100644 --- a/secure/lib/libcrypto/man/BIO_s_accept.3 +++ b/secure/lib/libcrypto/man/BIO_s_accept.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_accept 3" -.TH BIO_s_accept 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_accept 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_bio.3 b/secure/lib/libcrypto/man/BIO_s_bio.3 index a94fbfdc55b9..353124b3a955 100644 --- a/secure/lib/libcrypto/man/BIO_s_bio.3 +++ b/secure/lib/libcrypto/man/BIO_s_bio.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_bio 3" -.TH BIO_s_bio 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_bio 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_connect.3 b/secure/lib/libcrypto/man/BIO_s_connect.3 index 8e545f9cde37..6b258391628d 100644 --- a/secure/lib/libcrypto/man/BIO_s_connect.3 +++ b/secure/lib/libcrypto/man/BIO_s_connect.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_connect 3" -.TH BIO_s_connect 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_connect 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -158,8 +158,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/secure/lib/libcrypto/man/BIO_s_fd.3 b/secure/lib/libcrypto/man/BIO_s_fd.3 index e606e7428c36..43386d7b0c5c 100644 --- a/secure/lib/libcrypto/man/BIO_s_fd.3 +++ b/secure/lib/libcrypto/man/BIO_s_fd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_fd 3" -.TH BIO_s_fd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_fd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_file.3 b/secure/lib/libcrypto/man/BIO_s_file.3 index 0923f56e52c2..371eff0fb711 100644 --- a/secure/lib/libcrypto/man/BIO_s_file.3 +++ b/secure/lib/libcrypto/man/BIO_s_file.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_file 3" -.TH BIO_s_file 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_file 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_mem.3 b/secure/lib/libcrypto/man/BIO_s_mem.3 index cc1131e7685c..fe7b4acd9009 100644 --- a/secure/lib/libcrypto/man/BIO_s_mem.3 +++ b/secure/lib/libcrypto/man/BIO_s_mem.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_mem 3" -.TH BIO_s_mem 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_mem 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_null.3 b/secure/lib/libcrypto/man/BIO_s_null.3 index 0bc54c655ce1..ee4b3a13264d 100644 --- a/secure/lib/libcrypto/man/BIO_s_null.3 +++ b/secure/lib/libcrypto/man/BIO_s_null.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_null 3" -.TH BIO_s_null 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_null 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_s_socket.3 b/secure/lib/libcrypto/man/BIO_s_socket.3 index c42526688873..4321e8124aa1 100644 --- a/secure/lib/libcrypto/man/BIO_s_socket.3 +++ b/secure/lib/libcrypto/man/BIO_s_socket.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_s_socket 3" -.TH BIO_s_socket 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_s_socket 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_set_callback.3 b/secure/lib/libcrypto/man/BIO_set_callback.3 index 59a7d979fb5a..2ea32575d337 100644 --- a/secure/lib/libcrypto/man/BIO_set_callback.3 +++ b/secure/lib/libcrypto/man/BIO_set_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_set_callback 3" -.TH BIO_set_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_set_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BIO_should_retry.3 b/secure/lib/libcrypto/man/BIO_should_retry.3 index fc3aeadc8d05..7dc7ac6cc3aa 100644 --- a/secure/lib/libcrypto/man/BIO_should_retry.3 +++ b/secure/lib/libcrypto/man/BIO_should_retry.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BIO_should_retry 3" -.TH BIO_should_retry 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BIO_should_retry 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_BLINDING_new.3 b/secure/lib/libcrypto/man/BN_BLINDING_new.3 index 4029d060ae74..84ef4e40a921 100644 --- a/secure/lib/libcrypto/man/BN_BLINDING_new.3 +++ b/secure/lib/libcrypto/man/BN_BLINDING_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_BLINDING_new 3" -.TH BN_BLINDING_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_BLINDING_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_CTX_new.3 b/secure/lib/libcrypto/man/BN_CTX_new.3 index f3424a2a8e67..b56c161b4fa9 100644 --- a/secure/lib/libcrypto/man/BN_CTX_new.3 +++ b/secure/lib/libcrypto/man/BN_CTX_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_CTX_new 3" -.TH BN_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_CTX_start.3 b/secure/lib/libcrypto/man/BN_CTX_start.3 index e61bec2beefd..4a92f6d3a5ea 100644 --- a/secure/lib/libcrypto/man/BN_CTX_start.3 +++ b/secure/lib/libcrypto/man/BN_CTX_start.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_CTX_start 3" -.TH BN_CTX_start 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_CTX_start 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_add.3 b/secure/lib/libcrypto/man/BN_add.3 index adbfe1f51724..c674dc5a6ebb 100644 --- a/secure/lib/libcrypto/man/BN_add.3 +++ b/secure/lib/libcrypto/man/BN_add.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_add 3" -.TH BN_add 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_add 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_add_word.3 b/secure/lib/libcrypto/man/BN_add_word.3 index 1180231411b2..ec19be41498f 100644 --- a/secure/lib/libcrypto/man/BN_add_word.3 +++ b/secure/lib/libcrypto/man/BN_add_word.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_add_word 3" -.TH BN_add_word 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_add_word 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_bn2bin.3 b/secure/lib/libcrypto/man/BN_bn2bin.3 index 318afe60b28a..bc88eb8af4ab 100644 --- a/secure/lib/libcrypto/man/BN_bn2bin.3 +++ b/secure/lib/libcrypto/man/BN_bn2bin.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_bn2bin 3" -.TH BN_bn2bin 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_bn2bin 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_cmp.3 b/secure/lib/libcrypto/man/BN_cmp.3 index 1fe36bb164ec..5cc7945cb85a 100644 --- a/secure/lib/libcrypto/man/BN_cmp.3 +++ b/secure/lib/libcrypto/man/BN_cmp.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_cmp 3" -.TH BN_cmp 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_cmp 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_copy.3 b/secure/lib/libcrypto/man/BN_copy.3 index e90cb656f362..f371ea9a086b 100644 --- a/secure/lib/libcrypto/man/BN_copy.3 +++ b/secure/lib/libcrypto/man/BN_copy.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_copy 3" -.TH BN_copy 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_copy 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_generate_prime.3 b/secure/lib/libcrypto/man/BN_generate_prime.3 index 7b30f6e2e9ce..238a729480d5 100644 --- a/secure/lib/libcrypto/man/BN_generate_prime.3 +++ b/secure/lib/libcrypto/man/BN_generate_prime.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_generate_prime 3" -.TH BN_generate_prime 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_generate_prime 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_mod_inverse.3 b/secure/lib/libcrypto/man/BN_mod_inverse.3 index 360547ac349d..4f4d7acc90f0 100644 --- a/secure/lib/libcrypto/man/BN_mod_inverse.3 +++ b/secure/lib/libcrypto/man/BN_mod_inverse.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_mod_inverse 3" -.TH BN_mod_inverse 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_mod_inverse 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3 b/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3 index 89e295b3a90c..43d4269f4989 100644 --- a/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3 +++ b/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_mod_mul_montgomery 3" -.TH BN_mod_mul_montgomery 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_mod_mul_montgomery 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3 b/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3 index a486c2bbc6b5..a584766e76f7 100644 --- a/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3 +++ b/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_mod_mul_reciprocal 3" -.TH BN_mod_mul_reciprocal 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_mod_mul_reciprocal 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_new.3 b/secure/lib/libcrypto/man/BN_new.3 index ccedaa8e6d91..a9f4c8185d07 100644 --- a/secure/lib/libcrypto/man/BN_new.3 +++ b/secure/lib/libcrypto/man/BN_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_new 3" -.TH BN_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_num_bytes.3 b/secure/lib/libcrypto/man/BN_num_bytes.3 index fa1407e91c21..e134b243637c 100644 --- a/secure/lib/libcrypto/man/BN_num_bytes.3 +++ b/secure/lib/libcrypto/man/BN_num_bytes.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_num_bytes 3" -.TH BN_num_bytes 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_num_bytes 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_rand.3 b/secure/lib/libcrypto/man/BN_rand.3 index 26837ae27c9f..7725cd79f0c1 100644 --- a/secure/lib/libcrypto/man/BN_rand.3 +++ b/secure/lib/libcrypto/man/BN_rand.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_rand 3" -.TH BN_rand 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_rand 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_set_bit.3 b/secure/lib/libcrypto/man/BN_set_bit.3 index 75c6ce7bf0fc..f2a446c59f02 100644 --- a/secure/lib/libcrypto/man/BN_set_bit.3 +++ b/secure/lib/libcrypto/man/BN_set_bit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_set_bit 3" -.TH BN_set_bit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_set_bit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_swap.3 b/secure/lib/libcrypto/man/BN_swap.3 index fceba7fcc9da..568625059c40 100644 --- a/secure/lib/libcrypto/man/BN_swap.3 +++ b/secure/lib/libcrypto/man/BN_swap.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_swap 3" -.TH BN_swap 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_swap 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/BN_zero.3 b/secure/lib/libcrypto/man/BN_zero.3 index a3ede143b0e9..3db136551abf 100644 --- a/secure/lib/libcrypto/man/BN_zero.3 +++ b/secure/lib/libcrypto/man/BN_zero.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "BN_zero 3" -.TH BN_zero 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH BN_zero 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_add0_cert.3 b/secure/lib/libcrypto/man/CMS_add0_cert.3 index 0835fd851b26..283f3d729496 100644 --- a/secure/lib/libcrypto/man/CMS_add0_cert.3 +++ b/secure/lib/libcrypto/man/CMS_add0_cert.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_add0_cert 3" -.TH CMS_add0_cert 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_add0_cert 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3 b/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3 index 23b9801ea163..d4b96009d755 100644 --- a/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3 +++ b/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_add1_recipient_cert 3" -.TH CMS_add1_recipient_cert 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_add1_recipient_cert 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_add1_signer.3 b/secure/lib/libcrypto/man/CMS_add1_signer.3 index 7183e28dba68..75a65a7624a5 100644 --- a/secure/lib/libcrypto/man/CMS_add1_signer.3 +++ b/secure/lib/libcrypto/man/CMS_add1_signer.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_add1_signer 3" -.TH CMS_add1_signer 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_add1_signer 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_compress.3 b/secure/lib/libcrypto/man/CMS_compress.3 index 7ae678e30320..b5394799883a 100644 --- a/secure/lib/libcrypto/man/CMS_compress.3 +++ b/secure/lib/libcrypto/man/CMS_compress.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_compress 3" -.TH CMS_compress 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_compress 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_decrypt.3 b/secure/lib/libcrypto/man/CMS_decrypt.3 index 205144bdd65c..ce0eacdffa9d 100644 --- a/secure/lib/libcrypto/man/CMS_decrypt.3 +++ b/secure/lib/libcrypto/man/CMS_decrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_decrypt 3" -.TH CMS_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_encrypt.3 b/secure/lib/libcrypto/man/CMS_encrypt.3 index 8fd3af8271f8..7e94d64f055e 100644 --- a/secure/lib/libcrypto/man/CMS_encrypt.3 +++ b/secure/lib/libcrypto/man/CMS_encrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_encrypt 3" -.TH CMS_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_final.3 b/secure/lib/libcrypto/man/CMS_final.3 index 340beadb002e..4493a86b1b9c 100644 --- a/secure/lib/libcrypto/man/CMS_final.3 +++ b/secure/lib/libcrypto/man/CMS_final.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_final 3" -.TH CMS_final 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_final 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3 b/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3 index 931a88d202bd..4b4bc4ed1542 100644 --- a/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3 +++ b/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_get0_RecipientInfos 3" -.TH CMS_get0_RecipientInfos 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_get0_RecipientInfos 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3 b/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3 index 160057e33078..d724ae5b9856 100644 --- a/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3 +++ b/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_get0_SignerInfos 3" -.TH CMS_get0_SignerInfos 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_get0_SignerInfos 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_get0_type.3 b/secure/lib/libcrypto/man/CMS_get0_type.3 index dc32afc2c293..919d91889e13 100644 --- a/secure/lib/libcrypto/man/CMS_get0_type.3 +++ b/secure/lib/libcrypto/man/CMS_get0_type.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_get0_type 3" -.TH CMS_get0_type 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_get0_type 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3 b/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3 index e6c778803220..f3dcf2702cb8 100644 --- a/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3 +++ b/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_get1_ReceiptRequest 3" -.TH CMS_get1_ReceiptRequest 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_get1_ReceiptRequest 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_sign.3 b/secure/lib/libcrypto/man/CMS_sign.3 index bb0be5e6c44c..daf147a753ab 100644 --- a/secure/lib/libcrypto/man/CMS_sign.3 +++ b/secure/lib/libcrypto/man/CMS_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_sign 3" -.TH CMS_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_sign_receipt.3 b/secure/lib/libcrypto/man/CMS_sign_receipt.3 index 6311b4a6bccb..25baa891cd31 100644 --- a/secure/lib/libcrypto/man/CMS_sign_receipt.3 +++ b/secure/lib/libcrypto/man/CMS_sign_receipt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_sign_receipt 3" -.TH CMS_sign_receipt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_sign_receipt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_uncompress.3 b/secure/lib/libcrypto/man/CMS_uncompress.3 index 289e13859958..dea41858c32f 100644 --- a/secure/lib/libcrypto/man/CMS_uncompress.3 +++ b/secure/lib/libcrypto/man/CMS_uncompress.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_uncompress 3" -.TH CMS_uncompress 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_uncompress 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_verify.3 b/secure/lib/libcrypto/man/CMS_verify.3 index 52a45cdaf092..55803b6c2662 100644 --- a/secure/lib/libcrypto/man/CMS_verify.3 +++ b/secure/lib/libcrypto/man/CMS_verify.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_verify 3" -.TH CMS_verify 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_verify 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CMS_verify_receipt.3 b/secure/lib/libcrypto/man/CMS_verify_receipt.3 index fd9b9886319c..fbcd2ee5d983 100644 --- a/secure/lib/libcrypto/man/CMS_verify_receipt.3 +++ b/secure/lib/libcrypto/man/CMS_verify_receipt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS_verify_receipt 3" -.TH CMS_verify_receipt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS_verify_receipt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CONF_modules_free.3 b/secure/lib/libcrypto/man/CONF_modules_free.3 index 7d1415baa5dd..18d3c8f756b7 100644 --- a/secure/lib/libcrypto/man/CONF_modules_free.3 +++ b/secure/lib/libcrypto/man/CONF_modules_free.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CONF_modules_free 3" -.TH CONF_modules_free 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CONF_modules_free 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CONF_modules_load_file.3 b/secure/lib/libcrypto/man/CONF_modules_load_file.3 index c83ecbe1b2e8..e7af092c7c40 100644 --- a/secure/lib/libcrypto/man/CONF_modules_load_file.3 +++ b/secure/lib/libcrypto/man/CONF_modules_load_file.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CONF_modules_load_file 3" -.TH CONF_modules_load_file 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CONF_modules_load_file 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3 b/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3 index 38c95e5eecf7..1b14da5ddd8d 100644 --- a/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3 +++ b/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CRYPTO_set_ex_data 3" -.TH CRYPTO_set_ex_data 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CRYPTO_set_ex_data 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_generate_key.3 b/secure/lib/libcrypto/man/DH_generate_key.3 index cf99604ce045..942533ea05ee 100644 --- a/secure/lib/libcrypto/man/DH_generate_key.3 +++ b/secure/lib/libcrypto/man/DH_generate_key.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_generate_key 3" -.TH DH_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_generate_parameters.3 b/secure/lib/libcrypto/man/DH_generate_parameters.3 index a6e5964b29b6..ba364af40367 100644 --- a/secure/lib/libcrypto/man/DH_generate_parameters.3 +++ b/secure/lib/libcrypto/man/DH_generate_parameters.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_generate_parameters 3" -.TH DH_generate_parameters 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_generate_parameters 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_get_ex_new_index.3 b/secure/lib/libcrypto/man/DH_get_ex_new_index.3 index 7f8afb7ec5c9..e01b66e2c14b 100644 --- a/secure/lib/libcrypto/man/DH_get_ex_new_index.3 +++ b/secure/lib/libcrypto/man/DH_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_get_ex_new_index 3" -.TH DH_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_new.3 b/secure/lib/libcrypto/man/DH_new.3 index 13f05d77e35a..e13904e80a1f 100644 --- a/secure/lib/libcrypto/man/DH_new.3 +++ b/secure/lib/libcrypto/man/DH_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_new 3" -.TH DH_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_set_method.3 b/secure/lib/libcrypto/man/DH_set_method.3 index 1f7646a051b4..48525880cb1b 100644 --- a/secure/lib/libcrypto/man/DH_set_method.3 +++ b/secure/lib/libcrypto/man/DH_set_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_set_method 3" -.TH DH_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DH_size.3 b/secure/lib/libcrypto/man/DH_size.3 index e47d1f2226df..9a1ef7667a76 100644 --- a/secure/lib/libcrypto/man/DH_size.3 +++ b/secure/lib/libcrypto/man/DH_size.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DH_size 3" -.TH DH_size 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DH_size 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_SIG_new.3 b/secure/lib/libcrypto/man/DSA_SIG_new.3 index 701cd77aca8d..74abff2a8011 100644 --- a/secure/lib/libcrypto/man/DSA_SIG_new.3 +++ b/secure/lib/libcrypto/man/DSA_SIG_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_SIG_new 3" -.TH DSA_SIG_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_SIG_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_do_sign.3 b/secure/lib/libcrypto/man/DSA_do_sign.3 index 9fac79790065..6bfeb9510e67 100644 --- a/secure/lib/libcrypto/man/DSA_do_sign.3 +++ b/secure/lib/libcrypto/man/DSA_do_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_do_sign 3" -.TH DSA_do_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_do_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_dup_DH.3 b/secure/lib/libcrypto/man/DSA_dup_DH.3 index 142aa13f4963..b4b10d11bddf 100644 --- a/secure/lib/libcrypto/man/DSA_dup_DH.3 +++ b/secure/lib/libcrypto/man/DSA_dup_DH.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_dup_DH 3" -.TH DSA_dup_DH 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_dup_DH 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_generate_key.3 b/secure/lib/libcrypto/man/DSA_generate_key.3 index 6f12de9c2b9a..0b92e49a133b 100644 --- a/secure/lib/libcrypto/man/DSA_generate_key.3 +++ b/secure/lib/libcrypto/man/DSA_generate_key.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_generate_key 3" -.TH DSA_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_generate_parameters.3 b/secure/lib/libcrypto/man/DSA_generate_parameters.3 index 7ccc54b26564..99196a57f05f 100644 --- a/secure/lib/libcrypto/man/DSA_generate_parameters.3 +++ b/secure/lib/libcrypto/man/DSA_generate_parameters.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_generate_parameters 3" -.TH DSA_generate_parameters 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_generate_parameters 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_get_ex_new_index.3 b/secure/lib/libcrypto/man/DSA_get_ex_new_index.3 index f473de132eeb..78b4576d5c66 100644 --- a/secure/lib/libcrypto/man/DSA_get_ex_new_index.3 +++ b/secure/lib/libcrypto/man/DSA_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_get_ex_new_index 3" -.TH DSA_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_new.3 b/secure/lib/libcrypto/man/DSA_new.3 index e3fe4086158b..7ab990277933 100644 --- a/secure/lib/libcrypto/man/DSA_new.3 +++ b/secure/lib/libcrypto/man/DSA_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_new 3" -.TH DSA_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_set_method.3 b/secure/lib/libcrypto/man/DSA_set_method.3 index ba984e03cbba..212a12619f3c 100644 --- a/secure/lib/libcrypto/man/DSA_set_method.3 +++ b/secure/lib/libcrypto/man/DSA_set_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_set_method 3" -.TH DSA_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_sign.3 b/secure/lib/libcrypto/man/DSA_sign.3 index 5a018ac7dafa..4b931edb197f 100644 --- a/secure/lib/libcrypto/man/DSA_sign.3 +++ b/secure/lib/libcrypto/man/DSA_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_sign 3" -.TH DSA_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/DSA_size.3 b/secure/lib/libcrypto/man/DSA_size.3 index bfc328e0c4af..ba562fc3855e 100644 --- a/secure/lib/libcrypto/man/DSA_size.3 +++ b/secure/lib/libcrypto/man/DSA_size.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA_size 3" -.TH DSA_size 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA_size 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_GFp_simple_method.3 b/secure/lib/libcrypto/man/EC_GFp_simple_method.3 index 89a9b9d44c16..d340e16de0c6 100644 --- a/secure/lib/libcrypto/man/EC_GFp_simple_method.3 +++ b/secure/lib/libcrypto/man/EC_GFp_simple_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_GFp_simple_method 3" -.TH EC_GFp_simple_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_GFp_simple_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_GROUP_copy.3 b/secure/lib/libcrypto/man/EC_GROUP_copy.3 index 19ce288c76b7..673ac1fcb38c 100644 --- a/secure/lib/libcrypto/man/EC_GROUP_copy.3 +++ b/secure/lib/libcrypto/man/EC_GROUP_copy.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_GROUP_copy 3" -.TH EC_GROUP_copy 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_GROUP_copy 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_GROUP_new.3 b/secure/lib/libcrypto/man/EC_GROUP_new.3 index b21a561eedba..9b579f4b0b79 100644 --- a/secure/lib/libcrypto/man/EC_GROUP_new.3 +++ b/secure/lib/libcrypto/man/EC_GROUP_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_GROUP_new 3" -.TH EC_GROUP_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_GROUP_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_KEY_new.3 b/secure/lib/libcrypto/man/EC_KEY_new.3 index 9481b9f671d1..2133fe6be1cc 100644 --- a/secure/lib/libcrypto/man/EC_KEY_new.3 +++ b/secure/lib/libcrypto/man/EC_KEY_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_KEY_new 3" -.TH EC_KEY_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_KEY_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_POINT_add.3 b/secure/lib/libcrypto/man/EC_POINT_add.3 index 49475758fad4..20d23ced9f9d 100644 --- a/secure/lib/libcrypto/man/EC_POINT_add.3 +++ b/secure/lib/libcrypto/man/EC_POINT_add.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_POINT_add 3" -.TH EC_POINT_add 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_POINT_add 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EC_POINT_new.3 b/secure/lib/libcrypto/man/EC_POINT_new.3 index 16a26e571b9c..4c48143143e4 100644 --- a/secure/lib/libcrypto/man/EC_POINT_new.3 +++ b/secure/lib/libcrypto/man/EC_POINT_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC_POINT_new 3" -.TH EC_POINT_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC_POINT_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_GET_LIB.3 b/secure/lib/libcrypto/man/ERR_GET_LIB.3 index e44b533411d3..324acd356f43 100644 --- a/secure/lib/libcrypto/man/ERR_GET_LIB.3 +++ b/secure/lib/libcrypto/man/ERR_GET_LIB.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_GET_LIB 3" -.TH ERR_GET_LIB 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_GET_LIB 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_clear_error.3 b/secure/lib/libcrypto/man/ERR_clear_error.3 index e2e9b3c02cf1..d438690737b4 100644 --- a/secure/lib/libcrypto/man/ERR_clear_error.3 +++ b/secure/lib/libcrypto/man/ERR_clear_error.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_clear_error 3" -.TH ERR_clear_error 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_clear_error 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_error_string.3 b/secure/lib/libcrypto/man/ERR_error_string.3 index faa1815835e3..ceae6e9c5094 100644 --- a/secure/lib/libcrypto/man/ERR_error_string.3 +++ b/secure/lib/libcrypto/man/ERR_error_string.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_error_string 3" -.TH ERR_error_string 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_error_string 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_get_error.3 b/secure/lib/libcrypto/man/ERR_get_error.3 index 5f50af215535..e5e89d2670ef 100644 --- a/secure/lib/libcrypto/man/ERR_get_error.3 +++ b/secure/lib/libcrypto/man/ERR_get_error.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_get_error 3" -.TH ERR_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_load_crypto_strings.3 b/secure/lib/libcrypto/man/ERR_load_crypto_strings.3 index 542782fc674e..ab55cbe5400e 100644 --- a/secure/lib/libcrypto/man/ERR_load_crypto_strings.3 +++ b/secure/lib/libcrypto/man/ERR_load_crypto_strings.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_load_crypto_strings 3" -.TH ERR_load_crypto_strings 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_load_crypto_strings 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_load_strings.3 b/secure/lib/libcrypto/man/ERR_load_strings.3 index 2c2268774ddf..4fb6d8680ce0 100644 --- a/secure/lib/libcrypto/man/ERR_load_strings.3 +++ b/secure/lib/libcrypto/man/ERR_load_strings.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_load_strings 3" -.TH ERR_load_strings 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_load_strings 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_print_errors.3 b/secure/lib/libcrypto/man/ERR_print_errors.3 index 7048d50f1081..ce7846e88e3e 100644 --- a/secure/lib/libcrypto/man/ERR_print_errors.3 +++ b/secure/lib/libcrypto/man/ERR_print_errors.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_print_errors 3" -.TH ERR_print_errors 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_print_errors 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_put_error.3 b/secure/lib/libcrypto/man/ERR_put_error.3 index 4020eecdc643..f767258f4368 100644 --- a/secure/lib/libcrypto/man/ERR_put_error.3 +++ b/secure/lib/libcrypto/man/ERR_put_error.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_put_error 3" -.TH ERR_put_error 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_put_error 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_remove_state.3 b/secure/lib/libcrypto/man/ERR_remove_state.3 index 554ebc49f451..b276bc70ff91 100644 --- a/secure/lib/libcrypto/man/ERR_remove_state.3 +++ b/secure/lib/libcrypto/man/ERR_remove_state.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_remove_state 3" -.TH ERR_remove_state 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_remove_state 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ERR_set_mark.3 b/secure/lib/libcrypto/man/ERR_set_mark.3 index 1be092262d8d..7b33df8f606a 100644 --- a/secure/lib/libcrypto/man/ERR_set_mark.3 +++ b/secure/lib/libcrypto/man/ERR_set_mark.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERR_set_mark 3" -.TH ERR_set_mark 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERR_set_mark 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_BytesToKey.3 b/secure/lib/libcrypto/man/EVP_BytesToKey.3 index e092a1880b5c..24abfd790e75 100644 --- a/secure/lib/libcrypto/man/EVP_BytesToKey.3 +++ b/secure/lib/libcrypto/man/EVP_BytesToKey.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_BytesToKey 3" -.TH EVP_BytesToKey 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_BytesToKey 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_DigestInit.3 b/secure/lib/libcrypto/man/EVP_DigestInit.3 index 4096ca280634..964febe36d6c 100644 --- a/secure/lib/libcrypto/man/EVP_DigestInit.3 +++ b/secure/lib/libcrypto/man/EVP_DigestInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_DigestInit 3" -.TH EVP_DigestInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_DigestInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_DigestSignInit.3 b/secure/lib/libcrypto/man/EVP_DigestSignInit.3 index c3b4c3ba9b2e..526ec8092117 100644 --- a/secure/lib/libcrypto/man/EVP_DigestSignInit.3 +++ b/secure/lib/libcrypto/man/EVP_DigestSignInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_DigestSignInit 3" -.TH EVP_DigestSignInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_DigestSignInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3 b/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3 index dc14e4f75126..e5057c29875c 100644 --- a/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3 +++ b/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_DigestVerifyInit 3" -.TH EVP_DigestVerifyInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_DigestVerifyInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_EncryptInit.3 b/secure/lib/libcrypto/man/EVP_EncryptInit.3 index 5b6e418213f4..72750a8543f1 100644 --- a/secure/lib/libcrypto/man/EVP_EncryptInit.3 +++ b/secure/lib/libcrypto/man/EVP_EncryptInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_EncryptInit 3" -.TH EVP_EncryptInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_EncryptInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_OpenInit.3 b/secure/lib/libcrypto/man/EVP_OpenInit.3 index a9efbc2105d0..901bc2381f84 100644 --- a/secure/lib/libcrypto/man/EVP_OpenInit.3 +++ b/secure/lib/libcrypto/man/EVP_OpenInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_OpenInit 3" -.TH EVP_OpenInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_OpenInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 index 91e0a111bd07..c62d4e9c7138 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_CTX_ctrl 3" -.TH EVP_PKEY_CTX_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_CTX_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3 b/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3 index 6a6bedcf4ea2..ede32e48dcd9 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_CTX_new 3" -.TH EVP_PKEY_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_cmp.3 b/secure/lib/libcrypto/man/EVP_PKEY_cmp.3 index e27f023b77d6..83284c625be8 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_cmp.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_cmp.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_cmp 3" -.TH EVP_PKEY_cmp 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_cmp 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3 b/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3 index 7638dd3f29c0..317cbd39bd68 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_decrypt 3" -.TH EVP_PKEY_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_derive.3 b/secure/lib/libcrypto/man/EVP_PKEY_derive.3 index 73819794f202..cf6a3d2233dc 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_derive.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_derive.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_derive 3" -.TH EVP_PKEY_derive 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_derive 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3 b/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3 index 425b73fc3d7c..968c657a4a90 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_encrypt 3" -.TH EVP_PKEY_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3 b/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3 index 8e33b95ba454..baadde23b017 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_get_default_digest 3" -.TH EVP_PKEY_get_default_digest 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_get_default_digest 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_keygen.3 b/secure/lib/libcrypto/man/EVP_PKEY_keygen.3 index 30648cd127e2..40cadb1da222 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_keygen.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_keygen.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_keygen 3" -.TH EVP_PKEY_keygen 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_keygen 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_new.3 b/secure/lib/libcrypto/man/EVP_PKEY_new.3 index 60d80d33b77b..a215ffbe3dc2 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_new.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_new 3" -.TH EVP_PKEY_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_print_private.3 b/secure/lib/libcrypto/man/EVP_PKEY_print_private.3 index 3410aad09f03..45d7a8f12187 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_print_private.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_print_private.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_print_private 3" -.TH EVP_PKEY_print_private 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_print_private 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3 b/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3 index 8d65be999a2e..66749bd569aa 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_set1_RSA 3" -.TH EVP_PKEY_set1_RSA 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_set1_RSA 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_sign.3 b/secure/lib/libcrypto/man/EVP_PKEY_sign.3 index d165f826b34d..ecc7326a6f21 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_sign.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_sign 3" -.TH EVP_PKEY_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_verify.3 b/secure/lib/libcrypto/man/EVP_PKEY_verify.3 index 0218f2ba2723..9cef011226b7 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_verify.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_verify.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_verify 3" -.TH EVP_PKEY_verify 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_verify 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3 b/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3 index 982c4a84b736..f28916f3dbdb 100644 --- a/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3 +++ b/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_PKEY_verify_recover 3" -.TH EVP_PKEY_verify_recover 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_PKEY_verify_recover 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_SealInit.3 b/secure/lib/libcrypto/man/EVP_SealInit.3 index b6d3b0410623..0b195a4c25b6 100644 --- a/secure/lib/libcrypto/man/EVP_SealInit.3 +++ b/secure/lib/libcrypto/man/EVP_SealInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_SealInit 3" -.TH EVP_SealInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_SealInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_SignInit.3 b/secure/lib/libcrypto/man/EVP_SignInit.3 index 5199db549840..8d0c569d74fd 100644 --- a/secure/lib/libcrypto/man/EVP_SignInit.3 +++ b/secure/lib/libcrypto/man/EVP_SignInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_SignInit 3" -.TH EVP_SignInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_SignInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/EVP_VerifyInit.3 b/secure/lib/libcrypto/man/EVP_VerifyInit.3 index 06f8bf08257c..2076e1114fdb 100644 --- a/secure/lib/libcrypto/man/EVP_VerifyInit.3 +++ b/secure/lib/libcrypto/man/EVP_VerifyInit.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EVP_VerifyInit 3" -.TH EVP_VerifyInit 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EVP_VerifyInit 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OBJ_nid2obj.3 b/secure/lib/libcrypto/man/OBJ_nid2obj.3 index 878b6059a384..b8803cf06a43 100644 --- a/secure/lib/libcrypto/man/OBJ_nid2obj.3 +++ b/secure/lib/libcrypto/man/OBJ_nid2obj.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OBJ_nid2obj 3" -.TH OBJ_nid2obj 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OBJ_nid2obj 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_Applink.3 b/secure/lib/libcrypto/man/OPENSSL_Applink.3 index 4e219364a76e..156c01a990d3 100644 --- a/secure/lib/libcrypto/man/OPENSSL_Applink.3 +++ b/secure/lib/libcrypto/man/OPENSSL_Applink.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_Applink 3" -.TH OPENSSL_Applink 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_Applink 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3 b/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3 index b6210d3e4c35..15d8559ae3de 100644 --- a/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3 +++ b/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_VERSION_NUMBER 3" -.TH OPENSSL_VERSION_NUMBER 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_VERSION_NUMBER 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_config.3 b/secure/lib/libcrypto/man/OPENSSL_config.3 index dcc2ad28c467..3dda3057ef6e 100644 --- a/secure/lib/libcrypto/man/OPENSSL_config.3 +++ b/secure/lib/libcrypto/man/OPENSSL_config.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_config 3" -.TH OPENSSL_config 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_config 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_ia32cap.3 b/secure/lib/libcrypto/man/OPENSSL_ia32cap.3 index 3ac977a19ec7..d2ef459d7ca8 100644 --- a/secure/lib/libcrypto/man/OPENSSL_ia32cap.3 +++ b/secure/lib/libcrypto/man/OPENSSL_ia32cap.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_ia32cap 3" -.TH OPENSSL_ia32cap 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_ia32cap 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3 b/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3 index af916bea49a6..9bf6627e64ba 100644 --- a/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3 +++ b/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_instrument_bus 3" -.TH OPENSSL_instrument_bus 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_instrument_bus 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3 b/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3 index 812480db256e..9f288d856f17 100644 --- a/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3 +++ b/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL_load_builtin_modules 3" -.TH OPENSSL_load_builtin_modules 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL_load_builtin_modules 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3 b/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3 index 7b1b802943df..b31b05325a5c 100644 --- a/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3 +++ b/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OpenSSL_add_all_algorithms 3" -.TH OpenSSL_add_all_algorithms 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OpenSSL_add_all_algorithms 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3 b/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3 index 7d2079998d3b..8b963364e0ef 100644 --- a/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3 +++ b/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PEM_write_bio_CMS_stream 3" -.TH PEM_write_bio_CMS_stream 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PEM_write_bio_CMS_stream 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3 b/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3 index 14d9d1bdce3b..cf498f4dbd5d 100644 --- a/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3 +++ b/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PEM_write_bio_PKCS7_stream 3" -.TH PEM_write_bio_PKCS7_stream 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PEM_write_bio_PKCS7_stream 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS12_create.3 b/secure/lib/libcrypto/man/PKCS12_create.3 index 46a12b8ec5b5..b51d555adcab 100644 --- a/secure/lib/libcrypto/man/PKCS12_create.3 +++ b/secure/lib/libcrypto/man/PKCS12_create.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS12_create 3" -.TH PKCS12_create 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS12_create 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS12_parse.3 b/secure/lib/libcrypto/man/PKCS12_parse.3 index 3be106cebb1e..e6e31eb56487 100644 --- a/secure/lib/libcrypto/man/PKCS12_parse.3 +++ b/secure/lib/libcrypto/man/PKCS12_parse.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS12_parse 3" -.TH PKCS12_parse 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS12_parse 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS7_decrypt.3 b/secure/lib/libcrypto/man/PKCS7_decrypt.3 index 5321f9f9e467..9a177b32e2bd 100644 --- a/secure/lib/libcrypto/man/PKCS7_decrypt.3 +++ b/secure/lib/libcrypto/man/PKCS7_decrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7_decrypt 3" -.TH PKCS7_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS7_encrypt.3 b/secure/lib/libcrypto/man/PKCS7_encrypt.3 index e6c8552bb8b8..2a74fc73d454 100644 --- a/secure/lib/libcrypto/man/PKCS7_encrypt.3 +++ b/secure/lib/libcrypto/man/PKCS7_encrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7_encrypt 3" -.TH PKCS7_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS7_sign.3 b/secure/lib/libcrypto/man/PKCS7_sign.3 index 01de0aae96de..5939da522e20 100644 --- a/secure/lib/libcrypto/man/PKCS7_sign.3 +++ b/secure/lib/libcrypto/man/PKCS7_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7_sign 3" -.TH PKCS7_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3 b/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3 index 0149972fe1fd..aaa8e46cd659 100644 --- a/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3 +++ b/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7_sign_add_signer 3" -.TH PKCS7_sign_add_signer 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7_sign_add_signer 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/PKCS7_verify.3 b/secure/lib/libcrypto/man/PKCS7_verify.3 index 359e5a767206..f90834ee6fb0 100644 --- a/secure/lib/libcrypto/man/PKCS7_verify.3 +++ b/secure/lib/libcrypto/man/PKCS7_verify.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7_verify 3" -.TH PKCS7_verify 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7_verify 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_add.3 b/secure/lib/libcrypto/man/RAND_add.3 index 4dbb95e90cce..ecd87cf38c45 100644 --- a/secure/lib/libcrypto/man/RAND_add.3 +++ b/secure/lib/libcrypto/man/RAND_add.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_add 3" -.TH RAND_add 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_add 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_bytes.3 b/secure/lib/libcrypto/man/RAND_bytes.3 index 77b0179b9d2f..7d60d8749e0f 100644 --- a/secure/lib/libcrypto/man/RAND_bytes.3 +++ b/secure/lib/libcrypto/man/RAND_bytes.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_bytes 3" -.TH RAND_bytes 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_bytes 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_cleanup.3 b/secure/lib/libcrypto/man/RAND_cleanup.3 index 75444c09141a..fa98f1db4196 100644 --- a/secure/lib/libcrypto/man/RAND_cleanup.3 +++ b/secure/lib/libcrypto/man/RAND_cleanup.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_cleanup 3" -.TH RAND_cleanup 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_cleanup 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_egd.3 b/secure/lib/libcrypto/man/RAND_egd.3 index 482ff2cbf419..2d354cdf76cf 100644 --- a/secure/lib/libcrypto/man/RAND_egd.3 +++ b/secure/lib/libcrypto/man/RAND_egd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_egd 3" -.TH RAND_egd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_egd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_load_file.3 b/secure/lib/libcrypto/man/RAND_load_file.3 index 0d7851bf62c7..ddf8f741fd96 100644 --- a/secure/lib/libcrypto/man/RAND_load_file.3 +++ b/secure/lib/libcrypto/man/RAND_load_file.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_load_file 3" -.TH RAND_load_file 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_load_file 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RAND_set_rand_method.3 b/secure/lib/libcrypto/man/RAND_set_rand_method.3 index ba5c14953693..3cac460c525c 100644 --- a/secure/lib/libcrypto/man/RAND_set_rand_method.3 +++ b/secure/lib/libcrypto/man/RAND_set_rand_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND_set_rand_method 3" -.TH RAND_set_rand_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND_set_rand_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_blinding_on.3 b/secure/lib/libcrypto/man/RSA_blinding_on.3 index 68b0be5bedf9..9215584caee4 100644 --- a/secure/lib/libcrypto/man/RSA_blinding_on.3 +++ b/secure/lib/libcrypto/man/RSA_blinding_on.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_blinding_on 3" -.TH RSA_blinding_on 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_blinding_on 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_check_key.3 b/secure/lib/libcrypto/man/RSA_check_key.3 index 27df720af877..1b7d1c5bbe0c 100644 --- a/secure/lib/libcrypto/man/RSA_check_key.3 +++ b/secure/lib/libcrypto/man/RSA_check_key.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_check_key 3" -.TH RSA_check_key 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_check_key 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_generate_key.3 b/secure/lib/libcrypto/man/RSA_generate_key.3 index 5ee29d8d57dc..0c00558b513d 100644 --- a/secure/lib/libcrypto/man/RSA_generate_key.3 +++ b/secure/lib/libcrypto/man/RSA_generate_key.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_generate_key 3" -.TH RSA_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_get_ex_new_index.3 b/secure/lib/libcrypto/man/RSA_get_ex_new_index.3 index a73e50acff22..d6e364cffb16 100644 --- a/secure/lib/libcrypto/man/RSA_get_ex_new_index.3 +++ b/secure/lib/libcrypto/man/RSA_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_get_ex_new_index 3" -.TH RSA_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_new.3 b/secure/lib/libcrypto/man/RSA_new.3 index 39af29ec90c0..d280491792a0 100644 --- a/secure/lib/libcrypto/man/RSA_new.3 +++ b/secure/lib/libcrypto/man/RSA_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_new 3" -.TH RSA_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3 b/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3 index 60ded7ed2c69..5eee16f9cad5 100644 --- a/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3 +++ b/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_padding_add_PKCS1_type_1 3" -.TH RSA_padding_add_PKCS1_type_1 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_padding_add_PKCS1_type_1 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_print.3 b/secure/lib/libcrypto/man/RSA_print.3 index a48c6d6b28c0..0bb31e5812af 100644 --- a/secure/lib/libcrypto/man/RSA_print.3 +++ b/secure/lib/libcrypto/man/RSA_print.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_print 3" -.TH RSA_print 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_print 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_private_encrypt.3 b/secure/lib/libcrypto/man/RSA_private_encrypt.3 index cc98abde58ad..64502ad24a81 100644 --- a/secure/lib/libcrypto/man/RSA_private_encrypt.3 +++ b/secure/lib/libcrypto/man/RSA_private_encrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_private_encrypt 3" -.TH RSA_private_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_private_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_public_encrypt.3 b/secure/lib/libcrypto/man/RSA_public_encrypt.3 index 54b997db9ca4..f1e2e8f682e0 100644 --- a/secure/lib/libcrypto/man/RSA_public_encrypt.3 +++ b/secure/lib/libcrypto/man/RSA_public_encrypt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_public_encrypt 3" -.TH RSA_public_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_public_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_set_method.3 b/secure/lib/libcrypto/man/RSA_set_method.3 index a6aa98f01a51..7a3a26ab82ec 100644 --- a/secure/lib/libcrypto/man/RSA_set_method.3 +++ b/secure/lib/libcrypto/man/RSA_set_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_set_method 3" -.TH RSA_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_sign.3 b/secure/lib/libcrypto/man/RSA_sign.3 index 2f57c5a94898..a5d4e1fa719c 100644 --- a/secure/lib/libcrypto/man/RSA_sign.3 +++ b/secure/lib/libcrypto/man/RSA_sign.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_sign 3" -.TH RSA_sign 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_sign 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3 b/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3 index 32d579c44466..8d3909e8f4eb 100644 --- a/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3 +++ b/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_sign_ASN1_OCTET_STRING 3" -.TH RSA_sign_ASN1_OCTET_STRING 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_sign_ASN1_OCTET_STRING 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/RSA_size.3 b/secure/lib/libcrypto/man/RSA_size.3 index 6fb4b1c76be0..7bd820a48bb4 100644 --- a/secure/lib/libcrypto/man/RSA_size.3 +++ b/secure/lib/libcrypto/man/RSA_size.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA_size 3" -.TH RSA_size 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA_size 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/SMIME_read_CMS.3 b/secure/lib/libcrypto/man/SMIME_read_CMS.3 index 0f2e94e61cfb..8e61ff0cc1d2 100644 --- a/secure/lib/libcrypto/man/SMIME_read_CMS.3 +++ b/secure/lib/libcrypto/man/SMIME_read_CMS.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SMIME_read_CMS 3" -.TH SMIME_read_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SMIME_read_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/SMIME_read_PKCS7.3 b/secure/lib/libcrypto/man/SMIME_read_PKCS7.3 index 341a77c5f540..df097458df54 100644 --- a/secure/lib/libcrypto/man/SMIME_read_PKCS7.3 +++ b/secure/lib/libcrypto/man/SMIME_read_PKCS7.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SMIME_read_PKCS7 3" -.TH SMIME_read_PKCS7 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SMIME_read_PKCS7 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/SMIME_write_CMS.3 b/secure/lib/libcrypto/man/SMIME_write_CMS.3 index d1288aff6c72..ecd5d0aed945 100644 --- a/secure/lib/libcrypto/man/SMIME_write_CMS.3 +++ b/secure/lib/libcrypto/man/SMIME_write_CMS.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SMIME_write_CMS 3" -.TH SMIME_write_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SMIME_write_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/SMIME_write_PKCS7.3 b/secure/lib/libcrypto/man/SMIME_write_PKCS7.3 index 35ce5ceb04ee..65be1eebc9b5 100644 --- a/secure/lib/libcrypto/man/SMIME_write_PKCS7.3 +++ b/secure/lib/libcrypto/man/SMIME_write_PKCS7.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SMIME_write_PKCS7 3" -.TH SMIME_write_PKCS7 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SMIME_write_PKCS7 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3 b/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3 index 1145471bea1b..bc0c93aa7ae8 100644 --- a/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3 +++ b/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_NAME_ENTRY_get_object 3" -.TH X509_NAME_ENTRY_get_object 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_NAME_ENTRY_get_object 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3 b/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3 index 6faa83d7185b..4d0fd70af1fa 100644 --- a/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3 +++ b/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_NAME_add_entry_by_txt 3" -.TH X509_NAME_add_entry_by_txt 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_NAME_add_entry_by_txt 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3 b/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3 index 8899c51d6f47..1bd371d5664a 100644 --- a/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3 +++ b/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_NAME_get_index_by_NID 3" -.TH X509_NAME_get_index_by_NID 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_NAME_get_index_by_NID 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_NAME_print_ex.3 b/secure/lib/libcrypto/man/X509_NAME_print_ex.3 index 12a6a9ad2ce4..ab24f724f610 100644 --- a/secure/lib/libcrypto/man/X509_NAME_print_ex.3 +++ b/secure/lib/libcrypto/man/X509_NAME_print_ex.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_NAME_print_ex 3" -.TH X509_NAME_print_ex 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_NAME_print_ex 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3 index 5f550bcd9b7d..680446f8b34a 100644 --- a/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3 +++ b/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_STORE_CTX_get_error 3" -.TH X509_STORE_CTX_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_STORE_CTX_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3 index 2d2b3477c7e8..e65edff0af1a 100644 --- a/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3 +++ b/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_STORE_CTX_get_ex_new_index 3" -.TH X509_STORE_CTX_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_STORE_CTX_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_new.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_new.3 index 47e97c3b574b..b9e9433b5738 100644 --- a/secure/lib/libcrypto/man/X509_STORE_CTX_new.3 +++ b/secure/lib/libcrypto/man/X509_STORE_CTX_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_STORE_CTX_new 3" -.TH X509_STORE_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_STORE_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3 index 63e88462ca90..143b5da1278c 100644 --- a/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3 +++ b/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_STORE_CTX_set_verify_cb 3" -.TH X509_STORE_CTX_set_verify_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_STORE_CTX_set_verify_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3 b/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3 index 5ac5a469f124..265432cb748d 100644 --- a/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3 +++ b/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_STORE_set_verify_cb_func 3" -.TH X509_STORE_set_verify_cb_func 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_STORE_set_verify_cb_func 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 b/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 index 323e662d9d12..67a3adb2b632 100644 --- a/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 +++ b/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_VERIFY_PARAM_set_flags 3" -.TH X509_VERIFY_PARAM_set_flags 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_VERIFY_PARAM_set_flags 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_check_host.3 b/secure/lib/libcrypto/man/X509_check_host.3 index 87680786fb64..6214c0a94418 100644 --- a/secure/lib/libcrypto/man/X509_check_host.3 +++ b/secure/lib/libcrypto/man/X509_check_host.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_check_host 3" -.TH X509_check_host 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_check_host 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_new.3 b/secure/lib/libcrypto/man/X509_new.3 index 631398d50e6a..98b0a3d16a6b 100644 --- a/secure/lib/libcrypto/man/X509_new.3 +++ b/secure/lib/libcrypto/man/X509_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_new 3" -.TH X509_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/X509_verify_cert.3 b/secure/lib/libcrypto/man/X509_verify_cert.3 index f74bf50c21df..cf57e76b03ff 100644 --- a/secure/lib/libcrypto/man/X509_verify_cert.3 +++ b/secure/lib/libcrypto/man/X509_verify_cert.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509_verify_cert 3" -.TH X509_verify_cert 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509_verify_cert 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/bio.3 b/secure/lib/libcrypto/man/bio.3 index 86d132ca9fd6..9c78a7cc1614 100644 --- a/secure/lib/libcrypto/man/bio.3 +++ b/secure/lib/libcrypto/man/bio.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "bio 3" -.TH bio 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH bio 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/blowfish.3 b/secure/lib/libcrypto/man/blowfish.3 index 588c21fe7160..27ad78e32fc4 100644 --- a/secure/lib/libcrypto/man/blowfish.3 +++ b/secure/lib/libcrypto/man/blowfish.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "blowfish 3" -.TH blowfish 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH blowfish 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/bn.3 b/secure/lib/libcrypto/man/bn.3 index 23948eab1011..14b6923e83eb 100644 --- a/secure/lib/libcrypto/man/bn.3 +++ b/secure/lib/libcrypto/man/bn.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "bn 3" -.TH bn 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH bn 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/bn_internal.3 b/secure/lib/libcrypto/man/bn_internal.3 index 4b7108a046ac..49f2ac1376d6 100644 --- a/secure/lib/libcrypto/man/bn_internal.3 +++ b/secure/lib/libcrypto/man/bn_internal.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "bn_internal 3" -.TH bn_internal 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH bn_internal 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/buffer.3 b/secure/lib/libcrypto/man/buffer.3 index b47075a75737..806ed8b625cd 100644 --- a/secure/lib/libcrypto/man/buffer.3 +++ b/secure/lib/libcrypto/man/buffer.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "buffer 3" -.TH buffer 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH buffer 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/crypto.3 b/secure/lib/libcrypto/man/crypto.3 index 7c529546108b..4854cadd346c 100644 --- a/secure/lib/libcrypto/man/crypto.3 +++ b/secure/lib/libcrypto/man/crypto.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "crypto 3" -.TH crypto 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH crypto 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3 b/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3 index dc415b6f9281..9ec56417b1ec 100644 --- a/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3 +++ b/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_ASN1_OBJECT 3" -.TH d2i_ASN1_OBJECT 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_ASN1_OBJECT 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3 b/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3 index c89e582727ab..64bf083cf57e 100644 --- a/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3 +++ b/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_CMS_ContentInfo 3" -.TH d2i_CMS_ContentInfo 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_CMS_ContentInfo 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_DHparams.3 b/secure/lib/libcrypto/man/d2i_DHparams.3 index 93ac08e3f031..e76374189b39 100644 --- a/secure/lib/libcrypto/man/d2i_DHparams.3 +++ b/secure/lib/libcrypto/man/d2i_DHparams.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_DHparams 3" -.TH d2i_DHparams 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_DHparams 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_DSAPublicKey.3 b/secure/lib/libcrypto/man/d2i_DSAPublicKey.3 index 86c2f354295f..e121977727fa 100644 --- a/secure/lib/libcrypto/man/d2i_DSAPublicKey.3 +++ b/secure/lib/libcrypto/man/d2i_DSAPublicKey.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_DSAPublicKey 3" -.TH d2i_DSAPublicKey 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_DSAPublicKey 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_ECPKParameters.3 b/secure/lib/libcrypto/man/d2i_ECPKParameters.3 index 5108a824869e..d1e63d76737a 100644 --- a/secure/lib/libcrypto/man/d2i_ECPKParameters.3 +++ b/secure/lib/libcrypto/man/d2i_ECPKParameters.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_ECPKParameters 3" -.TH d2i_ECPKParameters 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_ECPKParameters 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_ECPrivateKey.3 b/secure/lib/libcrypto/man/d2i_ECPrivateKey.3 index a4deedc75882..337c08e85c1b 100644 --- a/secure/lib/libcrypto/man/d2i_ECPrivateKey.3 +++ b/secure/lib/libcrypto/man/d2i_ECPrivateKey.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_ECPrivateKey 3" -.TH d2i_ECPrivateKey 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_ECPrivateKey 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3 b/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3 index d72ddc0f7260..9a02a914f7ff 100644 --- a/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3 +++ b/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_PKCS8PrivateKey 3" -.TH d2i_PKCS8PrivateKey 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_PKCS8PrivateKey 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_RSAPublicKey.3 b/secure/lib/libcrypto/man/d2i_RSAPublicKey.3 index 71c85b8f3247..323c4900c65e 100644 --- a/secure/lib/libcrypto/man/d2i_RSAPublicKey.3 +++ b/secure/lib/libcrypto/man/d2i_RSAPublicKey.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_RSAPublicKey 3" -.TH d2i_RSAPublicKey 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_RSAPublicKey 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509.3 b/secure/lib/libcrypto/man/d2i_X509.3 index 5ad3dd2a6c4f..7d5fb607defa 100644 --- a/secure/lib/libcrypto/man/d2i_X509.3 +++ b/secure/lib/libcrypto/man/d2i_X509.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509 3" -.TH d2i_X509 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509_ALGOR.3 b/secure/lib/libcrypto/man/d2i_X509_ALGOR.3 index 5050f66c0b81..92b231367fd4 100644 --- a/secure/lib/libcrypto/man/d2i_X509_ALGOR.3 +++ b/secure/lib/libcrypto/man/d2i_X509_ALGOR.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509_ALGOR 3" -.TH d2i_X509_ALGOR 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509_ALGOR 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509_CRL.3 b/secure/lib/libcrypto/man/d2i_X509_CRL.3 index ec59a39603de..db2d71d1f892 100644 --- a/secure/lib/libcrypto/man/d2i_X509_CRL.3 +++ b/secure/lib/libcrypto/man/d2i_X509_CRL.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509_CRL 3" -.TH d2i_X509_CRL 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509_CRL 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509_NAME.3 b/secure/lib/libcrypto/man/d2i_X509_NAME.3 index cd795122445e..453a132a7541 100644 --- a/secure/lib/libcrypto/man/d2i_X509_NAME.3 +++ b/secure/lib/libcrypto/man/d2i_X509_NAME.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509_NAME 3" -.TH d2i_X509_NAME 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509_NAME 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509_REQ.3 b/secure/lib/libcrypto/man/d2i_X509_REQ.3 index b8d20a3bd706..72fc91608c48 100644 --- a/secure/lib/libcrypto/man/d2i_X509_REQ.3 +++ b/secure/lib/libcrypto/man/d2i_X509_REQ.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509_REQ 3" -.TH d2i_X509_REQ 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509_REQ 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/d2i_X509_SIG.3 b/secure/lib/libcrypto/man/d2i_X509_SIG.3 index 5dbb776dfab8..22ba9cd9126b 100644 --- a/secure/lib/libcrypto/man/d2i_X509_SIG.3 +++ b/secure/lib/libcrypto/man/d2i_X509_SIG.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_X509_SIG 3" -.TH d2i_X509_SIG 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_X509_SIG 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/des.3 b/secure/lib/libcrypto/man/des.3 index a177c27be66f..5274049a6a59 100644 --- a/secure/lib/libcrypto/man/des.3 +++ b/secure/lib/libcrypto/man/des.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "des 3" -.TH des 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH des 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/dh.3 b/secure/lib/libcrypto/man/dh.3 index cab08e2e4b61..e6cba172a2d7 100644 --- a/secure/lib/libcrypto/man/dh.3 +++ b/secure/lib/libcrypto/man/dh.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "dh 3" -.TH dh 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH dh 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/dsa.3 b/secure/lib/libcrypto/man/dsa.3 index d45505aecaa8..4533582aa55e 100644 --- a/secure/lib/libcrypto/man/dsa.3 +++ b/secure/lib/libcrypto/man/dsa.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "dsa 3" -.TH dsa 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH dsa 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ec.3 b/secure/lib/libcrypto/man/ec.3 index 6346a1573583..a5e483787880 100644 --- a/secure/lib/libcrypto/man/ec.3 +++ b/secure/lib/libcrypto/man/ec.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ec 3" -.TH ec 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ec 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ecdsa.3 b/secure/lib/libcrypto/man/ecdsa.3 index 60bd3d2b683b..43175249f2bd 100644 --- a/secure/lib/libcrypto/man/ecdsa.3 +++ b/secure/lib/libcrypto/man/ecdsa.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ecdsa 3" -.TH ecdsa 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ecdsa 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/engine.3 b/secure/lib/libcrypto/man/engine.3 index b6cb04a45909..c3059bbc53fb 100644 --- a/secure/lib/libcrypto/man/engine.3 +++ b/secure/lib/libcrypto/man/engine.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "engine 3" -.TH engine 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH engine 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/err.3 b/secure/lib/libcrypto/man/err.3 index 09f3f3a97208..f05c2d1888f0 100644 --- a/secure/lib/libcrypto/man/err.3 +++ b/secure/lib/libcrypto/man/err.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "err 3" -.TH err 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH err 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/evp.3 b/secure/lib/libcrypto/man/evp.3 index 37d7d2dabb84..68f84df70dd9 100644 --- a/secure/lib/libcrypto/man/evp.3 +++ b/secure/lib/libcrypto/man/evp.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "evp 3" -.TH evp 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH evp 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/hmac.3 b/secure/lib/libcrypto/man/hmac.3 index c5654455a74e..80e7f34da294 100644 --- a/secure/lib/libcrypto/man/hmac.3 +++ b/secure/lib/libcrypto/man/hmac.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "hmac 3" -.TH hmac 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH hmac 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3 b/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3 index 24375b1005b4..ade4ef0a748f 100644 --- a/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3 +++ b/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "i2d_CMS_bio_stream 3" -.TH i2d_CMS_bio_stream 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH i2d_CMS_bio_stream 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3 b/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3 index 6c436ce311e6..7864aef98b9f 100644 --- a/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3 +++ b/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "i2d_PKCS7_bio_stream 3" -.TH i2d_PKCS7_bio_stream 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH i2d_PKCS7_bio_stream 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/lh_stats.3 b/secure/lib/libcrypto/man/lh_stats.3 index 25a53b104062..0daa911ca364 100644 --- a/secure/lib/libcrypto/man/lh_stats.3 +++ b/secure/lib/libcrypto/man/lh_stats.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "lh_stats 3" -.TH lh_stats 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH lh_stats 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/lhash.3 b/secure/lib/libcrypto/man/lhash.3 index d976c7f5414c..c1eed4a3a1de 100644 --- a/secure/lib/libcrypto/man/lhash.3 +++ b/secure/lib/libcrypto/man/lhash.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "lhash 3" -.TH lhash 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH lhash 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/md5.3 b/secure/lib/libcrypto/man/md5.3 index 3cbe1ca02961..1ca7aa1ecc33 100644 --- a/secure/lib/libcrypto/man/md5.3 +++ b/secure/lib/libcrypto/man/md5.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "md5 3" -.TH md5 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH md5 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/mdc2.3 b/secure/lib/libcrypto/man/mdc2.3 index 8331daeb3662..01437dbb1c00 100644 --- a/secure/lib/libcrypto/man/mdc2.3 +++ b/secure/lib/libcrypto/man/mdc2.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "mdc2 3" -.TH mdc2 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH mdc2 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/pem.3 b/secure/lib/libcrypto/man/pem.3 index 4acb1e9f7708..85af9d78d555 100644 --- a/secure/lib/libcrypto/man/pem.3 +++ b/secure/lib/libcrypto/man/pem.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "pem 3" -.TH pem 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH pem 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/rand.3 b/secure/lib/libcrypto/man/rand.3 index 5af5acd386eb..a5f269246597 100644 --- a/secure/lib/libcrypto/man/rand.3 +++ b/secure/lib/libcrypto/man/rand.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "rand 3" -.TH rand 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH rand 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/rc4.3 b/secure/lib/libcrypto/man/rc4.3 index 10927467254f..122c4c2c0144 100644 --- a/secure/lib/libcrypto/man/rc4.3 +++ b/secure/lib/libcrypto/man/rc4.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "rc4 3" -.TH rc4 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH rc4 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ripemd.3 b/secure/lib/libcrypto/man/ripemd.3 index 979b866ee300..63f98c83468d 100644 --- a/secure/lib/libcrypto/man/ripemd.3 +++ b/secure/lib/libcrypto/man/ripemd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ripemd 3" -.TH ripemd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ripemd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/rsa.3 b/secure/lib/libcrypto/man/rsa.3 index c79febb36c57..e8c986ac94f5 100644 --- a/secure/lib/libcrypto/man/rsa.3 +++ b/secure/lib/libcrypto/man/rsa.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "rsa 3" -.TH rsa 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH rsa 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/sha.3 b/secure/lib/libcrypto/man/sha.3 index a375649bd1e3..5ae70f36a25c 100644 --- a/secure/lib/libcrypto/man/sha.3 +++ b/secure/lib/libcrypto/man/sha.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "sha 3" -.TH sha 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH sha 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/threads.3 b/secure/lib/libcrypto/man/threads.3 index 041c0ae6ae47..4b50d0ee5b66 100644 --- a/secure/lib/libcrypto/man/threads.3 +++ b/secure/lib/libcrypto/man/threads.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "threads 3" -.TH threads 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH threads 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ui.3 b/secure/lib/libcrypto/man/ui.3 index 93fcba655999..54950ab03dd4 100644 --- a/secure/lib/libcrypto/man/ui.3 +++ b/secure/lib/libcrypto/man/ui.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ui 3" -.TH ui 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ui 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/ui_compat.3 b/secure/lib/libcrypto/man/ui_compat.3 index 322d2144db99..99a8bb9131d1 100644 --- a/secure/lib/libcrypto/man/ui_compat.3 +++ b/secure/lib/libcrypto/man/ui_compat.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ui_compat 3" -.TH ui_compat 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ui_compat 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libcrypto/man/x509.3 b/secure/lib/libcrypto/man/x509.3 index 0e9faab26e8d..6be1e144b112 100644 --- a/secure/lib/libcrypto/man/x509.3 +++ b/secure/lib/libcrypto/man/x509.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "x509 3" -.TH x509 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH x509 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/Makefile.man b/secure/lib/libssl/Makefile.man index fdeb315f3c15..34e23870937a 100644 --- a/secure/lib/libssl/Makefile.man +++ b/secure/lib/libssl/Makefile.man @@ -46,6 +46,7 @@ MAN+= SSL_CTX_set_session_cache_mode.3 MAN+= SSL_CTX_set_session_id_context.3 MAN+= SSL_CTX_set_ssl_version.3 MAN+= SSL_CTX_set_timeout.3 +MAN+= SSL_CTX_set_tlsext_status_cb.3 MAN+= SSL_CTX_set_tlsext_ticket_key_cb.3 MAN+= SSL_CTX_set_tmp_dh_callback.3 MAN+= SSL_CTX_set_tmp_rsa_callback.3 @@ -215,6 +216,10 @@ MLINKS+= SSL_CTX_set_session_id_context.3 SSL_set_session_id_context.3 MLINKS+= SSL_CTX_set_ssl_version.3 SSL_set_ssl_method.3 MLINKS+= SSL_CTX_set_ssl_version.3 SSL_get_ssl_method.3 MLINKS+= SSL_CTX_set_timeout.3 SSL_CTX_get_timeout.3 +MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_CTX_set_tlsext_status_arg.3 +MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_set_tlsext_status_type.3 +MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_get_tlsext_status_ocsp_resp.3 +MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_set_tlsext_status_ocsp_resp.3 MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_CTX_set_tmp_dh.3 MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_set_tmp_dh_callback.3 MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_set_tmp_dh.3 diff --git a/secure/lib/libssl/man/SSL_CIPHER_get_name.3 b/secure/lib/libssl/man/SSL_CIPHER_get_name.3 index 7b944469bb55..fa4c52a953f8 100644 --- a/secure/lib/libssl/man/SSL_CIPHER_get_name.3 +++ b/secure/lib/libssl/man/SSL_CIPHER_get_name.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CIPHER_get_name 3" -.TH SSL_CIPHER_get_name 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CIPHER_get_name 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_COMP_add_compression_method.3 b/secure/lib/libssl/man/SSL_COMP_add_compression_method.3 index d327d528fbd5..93121584ebd8 100644 --- a/secure/lib/libssl/man/SSL_COMP_add_compression_method.3 +++ b/secure/lib/libssl/man/SSL_COMP_add_compression_method.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_COMP_add_compression_method 3" -.TH SSL_COMP_add_compression_method 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_COMP_add_compression_method 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_new.3 b/secure/lib/libssl/man/SSL_CONF_CTX_new.3 index 6104db510e5a..47ef5cad24c7 100644 --- a/secure/lib/libssl/man/SSL_CONF_CTX_new.3 +++ b/secure/lib/libssl/man/SSL_CONF_CTX_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_CTX_new 3" -.TH SSL_CONF_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3 index 905e7ac4361e..3f4d6fef9085 100644 --- a/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3 +++ b/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_CTX_set1_prefix 3" -.TH SSL_CONF_CTX_set1_prefix 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_CTX_set1_prefix 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3 index c75e2f5f0753..1d672673952e 100644 --- a/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3 +++ b/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_CTX_set_flags 3" -.TH SSL_CONF_CTX_set_flags 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_CTX_set_flags 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3 index eebb6d45df0b..9995aa66c4b0 100644 --- a/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3 +++ b/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_CTX_set_ssl_ctx 3" -.TH SSL_CONF_CTX_set_ssl_ctx 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_CTX_set_ssl_ctx 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_cmd.3 b/secure/lib/libssl/man/SSL_CONF_cmd.3 index 4b7135bb8f06..26a44ca2f0e7 100644 --- a/secure/lib/libssl/man/SSL_CONF_cmd.3 +++ b/secure/lib/libssl/man/SSL_CONF_cmd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_cmd 3" -.TH SSL_CONF_cmd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_cmd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CONF_cmd_argv.3 b/secure/lib/libssl/man/SSL_CONF_cmd_argv.3 index ec90cab43b69..67ee8cade308 100644 --- a/secure/lib/libssl/man/SSL_CONF_cmd_argv.3 +++ b/secure/lib/libssl/man/SSL_CONF_cmd_argv.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CONF_cmd_argv 3" -.TH SSL_CONF_cmd_argv 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CONF_cmd_argv 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3 b/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3 index 2b0b1554f93d..b0cabc398705 100644 --- a/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3 +++ b/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_add1_chain_cert 3" -.TH SSL_CTX_add1_chain_cert 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_add1_chain_cert 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3 b/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3 index e354223067a2..fc63eb07867a 100644 --- a/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3 +++ b/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_add_extra_chain_cert 3" -.TH SSL_CTX_add_extra_chain_cert 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_add_extra_chain_cert 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_add_session.3 b/secure/lib/libssl/man/SSL_CTX_add_session.3 index 0c4efd29fcd1..0a4afbd9c791 100644 --- a/secure/lib/libssl/man/SSL_CTX_add_session.3 +++ b/secure/lib/libssl/man/SSL_CTX_add_session.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_add_session 3" -.TH SSL_CTX_add_session 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_add_session 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_ctrl.3 b/secure/lib/libssl/man/SSL_CTX_ctrl.3 index 68bd173fde4c..1bd807858edf 100644 --- a/secure/lib/libssl/man/SSL_CTX_ctrl.3 +++ b/secure/lib/libssl/man/SSL_CTX_ctrl.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_ctrl 3" -.TH SSL_CTX_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_flush_sessions.3 b/secure/lib/libssl/man/SSL_CTX_flush_sessions.3 index 8fd1e30bca0a..4e8ce56c0883 100644 --- a/secure/lib/libssl/man/SSL_CTX_flush_sessions.3 +++ b/secure/lib/libssl/man/SSL_CTX_flush_sessions.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_flush_sessions 3" -.TH SSL_CTX_flush_sessions 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_flush_sessions 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_free.3 b/secure/lib/libssl/man/SSL_CTX_free.3 index 1a9bd9cf9f73..60e260842e71 100644 --- a/secure/lib/libssl/man/SSL_CTX_free.3 +++ b/secure/lib/libssl/man/SSL_CTX_free.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_free 3" -.TH SSL_CTX_free 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_free 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_get0_param.3 b/secure/lib/libssl/man/SSL_CTX_get0_param.3 index a05af054f8a0..c7b2a3227d27 100644 --- a/secure/lib/libssl/man/SSL_CTX_get0_param.3 +++ b/secure/lib/libssl/man/SSL_CTX_get0_param.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_get0_param 3" -.TH SSL_CTX_get0_param 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_get0_param 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3 index 6e5194cefc66..b4d4f90927e9 100644 --- a/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3 +++ b/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_get_ex_new_index 3" -.TH SSL_CTX_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3 b/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3 index aa9095eb7c23..7bb5439a3192 100644 --- a/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3 +++ b/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_get_verify_mode 3" -.TH SSL_CTX_get_verify_mode 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_get_verify_mode 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3 b/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3 index d2d37a880dd4..c5d794b49d4e 100644 --- a/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3 +++ b/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_load_verify_locations 3" -.TH SSL_CTX_load_verify_locations 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_load_verify_locations 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_new.3 b/secure/lib/libssl/man/SSL_CTX_new.3 index 60cb996daa91..3127c4ce9bf8 100644 --- a/secure/lib/libssl/man/SSL_CTX_new.3 +++ b/secure/lib/libssl/man/SSL_CTX_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_new 3" -.TH SSL_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_sess_number.3 b/secure/lib/libssl/man/SSL_CTX_sess_number.3 index 1515053d3794..662bcc704898 100644 --- a/secure/lib/libssl/man/SSL_CTX_sess_number.3 +++ b/secure/lib/libssl/man/SSL_CTX_sess_number.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_sess_number 3" -.TH SSL_CTX_sess_number 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_sess_number 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3 b/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3 index 0506967e82f8..9bdd6f25a3f2 100644 --- a/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3 +++ b/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_sess_set_cache_size 3" -.TH SSL_CTX_sess_set_cache_size 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_sess_set_cache_size 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3 b/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3 index d3515c4b7208..28c0d0b93428 100644 --- a/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3 +++ b/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_sess_set_get_cb 3" -.TH SSL_CTX_sess_set_get_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_sess_set_get_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_sessions.3 b/secure/lib/libssl/man/SSL_CTX_sessions.3 index bfe8b44baa33..b1947bc4ce0f 100644 --- a/secure/lib/libssl/man/SSL_CTX_sessions.3 +++ b/secure/lib/libssl/man/SSL_CTX_sessions.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_sessions 3" -.TH SSL_CTX_sessions 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_sessions 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set1_curves.3 b/secure/lib/libssl/man/SSL_CTX_set1_curves.3 index 946a2d77abfd..e5509a72f8c4 100644 --- a/secure/lib/libssl/man/SSL_CTX_set1_curves.3 +++ b/secure/lib/libssl/man/SSL_CTX_set1_curves.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set1_curves 3" -.TH SSL_CTX_set1_curves 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set1_curves 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3 b/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3 index f22269afefc1..7ff815340f22 100644 --- a/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3 +++ b/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set1_verify_cert_store 3" -.TH SSL_CTX_set1_verify_cert_store 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set1_verify_cert_store 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -154,10 +154,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); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3 index ed00c3693a21..f9412dcee441 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_cert_cb 3" -.TH SSL_CTX_set_cert_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_cert_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_store.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_store.3 index 445fa7e2f874..d617d38d433d 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_cert_store.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_cert_store.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_cert_store 3" -.TH SSL_CTX_set_cert_store 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_cert_store 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3 index 0599310ec028..784bfaf9d118 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_cert_verify_callback 3" -.TH SSL_CTX_set_cert_verify_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_cert_verify_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3 b/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3 index 3a711f51ea83..7ce22d6eac9d 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_cipher_list 3" -.TH SSL_CTX_set_cipher_list 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_cipher_list 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3 b/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3 index 8224a07a0b7f..f29270c279fe 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_client_CA_list 3" -.TH SSL_CTX_set_client_CA_list 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_client_CA_list 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3 index 551b489fe3dc..1cabee50395c 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_client_cert_cb 3" -.TH SSL_CTX_set_client_cert_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_client_cert_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3 b/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3 index 8ca38bf459f1..300093ab0f06 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_custom_cli_ext 3" -.TH SSL_CTX_set_custom_cli_ext 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_custom_cli_ext 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3 index 68c1b432c436..811db17dc1d2 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_default_passwd_cb 3" -.TH SSL_CTX_set_default_passwd_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_default_passwd_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3 b/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3 index 543072ec7af7..4c59a54a74c1 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_generate_session_id 3" -.TH SSL_CTX_set_generate_session_id 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_generate_session_id 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_info_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_info_callback.3 index 28307039015a..d2a92a6ba318 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_info_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_info_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_info_callback 3" -.TH SSL_CTX_set_info_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_info_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3 b/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3 index 31bf93d574a5..fffaed4b252d 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_max_cert_list 3" -.TH SSL_CTX_set_max_cert_list 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_max_cert_list 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_mode.3 b/secure/lib/libssl/man/SSL_CTX_set_mode.3 index bb63268e0f46..151ac0780a13 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_mode.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_mode.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_mode 3" -.TH SSL_CTX_set_mode 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_mode 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3 index ac58fe57ab1a..21f45ac1631d 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_msg_callback 3" -.TH SSL_CTX_set_msg_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_msg_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_options.3 b/secure/lib/libssl/man/SSL_CTX_set_options.3 index 138cdc54176a..93256e0d9646 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_options.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_options.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_options 3" -.TH SSL_CTX_set_options 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_options 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3 index b4708b80f29d..a92e797dc44f 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_psk_client_callback 3" -.TH SSL_CTX_set_psk_client_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_psk_client_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3 b/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3 index 8c9d08f33dc0..6f54754e54fa 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_quiet_shutdown 3" -.TH SSL_CTX_set_quiet_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_quiet_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3 b/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3 index da19c435034c..e73e0caa91fc 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_read_ahead 3" -.TH SSL_CTX_set_read_ahead 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_read_ahead 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3 b/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3 index 1881c7ed9438..dfcccbb859b4 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_session_cache_mode 3" -.TH SSL_CTX_set_session_cache_mode 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_session_cache_mode 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3 b/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3 index d93a804999e0..5c17448508ae 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_session_id_context 3" -.TH SSL_CTX_set_session_id_context 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_session_id_context 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3 b/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3 index 9339a29f67b1..452ebf7de636 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_ssl_version 3" -.TH SSL_CTX_set_ssl_version 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_ssl_version 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_timeout.3 b/secure/lib/libssl/man/SSL_CTX_set_timeout.3 index 121cc0496bad..70530e7c74b7 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_timeout.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_timeout.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_timeout 3" -.TH SSL_CTX_set_timeout 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_timeout 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3 new file mode 100644 index 000000000000..11f995efab50 --- /dev/null +++ b/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3 @@ -0,0 +1,207 @@ +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{ +. if \nF \{ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "SSL_CTX_set_tlsext_status_cb 3" +.TH SSL_CTX_set_tlsext_status_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "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 +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& #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); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +A client application may request that a server send back an \s-1OCSP\s0 status response +(also known as \s-1OCSP\s0 stapling). To do so the client should call the +\&\fISSL_set_tlsext_status_type()\fR function prior to the start of the handshake. +Currently the only supported type is \fBTLSEXT_STATUSTYPE_ocsp\fR. This value +should be passed in the \fBtype\fR argument. The client should additionally provide +a callback function to decide what to do with the returned \s-1OCSP\s0 response by +calling \fISSL_CTX_set_tlsext_status_cb()\fR. The callback function should determine +whether the returned \s-1OCSP\s0 response is acceptable or not. The callback will be +passed as an argument the value previously set via a call to +\&\fISSL_CTX_set_tlsext_status_arg()\fR. 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). +.PP +The response returned by the server can be obtained via a call to +\&\fISSL_get_tlsext_status_ocsp_resp()\fR. The value \fB*resp\fR will be updated to point +to the \s-1OCSP\s0 response data and the return value will be the length of that data. +Typically a callback would obtain an \s-1OCSP_RESPONSE\s0 object from this data via a +call to the \fId2i_OCSP_RESPONSE()\fR function. If the server has not provided any +response data then \fB*resp\fR will be \s-1NULL\s0 and the return value from +\&\fISSL_get_tlsext_status_ocsp_resp()\fR will be \-1. +.PP +A server application must also call the \fISSL_CTX_set_tlsext_status_cb()\fR function +if it wants to be able to provide clients with \s-1OCSP\s0 Certificate Status +responses. Typically the server callback would obtain the server certificate +that is being sent back to the client via a call to \fISSL_get_certificate()\fR; +obtain the \s-1OCSP\s0 response to be sent back; and then set that response data by +calling \fISSL_set_tlsext_status_ocsp_resp()\fR. A pointer to the response data should +be provided in the \fBresp\fR argument, and the length of that data should be in +the \fBlen\fR argument. +.SH "RETURN VALUES" +.IX Header "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. +.PP +The callback when used on the server side should return with either +\&\s-1SSL_TLSEXT_ERR_OK \s0(meaning that the \s-1OCSP\s0 response that has been set should be +returned), \s-1SSL_TLSEXT_ERR_NOACK \s0(meaning that an \s-1OCSP\s0 response should not be +returned) or \s-1SSL_TLSEXT_ERR_ALERT_FATAL \s0(meaning that a fatal error has +occurred). +.PP +\&\fISSL_CTX_set_tlsext_status_cb()\fR, \fISSL_CTX_set_tlsext_status_arg()\fR, +\&\fISSL_set_tlsext_status_type()\fR and \fISSL_set_tlsext_status_ocsp_resp()\fR return 0 on +error or 1 on success. +.PP +\&\fISSL_get_tlsext_status_ocsp_resp()\fR returns the length of the \s-1OCSP\s0 response data +or \-1 if there is no \s-1OCSP\s0 response data. diff --git a/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3 index 3d730efc0527..63e0baaf3f25 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_tlsext_ticket_key_cb 3" -.TH SSL_CTX_set_tlsext_ticket_key_cb 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_tlsext_ticket_key_cb 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3 index fc014875478e..c04a9e0bb97f 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_tmp_dh_callback 3" -.TH SSL_CTX_set_tmp_dh_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_tmp_dh_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -184,25 +184,8 @@ even if he gets hold of the normal (certified) key, as this key was only used for signing. .PP In order to perform a \s-1DH\s0 key exchange the server must use a \s-1DH\s0 group -(\s-1DH\s0 parameters) and generate a \s-1DH\s0 key. -The server will always generate a new \s-1DH\s0 key during the negotiation -if either the \s-1DH\s0 parameters are supplied via callback or the -\&\s-1SSL_OP_SINGLE_DH_USE\s0 option of \fISSL_CTX_set_options\fR\|(3) is set (or both). -It will immediately create a \s-1DH\s0 key if \s-1DH\s0 parameters are supplied via -\&\fISSL_CTX_set_tmp_dh()\fR and \s-1SSL_OP_SINGLE_DH_USE\s0 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. -.PP -If \*(L"strong\*(R" primes were used to generate the \s-1DH\s0 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 \*(L"strong\*(R" primes were used, -\&\s-1SSL_OP_SINGLE_DH_USE\s0 must be used in order to prevent small subgroup -attacks. Always using \s-1SSL_OP_SINGLE_DH_USE\s0 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 (\s-1PFS\s0). +(\s-1DH\s0 parameters) and generate a \s-1DH\s0 key. The server will always generate +a new \s-1DH\s0 key during the negotiation. .PP As generating \s-1DH\s0 parameters is extremely time consuming, an application should not generate the parameters on the fly but supply the parameters. @@ -229,10 +212,9 @@ can supply the \s-1DH\s0 parameters via a callback function. Previous versions of the callback used \fBis_export\fR and \fBkeylength\fR 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 \fISSL_CTX_set_tmp_dh()\fR in combination with -\&\s-1SSL_OP_SINGLE_DH_USE,\s0 or alternatively, use the callback but ignore -\&\fBkeylength\fR and \fBis_export\fR and simply supply at least 2048\-bit -parameters in the callback. +are advised to either use \fISSL_CTX_set_tmp_dh()\fR or alternatively, use +the callback but ignore \fBkeylength\fR and \fBis_export\fR and simply +supply at least 2048\-bit parameters in the callback. .SH "EXAMPLES" .IX Header "EXAMPLES" Setup \s-1DH\s0 parameters with a key length of 2048 bits. (Error handling @@ -264,7 +246,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); \& ... .Ve .SH "RETURN VALUES" diff --git a/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3 index 0eda38b759e0..abdb8243c762 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_tmp_rsa_callback 3" -.TH SSL_CTX_set_tmp_rsa_callback 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_tmp_rsa_callback 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_set_verify.3 b/secure/lib/libssl/man/SSL_CTX_set_verify.3 index ea6782839da6..2e7fdbbaadc9 100644 --- a/secure/lib/libssl/man/SSL_CTX_set_verify.3 +++ b/secure/lib/libssl/man/SSL_CTX_set_verify.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_set_verify 3" -.TH SSL_CTX_set_verify 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_set_verify 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_use_certificate.3 b/secure/lib/libssl/man/SSL_CTX_use_certificate.3 index 1e5b7e8958f3..c24675a379cd 100644 --- a/secure/lib/libssl/man/SSL_CTX_use_certificate.3 +++ b/secure/lib/libssl/man/SSL_CTX_use_certificate.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_use_certificate 3" -.TH SSL_CTX_use_certificate 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_use_certificate 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3 b/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3 index 198578b0f4e8..79d2f6eb55d8 100644 --- a/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3 +++ b/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_use_psk_identity_hint 3" -.TH SSL_CTX_use_psk_identity_hint 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_use_psk_identity_hint 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3 b/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3 index 948529cb51ea..bce5345f2877 100644 --- a/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3 +++ b/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_CTX_use_serverinfo 3" -.TH SSL_CTX_use_serverinfo 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_CTX_use_serverinfo 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_SESSION_free.3 b/secure/lib/libssl/man/SSL_SESSION_free.3 index 03d8b0e69abf..e473ebf204a7 100644 --- a/secure/lib/libssl/man/SSL_SESSION_free.3 +++ b/secure/lib/libssl/man/SSL_SESSION_free.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_SESSION_free 3" -.TH SSL_SESSION_free 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_SESSION_free 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3 index 293278238f76..fbc75bbb36e7 100644 --- a/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3 +++ b/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_SESSION_get_ex_new_index 3" -.TH SSL_SESSION_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_SESSION_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_SESSION_get_time.3 b/secure/lib/libssl/man/SSL_SESSION_get_time.3 index 0878ddcc9737..8d814bdfbb67 100644 --- a/secure/lib/libssl/man/SSL_SESSION_get_time.3 +++ b/secure/lib/libssl/man/SSL_SESSION_get_time.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_SESSION_get_time 3" -.TH SSL_SESSION_get_time 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_SESSION_get_time 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_accept.3 b/secure/lib/libssl/man/SSL_accept.3 index 85b68a24acb8..c6953adae1a4 100644 --- a/secure/lib/libssl/man/SSL_accept.3 +++ b/secure/lib/libssl/man/SSL_accept.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_accept 3" -.TH SSL_accept 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_accept 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_alert_type_string.3 b/secure/lib/libssl/man/SSL_alert_type_string.3 index 59571f20d3ae..b049a426275e 100644 --- a/secure/lib/libssl/man/SSL_alert_type_string.3 +++ b/secure/lib/libssl/man/SSL_alert_type_string.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_alert_type_string 3" -.TH SSL_alert_type_string 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_alert_type_string 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_check_chain.3 b/secure/lib/libssl/man/SSL_check_chain.3 index afd73e596149..bd424ae62337 100644 --- a/secure/lib/libssl/man/SSL_check_chain.3 +++ b/secure/lib/libssl/man/SSL_check_chain.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_check_chain 3" -.TH SSL_check_chain 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_check_chain 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_clear.3 b/secure/lib/libssl/man/SSL_clear.3 index 8889174a7e3f..417fc0077adf 100644 --- a/secure/lib/libssl/man/SSL_clear.3 +++ b/secure/lib/libssl/man/SSL_clear.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_clear 3" -.TH SSL_clear 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_clear 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_connect.3 b/secure/lib/libssl/man/SSL_connect.3 index 748c3f505e41..5b761503bf9b 100644 --- a/secure/lib/libssl/man/SSL_connect.3 +++ b/secure/lib/libssl/man/SSL_connect.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_connect 3" -.TH SSL_connect 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_connect 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_do_handshake.3 b/secure/lib/libssl/man/SSL_do_handshake.3 index 988ae4d063ed..f23876cf4381 100644 --- a/secure/lib/libssl/man/SSL_do_handshake.3 +++ b/secure/lib/libssl/man/SSL_do_handshake.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_do_handshake 3" -.TH SSL_do_handshake 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_do_handshake 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_free.3 b/secure/lib/libssl/man/SSL_free.3 index cb704d584077..22014b663e97 100644 --- a/secure/lib/libssl/man/SSL_free.3 +++ b/secure/lib/libssl/man/SSL_free.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_free 3" -.TH SSL_free 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_free 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_SSL_CTX.3 b/secure/lib/libssl/man/SSL_get_SSL_CTX.3 index c36c73455ddd..628adc96e525 100644 --- a/secure/lib/libssl/man/SSL_get_SSL_CTX.3 +++ b/secure/lib/libssl/man/SSL_get_SSL_CTX.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_SSL_CTX 3" -.TH SSL_get_SSL_CTX 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_SSL_CTX 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_ciphers.3 b/secure/lib/libssl/man/SSL_get_ciphers.3 index 6eee14fa2a90..2ded7803745d 100644 --- a/secure/lib/libssl/man/SSL_get_ciphers.3 +++ b/secure/lib/libssl/man/SSL_get_ciphers.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_ciphers 3" -.TH SSL_get_ciphers 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_ciphers 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_client_CA_list.3 b/secure/lib/libssl/man/SSL_get_client_CA_list.3 index 6294a424711a..04f5dbf85860 100644 --- a/secure/lib/libssl/man/SSL_get_client_CA_list.3 +++ b/secure/lib/libssl/man/SSL_get_client_CA_list.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_client_CA_list 3" -.TH SSL_get_client_CA_list 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_client_CA_list 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_current_cipher.3 b/secure/lib/libssl/man/SSL_get_current_cipher.3 index 8fa10a61151e..a431506964e0 100644 --- a/secure/lib/libssl/man/SSL_get_current_cipher.3 +++ b/secure/lib/libssl/man/SSL_get_current_cipher.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_current_cipher 3" -.TH SSL_get_current_cipher 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_current_cipher 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_default_timeout.3 b/secure/lib/libssl/man/SSL_get_default_timeout.3 index 24835f04d0ef..3e6d71223d80 100644 --- a/secure/lib/libssl/man/SSL_get_default_timeout.3 +++ b/secure/lib/libssl/man/SSL_get_default_timeout.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_default_timeout 3" -.TH SSL_get_default_timeout 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_default_timeout 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_error.3 b/secure/lib/libssl/man/SSL_get_error.3 index 5c2485db7c6e..156769754830 100644 --- a/secure/lib/libssl/man/SSL_get_error.3 +++ b/secure/lib/libssl/man/SSL_get_error.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_error 3" -.TH SSL_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3 b/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3 index 7db9989c2bdb..2f57f76a5ac0 100644 --- a/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3 +++ b/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_ex_data_X509_STORE_CTX_idx 3" -.TH SSL_get_ex_data_X509_STORE_CTX_idx 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_ex_data_X509_STORE_CTX_idx 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_get_ex_new_index.3 index f4aae89d89f0..dd95649cb859 100644 --- a/secure/lib/libssl/man/SSL_get_ex_new_index.3 +++ b/secure/lib/libssl/man/SSL_get_ex_new_index.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_ex_new_index 3" -.TH SSL_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_fd.3 b/secure/lib/libssl/man/SSL_get_fd.3 index 5f49b89af236..1871375b4c96 100644 --- a/secure/lib/libssl/man/SSL_get_fd.3 +++ b/secure/lib/libssl/man/SSL_get_fd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_fd 3" -.TH SSL_get_fd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_fd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_peer_cert_chain.3 b/secure/lib/libssl/man/SSL_get_peer_cert_chain.3 index 90fa8cf345a2..0780140439b2 100644 --- a/secure/lib/libssl/man/SSL_get_peer_cert_chain.3 +++ b/secure/lib/libssl/man/SSL_get_peer_cert_chain.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_peer_cert_chain 3" -.TH SSL_get_peer_cert_chain 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_peer_cert_chain 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_peer_certificate.3 b/secure/lib/libssl/man/SSL_get_peer_certificate.3 index d3f83bc5aad4..5395ae47ae6b 100644 --- a/secure/lib/libssl/man/SSL_get_peer_certificate.3 +++ b/secure/lib/libssl/man/SSL_get_peer_certificate.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_peer_certificate 3" -.TH SSL_get_peer_certificate 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_peer_certificate 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_psk_identity.3 b/secure/lib/libssl/man/SSL_get_psk_identity.3 index 918aa1a86d49..19cef683aacd 100644 --- a/secure/lib/libssl/man/SSL_get_psk_identity.3 +++ b/secure/lib/libssl/man/SSL_get_psk_identity.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_psk_identity 3" -.TH SSL_get_psk_identity 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_psk_identity 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_rbio.3 b/secure/lib/libssl/man/SSL_get_rbio.3 index cf64cc924967..256d5db24182 100644 --- a/secure/lib/libssl/man/SSL_get_rbio.3 +++ b/secure/lib/libssl/man/SSL_get_rbio.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_rbio 3" -.TH SSL_get_rbio 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_rbio 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_session.3 b/secure/lib/libssl/man/SSL_get_session.3 index d4554dad8860..7f6b591c2707 100644 --- a/secure/lib/libssl/man/SSL_get_session.3 +++ b/secure/lib/libssl/man/SSL_get_session.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_session 3" -.TH SSL_get_session 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_session 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_verify_result.3 b/secure/lib/libssl/man/SSL_get_verify_result.3 index 8c3aad56b59f..81d30682cf71 100644 --- a/secure/lib/libssl/man/SSL_get_verify_result.3 +++ b/secure/lib/libssl/man/SSL_get_verify_result.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_verify_result 3" -.TH SSL_get_verify_result 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_verify_result 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_get_version.3 b/secure/lib/libssl/man/SSL_get_version.3 index 7035ce624a83..1664a41bab9c 100644 --- a/secure/lib/libssl/man/SSL_get_version.3 +++ b/secure/lib/libssl/man/SSL_get_version.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_get_version 3" -.TH SSL_get_version 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_get_version 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_library_init.3 b/secure/lib/libssl/man/SSL_library_init.3 index 38b95af59765..33fb880dcef6 100644 --- a/secure/lib/libssl/man/SSL_library_init.3 +++ b/secure/lib/libssl/man/SSL_library_init.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_library_init 3" -.TH SSL_library_init 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_library_init 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_load_client_CA_file.3 b/secure/lib/libssl/man/SSL_load_client_CA_file.3 index 61b43a067928..17de1dcbf129 100644 --- a/secure/lib/libssl/man/SSL_load_client_CA_file.3 +++ b/secure/lib/libssl/man/SSL_load_client_CA_file.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_load_client_CA_file 3" -.TH SSL_load_client_CA_file 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_load_client_CA_file 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_new.3 b/secure/lib/libssl/man/SSL_new.3 index 7ed211498aaf..f05a985dbb8a 100644 --- a/secure/lib/libssl/man/SSL_new.3 +++ b/secure/lib/libssl/man/SSL_new.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_new 3" -.TH SSL_new 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_new 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_pending.3 b/secure/lib/libssl/man/SSL_pending.3 index d3903fcd6762..b10ea7eefbc0 100644 --- a/secure/lib/libssl/man/SSL_pending.3 +++ b/secure/lib/libssl/man/SSL_pending.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_pending 3" -.TH SSL_pending 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_pending 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_read.3 b/secure/lib/libssl/man/SSL_read.3 index 8fc6323722c3..3b2728e79605 100644 --- a/secure/lib/libssl/man/SSL_read.3 +++ b/secure/lib/libssl/man/SSL_read.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_read 3" -.TH SSL_read 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_read 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_rstate_string.3 b/secure/lib/libssl/man/SSL_rstate_string.3 index 57095ddf0585..acd782e9d6fc 100644 --- a/secure/lib/libssl/man/SSL_rstate_string.3 +++ b/secure/lib/libssl/man/SSL_rstate_string.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_rstate_string 3" -.TH SSL_rstate_string 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_rstate_string 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_session_reused.3 b/secure/lib/libssl/man/SSL_session_reused.3 index 4bd1b89b9d99..79624966f335 100644 --- a/secure/lib/libssl/man/SSL_session_reused.3 +++ b/secure/lib/libssl/man/SSL_session_reused.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_session_reused 3" -.TH SSL_session_reused 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_session_reused 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_bio.3 b/secure/lib/libssl/man/SSL_set_bio.3 index ec6fd412cdf2..bd2d51957b70 100644 --- a/secure/lib/libssl/man/SSL_set_bio.3 +++ b/secure/lib/libssl/man/SSL_set_bio.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_bio 3" -.TH SSL_set_bio 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_bio 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_connect_state.3 b/secure/lib/libssl/man/SSL_set_connect_state.3 index 5e2fed817705..8e51c95689e6 100644 --- a/secure/lib/libssl/man/SSL_set_connect_state.3 +++ b/secure/lib/libssl/man/SSL_set_connect_state.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_connect_state 3" -.TH SSL_set_connect_state 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_connect_state 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_fd.3 b/secure/lib/libssl/man/SSL_set_fd.3 index 5cb627c6c9a8..a8dec759253a 100644 --- a/secure/lib/libssl/man/SSL_set_fd.3 +++ b/secure/lib/libssl/man/SSL_set_fd.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_fd 3" -.TH SSL_set_fd 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_fd 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_session.3 b/secure/lib/libssl/man/SSL_set_session.3 index 7c9b269bbae6..55633c74bd2e 100644 --- a/secure/lib/libssl/man/SSL_set_session.3 +++ b/secure/lib/libssl/man/SSL_set_session.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_session 3" -.TH SSL_set_session 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_session 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_shutdown.3 b/secure/lib/libssl/man/SSL_set_shutdown.3 index 8983bfa8c7a9..6f93de769dda 100644 --- a/secure/lib/libssl/man/SSL_set_shutdown.3 +++ b/secure/lib/libssl/man/SSL_set_shutdown.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_shutdown 3" -.TH SSL_set_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_set_verify_result.3 b/secure/lib/libssl/man/SSL_set_verify_result.3 index 6492b9d30ffe..c5428546622f 100644 --- a/secure/lib/libssl/man/SSL_set_verify_result.3 +++ b/secure/lib/libssl/man/SSL_set_verify_result.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_set_verify_result 3" -.TH SSL_set_verify_result 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_set_verify_result 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_shutdown.3 b/secure/lib/libssl/man/SSL_shutdown.3 index 7975e98d35ac..02ededfb32ea 100644 --- a/secure/lib/libssl/man/SSL_shutdown.3 +++ b/secure/lib/libssl/man/SSL_shutdown.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_shutdown 3" -.TH SSL_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_state_string.3 b/secure/lib/libssl/man/SSL_state_string.3 index f8aad0c8cbaa..af8df58f924d 100644 --- a/secure/lib/libssl/man/SSL_state_string.3 +++ b/secure/lib/libssl/man/SSL_state_string.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_state_string 3" -.TH SSL_state_string 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_state_string 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_want.3 b/secure/lib/libssl/man/SSL_want.3 index 417f2fc28c2d..de4a5472c508 100644 --- a/secure/lib/libssl/man/SSL_want.3 +++ b/secure/lib/libssl/man/SSL_want.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_want 3" -.TH SSL_want 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_want 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/SSL_write.3 b/secure/lib/libssl/man/SSL_write.3 index d1e018d1114b..f1ff03bff3da 100644 --- a/secure/lib/libssl/man/SSL_write.3 +++ b/secure/lib/libssl/man/SSL_write.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SSL_write 3" -.TH SSL_write 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SSL_write 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/d2i_SSL_SESSION.3 b/secure/lib/libssl/man/d2i_SSL_SESSION.3 index 746576e9f68e..533612512d57 100644 --- a/secure/lib/libssl/man/d2i_SSL_SESSION.3 +++ b/secure/lib/libssl/man/d2i_SSL_SESSION.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "d2i_SSL_SESSION 3" -.TH d2i_SSL_SESSION 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH d2i_SSL_SESSION 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/lib/libssl/man/ssl.3 b/secure/lib/libssl/man/ssl.3 index 90fd9fbf8e50..bc27534c2821 100644 --- a/secure/lib/libssl/man/ssl.3 +++ b/secure/lib/libssl/man/ssl.3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ssl 3" -.TH ssl 3 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ssl 3 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/CA.pl.1 b/secure/usr.bin/openssl/man/CA.pl.1 index 1a9f97a7b5c7..81b0bf7b02a5 100644 --- a/secure/usr.bin/openssl/man/CA.pl.1 +++ b/secure/usr.bin/openssl/man/CA.pl.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CA.PL 1" -.TH CA.PL 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CA.PL 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/asn1parse.1 b/secure/usr.bin/openssl/man/asn1parse.1 index f02283d8e2dc..afc7a532b4bf 100644 --- a/secure/usr.bin/openssl/man/asn1parse.1 +++ b/secure/usr.bin/openssl/man/asn1parse.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ASN1PARSE 1" -.TH ASN1PARSE 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ASN1PARSE 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/c_rehash.1 b/secure/usr.bin/openssl/man/c_rehash.1 index b13de85c5769..a60ccb5cdd91 100644 --- a/secure/usr.bin/openssl/man/c_rehash.1 +++ b/secure/usr.bin/openssl/man/c_rehash.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "C_REHASH 1" -.TH C_REHASH 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH C_REHASH 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ca.1 b/secure/usr.bin/openssl/man/ca.1 index 1d55714a014e..d4cb79e9e51d 100644 --- a/secure/usr.bin/openssl/man/ca.1 +++ b/secure/usr.bin/openssl/man/ca.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CA 1" -.TH CA 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CA 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ciphers.1 b/secure/usr.bin/openssl/man/ciphers.1 index 934ce08ff678..e10144adc728 100644 --- a/secure/usr.bin/openssl/man/ciphers.1 +++ b/secure/usr.bin/openssl/man/ciphers.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CIPHERS 1" -.TH CIPHERS 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CIPHERS 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/cms.1 b/secure/usr.bin/openssl/man/cms.1 index 8c862b978ae9..7355c9a03206 100644 --- a/secure/usr.bin/openssl/man/cms.1 +++ b/secure/usr.bin/openssl/man/cms.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CMS 1" -.TH CMS 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CMS 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/crl.1 b/secure/usr.bin/openssl/man/crl.1 index 6e584721ad40..24c4efe2f764 100644 --- a/secure/usr.bin/openssl/man/crl.1 +++ b/secure/usr.bin/openssl/man/crl.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CRL 1" -.TH CRL 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CRL 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/crl2pkcs7.1 b/secure/usr.bin/openssl/man/crl2pkcs7.1 index fa7eb924de3b..f8d4573e2243 100644 --- a/secure/usr.bin/openssl/man/crl2pkcs7.1 +++ b/secure/usr.bin/openssl/man/crl2pkcs7.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "CRL2PKCS7 1" -.TH CRL2PKCS7 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH CRL2PKCS7 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/dgst.1 b/secure/usr.bin/openssl/man/dgst.1 index fa01dddf9140..746b2add1077 100644 --- a/secure/usr.bin/openssl/man/dgst.1 +++ b/secure/usr.bin/openssl/man/dgst.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DGST 1" -.TH DGST 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DGST 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/dhparam.1 b/secure/usr.bin/openssl/man/dhparam.1 index 601ba5c8caa7..28959e35c148 100644 --- a/secure/usr.bin/openssl/man/dhparam.1 +++ b/secure/usr.bin/openssl/man/dhparam.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DHPARAM 1" -.TH DHPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DHPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/dsa.1 b/secure/usr.bin/openssl/man/dsa.1 index 0bceba98df3c..933fb28a05f6 100644 --- a/secure/usr.bin/openssl/man/dsa.1 +++ b/secure/usr.bin/openssl/man/dsa.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSA 1" -.TH DSA 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSA 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/dsaparam.1 b/secure/usr.bin/openssl/man/dsaparam.1 index d09fba7e7f51..58622b954e65 100644 --- a/secure/usr.bin/openssl/man/dsaparam.1 +++ b/secure/usr.bin/openssl/man/dsaparam.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "DSAPARAM 1" -.TH DSAPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH DSAPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ec.1 b/secure/usr.bin/openssl/man/ec.1 index bec981fb4843..5382d829fe90 100644 --- a/secure/usr.bin/openssl/man/ec.1 +++ b/secure/usr.bin/openssl/man/ec.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "EC 1" -.TH EC 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH EC 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ecparam.1 b/secure/usr.bin/openssl/man/ecparam.1 index 81bf55db2c17..3737f865075a 100644 --- a/secure/usr.bin/openssl/man/ecparam.1 +++ b/secure/usr.bin/openssl/man/ecparam.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ECPARAM 1" -.TH ECPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ECPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/enc.1 b/secure/usr.bin/openssl/man/enc.1 index 27bd55daac89..8378679178fb 100644 --- a/secure/usr.bin/openssl/man/enc.1 +++ b/secure/usr.bin/openssl/man/enc.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ENC 1" -.TH ENC 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ENC 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/errstr.1 b/secure/usr.bin/openssl/man/errstr.1 index 1c171c0f1c06..558f9f4faf5e 100644 --- a/secure/usr.bin/openssl/man/errstr.1 +++ b/secure/usr.bin/openssl/man/errstr.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ERRSTR 1" -.TH ERRSTR 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH ERRSTR 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/gendsa.1 b/secure/usr.bin/openssl/man/gendsa.1 index 9c95a779520f..e98a2814de9f 100644 --- a/secure/usr.bin/openssl/man/gendsa.1 +++ b/secure/usr.bin/openssl/man/gendsa.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "GENDSA 1" -.TH GENDSA 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH GENDSA 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/genpkey.1 b/secure/usr.bin/openssl/man/genpkey.1 index 15cd25b22089..ad8fbd306d2a 100644 --- a/secure/usr.bin/openssl/man/genpkey.1 +++ b/secure/usr.bin/openssl/man/genpkey.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "GENPKEY 1" -.TH GENPKEY 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH GENPKEY 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/genrsa.1 b/secure/usr.bin/openssl/man/genrsa.1 index 94fbcb4a989a..f8415b0d8c1d 100644 --- a/secure/usr.bin/openssl/man/genrsa.1 +++ b/secure/usr.bin/openssl/man/genrsa.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "GENRSA 1" -.TH GENRSA 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH GENRSA 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/nseq.1 b/secure/usr.bin/openssl/man/nseq.1 index a760b1d8056c..f78ebd37c246 100644 --- a/secure/usr.bin/openssl/man/nseq.1 +++ b/secure/usr.bin/openssl/man/nseq.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "NSEQ 1" -.TH NSEQ 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH NSEQ 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ocsp.1 b/secure/usr.bin/openssl/man/ocsp.1 index fc08fefffd4f..da78b9b38f08 100644 --- a/secure/usr.bin/openssl/man/ocsp.1 +++ b/secure/usr.bin/openssl/man/ocsp.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OCSP 1" -.TH OCSP 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OCSP 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/openssl.1 b/secure/usr.bin/openssl/man/openssl.1 index f8e9017e13fa..bcdb8750930f 100644 --- a/secure/usr.bin/openssl/man/openssl.1 +++ b/secure/usr.bin/openssl/man/openssl.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "OPENSSL 1" -.TH OPENSSL 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH OPENSSL 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/passwd.1 b/secure/usr.bin/openssl/man/passwd.1 index a65ad30a62a6..6fd59b80174c 100644 --- a/secure/usr.bin/openssl/man/passwd.1 +++ b/secure/usr.bin/openssl/man/passwd.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PASSWD 1" -.TH PASSWD 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PASSWD 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkcs12.1 b/secure/usr.bin/openssl/man/pkcs12.1 index 7f0e7ce641e9..c43b106c75e2 100644 --- a/secure/usr.bin/openssl/man/pkcs12.1 +++ b/secure/usr.bin/openssl/man/pkcs12.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS12 1" -.TH PKCS12 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS12 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkcs7.1 b/secure/usr.bin/openssl/man/pkcs7.1 index 002224689b4e..7ea5a4d2ca3f 100644 --- a/secure/usr.bin/openssl/man/pkcs7.1 +++ b/secure/usr.bin/openssl/man/pkcs7.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS7 1" -.TH PKCS7 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS7 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkcs8.1 b/secure/usr.bin/openssl/man/pkcs8.1 index 11d9d0e988e4..bccfbefc7d8d 100644 --- a/secure/usr.bin/openssl/man/pkcs8.1 +++ b/secure/usr.bin/openssl/man/pkcs8.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKCS8 1" -.TH PKCS8 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKCS8 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkey.1 b/secure/usr.bin/openssl/man/pkey.1 index 3198c5ae3a3a..a2da1932841c 100644 --- a/secure/usr.bin/openssl/man/pkey.1 +++ b/secure/usr.bin/openssl/man/pkey.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKEY 1" -.TH PKEY 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKEY 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkeyparam.1 b/secure/usr.bin/openssl/man/pkeyparam.1 index 7be5d4c7e614..809cdf0ee60a 100644 --- a/secure/usr.bin/openssl/man/pkeyparam.1 +++ b/secure/usr.bin/openssl/man/pkeyparam.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKEYPARAM 1" -.TH PKEYPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKEYPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/pkeyutl.1 b/secure/usr.bin/openssl/man/pkeyutl.1 index fe398ffe4e13..7311f5234f09 100644 --- a/secure/usr.bin/openssl/man/pkeyutl.1 +++ b/secure/usr.bin/openssl/man/pkeyutl.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PKEYUTL 1" -.TH PKEYUTL 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH PKEYUTL 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/rand.1 b/secure/usr.bin/openssl/man/rand.1 index 788373c4274d..2f0804979d0b 100644 --- a/secure/usr.bin/openssl/man/rand.1 +++ b/secure/usr.bin/openssl/man/rand.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RAND 1" -.TH RAND 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RAND 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/req.1 b/secure/usr.bin/openssl/man/req.1 index d173049c628f..2b8eb1b30ce4 100644 --- a/secure/usr.bin/openssl/man/req.1 +++ b/secure/usr.bin/openssl/man/req.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "REQ 1" -.TH REQ 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH REQ 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/rsa.1 b/secure/usr.bin/openssl/man/rsa.1 index 0feeb417b31c..12f6bb785ec7 100644 --- a/secure/usr.bin/openssl/man/rsa.1 +++ b/secure/usr.bin/openssl/man/rsa.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSA 1" -.TH RSA 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSA 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/rsautl.1 b/secure/usr.bin/openssl/man/rsautl.1 index 76d0a6857aba..5d1d7ec1efd6 100644 --- a/secure/usr.bin/openssl/man/rsautl.1 +++ b/secure/usr.bin/openssl/man/rsautl.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "RSAUTL 1" -.TH RSAUTL 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH RSAUTL 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/s_client.1 b/secure/usr.bin/openssl/man/s_client.1 index bfed887e39dc..74aae106804f 100644 --- a/secure/usr.bin/openssl/man/s_client.1 +++ b/secure/usr.bin/openssl/man/s_client.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "S_CLIENT 1" -.TH S_CLIENT 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH S_CLIENT 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/s_server.1 b/secure/usr.bin/openssl/man/s_server.1 index ec7ad93e07a5..0436ae1d047a 100644 --- a/secure/usr.bin/openssl/man/s_server.1 +++ b/secure/usr.bin/openssl/man/s_server.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "S_SERVER 1" -.TH S_SERVER 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH S_SERVER 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/s_time.1 b/secure/usr.bin/openssl/man/s_time.1 index 4d2026ffc458..284acc1cf999 100644 --- a/secure/usr.bin/openssl/man/s_time.1 +++ b/secure/usr.bin/openssl/man/s_time.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "S_TIME 1" -.TH S_TIME 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH S_TIME 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -160,7 +160,7 @@ s_time \- SSL/TLS performance timing program [\fB\-cipher cipherlist\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" -The \fBs_client\fR command implements a generic \s-1SSL/TLS\s0 client which connects to a +The \fBs_time\fR command implements a generic \s-1SSL/TLS\s0 client which connects to a remote host using \s-1SSL/TLS.\s0 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 @@ -242,7 +242,7 @@ optionally transfer payload data from a server. Server and client performance and the link speed determine how many connections \fBs_time\fR can establish. .SH "NOTES" .IX Header "NOTES" -\&\fBs_client\fR can be used to measure the performance of an \s-1SSL\s0 connection. +\&\fBs_time\fR can be used to measure the performance of an \s-1SSL\s0 connection. To connect to an \s-1SSL HTTP\s0 server and get the default page the command .PP .Vb 1 diff --git a/secure/usr.bin/openssl/man/sess_id.1 b/secure/usr.bin/openssl/man/sess_id.1 index fe6a3c909296..b0c54f70aeed 100644 --- a/secure/usr.bin/openssl/man/sess_id.1 +++ b/secure/usr.bin/openssl/man/sess_id.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SESS_ID 1" -.TH SESS_ID 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SESS_ID 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/smime.1 b/secure/usr.bin/openssl/man/smime.1 index 943717f9b5d1..092218e781fd 100644 --- a/secure/usr.bin/openssl/man/smime.1 +++ b/secure/usr.bin/openssl/man/smime.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SMIME 1" -.TH SMIME 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SMIME 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/speed.1 b/secure/usr.bin/openssl/man/speed.1 index 217b068cd464..08639bd50c8d 100644 --- a/secure/usr.bin/openssl/man/speed.1 +++ b/secure/usr.bin/openssl/man/speed.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SPEED 1" -.TH SPEED 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SPEED 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/spkac.1 b/secure/usr.bin/openssl/man/spkac.1 index 7fc5fbfac086..8a551794a143 100644 --- a/secure/usr.bin/openssl/man/spkac.1 +++ b/secure/usr.bin/openssl/man/spkac.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "SPKAC 1" -.TH SPKAC 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH SPKAC 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/ts.1 b/secure/usr.bin/openssl/man/ts.1 index 29357eb8f328..ba62c06a9061 100644 --- a/secure/usr.bin/openssl/man/ts.1 +++ b/secure/usr.bin/openssl/man/ts.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "TS 1" -.TH TS 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH TS 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/tsget.1 b/secure/usr.bin/openssl/man/tsget.1 index 8bbec0d76034..5faa438b6a6e 100644 --- a/secure/usr.bin/openssl/man/tsget.1 +++ b/secure/usr.bin/openssl/man/tsget.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "TSGET 1" -.TH TSGET 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH TSGET 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/verify.1 b/secure/usr.bin/openssl/man/verify.1 index c987a55461b0..9141659ef38d 100644 --- a/secure/usr.bin/openssl/man/verify.1 +++ b/secure/usr.bin/openssl/man/verify.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "VERIFY 1" -.TH VERIFY 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH VERIFY 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/version.1 b/secure/usr.bin/openssl/man/version.1 index 1e22bab85419..40ec2acd256f 100644 --- a/secure/usr.bin/openssl/man/version.1 +++ b/secure/usr.bin/openssl/man/version.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "VERSION 1" -.TH VERSION 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH VERSION 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/x509.1 b/secure/usr.bin/openssl/man/x509.1 index 546fd9088ca2..46a9476d94be 100644 --- a/secure/usr.bin/openssl/man/x509.1 +++ b/secure/usr.bin/openssl/man/x509.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509 1" -.TH X509 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/secure/usr.bin/openssl/man/x509v3_config.1 b/secure/usr.bin/openssl/man/x509v3_config.1 index d5936ecc5d88..b4f3246f1002 100644 --- a/secure/usr.bin/openssl/man/x509v3_config.1 +++ b/secure/usr.bin/openssl/man/x509v3_config.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "X509V3_CONFIG 1" -.TH X509V3_CONFIG 1 "2015-12-03" "1.0.2e" "OpenSSL" +.TH X509V3_CONFIG 1 "2016-01-28" "1.0.2f" "OpenSSL" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l 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 diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4 index a1522c8df6ca..c0b4a51c5b4a 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,12 @@ A .Nm device appeared in .Fx 9.1 . +.Sh BUGS +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. diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4 index a1d0a1cf82e3..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 @@ -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 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/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. diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk index 8ea97ba14fc8..0897e8d8ca35 100644 --- a/share/mk/bsd.incs.mk +++ b/share/mk/bsd.incs.mk @@ -80,8 +80,7 @@ _${group}INS: ${_${group}INCS} .if defined(INCSLINKS) && !empty(INCSLINKS) installincludes: .for s t in ${INCSLINKS} - @${ECHO} "$t -> $s" ; \ - ${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 4f8565c255f9..9e24af86624f 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 + ${INSTALL_LINK} ${DESTDIR}${s} ${DESTDIR}${t} .endfor .for s t in ${SYMLINKS} - @${ECHO} "$t -> $s" ;\ - ${INSTALL_SYMLINK} $s ${DESTDIR}/$t + ${INSTALL_SYMLINK} ${s} ${DESTDIR}${t} .endfor diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk index d0992b630dfb..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}${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} -.endfor -.endif -.endif manlint: .if defined(MAN) && !empty(MAN) 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}} 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/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/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/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 0dd9241f27df..139899139346 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 @@ -99,35 +88,26 @@ 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 */ - 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 */ 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 */ /* Cache operations */ - arm9_icache_sync_all, /* icache_sync_all */ arm9_icache_sync_range, /* icache_sync_range */ arm9_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -146,18 +126,12 @@ struct cpu_functions arm9_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm9_context_switch, /* context_switch */ arm9_setup /* cpu setup */ @@ -169,29 +143,22 @@ 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 */ armv4_tlb_flushID, /* tlb_flushID */ - arm10_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - arm10_tlb_flushI_SE, /* tlb_flushI_SE */ + arm9_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* 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 */ @@ -211,19 +178,13 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - - arm10_context_switch, /* context_switch */ + arm9_context_switch, /* context_switch */ arm10_setup /* cpu setup */ @@ -232,29 +193,22 @@ 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 */ armv4_tlb_flushID, /* tlb_flushID */ - arm10_tlb_flushID_SE, /* tlb_flushID_SE */ - armv4_tlb_flushI, /* tlb_flushI */ - arm10_tlb_flushI_SE, /* tlb_flushI_SE */ + arm9_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* 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 */ @@ -274,19 +228,13 @@ struct cpu_functions sheeva_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ sheeva_cpu_sleep, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - - arm10_context_switch, /* context_switch */ + arm9_context_switch, /* context_switch */ arm10_setup /* cpu setup */ }; @@ -296,28 +244,21 @@ 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 */ 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 */ /* Cache operations */ - armv7_idcache_wbinv_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -337,54 +278,38 @@ struct cpu_functions pj4bv7_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (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 */ }; #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 */ - 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 */ 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 */ /* Cache operations */ - xscale_cache_syncI, /* icache_sync_all */ xscale_cache_syncI_rng, /* icache_sync_range */ xscale_cache_purgeD, /* dcache_wbinv_all */ @@ -403,53 +328,39 @@ struct cpu_functions xscale_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - xscale_context_switch, /* context_switch */ 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 = { /* 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 */ 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 */ /* Cache operations */ - xscalec3_cache_syncI, /* icache_sync_all */ xscalec3_cache_syncI_rng, /* icache_sync_range */ xscalec3_cache_purgeD, /* dcache_wbinv_all */ @@ -468,18 +379,12 @@ struct cpu_functions xscalec3_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - xscalec3_context_switch, /* context_switch */ xscale_setup /* cpu setup */ @@ -491,29 +396,22 @@ 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 */ 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 */ /* Cache operations */ - fa526_icache_sync_all, /* icache_sync_all */ fa526_icache_sync_range, /* icache_sync_range */ fa526_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -532,17 +430,12 @@ struct cpu_functions fa526_cpufuncs = { /* Other functions */ - 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 */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ fa526_context_switch, /* context_switch */ @@ -554,29 +447,22 @@ 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 */ 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 */ /* Cache operations */ - arm11x6_icache_sync_all, /* icache_sync_all */ arm11x6_icache_sync_range, /* icache_sync_range */ arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -596,18 +482,12 @@ struct cpu_functions arm1176_cpufuncs = { /* Other functions */ - arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */ arm11_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ arm11x6_sleep, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - arm11_context_switch, /* context_switch */ arm11x6_setup /* cpu setup */ @@ -618,16 +498,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 @@ -637,14 +513,11 @@ 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 */ /* Cache operations */ - armv7_icache_sync_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -668,18 +541,12 @@ struct cpu_functions cortexa_cpufuncs = { /* Other functions */ - cpufunc_nullop, /* flush_prefetchbuf */ armv7_drain_writebuf, /* drain_writebuf */ - cpufunc_nullop, /* flush_brnchtgt_C */ - (void *)cpufunc_nullop, /* flush_brnchtgt_E */ armv7_cpu_sleep, /* sleep */ /* Soft functions */ - cpufunc_null_fixup, /* dataabt_fixup */ - cpufunc_null_fixup, /* prefetchabt_fixup */ - armv7_context_switch, /* context_switch */ cortexa_setup /* cpu setup */ @@ -696,10 +563,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 */ @@ -726,7 +593,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: * @@ -833,7 +700,7 @@ get_cachetype_cp15() int set_cpufuncs() { - cputype = cpufunc_id(); + cputype = cpu_ident(); cputype &= CPU_ID_CPU_MASK; #ifdef CPU_ARM9 @@ -889,9 +756,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 +779,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 +789,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 */ @@ -943,18 +804,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; @@ -1000,27 +849,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 */ @@ -1059,7 +887,6 @@ arm9_setup(void) /* Set the control register */ cpu_control(cpuctrlmask, cpuctrl); - ctrl = cpuctrl; } #endif /* CPU_ARM9 */ @@ -1098,7 +925,6 @@ arm10_setup(void) cpuctrl |= CPU_CONTROL_VECRELOC; /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* And again. */ @@ -1140,46 +966,11 @@ 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 = cpufunc_id(); - - 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; + cpuid = cpu_ident(); auxctrl = 0; auxctrl_wax = ~0; @@ -1192,19 +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 */ - ctrl = cpuctrl; - cpu_control(~cpuctrl_wax, cpuctrl); - tmp = cp15_actlr_get(); tmp2 = tmp; tmp &= auxctrl_wax; @@ -1212,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 */ @@ -1223,33 +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 */ - ctrl = cpuctrl; - cpu_control(0xFFFFFFFF, cpuctrl); - - /* And again. */ - cpu_idcache_wbinv_all(); - cpu_scc_setup_ccnt(); } #endif /* CPU_MV_PJ4B */ @@ -1259,45 +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 */ - ctrl = cpuctrl; - 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(); } @@ -1337,14 +1048,12 @@ fa526_setup(void) cpu_idcache_wbinv_all(); /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #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) { @@ -1392,7 +1101,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); @@ -1411,5 +1119,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/cpufunc_asm.S b/sys/arm/arm/cpufunc_asm.S index 12f5840365d1..2f733f564cbf 100644 --- a/sys/arm/arm/cpufunc_asm.S +++ b/sys/arm/arm/cpufunc_asm.S @@ -62,15 +62,10 @@ 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) +END(cpu_ident) ENTRY(cpu_get_control) mrc p15, 0, r0, c1, c0, 0 @@ -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/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S deleted file mode 100644 index ab5f791976aa..000000000000 --- a/sys/arm/arm/cpufunc_asm_arm10.S +++ /dev/null @@ -1,76 +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) - -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. - * - * 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/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_arm11x6.S b/sys/arm/arm/cpufunc_asm_arm11x6.S index b88c0fd67ee2..793c690c9fd3 100644 --- a/sys/arm/arm/cpufunc_asm_arm11x6.S +++ b/sys/arm/arm/cpufunc_asm_arm11x6.S @@ -132,17 +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_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_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_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_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 55c2f376f738..20530ac41951 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 @@ -80,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 */ @@ -97,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$ */ @@ -184,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 @@ -198,13 +178,12 @@ ENTRY(fa526_icache_sync_range) 2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ mov pc, lr -END(fa526_icache_sync_range) -ENTRY(fa526_flush_brnchtgt_E) +.Lfa526_icache_sync_all: mov r0, #0 - mcr p15, 0, r0, c7, c5, 6 /* invalidate BTB cache */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */ mov pc, lr -END(fa526_flush_brnchtgt_E) +END(fa526_icache_sync_range) ENTRY(fa526_context_switch) /* 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/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/db_interface.c b/sys/arm/arm/db_interface.c index 43831462d896..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; @@ -170,7 +171,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; @@ -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/debug_monitor.c b/sys/arm/arm/debug_monitor.c index 7eba5959f8e3..eaf88e9d1f07 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 @@ -782,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); @@ -941,3 +1006,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/devmap.c b/sys/arm/arm/devmap.c index 823210f90604..011b5797881a 100644 --- a/sys/arm/arm/devmap.c +++ b/sys/arm/arm/devmap.c @@ -40,6 +40,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef __arm__ +#include +#endif #include #include #include @@ -204,8 +207,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/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/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/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index c3a7eeddfc93..22f0f44ae575 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); @@ -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) @@ -127,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; @@ -248,7 +245,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 +263,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 +680,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/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/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/genassym.c b/sys/arm/arm/genassym.c index 659c47153fd6..41497714619f 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -45,11 +45,9 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include -#include #include #include @@ -60,17 +58,15 @@ __FBSDID("$FreeBSD$"); #include 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 @@ -94,24 +90,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(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)); -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)); @@ -148,10 +135,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); 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/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index b66b60183c61..b93af2c4b6b5 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__) @@ -136,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) @@ -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 @@ -476,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) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index d2811a6dc071..4e7cb70c84bb 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) { @@ -199,7 +198,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; @@ -397,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; @@ -427,10 +426,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(); @@ -455,12 +452,10 @@ 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); -#ifndef ARM_NEW_PMAP + pmap_set_pcb_pagedir(kernel_pmap, pcb); +#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); @@ -483,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. */ @@ -1283,7 +1273,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 +1437,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) { @@ -1626,7 +1616,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)); @@ -1679,7 +1669,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. @@ -1717,7 +1707,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) { @@ -1871,7 +1861,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. @@ -1905,7 +1895,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/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 60bb59895a44..8643860792d5 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -43,13 +43,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include +#include #include #include #include -#include #include #include #include @@ -122,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(); @@ -154,7 +153,6 @@ init_secondary(int cpu) #ifndef ARM_INTRNG int start = 0, end = 0; #endif -#ifdef ARM_NEW_PMAP uint32_t actlr_mask, actlr_set; pmap_set_tex(); @@ -166,11 +164,6 @@ init_secondary(int cpu) set_stackptrs(cpu); enable_interrupts(PSR_A); -#else /* ARM_NEW_PMAP */ - cpu_setup(); - setttb(pmap_pa); - cpu_tlb_flushID(); -#endif /* ARM_NEW_PMAP */ pc = &__pcpu[cpu]; /* @@ -182,10 +175,6 @@ init_secondary(int cpu) pcpu_init(pc, cpu, sizeof(struct pcpu)); dpcpu_init(dpcpu[cpu - 1], cpu); -#ifndef ARM_NEW_PMAP - /* Provide stack pointers for other processor modes. */ - set_stackptrs(cpu); -#endif /* Signal our startup to BSP */ atomic_add_rel_32(&mp_naps, 1); @@ -292,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); @@ -303,6 +292,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)"); } @@ -346,13 +338,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) @@ -394,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); @@ -405,6 +390,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: @@ -415,10 +403,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); } @@ -448,7 +432,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 @@ -540,10 +523,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/arm/pmap-v6-new.c b/sys/arm/arm/pmap-v6-new.c deleted file mode 100644 index 2996898a4510..000000000000 --- a/sys/arm/arm/pmap-v6-new.c +++ /dev/null @@ -1,6634 +0,0 @@ -/*- - * Copyright (c) 1991 Regents of the University of California. - * 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 - * 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. - * - * 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: @(#)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 "opt_vm.h" -#include "opt_pmap.h" -#include "opt_ddb.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SMP -#include -#else -#include -#endif - -#ifdef DDB -#include -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#ifdef SMP -#include -#endif - -#ifndef PMAP_SHPGPERPROC -#define PMAP_SHPGPERPROC 200 -#endif - -#ifndef DIAGNOSTIC -#define PMAP_INLINE __inline -#else -#define PMAP_INLINE -#endif - -#ifdef PMAP_DEBUG -static void pmap_zero_page_check(vm_page_t m); -void pmap_debug(int level); -int pmap_pid_dump(int pid); - -#define PDEBUG(_lev_,_stat_) \ - if (pmap_debug_level >= (_lev_)) \ - ((_stat_)) -#define dprintf printf -int pmap_debug_level = 1; -#else /* PMAP_DEBUG */ -#define PDEBUG(_lev_,_stat_) /* Nothing */ -#define dprintf(x, arg...) -#endif /* PMAP_DEBUG */ - -/* - * Level 2 page tables map definion ('max' is excluded). - */ - -#define PT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP) -#define PT2V_MAX_ADDRESS ((vm_offset_t)PT2MAP + PT2MAP_SIZE) - -#define UPT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP) -#define UPT2V_MAX_ADDRESS \ - ((vm_offset_t)(PT2MAP + (KERNBASE >> PT2MAP_SHIFT))) - -/* - * Promotion to a 1MB (PTE1) page mapping requires that the corresponding - * 4KB (PTE2) page mappings have identical settings for the following fields: - */ -#define PTE2_PROMOTE (PTE2_V | PTE2_A | PTE2_NM | PTE2_S | PTE2_NG | \ - PTE2_NX | PTE2_RO | PTE2_U | PTE2_W | \ - PTE2_ATTR_MASK) - -#define PTE1_PROMOTE (PTE1_V | PTE1_A | PTE1_NM | PTE1_S | PTE1_NG | \ - PTE1_NX | PTE1_RO | PTE1_U | PTE1_W | \ - PTE1_ATTR_MASK) - -#define ATTR_TO_L1(l2_attr) ((((l2_attr) & L2_TEX0) ? L1_S_TEX0 : 0) | \ - (((l2_attr) & L2_C) ? L1_S_C : 0) | \ - (((l2_attr) & L2_B) ? L1_S_B : 0) | \ - (((l2_attr) & PTE2_A) ? PTE1_A : 0) | \ - (((l2_attr) & PTE2_NM) ? PTE1_NM : 0) | \ - (((l2_attr) & PTE2_S) ? PTE1_S : 0) | \ - (((l2_attr) & PTE2_NG) ? PTE1_NG : 0) | \ - (((l2_attr) & PTE2_NX) ? PTE1_NX : 0) | \ - (((l2_attr) & PTE2_RO) ? PTE1_RO : 0) | \ - (((l2_attr) & PTE2_U) ? PTE1_U : 0) | \ - (((l2_attr) & PTE2_W) ? PTE1_W : 0)) - -#define ATTR_TO_L2(l1_attr) ((((l1_attr) & L1_S_TEX0) ? L2_TEX0 : 0) | \ - (((l1_attr) & L1_S_C) ? L2_C : 0) | \ - (((l1_attr) & L1_S_B) ? L2_B : 0) | \ - (((l1_attr) & PTE1_A) ? PTE2_A : 0) | \ - (((l1_attr) & PTE1_NM) ? PTE2_NM : 0) | \ - (((l1_attr) & PTE1_S) ? PTE2_S : 0) | \ - (((l1_attr) & PTE1_NG) ? PTE2_NG : 0) | \ - (((l1_attr) & PTE1_NX) ? PTE2_NX : 0) | \ - (((l1_attr) & PTE1_RO) ? PTE2_RO : 0) | \ - (((l1_attr) & PTE1_U) ? PTE2_U : 0) | \ - (((l1_attr) & PTE1_W) ? PTE2_W : 0)) - -/* - * PTE2 descriptors creation macros. - */ -#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 PV_STATS -#ifdef PV_STATS -#define PV_STAT(x) do { x ; } while (0) -#else -#define PV_STAT(x) do { } while (0) -#endif - -/* - * The boot_pt1 is used temporary in very early boot stage as L1 page table. - * We can init many things with no memory allocation thanks to its static - * allocation and this brings two main advantages: - * (1) other cores can be started very simply, - * (2) various boot loaders can be supported as its arguments can be processed - * in virtual address space and can be moved to safe location before - * first allocation happened. - * Only disadvantage is that boot_pt1 is used only in very early boot stage. - * However, the table is uninitialized and so lays in bss. Therefore kernel - * image size is not influenced. - * - * QQQ: In the future, maybe, boot_pt1 can be used for soft reset and - * CPU suspend/resume game. - */ -extern pt1_entry_t boot_pt1[]; - -vm_paddr_t base_pt1; -pt1_entry_t *kern_pt1; -pt2_entry_t *kern_pt2tab; -pt2_entry_t *PT2MAP; - -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; -static struct mtx allpmaps_lock; - -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) */ - -static vm_offset_t kernel_vm_end_new; -vm_offset_t kernel_vm_end = KERNBASE + NKPT2PG * NPT2_IN_PG * PTE1_SIZE; -vm_offset_t vm_max_kernel_address; -vm_paddr_t kernel_l1pa; - -static struct rwlock __aligned(CACHE_LINE_SIZE) pvh_global_lock; - -/* - * 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 = 0, pv_entry_max = 0, pv_entry_high_water = 0; -static struct md_page *pv_table; /* XXX: Is it used only the list in md_page? */ -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 */ - -vm_paddr_t first_managed_pa; -#define pa_to_pvh(pa) (&pv_table[pte1_index(pa - first_managed_pa)]) - -/* - * All those kernel PT submaps that BSD is so fond of - */ -struct sysmaps { - struct mtx lock; - pt2_entry_t *CMAP1; - pt2_entry_t *CMAP2; - pt2_entry_t *CMAP3; - caddr_t CADDR1; - caddr_t CADDR2; - caddr_t CADDR3; -}; -static struct sysmaps sysmaps_pcpu[MAXCPU]; -static pt2_entry_t *CMAP3; -static caddr_t CADDR3; -caddr_t _tmppt = 0; - -struct msgbuf *msgbufp = 0; /* XXX move it to machdep.c */ - -/* - * Crashdump maps. - */ -static caddr_t crashdumpmap; - -static pt2_entry_t *PMAP1 = 0, *PMAP2; -static pt2_entry_t *PADDR1 = 0, *PADDR2; -#ifdef DDB -static pt2_entry_t *PMAP3; -static pt2_entry_t *PADDR3; -static int PMAP3cpu __unused; /* for SMP only */ -#endif -#ifdef SMP -static int PMAP1cpu; -static int PMAP1changedcpu; -SYSCTL_INT(_debug, OID_AUTO, PMAP1changedcpu, CTLFLAG_RD, - &PMAP1changedcpu, 0, - "Number of times pmap_pte2_quick changed CPU with same PMAP1"); -#endif -static int PMAP1changed; -SYSCTL_INT(_debug, OID_AUTO, PMAP1changed, CTLFLAG_RD, - &PMAP1changed, 0, - "Number of times pmap_pte2_quick changed PMAP1"); -static int PMAP1unchanged; -SYSCTL_INT(_debug, OID_AUTO, PMAP1unchanged, CTLFLAG_RD, - &PMAP1unchanged, 0, - "Number of times pmap_pte2_quick didn't change PMAP1"); -static struct mtx PMAP2mutex; - -static __inline void pt2_wirecount_init(vm_page_t m); -static boolean_t pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, - vm_offset_t va); -void cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size); - -/* - * 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 */ - -/* - * This table must corespond with memory attribute configuration in vm.h. - * First entry is used for normal system mapping. - * - * Device memory is always marked as shared. - * Normal memory is shared only in SMP . - * Not outer shareable bits are not used yet. - * Class 6 cannot be used on ARM11. - */ -#define TEXDEF_TYPE_SHIFT 0 -#define TEXDEF_TYPE_MASK 0x3 -#define TEXDEF_INNER_SHIFT 2 -#define TEXDEF_INNER_MASK 0x3 -#define TEXDEF_OUTER_SHIFT 4 -#define TEXDEF_OUTER_MASK 0x3 -#define TEXDEF_NOS_SHIFT 6 -#define TEXDEF_NOS_MASK 0x1 - -#define TEX(t, i, o, s) \ - ((t) << TEXDEF_TYPE_SHIFT) | \ - ((i) << TEXDEF_INNER_SHIFT) | \ - ((o) << TEXDEF_OUTER_SHIFT | \ - ((s) << TEXDEF_NOS_SHIFT)) - -static uint32_t tex_class[8] = { -/* type inner cache outer cache */ - TEX(PRRR_MEM, NMRR_WB_WA, NMRR_WB_WA, 0), /* 0 - ATTR_WB_WA */ - TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 1 - ATTR_NOCACHE */ - TEX(PRRR_DEV, NMRR_NC, NMRR_NC, 0), /* 2 - ATTR_DEVICE */ - TEX(PRRR_SO, NMRR_NC, NMRR_NC, 0), /* 3 - ATTR_SO */ - TEX(PRRR_MEM, NMRR_WT, NMRR_WT, 0), /* 4 - ATTR_WT */ - TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 5 - NOT USED YET */ - TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 6 - NOT USED YET */ - TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 7 - NOT USED YET */ -}; -#undef TEX - -/* - * Convert TEX definition entry to TTB flags. - */ -static uint32_t -encode_ttb_flags(int idx) -{ - uint32_t inner, outer, nos, reg; - - inner = (tex_class[idx] >> TEXDEF_INNER_SHIFT) & - TEXDEF_INNER_MASK; - outer = (tex_class[idx] >> TEXDEF_OUTER_SHIFT) & - TEXDEF_OUTER_MASK; - nos = (tex_class[idx] >> TEXDEF_NOS_SHIFT) & - TEXDEF_NOS_MASK; - - reg = nos << 5; - reg |= outer << 3; - if (cpuinfo.coherent_walk) - reg |= (inner & 0x1) << 6; - reg |= (inner & 0x2) >> 1; -#ifdef SMP - reg |= 1 << 1; -#endif - return reg; -} - -/* - * Set TEX remapping registers in current CPU. - */ -void -pmap_set_tex(void) -{ - uint32_t prrr, nmrr; - uint32_t type, inner, outer, nos; - int i; - -#ifdef PMAP_PTE_NOCACHE - /* XXX fixme */ - if (cpuinfo.coherent_walk) { - pt_memattr = VM_MEMATTR_WB_WA; - ttb_flags = encode_ttb_flags(0); - } - else { - pt_memattr = VM_MEMATTR_NOCACHE; - ttb_flags = encode_ttb_flags(1); - } -#else - pt_memattr = VM_MEMATTR_WB_WA; - ttb_flags = encode_ttb_flags(0); -#endif - - prrr = 0; - nmrr = 0; - - /* Build remapping register from TEX classes. */ - for (i = 0; i < 8; i++) { - type = (tex_class[i] >> TEXDEF_TYPE_SHIFT) & - TEXDEF_TYPE_MASK; - inner = (tex_class[i] >> TEXDEF_INNER_SHIFT) & - TEXDEF_INNER_MASK; - outer = (tex_class[i] >> TEXDEF_OUTER_SHIFT) & - TEXDEF_OUTER_MASK; - nos = (tex_class[i] >> TEXDEF_NOS_SHIFT) & - TEXDEF_NOS_MASK; - - prrr |= type << (i * 2); - prrr |= nos << (i + 24); - nmrr |= inner << (i * 2); - nmrr |= outer << (i * 2 + 16); - } - /* Add shareable bits for device memory. */ - prrr |= PRRR_DS0 | PRRR_DS1; - - /* Add shareable bits for normal memory in SMP case. */ -#ifdef SMP - prrr |= PRRR_NS1; -#endif - cp15_prrr_set(prrr); - cp15_nmrr_set(nmrr); - - /* Caches are disabled, so full TLB flush should be enough. */ - tlb_flush_all_local(); -} - -/* - * KERNBASE must be multiple of NPT2_IN_PG * PTE1_SIZE. In other words, - * KERNBASE is mapped by first L2 page table in L2 page table page. It - * meets same constrain due to PT2MAP being placed just under KERNBASE. - */ -CTASSERT((KERNBASE & (NPT2_IN_PG * PTE1_SIZE - 1)) == 0); -CTASSERT((KERNBASE - VM_MAXUSER_ADDRESS) >= PT2MAP_SIZE); - -/* - * In crazy dreams, PAGE_SIZE could be a multiple of PTE2_SIZE in general. - * For now, anyhow, the following check must be fulfilled. - */ -CTASSERT(PAGE_SIZE == PTE2_SIZE); -/* - * We don't want to mess up MI code with all MMU and PMAP definitions, - * so some things, which depend on other ones, are defined independently. - * Now, it is time to check that we don't screw up something. - */ -CTASSERT(PDRSHIFT == PTE1_SHIFT); -/* - * Check L1 and L2 page table entries definitions consistency. - */ -CTASSERT(NB_IN_PT1 == (sizeof(pt1_entry_t) * NPTE1_IN_PT1)); -CTASSERT(NB_IN_PT2 == (sizeof(pt2_entry_t) * NPTE2_IN_PT2)); -/* - * Check L2 page tables page consistency. - */ -CTASSERT(PAGE_SIZE == (NPT2_IN_PG * NB_IN_PT2)); -CTASSERT((1 << PT2PG_SHIFT) == NPT2_IN_PG); -/* - * Check PT2TAB consistency. - * PT2TAB_ENTRIES is defined as a division of NPTE1_IN_PT1 by NPT2_IN_PG. - * This should be done without remainder. - */ -CTASSERT(NPTE1_IN_PT1 == (PT2TAB_ENTRIES * NPT2_IN_PG)); - -/* - * A PT2MAP magic. - * - * All level 2 page tables (PT2s) are mapped continuously and accordingly - * into PT2MAP address space. As PT2 size is less than PAGE_SIZE, this can - * be done only if PAGE_SIZE is a multiple of PT2 size. All PT2s in one page - * must be used together, but not necessary at once. The first PT2 in a page - * must map things on correctly aligned address and the others must follow - * in right order. - */ -#define NB_IN_PT2TAB (PT2TAB_ENTRIES * sizeof(pt2_entry_t)) -#define NPT2_IN_PT2TAB (NB_IN_PT2TAB / NB_IN_PT2) -#define NPG_IN_PT2TAB (NB_IN_PT2TAB / PAGE_SIZE) - -/* - * Check PT2TAB consistency. - * NPT2_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by NB_IN_PT2. - * NPG_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by PAGE_SIZE. - * The both should be done without remainder. - */ -CTASSERT(NB_IN_PT2TAB == (NPT2_IN_PT2TAB * NB_IN_PT2)); -CTASSERT(NB_IN_PT2TAB == (NPG_IN_PT2TAB * PAGE_SIZE)); -/* - * The implementation was made general, however, with the assumption - * bellow in mind. In case of another value of NPG_IN_PT2TAB, - * the code should be once more rechecked. - */ -CTASSERT(NPG_IN_PT2TAB == 1); - -/* - * Get offset of PT2 in a page - * associated with given PT1 index. - */ -static __inline u_int -page_pt2off(u_int pt1_idx) -{ - - return ((pt1_idx & PT2PG_MASK) * NB_IN_PT2); -} - -/* - * Get physical address of PT2 - * associated with given PT2s page and PT1 index. - */ -static __inline vm_paddr_t -page_pt2pa(vm_paddr_t pgpa, u_int pt1_idx) -{ - - return (pgpa + page_pt2off(pt1_idx)); -} - -/* - * Get first entry of PT2 - * associated with given PT2s page and PT1 index. - */ -static __inline pt2_entry_t * -page_pt2(vm_offset_t pgva, u_int pt1_idx) -{ - - return ((pt2_entry_t *)(pgva + page_pt2off(pt1_idx))); -} - -/* - * Get virtual address of PT2s page (mapped in PT2MAP) - * which holds PT2 which holds entry which maps given virtual address. - */ -static __inline vm_offset_t -pt2map_pt2pg(vm_offset_t va) -{ - - va &= ~(NPT2_IN_PG * PTE1_SIZE - 1); - return ((vm_offset_t)pt2map_entry(va)); -} - -/***************************************************************************** - * - * THREE pmap initialization milestones exist: - * - * locore.S - * -> fundamental init (including MMU) in ASM - * - * initarm() - * -> fundamental init continues in C - * -> first available physical address is known - * - * pmap_bootstrap_prepare() -> FIRST PMAP MILESTONE (first epoch begins) - * -> basic (safe) interface for physical address allocation is made - * -> basic (safe) interface for virtual mapping is made - * -> limited not SMP coherent work is possible - * - * -> more fundamental init continues in C - * -> locks and some more things are available - * -> all fundamental allocations and mappings are done - * - * pmap_bootstrap() -> SECOND PMAP MILESTONE (second epoch begins) - * -> phys_avail[] and virtual_avail is set - * -> control is passed to vm subsystem - * -> physical and virtual address allocation are off limit - * -> low level mapping functions, some SMP coherent, - * are available, which cannot be used before vm subsystem - * is being inited - * - * mi_startup() - * -> vm subsystem is being inited - * - * pmap_init() -> THIRD PMAP MILESTONE (third epoch begins) - * -> pmap is fully inited - * - *****************************************************************************/ - -/***************************************************************************** - * - * PMAP first stage initialization and utility functions - * for pre-bootstrap epoch. - * - * After pmap_bootstrap_prepare() is called, the following functions - * can be used: - * - * (1) strictly only for this stage functions for physical page allocations, - * virtual space allocations, and mappings: - * - * vm_paddr_t pmap_preboot_get_pages(u_int num); - * void pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num); - * 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); - * - * (2) for all stages: - * - * vm_paddr_t pmap_kextract(vm_offset_t va); - * - * NOTE: This is not SMP coherent stage. - * - *****************************************************************************/ - -#define KERNEL_P2V(pa) \ - ((vm_offset_t)((pa) - arm_physmem_kernaddr + KERNVIRTADDR)) -#define KERNEL_V2P(va) \ - ((vm_paddr_t)((va) - KERNVIRTADDR + arm_physmem_kernaddr)) - -static vm_paddr_t last_paddr; - -/* - * Pre-bootstrap epoch page allocator. - */ -vm_paddr_t -pmap_preboot_get_pages(u_int num) -{ - vm_paddr_t ret; - - ret = last_paddr; - last_paddr += num * PAGE_SIZE; - - return (ret); -} - -/* - * The fundamental initalization of PMAP stuff. - * - * Some things already happened in locore.S and some things could happen - * before pmap_bootstrap_prepare() is called, so let's recall what is done: - * 1. Caches are disabled. - * 2. We are running on virtual addresses already with 'boot_pt1' - * as L1 page table. - * 3. So far, all virtual addresses can be converted to physical ones and - * vice versa by the following macros: - * KERNEL_P2V(pa) .... physical to virtual ones, - * KERNEL_V2P(va) .... virtual to physical ones. - * - * What is done herein: - * 1. The 'boot_pt1' is replaced by real kernel L1 page table 'kern_pt1'. - * 2. PT2MAP magic is brought to live. - * 3. Basic preboot functions for page allocations and mappings can be used. - * 4. Everything is prepared for L1 cache enabling. - * - * Variations: - * 1. To use second TTB register, so kernel and users page tables will be - * separated. This way process forking - pmap_pinit() - could be faster, - * it saves physical pages and KVA per a process, and it's simple change. - * However, it will lead, due to hardware matter, to the following: - * (a) 2G space for kernel and 2G space for users. - * (b) 1G space for kernel in low addresses and 3G for users above it. - * A question is: Is the case (b) really an option? Note that case (b) - * does save neither physical memory and KVA. - */ -void -pmap_bootstrap_prepare(vm_paddr_t last) -{ - vm_paddr_t pt2pg_pa, pt2tab_pa, pa, size; - vm_offset_t pt2pg_va; - pt1_entry_t *pte1p; - pt2_entry_t *pte2p; - u_int i; - uint32_t actlr_mask, actlr_set; - - /* - * Now, we are going to make real kernel mapping. Note that we are - * already running on some mapping made in locore.S and we expect - * that it's large enough to ensure nofault access to physical memory - * allocated herein before switch. - * - * As kernel image and everything needed before are and will be mapped - * by section mappings, we align last physical address to PTE1_SIZE. - */ - last_paddr = pte1_roundup(last); - - /* - * Allocate and zero page(s) for kernel L1 page table. - * - * Note that it's first allocation on space which was PTE1_SIZE - * aligned and as such base_pt1 is aligned to NB_IN_PT1 too. - */ - base_pt1 = pmap_preboot_get_pages(NPG_IN_PT1); - kern_pt1 = (pt1_entry_t *)KERNEL_P2V(base_pt1); - bzero((void*)kern_pt1, NB_IN_PT1); - pte1_sync_range(kern_pt1, NB_IN_PT1); - - /* Allocate and zero page(s) for kernel PT2TAB. */ - pt2tab_pa = pmap_preboot_get_pages(NPG_IN_PT2TAB); - kern_pt2tab = (pt2_entry_t *)KERNEL_P2V(pt2tab_pa); - bzero(kern_pt2tab, NB_IN_PT2TAB); - pte2_sync_range(kern_pt2tab, NB_IN_PT2TAB); - - /* Allocate and zero page(s) for kernel L2 page tables. */ - pt2pg_pa = pmap_preboot_get_pages(NKPT2PG); - pt2pg_va = KERNEL_P2V(pt2pg_pa); - size = NKPT2PG * PAGE_SIZE; - bzero((void*)pt2pg_va, size); - pte2_sync_range((pt2_entry_t *)pt2pg_va, size); - - /* - * Add a physical memory segment (vm_phys_seg) corresponding to the - * preallocated pages for kernel L2 page tables so that vm_page - * structures representing these pages will be created. The vm_page - * structures are required for promotion of the corresponding kernel - * virtual addresses to section mappings. - */ - vm_phys_add_seg(pt2tab_pa, pmap_preboot_get_pages(0)); - - /* - * Insert allocated L2 page table pages to PT2TAB and make - * link to all PT2s in L1 page table. See how kernel_vm_end - * is initialized. - * - * We play simple and safe. So every KVA will have underlaying - * L2 page table, even kernel image mapped by sections. - */ - pte2p = kern_pt2tab_entry(KERNBASE); - for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += PTE2_SIZE) - pt2tab_store(pte2p++, PTE2_KPT(pa)); - - pte1p = kern_pte1(KERNBASE); - for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += NB_IN_PT2) - pte1_store(pte1p++, PTE1_LINK(pa)); - - /* Make section mappings for kernel. */ - 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))); - - /* - * Get free and aligned space for PT2MAP and make L1 page table links - * to L2 page tables held in PT2TAB. - * - * Note that pages holding PT2s are stored in PT2TAB as pt2_entry_t - * descriptors and PT2TAB page(s) itself is(are) used as PT2s. Thus - * each entry in PT2TAB maps all PT2s in a page. This implies that - * virtual address of PT2MAP must be aligned to NPT2_IN_PG * PTE1_SIZE. - */ - PT2MAP = (pt2_entry_t *)(KERNBASE - PT2MAP_SIZE); - pte1p = kern_pte1((vm_offset_t)PT2MAP); - for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) { - pte1_store(pte1p++, PTE1_LINK(pa)); - } - - /* - * Store PT2TAB in PT2TAB itself, i.e. self reference mapping. - * Each pmap will hold own PT2TAB, so the mapping should be not global. - */ - pte2p = kern_pt2tab_entry((vm_offset_t)PT2MAP); - for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) { - pt2tab_store(pte2p++, PTE2_KPT_NG(pa)); - } - - /* - * Choose correct L2 page table and make mappings for allocations - * made herein which replaces temporary locore.S mappings after a while. - * Note that PT2MAP cannot be used until we switch to kern_pt1. - * - * Note, that these allocations started aligned on 1M section and - * kernel PT1 was allocated first. Making of mappings must follow - * order of physical allocations as we've used KERNEL_P2V() macro - * for virtual addresses resolution. - */ - pte2p = kern_pt2tab_entry((vm_offset_t)kern_pt1); - pt2pg_va = KERNEL_P2V(pte2_pa(pte2_load(pte2p))); - - pte2p = page_pt2(pt2pg_va, pte1_index((vm_offset_t)kern_pt1)); - - /* Make mapping for kernel L1 page table. */ - for (pa = base_pt1, i = 0; i < NPG_IN_PT1; i++, pa += PTE2_SIZE) - pte2_store(pte2p++, PTE2_KPT(pa)); - - /* Make mapping for kernel PT2TAB. */ - for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) - pte2_store(pte2p++, PTE2_KPT(pa)); - - /* Finally, switch from 'boot_pt1' to 'kern_pt1'. */ - pmap_kern_ttb = base_pt1 | ttb_flags; - cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set); - reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set); - /* - * Initialize the first available KVA. As kernel image is mapped by - * sections, we are leaving some gap behind. - */ - virtual_avail = (vm_offset_t)kern_pt2tab + NPG_IN_PT2TAB * PAGE_SIZE; -} - -/* - * Setup L2 page table page for given KVA. - * Used in pre-bootstrap epoch. - * - * Note that we have allocated NKPT2PG pages for L2 page tables in advance - * and used them for mapping KVA starting from KERNBASE. However, this is not - * enough. Vectors and devices need L2 page tables too. Note that they are - * even above VM_MAX_KERNEL_ADDRESS. - */ -static __inline vm_paddr_t -pmap_preboot_pt2pg_setup(vm_offset_t va) -{ - pt2_entry_t *pte2p, pte2; - vm_paddr_t pt2pg_pa; - - /* Get associated entry in PT2TAB. */ - pte2p = kern_pt2tab_entry(va); - - /* Just return, if PT2s page exists already. */ - pte2 = pt2tab_load(pte2p); - if (pte2_is_valid(pte2)) - return (pte2_pa(pte2)); - - KASSERT(va >= VM_MAX_KERNEL_ADDRESS, - ("%s: NKPT2PG too small", __func__)); - - /* - * Allocate page for PT2s and insert it to PT2TAB. - * In other words, map it into PT2MAP space. - */ - pt2pg_pa = pmap_preboot_get_pages(1); - pt2tab_store(pte2p, PTE2_KPT(pt2pg_pa)); - - /* Zero all PT2s in allocated page. */ - bzero((void*)pt2map_pt2pg(va), PAGE_SIZE); - pte2_sync_range((pt2_entry_t *)pt2map_pt2pg(va), PAGE_SIZE); - - return (pt2pg_pa); -} - -/* - * Setup L2 page table for given KVA. - * Used in pre-bootstrap epoch. - */ -static void -pmap_preboot_pt2_setup(vm_offset_t va) -{ - pt1_entry_t *pte1p; - vm_paddr_t pt2pg_pa, pt2_pa; - - /* Setup PT2's page. */ - pt2pg_pa = pmap_preboot_pt2pg_setup(va); - pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(va)); - - /* Insert PT2 to PT1. */ - pte1p = kern_pte1(va); - pte1_store(pte1p, PTE1_LINK(pt2_pa)); -} - -/* - * Get L2 page entry associated with given KVA. - * Used in pre-bootstrap epoch. - */ -static __inline pt2_entry_t* -pmap_preboot_vtopte2(vm_offset_t va) -{ - pt1_entry_t *pte1p; - - /* Setup PT2 if needed. */ - pte1p = kern_pte1(va); - if (!pte1_is_valid(pte1_load(pte1p))) /* XXX - sections ?! */ - pmap_preboot_pt2_setup(va); - - return (pt2map_entry(va)); -} - -/* - * Pre-bootstrap epoch page(s) mapping(s). - */ -void -pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num) -{ - u_int i; - pt2_entry_t *pte2p; - - /* Map all the pages. */ - for (i = 0; i < num; i++) { - pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, PTE2_KRW(pa)); - va += PAGE_SIZE; - pa += PAGE_SIZE; - } -} - -/* - * Pre-bootstrap epoch virtual space alocator. - */ -vm_offset_t -pmap_preboot_reserve_pages(u_int num) -{ - u_int i; - vm_offset_t start, va; - pt2_entry_t *pte2p; - - /* Allocate virtual space. */ - start = va = virtual_avail; - virtual_avail += num * PAGE_SIZE; - - /* Zero the mapping. */ - for (i = 0; i < num; i++) { - pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, 0); - va += PAGE_SIZE; - } - - return (start); -} - -/* - * Pre-bootstrap epoch page(s) allocation and mapping(s). - */ -vm_offset_t -pmap_preboot_get_vpages(u_int num) -{ - vm_paddr_t pa; - vm_offset_t va; - - /* Allocate physical page(s). */ - pa = pmap_preboot_get_pages(num); - - /* Allocate virtual space. */ - va = virtual_avail; - virtual_avail += num * PAGE_SIZE; - - /* Map and zero all. */ - pmap_preboot_map_pages(pa, va, num); - bzero((void *)va, num * PAGE_SIZE); - - return (va); -} - -/* - * 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) -{ - u_int num; - u_int l1_attr, l1_prot; - pt1_entry_t *pte1p; - pt2_entry_t *pte2p; - - l1_prot = ATTR_TO_L1(prot); - l1_attr = ATTR_TO_L1(attr); - - /* Map all the pages. */ - num = round_page(size); - while (num > 0) { - if ((((va | pa) & PTE1_OFFSET) == 0) && (num >= PTE1_SIZE)) { - pte1p = kern_pte1(va); - pte1_store(pte1p, PTE1_KERN(pa, l1_prot, l1_attr)); - va += PTE1_SIZE; - pa += PTE1_SIZE; - num -= PTE1_SIZE; - } else { - pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, PTE2_KERN(pa, prot, attr)); - va += PAGE_SIZE; - pa += PAGE_SIZE; - num -= PAGE_SIZE; - } - } - -} - -/* - * Extract from the kernel page table the physical address - * that is mapped by the given virtual address "va". - */ -vm_paddr_t -pmap_kextract(vm_offset_t va) -{ - vm_paddr_t pa; - pt1_entry_t pte1; - pt2_entry_t pte2; - - pte1 = pte1_load(kern_pte1(va)); - if (pte1_is_section(pte1)) { - pa = pte1_pa(pte1) | (va & PTE1_OFFSET); - } else if (pte1_is_link(pte1)) { - /* - * We should beware of concurrent promotion that changes - * pte1 at this point. However, it's not a problem as PT2 - * page is preserved by promotion in PT2TAB. So even if - * it happens, using of PT2MAP is still safe. - * - * QQQ: However, concurrent removing is a problem which - * ends in abort on PT2MAP space. Locking must be used - * to deal with this. - */ - pte2 = pte2_load(pt2map_entry(va)); - pa = pte2_pa(pte2) | (va & PTE2_OFFSET); - } - else { - panic("%s: va %#x pte1 %#x", __func__, va, pte1); - } - return (pa); -} - -/* - * Extract from the kernel page table the physical address - * that is mapped by the given virtual address "va". Also - * return L2 page table entry which maps the address. - * - * This is only intended to be used for panic dumps. - */ -vm_paddr_t -pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) -{ - vm_paddr_t pa; - pt1_entry_t pte1; - pt2_entry_t pte2; - - pte1 = pte1_load(kern_pte1(va)); - if (pte1_is_section(pte1)) { - pa = pte1_pa(pte1) | (va & PTE1_OFFSET); - pte2 = pa | ATTR_TO_L2(pte1) | PTE2_V; - } else if (pte1_is_link(pte1)) { - pte2 = pte2_load(pt2map_entry(va)); - pa = pte2_pa(pte2); - } else { - pte2 = 0; - pa = 0; - } - if (pte2p != NULL) - *pte2p = pte2; - return (pa); -} - -/***************************************************************************** - * - * PMAP second stage initialization and utility functions - * for bootstrap epoch. - * - * After pmap_bootstrap() is called, the following functions for - * mappings can be used: - * - * void pmap_kenter(vm_offset_t va, vm_paddr_t pa); - * void pmap_kremove(vm_offset_t va); - * vm_offset_t pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, - * int prot); - * - * NOTE: This is not SMP coherent stage. And physical page allocation is not - * allowed during this stage. - * - *****************************************************************************/ - -/* - * Initialize kernel PMAP locks and lists, kernel_pmap itself, and - * reserve various virtual spaces for temporary mappings. - */ -void -pmap_bootstrap(vm_offset_t firstaddr) -{ - pt2_entry_t *unused __unused; - struct sysmaps *sysmaps; - u_int i; - - /* - * Initialize the kernel pmap (which is statically allocated). - */ - PMAP_LOCK_INIT(kernel_pmap); - kernel_l1pa = (vm_paddr_t)kern_pt1; /* for libkvm */ - kernel_pmap->pm_pt1 = kern_pt1; - kernel_pmap->pm_pt2tab = kern_pt2tab; - CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */ - TAILQ_INIT(&kernel_pmap->pm_pvchunk); - - /* - * Initialize the global pv list lock. - */ - rw_init(&pvh_global_lock, "pmap pv global"); - - LIST_INIT(&allpmaps); - - /* - * Request a spin mutex so that changes to allpmaps cannot be - * preempted by smp_rendezvous_cpus(). - */ - mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN); - mtx_lock_spin(&allpmaps_lock); - LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list); - mtx_unlock_spin(&allpmaps_lock); - - /* - * Reserve some special page table entries/VA space for temporary - * mapping of pages. - */ -#define SYSMAP(c, p, v, n) do { \ - v = (c)pmap_preboot_reserve_pages(n); \ - p = pt2map_entry((vm_offset_t)v); \ - } while (0) - - /* - * Local CMAP1/CMAP2 are used for zeroing and copying pages. - * Local CMAP3 is used for data cache cleaning. - * Global CMAP3 is used for the idle process page zeroing. - */ - for (i = 0; i < MAXCPU; i++) { - sysmaps = &sysmaps_pcpu[i]; - mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF); - SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1); - SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1); - SYSMAP(caddr_t, sysmaps->CMAP3, sysmaps->CADDR3, 1); - } - SYSMAP(caddr_t, CMAP3, CADDR3, 1); - - /* - * Crashdump maps. - */ - SYSMAP(caddr_t, unused, crashdumpmap, MAXDUMPPGS); - - /* - * _tmppt is used for reading arbitrary physical pages via /dev/mem. - */ - SYSMAP(caddr_t, unused, _tmppt, 1); - - /* - * PADDR1 and PADDR2 are used by pmap_pte2_quick() and pmap_pte2(), - * respectively. PADDR3 is used by pmap_pte2_ddb(). - */ - SYSMAP(pt2_entry_t *, PMAP1, PADDR1, 1); - SYSMAP(pt2_entry_t *, PMAP2, PADDR2, 1); -#ifdef DDB - SYSMAP(pt2_entry_t *, PMAP3, PADDR3, 1); -#endif - mtx_init(&PMAP2mutex, "PMAP2", NULL, MTX_DEF); - - /* - * Note that in very short time in initarm(), we are going to - * initialize phys_avail[] array and no futher page allocation - * can happen after that until vm subsystem will be initialized. - */ - kernel_vm_end_new = kernel_vm_end; - virtual_end = vm_max_kernel_address; -} - -static void -pmap_init_qpages(void) -{ - struct pcpu *pc; - int i; - - CPU_FOREACH(i) { - pc = pcpu_find(i); - pc->pc_qmap_addr = kva_alloc(PAGE_SIZE); - if (pc->pc_qmap_addr == 0) - panic("%s: unable to allocate KVA", __func__); - } -} -SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL); - -/* - * The function can already be use in second initialization stage. - * As such, the function DOES NOT call pmap_growkernel() where PT2 - * allocation can happen. So if used, be sure that PT2 for given - * virtual address is allocated already! - * - * Add a wired page to the kva. - * Note: not SMP coherent. - */ -static __inline void -pmap_kenter_prot_attr(vm_offset_t va, vm_paddr_t pa, uint32_t prot, - uint32_t attr) -{ - pt1_entry_t *pte1p; - pt2_entry_t *pte2p; - - pte1p = kern_pte1(va); - if (!pte1_is_valid(pte1_load(pte1p))) { /* XXX - sections ?! */ - /* - * This is a very low level function, so PT2 and particularly - * PT2PG associated with given virtual address must be already - * allocated. It's a pain mainly during pmap initialization - * stage. However, called after pmap initialization with - * virtual address not under kernel_vm_end will lead to - * the same misery. - */ - if (!pte2_is_valid(pte2_load(kern_pt2tab_entry(va)))) - panic("%s: kernel PT2 not allocated!", __func__); - } - - pte2p = pt2map_entry(va); - pte2_store(pte2p, PTE2_KERN(pa, prot, attr)); -} - -static __inline void -pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr) -{ - - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, attr); -} - -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); -} - -/* - * Remove a page from the kernel pagetables. - * Note: not SMP coherent. - */ -PMAP_INLINE void -pmap_kremove(vm_offset_t va) -{ - pt2_entry_t *pte2p; - - pte2p = pt2map_entry(va); - pte2_clear(pte2p); -} - -/* - * Share new kernel PT2PG with all pmaps. - * The caller is responsible for maintaining TLB consistency. - */ -static void -pmap_kenter_pt2tab(vm_offset_t va, pt2_entry_t npte2) -{ - pmap_t pmap; - pt2_entry_t *pte2p; - - mtx_lock_spin(&allpmaps_lock); - LIST_FOREACH(pmap, &allpmaps, pm_list) { - pte2p = pmap_pt2tab_entry(pmap, va); - pt2tab_store(pte2p, npte2); - } - mtx_unlock_spin(&allpmaps_lock); -} - -/* - * Share new kernel PTE1 with all pmaps. - * The caller is responsible for maintaining TLB consistency. - */ -static void -pmap_kenter_pte1(vm_offset_t va, pt1_entry_t npte1) -{ - pmap_t pmap; - pt1_entry_t *pte1p; - - mtx_lock_spin(&allpmaps_lock); - LIST_FOREACH(pmap, &allpmaps, pm_list) { - pte1p = pmap_pte1(pmap, va); - pte1_store(pte1p, npte1); - } - mtx_unlock_spin(&allpmaps_lock); -} - -/* - * 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. - * - * NOTE: Read the comments above pmap_kenter_prot_attr() as - * the function is used herein! - */ -vm_offset_t -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; - - 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_EXECUTE) ? PTE2_X : PTE2_NX; - l1prot = ATTR_TO_L1(l2prot); - - va = *virt; - /* - * Does the physical address range's size and alignment permit at - * least one section mapping to be created? - */ - pte1_offset = start & PTE1_OFFSET; - if ((end - start) - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) >= - PTE1_SIZE) { - /* - * Increase the starting virtual address so that its alignment - * does not preclude the use of section mappings. - */ - if ((va & PTE1_OFFSET) < pte1_offset) - va = pte1_trunc(va) + pte1_offset; - else if ((va & PTE1_OFFSET) > pte1_offset) - va = pte1_roundup(va) + pte1_offset; - } - sva = va; - while (start < end) { - 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); - pmap_kenter_pte1(va, npte1); - va += PTE1_SIZE; - start += PTE1_SIZE; - } else { - pmap_kenter_prot_attr(va, start, l2prot, - PTE2_ATTR_NORMAL); - va += PAGE_SIZE; - start += PAGE_SIZE; - } - } - tlb_flush_range(sva, va - sva); - *virt = va; - return (sva); -} - -/* - * 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; - - /* QQQ: 'i' should be less or equal to MAXDUMPPGS. */ - - va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE); - pmap_kenter(va, pa); - tlb_flush_local(va); - return ((void *)crashdumpmap); -} - - -/************************************* - * - * TLB & cache maintenance routines. - * - *************************************/ - -/* - * We inline these within pmap.c for speed. - */ -PMAP_INLINE void -pmap_tlb_flush(pmap_t pmap, vm_offset_t va) -{ - - if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active)) - tlb_flush(va); -} - -PMAP_INLINE void -pmap_tlb_flush_range(pmap_t pmap, vm_offset_t sva, vm_size_t size) -{ - - if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active)) - tlb_flush_range(sva, size); -} - -/* - * Abuse the pte2 nodes for unmapped kva to thread a kva freelist through. - * Requirements: - * - Must deal with pages in order to ensure that none of the PTE2_* bits - * are ever set, PTE2_V in particular. - * - Assumes we can write to pte2s without pte2_store() atomic ops. - * - Assumes nothing will ever test these addresses for 0 to indicate - * no mapping instead of correctly checking PTE2_V. - * - Assumes a vm_offset_t will fit in a pte2 (true for arm). - * Because PTE2_V is never set, there can be no mappings to invalidate. - */ -static vm_offset_t -pmap_pte2list_alloc(vm_offset_t *head) -{ - pt2_entry_t *pte2p; - vm_offset_t va; - - va = *head; - if (va == 0) - panic("pmap_ptelist_alloc: exhausted ptelist KVA"); - pte2p = pt2map_entry(va); - *head = *pte2p; - if (*head & PTE2_V) - panic("%s: va with PTE2_V set!", __func__); - *pte2p = 0; - return (va); -} - -static void -pmap_pte2list_free(vm_offset_t *head, vm_offset_t va) -{ - pt2_entry_t *pte2p; - - if (va & PTE2_V) - panic("%s: freeing va with PTE2_V set!", __func__); - pte2p = pt2map_entry(va); - *pte2p = *head; /* virtual! PTE2_V is 0 though */ - *head = va; -} - -static void -pmap_pte2list_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_pte2list_free(head, va); - } -} - -/***************************************************************************** - * - * PMAP third and final stage initialization. - * - * After pmap_init() is called, PMAP subsystem is fully initialized. - * - *****************************************************************************/ - -SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); - -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 u_long nkpt2pg = NKPT2PG; -SYSCTL_ULONG(_vm_pmap, OID_AUTO, nkpt2pg, CTLFLAG_RD, - &nkpt2pg, 0, "Pre-allocated pages for kernel PT2s"); - -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?"); - -static SYSCTL_NODE(_vm_pmap, OID_AUTO, pte1, CTLFLAG_RD, 0, - "1MB page mapping counters"); - -static u_long pmap_pte1_demotions; -SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, demotions, CTLFLAG_RD, - &pmap_pte1_demotions, 0, "1MB page demotions"); - -static u_long pmap_pte1_mappings; -SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, mappings, CTLFLAG_RD, - &pmap_pte1_mappings, 0, "1MB page mappings"); - -static u_long pmap_pte1_p_failures; -SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, p_failures, CTLFLAG_RD, - &pmap_pte1_p_failures, 0, "1MB page promotion failures"); - -static u_long pmap_pte1_promotions; -SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, promotions, CTLFLAG_RD, - &pmap_pte1_promotions, 0, "1MB page promotions"); - -static __inline ttb_entry_t -pmap_ttb_get(pmap_t pmap) -{ - - return (vtophys(pmap->pm_pt1) | ttb_flags); -} - -/* - * Initialize a vm_page's machine-dependent fields. - * - * Variations: - * 1. Pages for L2 page tables are always not managed. So, pv_list and - * pt2_wirecount can share same physical space. However, proper - * initialization on a page alloc for page tables and reinitialization - * on the page free must be ensured. - */ -void -pmap_page_init(vm_page_t m) -{ - - TAILQ_INIT(&m->md.pv_list); - pt2_wirecount_init(m); - m->md.pat_mode = PTE2_ATTR_NORMAL; -} - -/* - * Virtualization for faster way how to zero whole page. - */ -static __inline void -pagezero(void *page) -{ - - bzero(page, PAGE_SIZE); -} - -/* - * Zero L2 page table page. - * Use same KVA as in pmap_zero_page(). - */ -static __inline vm_paddr_t -pmap_pt2pg_zero(vm_page_t m) -{ - vm_paddr_t pa; - struct sysmaps *sysmaps; - - pa = VM_PAGE_TO_PHYS(m); - - /* - * XXX: For now, we map whole page even if it's already zero, - * to sync it even if the sync is only DSB. - */ - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - 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)); - /* Even VM_ALLOC_ZERO request is only advisory. */ - if ((m->flags & PG_ZERO) == 0) - pagezero(sysmaps->CADDR2); - pte2_sync_range((pt2_entry_t *)sysmaps->CADDR2, PAGE_SIZE); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); - - return (pa); -} - -/* - * Init just allocated page as L2 page table(s) holder - * and return its physical address. - */ -static __inline vm_paddr_t -pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m) -{ - vm_paddr_t pa; - pt2_entry_t *pte2p; - - /* Check page attributes. */ - if (pmap_page_get_memattr(m) != pt_memattr) - pmap_page_set_memattr(m, pt_memattr); - - /* Zero page and init wire counts. */ - pa = pmap_pt2pg_zero(m); - pt2_wirecount_init(m); - - /* - * Map page to PT2MAP address space for given pmap. - * Note that PT2MAP space is shared with all pmaps. - */ - if (pmap == kernel_pmap) - pmap_kenter_pt2tab(va, PTE2_KPT(pa)); - else { - pte2p = pmap_pt2tab_entry(pmap, va); - pt2tab_store(pte2p, PTE2_KPT_NG(pa)); - } - - return (pa); -} - -/* - * 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; - pt2_entry_t *pte2p, pte2; - u_int i, pte1_idx, pv_npg; - - PDEBUG(1, printf("%s: phys_start = %#x\n", __func__, PHYSADDR)); - - /* - * Initialize the vm page array entries for kernel pmap's - * L2 page table pages allocated in advance. - */ - pte1_idx = pte1_index(KERNBASE - PT2MAP_SIZE); - pte2p = kern_pt2tab_entry(KERNBASE - PT2MAP_SIZE); - for (i = 0; i < nkpt2pg + NPG_IN_PT2TAB; i++, pte2p++) { - vm_paddr_t pa; - vm_page_t m; - - pte2 = pte2_load(pte2p); - KASSERT(pte2_is_valid(pte2), ("%s: no valid entry", __func__)); - - pa = pte2_pa(pte2); - m = PHYS_TO_VM_PAGE(pa); - KASSERT(m >= vm_page_array && - m < &vm_page_array[vm_page_array_size], - ("%s: L2 page table page is out of range", __func__)); - - m->pindex = pte1_idx; - m->phys_addr = pa; - pte1_idx += NPT2_IN_PG; - } - - /* - * Initialize the address space (zone) for the pv entries. Set a - * high water mark so that the system can recover from excessive - * numbers of pv entries. - */ - 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); - - /* - * Are large page mappings enabled? - */ - TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled); - if (sp_enabled) { - KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, - ("%s: can't assign to pagesizes[1]", __func__)); - pagesizes[1] = PTE1_SIZE; - } - - /* - * Calculate the size of the pv head table for sections. - * Handle the possibility that "vm_phys_segs[...].end" is zero. - * Note that the table is only for sections which could be promoted. - */ - first_managed_pa = pte1_trunc(vm_phys_segs[0].start); - pv_npg = (pte1_trunc(vm_phys_segs[vm_phys_nsegs - 1].end - PAGE_SIZE) - - first_managed_pa) / PTE1_SIZE + 1; - - /* - * Allocate memory for the pv head table for sections. - */ - 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); - - pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc); - pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks); - if (pv_chunkbase == NULL) - panic("%s: not enough kvm for pv chunks", __func__); - pmap_pte2list_init(&pv_vafree, pv_chunkbase, pv_maxchunks); -} - -/* - * 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) -{ - u_int anychanged; - pt2_entry_t *epte2p, *pte2p, pte2; - vm_page_t m; - vm_paddr_t pa; - - anychanged = 0; - pte2p = pt2map_entry(sva); - epte2p = pte2p + count; - while (pte2p < epte2p) { - m = *ma++; - pa = VM_PAGE_TO_PHYS(m); - pte2 = pte2_load(pte2p); - if ((pte2_pa(pte2) != pa) || - (pte2_attr(pte2) != m->md.pat_mode)) { - anychanged++; - pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW, - m->md.pat_mode)); - } - pte2p++; - } - if (__predict_false(anychanged)) - tlb_flush_range(sva, count * PAGE_SIZE); -} - -/* - * 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) -{ - vm_offset_t va; - - va = sva; - while (count-- > 0) { - pmap_kremove(va); - va += PAGE_SIZE; - } - tlb_flush_range(sva, va - sva); -} - -/* - * Are we current address space or kernel? - */ -static __inline int -pmap_is_current(pmap_t pmap) -{ - - return (pmap == kernel_pmap || - (pmap == vmspace_pmap(curthread->td_proc->p_vmspace))); -} - -/* - * If the given pmap is not the current or kernel pmap, the returned - * pte2 must be released by passing it to pmap_pte2_release(). - */ -static pt2_entry_t * -pmap_pte2(pmap_t pmap, vm_offset_t va) -{ - pt1_entry_t pte1; - vm_paddr_t pt2pg_pa; - - pte1 = pte1_load(pmap_pte1(pmap, va)); - if (pte1_is_section(pte1)) - panic("%s: attempt to map PTE1", __func__); - if (pte1_is_link(pte1)) { - /* Are we current address space or kernel? */ - if (pmap_is_current(pmap)) - return (pt2map_entry(va)); - /* Note that L2 page table size is not equal to PAGE_SIZE. */ - pt2pg_pa = trunc_page(pte1_link_pa(pte1)); - mtx_lock(&PMAP2mutex); - if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) { - pte2_store(PMAP2, PTE2_KPT(pt2pg_pa)); - tlb_flush((vm_offset_t)PADDR2); - } - return (PADDR2 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); - } - return (NULL); -} - -/* - * Releases a pte2 that was obtained from pmap_pte2(). - * Be prepared for the pte2p being NULL. - */ -static __inline void -pmap_pte2_release(pt2_entry_t *pte2p) -{ - - if ((pt2_entry_t *)(trunc_page((vm_offset_t)pte2p)) == PADDR2) { - mtx_unlock(&PMAP2mutex); - } -} - -/* - * Super fast pmap_pte2 routine best used when scanning - * the pv lists. This eliminates many coarse-grained - * invltlb calls. Note that many of the pv list - * scans are across different pmaps. It is very wasteful - * to do an entire tlb flush for checking a single mapping. - * - * If the given pmap is not the current pmap, pvh_global_lock - * must be held and curthread pinned to a CPU. - */ -static pt2_entry_t * -pmap_pte2_quick(pmap_t pmap, vm_offset_t va) -{ - pt1_entry_t pte1; - vm_paddr_t pt2pg_pa; - - pte1 = pte1_load(pmap_pte1(pmap, va)); - if (pte1_is_section(pte1)) - panic("%s: attempt to map PTE1", __func__); - if (pte1_is_link(pte1)) { - /* Are we current address space or kernel? */ - if (pmap_is_current(pmap)) - return (pt2map_entry(va)); - rw_assert(&pvh_global_lock, RA_WLOCKED); - KASSERT(curthread->td_pinned > 0, - ("%s: curthread not pinned", __func__)); - /* Note that L2 page table size is not equal to PAGE_SIZE. */ - pt2pg_pa = trunc_page(pte1_link_pa(pte1)); - if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) { - pte2_store(PMAP1, PTE2_KPT(pt2pg_pa)); -#ifdef SMP - PMAP1cpu = PCPU_GET(cpuid); -#endif - tlb_flush_local((vm_offset_t)PADDR1); - PMAP1changed++; - } else -#ifdef SMP - if (PMAP1cpu != PCPU_GET(cpuid)) { - PMAP1cpu = PCPU_GET(cpuid); - tlb_flush_local((vm_offset_t)PADDR1); - PMAP1changedcpu++; - } else -#endif - PMAP1unchanged++; - return (PADDR1 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); - } - return (NULL); -} - -/* - * 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; - pt1_entry_t pte1; - pt2_entry_t *pte2p; - - PMAP_LOCK(pmap); - pte1 = pte1_load(pmap_pte1(pmap, va)); - if (pte1_is_section(pte1)) - pa = pte1_pa(pte1) | (va & PTE1_OFFSET); - else if (pte1_is_link(pte1)) { - pte2p = pmap_pte2(pmap, va); - pa = pte2_pa(pte2_load(pte2p)) | (va & PTE2_OFFSET); - pmap_pte2_release(pte2p); - } else - pa = 0; - 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) -{ - vm_paddr_t pa, lockpa; - pt1_entry_t pte1; - pt2_entry_t pte2, *pte2p; - vm_page_t m; - - lockpa = 0; - m = NULL; - PMAP_LOCK(pmap); -retry: - pte1 = pte1_load(pmap_pte1(pmap, va)); - if (pte1_is_section(pte1)) { - if (!(pte1 & PTE1_RO) || !(prot & VM_PROT_WRITE)) { - pa = pte1_pa(pte1) | (va & PTE1_OFFSET); - if (vm_page_pa_tryrelock(pmap, pa, &lockpa)) - goto retry; - m = PHYS_TO_VM_PAGE(pa); - vm_page_hold(m); - } - } else if (pte1_is_link(pte1)) { - pte2p = pmap_pte2(pmap, va); - pte2 = pte2_load(pte2p); - pmap_pte2_release(pte2p); - if (pte2_is_valid(pte2) && - (!(pte2 & PTE2_RO) || !(prot & VM_PROT_WRITE))) { - pa = pte2_pa(pte2); - if (vm_page_pa_tryrelock(pmap, pa, &lockpa)) - goto retry; - m = PHYS_TO_VM_PAGE(pa); - vm_page_hold(m); - } - } - PA_UNLOCK_COND(lockpa); - PMAP_UNLOCK(pmap); - return (m); -} - -/* - * Grow the number of kernel L2 page table entries, if needed. - */ -void -pmap_growkernel(vm_offset_t addr) -{ - vm_page_t m; - vm_paddr_t pt2pg_pa, pt2_pa; - pt1_entry_t pte1; - pt2_entry_t pte2; - - PDEBUG(1, printf("%s: addr = %#x\n", __func__, addr)); - /* - * All the time kernel_vm_end is first KVA for which underlying - * L2 page table is either not allocated or linked from L1 page table - * (not considering sections). Except for two possible cases: - * - * (1) in the very beginning as long as pmap_growkernel() was - * not called, it could be first unused KVA (which is not - * rounded up to PTE1_SIZE), - * - * (2) when all KVA space is mapped and kernel_map->max_offset - * address is not rounded up to PTE1_SIZE. (For example, - * it could be 0xFFFFFFFF.) - */ - kernel_vm_end = pte1_roundup(kernel_vm_end); - mtx_assert(&kernel_map->system_mtx, MA_OWNED); - addr = roundup2(addr, PTE1_SIZE); - if (addr - 1 >= kernel_map->max_offset) - addr = kernel_map->max_offset; - while (kernel_vm_end < addr) { - pte1 = pte1_load(kern_pte1(kernel_vm_end)); - if (pte1_is_valid(pte1)) { - kernel_vm_end += PTE1_SIZE; - if (kernel_vm_end - 1 >= kernel_map->max_offset) { - kernel_vm_end = kernel_map->max_offset; - break; - } - continue; - } - - /* - * kernel_vm_end_new is used in pmap_pinit() when kernel - * mappings are entered to new pmap all at once to avoid race - * between pmap_kenter_pte1() and kernel_vm_end increase. - * The same aplies to pmap_kenter_pt2tab(). - */ - kernel_vm_end_new = kernel_vm_end + PTE1_SIZE; - - pte2 = pt2tab_load(kern_pt2tab_entry(kernel_vm_end)); - if (!pte2_is_valid(pte2)) { - /* - * Install new PT2s page into kernel PT2TAB. - */ - m = vm_page_alloc(NULL, - pte1_index(kernel_vm_end) & ~PT2PG_MASK, - VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | - VM_ALLOC_WIRED | VM_ALLOC_ZERO); - if (m == NULL) - panic("%s: no memory to grow kernel", __func__); - /* - * QQQ: To link all new L2 page tables from L1 page - * table now and so pmap_kenter_pte1() them - * at once together with pmap_kenter_pt2tab() - * could be nice speed up. However, - * pmap_growkernel() does not happen so often... - * QQQ: The other TTBR is another option. - */ - pt2pg_pa = pmap_pt2pg_init(kernel_pmap, kernel_vm_end, - m); - } else - pt2pg_pa = pte2_pa(pte2); - - pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(kernel_vm_end)); - pmap_kenter_pte1(kernel_vm_end, PTE1_LINK(pt2_pa)); - - kernel_vm_end = kernel_vm_end_new; - if (kernel_vm_end - 1 >= kernel_map->max_offset) { - kernel_vm_end = kernel_map->max_offset; - break; - } - } -} - -static int -kvm_size(SYSCTL_HANDLER_ARGS) -{ - unsigned long ksize = vm_max_kernel_address - KERNBASE; - - return (sysctl_handle_long(oidp, &ksize, 0, req)); -} -SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD, - 0, 0, kvm_size, "IU", "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, "IU", "Amount of KVM free"); - -/*********************************************** - * - * Pmap allocation/deallocation routines. - * - ***********************************************/ - -/* - * Initialize the pmap for the swapper process. - */ -void -pmap_pinit0(pmap_t pmap) -{ - PDEBUG(1, printf("%s: pmap = %p\n", __func__, pmap)); - - PMAP_LOCK_INIT(pmap); - - /* - * Kernel page table directory and pmap stuff around is already - * initialized, we are using it right now and here. So, finish - * only PMAP structures initialization for process0 ... - * - * Since the L1 page table and PT2TAB is shared with the kernel pmap, - * which is already included in the list "allpmaps", this pmap does - * not need to be inserted into that list. - */ - pmap->pm_pt1 = kern_pt1; - pmap->pm_pt2tab = kern_pt2tab; - CPU_ZERO(&pmap->pm_active); - PCPU_SET(curpmap, pmap); - TAILQ_INIT(&pmap->pm_pvchunk); - bzero(&pmap->pm_stats, sizeof pmap->pm_stats); - CPU_SET(0, &pmap->pm_active); -} - -static __inline void -pte1_copy_nosync(pt1_entry_t *spte1p, pt1_entry_t *dpte1p, vm_offset_t sva, - vm_offset_t eva) -{ - u_int idx, count; - - idx = pte1_index(sva); - count = (pte1_index(eva) - idx + 1) * sizeof(pt1_entry_t); - bcopy(spte1p + idx, dpte1p + idx, count); -} - -static __inline void -pt2tab_copy_nosync(pt2_entry_t *spte2p, pt2_entry_t *dpte2p, vm_offset_t sva, - vm_offset_t eva) -{ - u_int idx, count; - - idx = pt2tab_index(sva); - count = (pt2tab_index(eva) - idx + 1) * sizeof(pt2_entry_t); - bcopy(spte2p + idx, dpte2p + idx, count); -} - -/* - * Initialize a preallocated and zeroed pmap structure, - * such as one in a vmspace structure. - */ -int -pmap_pinit(pmap_t pmap) -{ - pt1_entry_t *pte1p; - pt2_entry_t *pte2p; - vm_paddr_t pa, pt2tab_pa; - u_int i; - - PDEBUG(6, printf("%s: pmap = %p, pm_pt1 = %p\n", __func__, pmap, - pmap->pm_pt1)); - - /* - * No need to allocate L2 page table space yet but we do need - * a valid L1 page table and PT2TAB table. - * - * Install shared kernel mappings to these tables. It's a little - * tricky as some parts of KVA are reserved for vectors, devices, - * and whatever else. These parts are supposed to be above - * vm_max_kernel_address. Thus two regions should be installed: - * - * (1) . - * - * QQQ: The second region should be stable enough to be installed - * only once in time when the tables are allocated. - * QQQ: Maybe copy of both regions at once could be faster ... - * QQQ: Maybe the other TTBR is an option. - * - * Finally, install own PT2TAB table to these tables. - */ - - if (pmap->pm_pt1 == NULL) { - pmap->pm_pt1 = (pt1_entry_t *)kmem_alloc_contig(kernel_arena, - NB_IN_PT1, M_NOWAIT | M_ZERO, 0, -1UL, NB_IN_PT1, 0, - pt_memattr); - if (pmap->pm_pt1 == NULL) - return (0); - } - if (pmap->pm_pt2tab == NULL) { - /* - * QQQ: (1) PT2TAB must be contiguous. If PT2TAB is one page - * only, what should be the only size for 32 bit systems, - * then we could allocate it with vm_page_alloc() and all - * the stuff needed as other L2 page table pages. - * (2) Note that a process PT2TAB is special L2 page table - * page. Its mapping in kernel_arena is permanent and can - * be used no matter which process is current. Its mapping - * in PT2MAP can be used only for current process. - */ - pmap->pm_pt2tab = (pt2_entry_t *)kmem_alloc_attr(kernel_arena, - NB_IN_PT2TAB, M_NOWAIT | M_ZERO, 0, -1UL, pt_memattr); - if (pmap->pm_pt2tab == NULL) { - /* - * QQQ: As struct pmap is allocated from UMA with - * UMA_ZONE_NOFREE flag, it's important to leave - * no allocation in pmap if initialization failed. - */ - kmem_free(kernel_arena, (vm_offset_t)pmap->pm_pt1, - NB_IN_PT1); - pmap->pm_pt1 = NULL; - return (0); - } - /* - * QQQ: Each L2 page table page vm_page_t has pindex set to - * pte1 index of virtual address mapped by this page. - * It's not valid for non kernel PT2TABs themselves. - * The pindex of these pages can not be altered because - * of the way how they are allocated now. However, it - * should not be a problem. - */ - } - - mtx_lock_spin(&allpmaps_lock); - /* - * To avoid race with pmap_kenter_pte1() and pmap_kenter_pt2tab(), - * kernel_vm_end_new is used here instead of kernel_vm_end. - */ - pte1_copy_nosync(kern_pt1, pmap->pm_pt1, KERNBASE, - kernel_vm_end_new - 1); - pte1_copy_nosync(kern_pt1, pmap->pm_pt1, vm_max_kernel_address, - 0xFFFFFFFF); - pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, KERNBASE, - kernel_vm_end_new - 1); - pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, vm_max_kernel_address, - 0xFFFFFFFF); - LIST_INSERT_HEAD(&allpmaps, pmap, pm_list); - mtx_unlock_spin(&allpmaps_lock); - - /* - * Store PT2MAP PT2 pages (a.k.a. PT2TAB) in PT2TAB itself. - * I.e. self reference mapping. The PT2TAB is private, however mapped - * into shared PT2MAP space, so the mapping should be not global. - */ - pt2tab_pa = vtophys(pmap->pm_pt2tab); - pte2p = pmap_pt2tab_entry(pmap, (vm_offset_t)PT2MAP); - for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) { - pt2tab_store(pte2p++, PTE2_KPT_NG(pa)); - } - - /* Insert PT2MAP PT2s into pmap PT1. */ - pte1p = pmap_pte1(pmap, (vm_offset_t)PT2MAP); - for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) { - pte1_store(pte1p++, PTE1_LINK(pa)); - } - - /* - * Now synchronize new mapping which was made above. - */ - pte1_sync_range(pmap->pm_pt1, NB_IN_PT1); - pte2_sync_range(pmap->pm_pt2tab, NB_IN_PT2TAB); - - CPU_ZERO(&pmap->pm_active); - TAILQ_INIT(&pmap->pm_pvchunk); - bzero(&pmap->pm_stats, sizeof pmap->pm_stats); - - return (1); -} - -#ifdef INVARIANTS -static boolean_t -pt2tab_user_is_empty(pt2_entry_t *tab) -{ - u_int i, end; - - end = pt2tab_index(VM_MAXUSER_ADDRESS); - for (i = 0; i < end; i++) - if (tab[i] != 0) return (FALSE); - return (TRUE); -} -#endif -/* - * 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) -{ -#ifdef INVARIANTS - vm_offset_t start, end; -#endif - KASSERT(pmap->pm_stats.resident_count == 0, - ("%s: pmap resident count %ld != 0", __func__, - pmap->pm_stats.resident_count)); - KASSERT(pt2tab_user_is_empty(pmap->pm_pt2tab), - ("%s: has allocated user PT2(s)", __func__)); - KASSERT(CPU_EMPTY(&pmap->pm_active), - ("%s: pmap %p is active on some CPU(s)", __func__, pmap)); - - mtx_lock_spin(&allpmaps_lock); - LIST_REMOVE(pmap, pm_list); - mtx_unlock_spin(&allpmaps_lock); - -#ifdef INVARIANTS - start = pte1_index(KERNBASE) * sizeof(pt1_entry_t); - end = (pte1_index(0xFFFFFFFF) + 1) * sizeof(pt1_entry_t); - bzero((char *)pmap->pm_pt1 + start, end - start); - - start = pt2tab_index(KERNBASE) * sizeof(pt2_entry_t); - end = (pt2tab_index(0xFFFFFFFF) + 1) * sizeof(pt2_entry_t); - bzero((char *)pmap->pm_pt2tab + start, end - start); -#endif - /* - * We are leaving PT1 and PT2TAB allocated on released pmap, - * so hopefully UMA vmspace_zone will always be inited with - * UMA_ZONE_NOFREE flag. - */ -} - -/********************************************************* - * - * L2 table pages and their pages management routines. - * - *********************************************************/ - -/* - * Virtual interface for L2 page table wire counting. - * - * Each L2 page table in a page has own counter which counts a number of - * valid mappings in a table. Global page counter counts mappings in all - * tables in a page plus a single itself mapping in PT2TAB. - * - * During a promotion we leave the associated L2 page table counter - * untouched, so the table (strictly speaking a page which holds it) - * is never freed if promoted. - * - * If a page m->wire_count == 1 then no valid mappings exist in any L2 page - * table in the page and the page itself is only mapped in PT2TAB. - */ - -static __inline void -pt2_wirecount_init(vm_page_t m) -{ - u_int i; - - /* - * Note: A page m is allocated with VM_ALLOC_WIRED flag and - * m->wire_count should be already set correctly. - * So, there is no need to set it again herein. - */ - for (i = 0; i < NPT2_IN_PG; i++) - m->md.pt2_wirecount[i] = 0; -} - -static __inline void -pt2_wirecount_inc(vm_page_t m, uint32_t pte1_idx) -{ - - /* - * Note: A just modificated pte2 (i.e. already allocated) - * is acquiring one extra reference which must be - * explicitly cleared. It influences the KASSERTs herein. - * All L2 page tables in a page always belong to the same - * pmap, so we allow only one extra reference for the page. - */ - KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] < (NPTE2_IN_PT2 + 1), - ("%s: PT2 is overflowing ...", __func__)); - KASSERT(m->wire_count <= (NPTE2_IN_PG + 1), - ("%s: PT2PG is overflowing ...", __func__)); - - m->wire_count++; - m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]++; -} - -static __inline void -pt2_wirecount_dec(vm_page_t m, uint32_t pte1_idx) -{ - - KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] != 0, - ("%s: PT2 is underflowing ...", __func__)); - KASSERT(m->wire_count > 1, - ("%s: PT2PG is underflowing ...", __func__)); - - m->wire_count--; - m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]--; -} - -static __inline void -pt2_wirecount_set(vm_page_t m, uint32_t pte1_idx, uint16_t count) -{ - - KASSERT(count <= NPTE2_IN_PT2, - ("%s: invalid count %u", __func__, count)); - KASSERT(m->wire_count > m->md.pt2_wirecount[pte1_idx & PT2PG_MASK], - ("%s: PT2PG corrupting (%u, %u) ...", __func__, m->wire_count, - m->md.pt2_wirecount[pte1_idx & PT2PG_MASK])); - - m->wire_count -= m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]; - m->wire_count += count; - m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] = count; - - KASSERT(m->wire_count <= (NPTE2_IN_PG + 1), - ("%s: PT2PG is overflowed (%u) ...", __func__, m->wire_count)); -} - -static __inline uint32_t -pt2_wirecount_get(vm_page_t m, uint32_t pte1_idx) -{ - - return (m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]); -} - -static __inline boolean_t -pt2_is_empty(vm_page_t m, vm_offset_t va) -{ - - return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == 0); -} - -static __inline boolean_t -pt2_is_full(vm_page_t m, vm_offset_t va) -{ - - return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == - NPTE2_IN_PT2); -} - -static __inline boolean_t -pt2pg_is_empty(vm_page_t m) -{ - - return (m->wire_count == 1); -} - -/* - * This routine is called if the L2 page table - * is not mapped correctly. - */ -static vm_page_t -_pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags) -{ - uint32_t pte1_idx; - pt1_entry_t *pte1p; - pt2_entry_t pte2; - vm_page_t m; - vm_paddr_t pt2pg_pa, pt2_pa; - - pte1_idx = pte1_index(va); - pte1p = pmap->pm_pt1 + pte1_idx; - - KASSERT(pte1_load(pte1p) == 0, - ("%s: pm_pt1[%#x] is not zero: %#x", __func__, pte1_idx, - pte1_load(pte1p))); - - pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, va)); - if (!pte2_is_valid(pte2)) { - /* - * Install new PT2s page into pmap PT2TAB. - */ - m = vm_page_alloc(NULL, pte1_idx & ~PT2PG_MASK, - VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO); - if (m == 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); - } - - /* - * Indicate the need to retry. While waiting, - * the L2 page table page may have been allocated. - */ - return (NULL); - } - pmap->pm_stats.resident_count++; - pt2pg_pa = pmap_pt2pg_init(pmap, va, m); - } else { - pt2pg_pa = pte2_pa(pte2); - m = PHYS_TO_VM_PAGE(pt2pg_pa); - } - - pt2_wirecount_inc(m, pte1_idx); - pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx); - pte1_store(pte1p, PTE1_LINK(pt2_pa)); - - return (m); -} - -static vm_page_t -pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags) -{ - u_int pte1_idx; - pt1_entry_t *pte1p, pte1; - vm_page_t m; - - pte1_idx = pte1_index(va); -retry: - pte1p = pmap->pm_pt1 + pte1_idx; - pte1 = pte1_load(pte1p); - - /* - * This supports switching from a 1MB page to a - * normal 4K page. - */ - if (pte1_is_section(pte1)) { - (void)pmap_demote_pte1(pmap, pte1p, va); - /* - * Reload pte1 after demotion. - * - * Note: Demotion can even fail as either PT2 is not find for - * the virtual address or PT2PG can not be allocated. - */ - pte1 = pte1_load(pte1p); - } - - /* - * If the L2 page table page is mapped, we just increment the - * hold count, and activate it. - */ - if (pte1_is_link(pte1)) { - m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); - pt2_wirecount_inc(m, pte1_idx); - } else { - /* - * Here if the PT2 isn't mapped, or if it has - * been deallocated. - */ - m = _pmap_allocpte2(pmap, va, flags); - if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0) - goto retry; - } - - return (m); -} - -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 L2 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) -{ - - /* - * Put page on a list so that it is released after - * *ALL* TLB shootdown is done - */ -#ifdef PMAP_DEBUG - pmap_zero_page_check(m); -#endif - m->flags |= PG_ZERO; - SLIST_INSERT_HEAD(free, m, plinks.s.ss); -} - -/* - * Unwire L2 page tables page. - */ -static void -pmap_unwire_pt2pg(pmap_t pmap, vm_offset_t va, vm_page_t m) -{ - pt1_entry_t *pte1p, opte1 __unused; - pt2_entry_t *pte2p; - uint32_t i; - - KASSERT(pt2pg_is_empty(m), - ("%s: pmap %p PT2PG %p wired", __func__, pmap, m)); - - /* - * Unmap all L2 page tables in the page from L1 page table. - * - * QQQ: Individual L2 page tables (except the last one) can be unmapped - * earlier. However, we are doing that this way. - */ - KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK), - ("%s: pmap %p va %#x PT2PG %p bad index", __func__, pmap, va, m)); - pte1p = pmap->pm_pt1 + m->pindex; - for (i = 0; i < NPT2_IN_PG; i++, pte1p++) { - KASSERT(m->md.pt2_wirecount[i] == 0, - ("%s: pmap %p PT2 %u (PG %p) wired", __func__, pmap, i, m)); - opte1 = pte1_load(pte1p); - if (pte1_is_link(opte1)) { - pte1_clear(pte1p); - /* - * Flush intermediate TLB cache. - */ - pmap_tlb_flush(pmap, (m->pindex + i) << PTE1_SHIFT); - } -#ifdef INVARIANTS - else - KASSERT((opte1 == 0) || pte1_is_section(opte1), - ("%s: pmap %p va %#x bad pte1 %x at %u", __func__, - pmap, va, opte1, i)); -#endif - } - - /* - * Unmap the page from PT2TAB. - */ - pte2p = pmap_pt2tab_entry(pmap, va); - (void)pt2tab_load_clear(pte2p); - pmap_tlb_flush(pmap, pt2map_pt2pg(va)); - - m->wire_count = 0; - pmap->pm_stats.resident_count--; - - /* - * This is a release store so that the ordinary store unmapping - * the L2 page table page is globally performed before TLB shoot- - * down is begun. - */ - atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1); -} - -/* - * Decrements a L2 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_pt2(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free) -{ - pt2_wirecount_dec(m, pte1_index(va)); - if (pt2pg_is_empty(m)) { - /* - * QQQ: Wire count is zero, so whole page should be zero and - * we can set PG_ZERO flag to it. - * Note that when promotion is enabled, it takes some - * more efforts. See pmap_unwire_pt2_all() below. - */ - pmap_unwire_pt2pg(pmap, va, m); - pmap_add_delayed_free_list(m, free); - return (TRUE); - } else - return (FALSE); -} - -/* - * Drop a L2 page table page's wire count at once, which is used to record - * the number of valid L2 page table entries within the page. If the wire - * count drops to zero, then the L2 page table page is unmapped. - */ -static __inline void -pmap_unwire_pt2_all(pmap_t pmap, vm_offset_t va, vm_page_t m, - struct spglist *free) -{ - u_int pte1_idx = pte1_index(va); - - KASSERT(m->pindex == (pte1_idx & ~PT2PG_MASK), - ("%s: PT2 page's pindex is wrong", __func__)); - KASSERT(m->wire_count > pt2_wirecount_get(m, pte1_idx), - ("%s: bad pt2 wire count %u > %u", __func__, m->wire_count, - pt2_wirecount_get(m, pte1_idx))); - - /* - * It's possible that the L2 page table was never used. - * It happened in case that a section was created without promotion. - */ - if (pt2_is_full(m, va)) { - pt2_wirecount_set(m, pte1_idx, 0); - - /* - * QQQ: We clear L2 page table now, so when L2 page table page - * is going to be freed, we can set it PG_ZERO flag ... - * This function is called only on section mappings, so - * hopefully it's not to big overload. - * - * XXX: If pmap is current, existing PT2MAP mapping could be - * used for zeroing. - */ - pmap_zero_page_area(m, page_pt2off(pte1_idx), NB_IN_PT2); - } -#ifdef INVARIANTS - else - KASSERT(pt2_is_empty(m, va), ("%s: PT2 is not empty (%u)", - __func__, pt2_wirecount_get(m, pte1_idx))); -#endif - if (pt2pg_is_empty(m)) { - pmap_unwire_pt2pg(pmap, va, m); - pmap_add_delayed_free_list(m, free); - } -} - -/* - * After removing a L2 page table entry, this routine is used to - * conditionally free the page, and manage the hold/wire counts. - */ -static boolean_t -pmap_unuse_pt2(pmap_t pmap, vm_offset_t va, struct spglist *free) -{ - pt1_entry_t pte1; - vm_page_t mpte; - - if (va >= VM_MAXUSER_ADDRESS) - return (FALSE); - pte1 = pte1_load(pmap_pte1(pmap, va)); - mpte = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); - return (pmap_unwire_pt2(pmap, va, mpte, free)); -} - -/************************************* - * - * Page management routines. - * - *************************************/ - -CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE); -CTASSERT(_NPCM == 11); -CTASSERT(_NPCPV == 336); - -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_9 0xfffffffful /* Free values for index 0 through 9 */ -#define PC_FREE10 0x0000fffful /* Free values for index 10 */ - -static const uint32_t pc_freemask[_NPCM] = { - PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, - PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, - PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, - PC_FREE0_9, PC_FREE10 -}; - -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 - -/* - * Is given page managed? - */ -static __inline boolean_t -is_managed(vm_paddr_t pa) -{ - vm_offset_t pgnum; - vm_page_t m; - - pgnum = atop(pa); - if (pgnum >= first_page) { - m = PHYS_TO_VM_PAGE(pa); - if (m == NULL) - return (FALSE); - if ((m->oflags & VPO_UNMANAGED) == 0) - return (TRUE); - } - return (FALSE); -} - -static __inline boolean_t -pte1_is_managed(pt1_entry_t pte1) -{ - - return (is_managed(pte1_pa(pte1))); -} - -static __inline boolean_t -pte2_is_managed(pt2_entry_t pte2) -{ - - return (is_managed(pte2_pa(pte2))); -} - -/* - * 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 md_page *pvh; - pt1_entry_t *pte1p; - pmap_t pmap; - pt2_entry_t *pte2p, tpte2; - pv_entry_t pv; - vm_offset_t va; - vm_page_t m, m_pc; - struct spglist free; - uint32_t inuse; - int bit, field, freed; - - PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED); - pmap = NULL; - m_pc = NULL; - SLIST_INIT(&free); - TAILQ_INIT(&newtail); - while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 || - SLIST_EMPTY(&free))) { - TAILQ_REMOVE(&pv_chunks, pc, pc_lru); - if (pmap != pc->pc_pmap) { - if (pmap != NULL) { - 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; - pv = &pc->pc_pventry[field * 32 + bit]; - va = pv->pv_va; - pte1p = pmap_pte1(pmap, va); - if (pte1_is_section(pte1_load(pte1p))) - continue; - pte2p = pmap_pte2(pmap, va); - tpte2 = pte2_load(pte2p); - if ((tpte2 & PTE2_W) == 0) - tpte2 = pte2_load_clear(pte2p); - pmap_pte2_release(pte2p); - if ((tpte2 & PTE2_W) != 0) - continue; - KASSERT(tpte2 != 0, - ("pmap_pv_reclaim: pmap %p va %#x zero pte", - pmap, va)); - pmap_tlb_flush(pmap, va); - m = PHYS_TO_VM_PAGE(pte2_pa(tpte2)); - if (pte2_is_dirty(tpte2)) - vm_page_dirty(m); - if ((tpte2 & PTE2_A) != 0) - vm_page_aflag_set(m, PGA_REFERENCED); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); - if (TAILQ_EMPTY(&m->md.pv_list) && - (m->flags & PG_FICTITIOUS) == 0) { - pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); - if (TAILQ_EMPTY(&pvh->pv_list)) { - vm_page_aflag_clear(m, - PGA_WRITEABLE); - } - } - pc->pc_map[field] |= 1UL << bit; - pmap_unuse_pt2(pmap, va, &free); - 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_pte2list_free(&pv_vafree, (vm_offset_t)pc); - break; - } - } -out: - TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru); - if (pmap != NULL) { - if (pmap != locked_pmap) - PMAP_UNLOCK(pmap); - } - if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { - m_pc = SLIST_FIRST(&free); - SLIST_REMOVE_HEAD(&free, plinks.s.ss); - /* Recycle a freed page table page. */ - m_pc->wire_count = 1; - atomic_add_int(&vm_cnt.v_wire_count, 1); - } - pmap_free_zero_pages(&free); - return (m_pc); -} - -static void -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_pte2list_free(&pv_vafree, (vm_offset_t)pc); -} - -/* - * 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_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - 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 / 32; - bit = idx % 32; - 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); - free_pv_chunk(pc); -} - -/* - * Get a new pv_entry, allocating a block from the system - * when needed. - */ -static pv_entry_t -get_pv_entry(pmap_t pmap, boolean_t try) -{ - static const struct timeval printinterval = { 60, 0 }; - static struct timeval lastprint; - int bit, field; - pv_entry_t pv; - struct pv_chunk *pc; - vm_page_t m; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - PV_STAT(pv_entry_allocs++); - pv_entry_count++; - if (pv_entry_count > pv_entry_high_water) - if (ratecheck(&lastprint, &printinterval)) - printf("Approaching the limit on PV entries, consider " - "increasing either the vm.pmap.shpgperproc or the " - "vm.pmap.pv_entry_max tunable.\n"); -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) { - pv = &pc->pc_pventry[field * 32 + bit]; - 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 pte2list "pv_vafree" is synchronized by the pvh - * global lock. If "pv_vafree" is currently non-empty, it will - * remain non-empty until pmap_pte2list_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_pte2list_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); -} - -/* - * Create a pv entry for page at pa for - * (pmap, va). - */ -static void -pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m) -{ - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - pv = get_pv_entry(pmap, FALSE); - pv->pv_va = va; - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); -} - -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_WLOCKED); - 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); - break; - } - } - 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")); - free_pv_entry(pmap, pv); -} - -static void -pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) -{ - struct md_page *pvh; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - pmap_pvh_free(&m->md, pmap, va); - if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) { - pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); - if (TAILQ_EMPTY(&pvh->pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - } -} - -static void -pmap_pv_demote_pte1(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 & PTE1_OFFSET) == 0, - ("pmap_pv_demote_pte1: 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 = pte1_trunc(va); - pv = pmap_pvh_remove(pvh, pmap, va); - KASSERT(pv != NULL, ("pmap_pv_demote_pte1: pv not found")); - m = PHYS_TO_VM_PAGE(pa); - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); - /* Instantiate the remaining NPTE2_IN_PT2 - 1 pv entries. */ - va_last = va + PTE1_SIZE - PAGE_SIZE; - do { - m++; - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_pv_demote_pte1: page %p is not managed", m)); - va += PAGE_SIZE; - pmap_insert_entry(pmap, va, m); - } while (va < va_last); -} - -static void -pmap_pv_promote_pte1(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 & PTE1_OFFSET) == 0, - ("pmap_pv_promote_pte1: 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 = pte1_trunc(va); - pv = pmap_pvh_remove(&m->md, pmap, va); - KASSERT(pv != NULL, ("pmap_pv_promote_pte1: pv not found")); - pvh = pa_to_pvh(pa); - TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); - /* Free the remaining NPTE2_IN_PT2 - 1 pv entries. */ - va_last = va + PTE1_SIZE - PAGE_SIZE; - do { - m++; - va += PAGE_SIZE; - pmap_pvh_free(&m->md, pmap, va); - } while (va < va_last); -} - -/* - * Conditionally create a pv entry. - */ -static boolean_t -pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m) -{ - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - if (pv_entry_count < pv_entry_high_water && - (pv = get_pv_entry(pmap, TRUE)) != NULL) { - pv->pv_va = va; - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); - return (TRUE); - } else - return (FALSE); -} - -/* - * Create the pv entries for each of the pages within a section. - */ -static boolean_t -pmap_pv_insert_pte1(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 = get_pv_entry(pmap, TRUE)) != NULL) { - pv->pv_va = va; - pvh = pa_to_pvh(pa); - TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); - return (TRUE); - } else - return (FALSE); -} - -/* - * Tries to promote the NPTE2_IN_PT2, contiguous 4KB page mappings that are - * within a single page table page (PT2) to a single 1MB page 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. - * - * Managed (PG_MANAGED) mappings within the kernel address space are not - * promoted. The reason is that kernel PTE1s are replicated in each pmap but - * pmap_remove_write(), pmap_clear_modify(), and pmap_clear_reference() only - * read the PTE1 from the kernel pmap. - */ -static void -pmap_promote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) -{ - pt1_entry_t npte1; - pt2_entry_t *fpte2p, fpte2, fpte2_fav; - pt2_entry_t *pte2p, pte2; - vm_offset_t pteva __unused; - vm_page_t m __unused; - - PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__, - pmap, va, pte1_load(pte1p), pte1p)); - - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - - /* - * Examine the first PTE2 in the specified PT2. Abort if this PTE2 is - * either invalid, unused, or does not map the first 4KB physical page - * within a 1MB page. - */ - fpte2p = pmap_pte2_quick(pmap, pte1_trunc(va)); -setpte1: - fpte2 = pte2_load(fpte2p); - if ((fpte2 & ((PTE2_FRAME & PTE1_OFFSET) | PTE2_A | PTE2_V)) != - (PTE2_A | PTE2_V)) { - pmap_pte1_p_failures++; - CTR3(KTR_PMAP, "%s: failure(1) for va %#x in pmap %p", - __func__, va, pmap); - return; - } - if (pte2_is_managed(fpte2) && pmap == kernel_pmap) { - pmap_pte1_p_failures++; - CTR3(KTR_PMAP, "%s: failure(2) for va %#x in pmap %p", - __func__, va, pmap); - return; - } - if ((fpte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) { - /* - * When page is not modified, PTE2_RO can be set without - * a TLB invalidation. - * - * Note: When modified bit is being set, then in hardware case, - * the TLB entry is re-read (updated) from PT2, and in - * software case (abort), the PTE2 is read from PT2 and - * TLB flushed if changed. The following cmpset() solves - * any race with setting this bit in both cases. - */ - if (!pte2_cmpset(fpte2p, fpte2, fpte2 | PTE2_RO)) - goto setpte1; - fpte2 |= PTE2_RO; - } - - /* - * Examine each of the other PTE2s in the specified PT2. Abort if this - * PTE2 maps an unexpected 4KB physical page or does not have identical - * characteristics to the first PTE2. - */ - fpte2_fav = (fpte2 & (PTE2_FRAME | PTE2_A | PTE2_V)); - fpte2_fav += PTE1_SIZE - PTE2_SIZE; /* examine from the end */ - for (pte2p = fpte2p + NPTE2_IN_PT2 - 1; pte2p > fpte2p; pte2p--) { -setpte2: - pte2 = pte2_load(pte2p); - if ((pte2 & (PTE2_FRAME | PTE2_A | PTE2_V)) != fpte2_fav) { - pmap_pte1_p_failures++; - CTR3(KTR_PMAP, "%s: failure(3) for va %#x in pmap %p", - __func__, va, pmap); - return; - } - if ((pte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) { - /* - * When page is not modified, PTE2_RO can be set - * without a TLB invalidation. See note above. - */ - if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_RO)) - goto setpte2; - pte2 |= PTE2_RO; - pteva = pte1_trunc(va) | (pte2 & PTE1_OFFSET & - PTE2_FRAME); - CTR3(KTR_PMAP, "%s: protect for va %#x in pmap %p", - __func__, pteva, pmap); - } - if ((pte2 & PTE2_PROMOTE) != (fpte2 & PTE2_PROMOTE)) { - pmap_pte1_p_failures++; - CTR3(KTR_PMAP, "%s: failure(4) for va %#x in pmap %p", - __func__, va, pmap); - return; - } - - fpte2_fav -= PTE2_SIZE; - } - /* - * The page table page in its current state will stay in PT2TAB - * until the PTE1 mapping the section is demoted by pmap_demote_pte1() - * or destroyed by pmap_remove_pte1(). - * - * Note that L2 page table size is not equal to PAGE_SIZE. - */ - m = PHYS_TO_VM_PAGE(trunc_page(pte1_link_pa(pte1_load(pte1p)))); - KASSERT(m >= vm_page_array && m < &vm_page_array[vm_page_array_size], - ("%s: PT2 page is out of range", __func__)); - KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK), - ("%s: PT2 page's pindex is wrong", __func__)); - - /* - * Get pte1 from pte2 format. - */ - npte1 = (fpte2 & PTE1_FRAME) | ATTR_TO_L1(fpte2) | PTE1_V; - - /* - * Promote the pv entries. - */ - if (pte2_is_managed(fpte2)) - pmap_pv_promote_pte1(pmap, va, pte1_pa(npte1)); - - /* - * Map the section. - */ - if (pmap == kernel_pmap) - pmap_kenter_pte1(va, npte1); - else - pte1_store(pte1p, npte1); - /* - * Flush old small mappings. We call single pmap_tlb_flush() in - * pmap_demote_pte1() and pmap_remove_pte1(), so we must be sure that - * no small mappings survive. We assume that given pmap is current and - * don't play game with PTE2_NG. - */ - pmap_tlb_flush_range(pmap, pte1_trunc(va), PTE1_SIZE); - - pmap_pte1_promotions++; - CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p", - __func__, va, pmap); - - PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n", - __func__, pmap, va, npte1, pte1_load(pte1p), pte1p)); -} - -/* - * Zero L2 page table page. - */ -static __inline void -pmap_clear_pt2(pt2_entry_t *fpte2p) -{ - pt2_entry_t *pte2p; - - for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) - pte2_clear(pte2p); - -} - -/* - * Removes a 1MB page mapping from the kernel pmap. - */ -static void -pmap_remove_kernel_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) -{ - vm_page_t m; - uint32_t pte1_idx; - pt2_entry_t *fpte2p; - vm_paddr_t pt2_pa; - - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - m = pmap_pt2_page(pmap, va); - if (m == NULL) - /* - * QQQ: Is this function called only on promoted pte1? - * We certainly do section mappings directly - * (without promotion) in kernel !!! - */ - panic("%s: missing pt2 page", __func__); - - pte1_idx = pte1_index(va); - - /* - * Initialize the L2 page table. - */ - fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx); - pmap_clear_pt2(fpte2p); - - /* - * Remove the mapping. - */ - pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(m), pte1_idx); - pmap_kenter_pte1(va, PTE1_LINK(pt2_pa)); - - /* - * QQQ: We do not need to invalidate PT2MAP mapping - * as we did not change it. I.e. the L2 page table page - * was and still is mapped the same way. - */ -} - -/* - * Do the things to unmap a section in a process - */ -static void -pmap_remove_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva, - struct spglist *free) -{ - pt1_entry_t opte1; - struct md_page *pvh; - vm_offset_t eva, va; - vm_page_t m; - - PDEBUG(6, printf("%s(%p): va %#x pte1 %#x at %p\n", __func__, pmap, sva, - pte1_load(pte1p), pte1p)); - - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - KASSERT((sva & PTE1_OFFSET) == 0, - ("%s: sva is not 1mpage aligned", __func__)); - - /* - * Clear and invalidate the mapping. It should occupy one and only TLB - * entry. So, pmap_tlb_flush() called with aligned address should be - * sufficient. - */ - opte1 = pte1_load_clear(pte1p); - pmap_tlb_flush(pmap, sva); - - if (pte1_is_wired(opte1)) - pmap->pm_stats.wired_count -= PTE1_SIZE / PAGE_SIZE; - pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE; - if (pte1_is_managed(opte1)) { - pvh = pa_to_pvh(pte1_pa(opte1)); - pmap_pvh_free(pvh, pmap, sva); - eva = sva + PTE1_SIZE; - for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1)); - va < eva; va += PAGE_SIZE, m++) { - if (pte1_is_dirty(opte1)) - vm_page_dirty(m); - if (opte1 & PTE1_A) - 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); - } - } - if (pmap == kernel_pmap) { - /* - * L2 page table(s) can't be removed from kernel map as - * kernel counts on it (stuff around pmap_growkernel()). - */ - pmap_remove_kernel_pte1(pmap, pte1p, sva); - } else { - /* - * Get associated L2 page table page. - * It's possible that the page was never allocated. - */ - m = pmap_pt2_page(pmap, sva); - if (m != NULL) - pmap_unwire_pt2_all(pmap, sva, m, free); - } -} - -/* - * Fills L2 page table page with mappings to consecutive physical pages. - */ -static __inline void -pmap_fill_pt2(pt2_entry_t *fpte2p, pt2_entry_t npte2) -{ - pt2_entry_t *pte2p; - - for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) { - pte2_store(pte2p, npte2); - npte2 += PTE2_SIZE; - } -} - -/* - * Tries to demote a 1MB page mapping. If demotion fails, the - * 1MB page mapping is invalidated. - */ -static boolean_t -pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) -{ - pt1_entry_t opte1, npte1; - pt2_entry_t *fpte2p, npte2; - vm_paddr_t pt2pg_pa, pt2_pa; - vm_page_t m; - struct spglist free; - uint32_t pte1_idx, isnew = 0; - - PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__, - pmap, va, pte1_load(pte1p), pte1p)); - - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - - opte1 = pte1_load(pte1p); - KASSERT(pte1_is_section(opte1), ("%s: opte1 not a section", __func__)); - - if ((opte1 & PTE1_A) == 0 || (m = pmap_pt2_page(pmap, va)) == NULL) { - KASSERT(!pte1_is_wired(opte1), - ("%s: PT2 page for a wired mapping is missing", __func__)); - - /* - * Invalidate the 1MB page mapping and return - * "failure" if the mapping was never accessed or the - * allocation of the new page table page fails. - */ - if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL, - pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ | - VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) { - SLIST_INIT(&free); - pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free); - pmap_free_zero_pages(&free); - CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p", - __func__, va, pmap); - return (FALSE); - } - if (va < VM_MAXUSER_ADDRESS) - pmap->pm_stats.resident_count++; - - isnew = 1; - - /* - * We init all L2 page tables in the page even if - * we are going to change everything for one L2 page - * table in a while. - */ - pt2pg_pa = pmap_pt2pg_init(pmap, va, m); - } else { - if (va < VM_MAXUSER_ADDRESS) { - if (pt2_is_empty(m, va)) - isnew = 1; /* Demoting section w/o promotion. */ -#ifdef INVARIANTS - else - KASSERT(pt2_is_full(m, va), ("%s: bad PT2 wire" - " count %u", __func__, - pt2_wirecount_get(m, pte1_index(va)))); -#endif - } - } - - pt2pg_pa = VM_PAGE_TO_PHYS(m); - pte1_idx = pte1_index(va); - /* - * If the pmap is current, then the PT2MAP can provide access to - * the page table page (promoted L2 page tables are not unmapped). - * Otherwise, temporarily map the L2 page table page (m) into - * the kernel's address space at either PADDR1 or PADDR2. - * - * Note that L2 page table size is not equal to PAGE_SIZE. - */ - if (pmap_is_current(pmap)) - fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx); - else if (curthread->td_pinned > 0 && rw_wowned(&pvh_global_lock)) { - if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) { - pte2_store(PMAP1, PTE2_KPT(pt2pg_pa)); -#ifdef SMP - PMAP1cpu = PCPU_GET(cpuid); -#endif - tlb_flush_local((vm_offset_t)PADDR1); - PMAP1changed++; - } else -#ifdef SMP - if (PMAP1cpu != PCPU_GET(cpuid)) { - PMAP1cpu = PCPU_GET(cpuid); - tlb_flush_local((vm_offset_t)PADDR1); - PMAP1changedcpu++; - } else -#endif - PMAP1unchanged++; - fpte2p = page_pt2((vm_offset_t)PADDR1, pte1_idx); - } else { - mtx_lock(&PMAP2mutex); - if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) { - pte2_store(PMAP2, PTE2_KPT(pt2pg_pa)); - tlb_flush((vm_offset_t)PADDR2); - } - fpte2p = page_pt2((vm_offset_t)PADDR2, pte1_idx); - } - pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx); - npte1 = PTE1_LINK(pt2_pa); - - KASSERT((opte1 & PTE1_A) != 0, - ("%s: opte1 is missing PTE1_A", __func__)); - KASSERT((opte1 & (PTE1_NM | PTE1_RO)) != PTE1_NM, - ("%s: opte1 has PTE1_NM", __func__)); - - /* - * Get pte2 from pte1 format. - */ - npte2 = pte1_pa(opte1) | ATTR_TO_L2(opte1) | PTE2_V; - - /* - * If the L2 page table page is new, initialize it. If the mapping - * has changed attributes, update the page table entries. - */ - if (isnew != 0) { - pt2_wirecount_set(m, pte1_idx, NPTE2_IN_PT2); - pmap_fill_pt2(fpte2p, npte2); - } else if ((pte2_load(fpte2p) & PTE2_PROMOTE) != - (npte2 & PTE2_PROMOTE)) - pmap_fill_pt2(fpte2p, npte2); - - KASSERT(pte2_pa(pte2_load(fpte2p)) == pte2_pa(npte2), - ("%s: fpte2p and npte2 map different physical addresses", - __func__)); - - if (fpte2p == PADDR2) - mtx_unlock(&PMAP2mutex); - - /* - * Demote the mapping. This pmap is locked. The old PTE1 has - * PTE1_A set. If the old PTE1 has not PTE1_RO set, it also - * has not PTE1_NM set. Thus, there is no danger of a race with - * another processor changing the setting of PTE1_A and/or PTE1_NM - * between the read above and the store below. - */ - if (pmap == kernel_pmap) - pmap_kenter_pte1(va, npte1); - else - pte1_store(pte1p, npte1); - - /* - * Flush old big mapping. The mapping should occupy one and only - * TLB entry. So, pmap_tlb_flush() called with aligned address - * should be sufficient. - */ - pmap_tlb_flush(pmap, pte1_trunc(va)); - - /* - * Demote the pv entry. This depends on the earlier demotion - * of the mapping. Specifically, the (re)creation of a per- - * page pv entry might trigger the execution of pmap_pv_reclaim(), - * which might reclaim a newly (re)created per-page pv entry - * and destroy the associated mapping. In order to destroy - * the mapping, the PTE1 must have already changed from mapping - * the 1mpage to referencing the page table page. - */ - if (pte1_is_managed(opte1)) - pmap_pv_demote_pte1(pmap, va, pte1_pa(opte1)); - - pmap_pte1_demotions++; - CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p", - __func__, va, pmap); - - PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n", - __func__, pmap, va, npte1, pte1_load(pte1p), pte1p)); - return (TRUE); -} - -/* - * 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) -{ - pt1_entry_t *pte1p; - pt2_entry_t *pte2p; - pt2_entry_t npte2, opte2; - pv_entry_t pv; - vm_paddr_t opa, pa; - vm_page_t mpte2, om; - boolean_t wired; - - va = trunc_page(va); - mpte2 = NULL; - wired = (flags & PMAP_ENTER_WIRED) != 0; - - KASSERT(va <= vm_max_kernel_address, ("%s: toobig", __func__)); - KASSERT(va < UPT2V_MIN_ADDRESS || va >= UPT2V_MAX_ADDRESS, - ("%s: invalid to pmap_enter page table pages (va: 0x%x)", __func__, - va)); - if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m)) - VM_OBJECT_ASSERT_LOCKED(m->object); - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - sched_pin(); - - /* - * In the case that a page table page is not - * resident, we are creating it here. - */ - if (va < VM_MAXUSER_ADDRESS) { - mpte2 = pmap_allocpte2(pmap, va, flags); - if (mpte2 == NULL) { - KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0, - ("pmap_allocpte2 failed with sleep allowed")); - sched_unpin(); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); - return (KERN_RESOURCE_SHORTAGE); - } - } - pte1p = pmap_pte1(pmap, va); - if (pte1_is_section(pte1_load(pte1p))) - panic("%s: attempted on 1MB page", __func__); - pte2p = pmap_pte2_quick(pmap, va); - if (pte2p == NULL) - panic("%s: invalid L1 page table entry va=%#x", __func__, va); - - om = NULL; - pa = VM_PAGE_TO_PHYS(m); - opte2 = pte2_load(pte2p); - opa = pte2_pa(opte2); - /* - * Mapping has not changed, must be protection or wiring change. - */ - if (pte2_is_valid(opte2) && (opa == pa)) { - /* - * Wiring change, just update stats. We don't worry about - * wiring PT2 pages as they remain resident as long as there - * are valid mappings in them. Hence, if a user page is wired, - * the PT2 page will be also. - */ - if (wired && !pte2_is_wired(opte2)) - pmap->pm_stats.wired_count++; - else if (!wired && pte2_is_wired(opte2)) - pmap->pm_stats.wired_count--; - - /* - * Remove extra pte2 reference - */ - if (mpte2) - pt2_wirecount_dec(mpte2, pte1_index(va)); - if (pte2_is_managed(opte2)) - om = m; - goto validate; - } - - /* - * QQQ: We think that changing physical address on writeable mapping - * is not safe. Well, maybe on kernel address space with correct - * locking, it can make a sense. However, we have no idea why - * anyone should do that on user address space. Are we wrong? - */ - KASSERT((opa == 0) || (opa == pa) || - !pte2_is_valid(opte2) || ((opte2 & PTE2_RO) != 0), - ("%s: pmap %p va %#x(%#x) opa %#x pa %#x - gotcha %#x %#x!", - __func__, pmap, va, opte2, opa, pa, flags, prot)); - - pv = NULL; - - /* - * Mapping has changed, invalidate old range and fall through to - * handle validating new mapping. - */ - if (opa) { - if (pte2_is_wired(opte2)) - pmap->pm_stats.wired_count--; - if (pte2_is_managed(opte2)) { - om = PHYS_TO_VM_PAGE(opa); - pv = pmap_pvh_remove(&om->md, pmap, va); - } - /* - * Remove extra pte2 reference - */ - if (mpte2 != NULL) - pt2_wirecount_dec(mpte2, va >> PTE1_SHIFT); - } else - pmap->pm_stats.resident_count++; - - /* - * Enter on the PV list if part of our managed memory. - */ - if ((m->oflags & VPO_UNMANAGED) == 0) { - KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva, - ("%s: managed mapping within the clean submap", __func__)); - if (pv == NULL) - pv = get_pv_entry(pmap, FALSE); - pv->pv_va = va; - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); - } else if (pv != NULL) - free_pv_entry(pmap, pv); - - /* - * Increment counters - */ - if (wired) - pmap->pm_stats.wired_count++; - -validate: - /* - * Now validate mapping with desired protection/wiring. - */ - npte2 = PTE2(pa, PTE2_NM, m->md.pat_mode); - if (prot & VM_PROT_WRITE) { - if (pte2_is_managed(npte2)) - vm_page_aflag_set(m, PGA_WRITEABLE); - } - else - npte2 |= PTE2_RO; - if ((prot & VM_PROT_EXECUTE) == 0) - npte2 |= PTE2_NX; - if (wired) - npte2 |= PTE2_W; - if (va < VM_MAXUSER_ADDRESS) - npte2 |= PTE2_U; - if (pmap != kernel_pmap) - npte2 |= PTE2_NG; - - /* - * If the mapping or permission bits are different, we need - * to update the pte2. - * - * QQQ: Think again and again what to do - * if the mapping is going to be changed! - */ - if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) { - /* - * Sync icache if exec permission and attribute PTE2_ATTR_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. - * Don't do it for kernel memory which is mapped with exec - * permission even if the memory isn't going to hold executable - * code. The only time when icache sync is needed is after - * kernel module is loaded and the relocation info is processed. - * And it's done in elf_cpu_load_file(). - * - * QQQ: (1) Does it exist any better way where - * or how to sync icache? - * (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 && - (opa != pa || (opte2 & PTE2_NX))) - cache_icache_sync_fresh(va, pa, PAGE_SIZE); - - npte2 |= PTE2_A; - if (flags & VM_PROT_WRITE) - npte2 &= ~PTE2_NM; - if (opte2 & PTE2_V) { - /* Change mapping with break-before-make approach. */ - opte2 = pte2_load_clear(pte2p); - pmap_tlb_flush(pmap, va); - pte2_store(pte2p, npte2); - if (opte2 & PTE2_A) { - if (pte2_is_managed(opte2)) - vm_page_aflag_set(om, PGA_REFERENCED); - } - if (pte2_is_dirty(opte2)) { - if (pte2_is_managed(opte2)) - vm_page_dirty(om); - } - if (pte2_is_managed(opte2) && - TAILQ_EMPTY(&om->md.pv_list) && - ((om->flags & PG_FICTITIOUS) != 0 || - TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list))) - vm_page_aflag_clear(om, PGA_WRITEABLE); - } else - pte2_store(pte2p, npte2); - } -#if 0 - else { - /* - * QQQ: In time when both access and not mofified bits are - * emulated by software, this should not happen. Some - * analysis is need, if this really happen. Missing - * tlb flush somewhere could be the reason. - */ - panic("%s: pmap %p va %#x opte2 %x npte2 %x !!", __func__, pmap, - va, opte2, npte2); - } -#endif - /* - * If both the L2 page table page and the reservation are fully - * populated, then attempt promotion. - */ - if ((mpte2 == NULL || pt2_is_full(mpte2, va)) && - sp_enabled && (m->flags & PG_FICTITIOUS) == 0 && - vm_reserv_level_iffullpop(m) == 0) - pmap_promote_pte1(pmap, pte1p, va); - sched_unpin(); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); - return (KERN_SUCCESS); -} - -/* - * Do the things to unmap a page in a process. - */ -static int -pmap_remove_pte2(pmap_t pmap, pt2_entry_t *pte2p, vm_offset_t va, - struct spglist *free) -{ - pt2_entry_t opte2; - vm_page_t m; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - - /* Clear and invalidate the mapping. */ - opte2 = pte2_load_clear(pte2p); - pmap_tlb_flush(pmap, va); - - KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %#x not link pte2 %#x", - __func__, pmap, va, opte2)); - - if (opte2 & PTE2_W) - pmap->pm_stats.wired_count -= 1; - pmap->pm_stats.resident_count -= 1; - if (pte2_is_managed(opte2)) { - m = PHYS_TO_VM_PAGE(pte2_pa(opte2)); - if (pte2_is_dirty(opte2)) - vm_page_dirty(m); - if (opte2 & PTE2_A) - vm_page_aflag_set(m, PGA_REFERENCED); - pmap_remove_entry(pmap, m, va); - } - return (pmap_unuse_pt2(pmap, va, free)); -} - -/* - * Remove a single page from a process address space. - */ -static void -pmap_remove_page(pmap_t pmap, vm_offset_t va, struct spglist *free) -{ - pt2_entry_t *pte2p; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - KASSERT(curthread->td_pinned > 0, - ("%s: curthread not pinned", __func__)); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - if ((pte2p = pmap_pte2_quick(pmap, va)) == NULL || - !pte2_is_valid(pte2_load(pte2p))) - return; - pmap_remove_pte2(pmap, pte2p, va, 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) -{ - vm_offset_t nextva; - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, pte2; - struct spglist free; - - /* - * Perform an unsynchronized read. This is, however, safe. - */ - if (pmap->pm_stats.resident_count == 0) - return; - - SLIST_INIT(&free); - - rw_wlock(&pvh_global_lock); - sched_pin(); - PMAP_LOCK(pmap); - - /* - * Special handling of removing one page. A very common - * operation and easy to short circuit some code. - */ - if (sva + PAGE_SIZE == eva) { - pte1 = pte1_load(pmap_pte1(pmap, sva)); - if (pte1_is_link(pte1)) { - pmap_remove_page(pmap, sva, &free); - goto out; - } - } - - for (; sva < eva; sva = nextva) { - /* - * Calculate address for next L2 page table. - */ - nextva = pte1_trunc(sva + PTE1_SIZE); - if (nextva < sva) - nextva = eva; - if (pmap->pm_stats.resident_count == 0) - break; - - pte1p = pmap_pte1(pmap, sva); - pte1 = pte1_load(pte1p); - - /* - * Weed out invalid mappings. Note: we assume that the L1 page - * table is always allocated, and in kernel virtual. - */ - if (pte1 == 0) - continue; - - if (pte1_is_section(pte1)) { - /* - * Are we removing the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + PTE1_SIZE == nextva && eva >= nextva) { - pmap_remove_pte1(pmap, pte1p, sva, &free); - continue; - } else if (!pmap_demote_pte1(pmap, pte1p, sva)) { - /* The large page mapping was destroyed. */ - continue; - } -#ifdef INVARIANTS - else { - /* Update pte1 after demotion. */ - pte1 = pte1_load(pte1p); - } -#endif - } - - KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" - " is not link", __func__, pmap, sva, pte1, pte1p)); - - /* - * Limit our scan to either the end of the va represented - * by the current L2 page table page, or to the end of the - * range being removed. - */ - if (nextva > eva) - nextva = eva; - - for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; - pte2p++, sva += PAGE_SIZE) { - pte2 = pte2_load(pte2p); - if (!pte2_is_valid(pte2)) - continue; - if (pmap_remove_pte2(pmap, pte2p, sva, &free)) - break; - } - } -out: - sched_unpin(); - rw_wunlock(&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) -{ - struct md_page *pvh; - pv_entry_t pv; - pmap_t pmap; - pt2_entry_t *pte2p, opte2; - pt1_entry_t *pte1p; - vm_offset_t va; - struct spglist free; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, m)); - SLIST_INIT(&free); - rw_wlock(&pvh_global_lock); - sched_pin(); - 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) { - va = pv->pv_va; - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, va); - (void)pmap_demote_pte1(pmap, pte1p, va); - PMAP_UNLOCK(pmap); - } -small_mappings: - while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pmap->pm_stats.resident_count--; - pte1p = pmap_pte1(pmap, pv->pv_va); - KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found " - "a 1mpage in page %p's pv list", __func__, m)); - pte2p = pmap_pte2_quick(pmap, pv->pv_va); - opte2 = pte2_load_clear(pte2p); - pmap_tlb_flush(pmap, pv->pv_va); - KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %x zero pte2", - __func__, pmap, pv->pv_va)); - if (pte2_is_wired(opte2)) - pmap->pm_stats.wired_count--; - if (opte2 & PTE2_A) - vm_page_aflag_set(m, PGA_REFERENCED); - - /* - * Update the vm_page_t clean and reference bits. - */ - if (pte2_is_dirty(opte2)) - vm_page_dirty(m); - pmap_unuse_pt2(pmap, pv->pv_va, &free); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); - free_pv_entry(pmap, pv); - PMAP_UNLOCK(pmap); - } - vm_page_aflag_clear(m, PGA_WRITEABLE); - sched_unpin(); - rw_wunlock(&pvh_global_lock); - pmap_free_zero_pages(&free); -} - -/* - * Just subroutine for pmap_remove_pages() to reasonably satisfy - * good coding style, a.k.a. 80 character line width limit hell. - */ -static __inline void -pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv, - struct spglist *free) -{ - vm_paddr_t pa; - vm_page_t m, mt, mpt2pg; - struct md_page *pvh; - - pa = pte1_pa(pte1); - m = PHYS_TO_VM_PAGE(pa); - - KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x", - __func__, m, m->phys_addr, pa)); - KASSERT((m->flags & PG_FICTITIOUS) != 0 || - m < &vm_page_array[vm_page_array_size], - ("%s: bad pte1 %#x", __func__, pte1)); - - if (pte1_is_dirty(pte1)) { - for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++) - vm_page_dirty(mt); - } - - pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE; - pvh = pa_to_pvh(pa); - TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); - if (TAILQ_EMPTY(&pvh->pv_list)) { - for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++) - if (TAILQ_EMPTY(&mt->md.pv_list)) - vm_page_aflag_clear(mt, PGA_WRITEABLE); - } - mpt2pg = pmap_pt2_page(pmap, pv->pv_va); - if (mpt2pg != NULL) - pmap_unwire_pt2_all(pmap, pv->pv_va, mpt2pg, free); -} - -/* - * Just subroutine for pmap_remove_pages() to reasonably satisfy - * good coding style, a.k.a. 80 character line width limit hell. - */ -static __inline void -pmap_remove_pte2_quick(pmap_t pmap, pt2_entry_t pte2, pv_entry_t pv, - struct spglist *free) -{ - vm_paddr_t pa; - vm_page_t m; - struct md_page *pvh; - - pa = pte2_pa(pte2); - m = PHYS_TO_VM_PAGE(pa); - - KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x", - __func__, m, m->phys_addr, pa)); - KASSERT((m->flags & PG_FICTITIOUS) != 0 || - m < &vm_page_array[vm_page_array_size], - ("%s: bad pte2 %#x", __func__, pte2)); - - if (pte2_is_dirty(pte2)) - vm_page_dirty(m); - - pmap->pm_stats.resident_count--; - TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); - if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) { - pvh = pa_to_pvh(pa); - if (TAILQ_EMPTY(&pvh->pv_list)) - vm_page_aflag_clear(m, PGA_WRITEABLE); - } - pmap_unuse_pt2(pmap, pv->pv_va, free); -} - -/* - * 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) -{ - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, pte2; - pv_entry_t pv; - struct pv_chunk *pc, *npc; - struct spglist free; - int field, idx; - int32_t bit; - uint32_t inuse, bitmask; - boolean_t allfree; - - /* - * Assert that the given pmap is only active on the current - * CPU. Unfortunately, we cannot block another CPU from - * activating the pmap while this function is executing. - */ - KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace), - ("%s: non-current pmap %p", __func__, pmap)); -#if defined(SMP) && defined(INVARIANTS) - { - cpuset_t other_cpus; - - sched_pin(); - other_cpus = pmap->pm_active; - CPU_CLR(PCPU_GET(cpuid), &other_cpus); - sched_unpin(); - KASSERT(CPU_EMPTY(&other_cpus), - ("%s: pmap %p active on other cpus", __func__, pmap)); - } -#endif - SLIST_INIT(&free); - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - sched_pin(); - TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) { - KASSERT(pc->pc_pmap == pmap, ("%s: wrong pmap %p %p", - __func__, pmap, pc->pc_pmap)); - allfree = TRUE; - 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 * 32 + bit; - pv = &pc->pc_pventry[idx]; - inuse &= ~bitmask; - - /* - * Note that we cannot remove wired pages - * from a process' mapping at this time - */ - pte1p = pmap_pte1(pmap, pv->pv_va); - pte1 = pte1_load(pte1p); - if (pte1_is_section(pte1)) { - if (pte1_is_wired(pte1)) { - allfree = FALSE; - continue; - } - pte1_clear(pte1p); - pmap_remove_pte1_quick(pmap, pte1, pv, - &free); - } - else if (pte1_is_link(pte1)) { - pte2p = pt2map_entry(pv->pv_va); - pte2 = pte2_load(pte2p); - - if (!pte2_is_valid(pte2)) { - printf("%s: pmap %p va %#x " - "pte2 %#x\n", __func__, - pmap, pv->pv_va, pte2); - panic("bad pte2"); - } - - if (pte2_is_wired(pte2)) { - allfree = FALSE; - continue; - } - pte2_clear(pte2p); - pmap_remove_pte2_quick(pmap, pte2, pv, - &free); - } else { - printf("%s: pmap %p va %#x pte1 %#x\n", - __func__, pmap, pv->pv_va, pte1); - panic("bad pte1"); - } - - /* 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); - free_pv_chunk(pc); - } - } - tlb_flush_all_ng_local(); - sched_unpin(); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); - pmap_free_zero_pages(&free); -} - -/* - * This code makes some *MAJOR* assumptions: - * 1. Current pmap & pmap exists. - * 2. Not wired. - * 3. Read access. - * 4. No L2 page table pages. - * but is *MUCH* faster than pmap_enter... - */ -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 mpt2pg) -{ - pt2_entry_t *pte2p, pte2; - vm_paddr_t pa; - struct spglist free; - uint32_t l2prot; - - KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva || - (m->oflags & VPO_UNMANAGED) != 0, - ("%s: managed mapping within the clean submap", __func__)); - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - - /* - * In the case that a L2 page table page is not - * resident, we are creating it here. - */ - if (va < VM_MAXUSER_ADDRESS) { - u_int pte1_idx; - pt1_entry_t pte1, *pte1p; - vm_paddr_t pt2_pa; - - /* - * Get L1 page table things. - */ - pte1_idx = pte1_index(va); - pte1p = pmap_pte1(pmap, va); - pte1 = pte1_load(pte1p); - - if (mpt2pg && (mpt2pg->pindex == (pte1_idx & ~PT2PG_MASK))) { - /* - * Each of NPT2_IN_PG L2 page tables on the page can - * come here. Make sure that associated L1 page table - * link is established. - * - * QQQ: It comes that we don't establish all links to - * L2 page tables for newly allocated L2 page - * tables page. - */ - KASSERT(!pte1_is_section(pte1), - ("%s: pte1 %#x is section", __func__, pte1)); - if (!pte1_is_link(pte1)) { - pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(mpt2pg), - pte1_idx); - pte1_store(pte1p, PTE1_LINK(pt2_pa)); - } - pt2_wirecount_inc(mpt2pg, pte1_idx); - } else { - /* - * If the L2 page table page is mapped, we just - * increment the hold count, and activate it. - */ - if (pte1_is_section(pte1)) { - return (NULL); - } else if (pte1_is_link(pte1)) { - mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); - pt2_wirecount_inc(mpt2pg, pte1_idx); - } else { - mpt2pg = _pmap_allocpte2(pmap, va, - PMAP_ENTER_NOSLEEP); - if (mpt2pg == NULL) - return (NULL); - } - } - } else { - mpt2pg = NULL; - } - - /* - * This call to pt2map_entry() makes the assumption that we are - * entering the page into the current pmap. In order to support - * quick entry into any pmap, one would likely use pmap_pte2_quick(). - * But that isn't as quick as pt2map_entry(). - */ - pte2p = pt2map_entry(va); - pte2 = pte2_load(pte2p); - if (pte2_is_valid(pte2)) { - if (mpt2pg != NULL) { - /* - * Remove extra pte2 reference - */ - pt2_wirecount_dec(mpt2pg, pte1_index(va)); - mpt2pg = NULL; - } - return (NULL); - } - - /* - * 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)) { - if (mpt2pg != NULL) { - SLIST_INIT(&free); - if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) { - pmap_tlb_flush(pmap, va); - pmap_free_zero_pages(&free); - } - - mpt2pg = NULL; - } - return (NULL); - } - - /* - * Increment counters - */ - pmap->pm_stats.resident_count++; - - /* - * Now validate mapping with RO protection - */ - pa = VM_PAGE_TO_PHYS(m); - l2prot = PTE2_RO | PTE2_NM; - if (va < VM_MAXUSER_ADDRESS) - 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) { - /* - * Sync icache if exec permission and attribute PTE2_ATTR_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)); - - return (mpt2pg); -} - -void -pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) -{ - - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); -} - -/* - * Tries to create 1MB page mapping. Returns TRUE if successful and - * FALSE otherwise. Fails if (1) a page table page cannot be allocated without - * blocking, (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_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) -{ - pt1_entry_t *pte1p; - vm_paddr_t pa; - uint32_t l1prot; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - pte1p = pmap_pte1(pmap, va); - if (pte1_is_valid(pte1_load(pte1p))) { - CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", __func__, - va, pmap); - return (FALSE); - } - if ((m->oflags & VPO_UNMANAGED) == 0) { - /* - * Abort this mapping if its PV entry could not be created. - */ - if (!pmap_pv_insert_pte1(pmap, va, VM_PAGE_TO_PHYS(m))) { - CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", - __func__, va, pmap); - return (FALSE); - } - } - /* - * Increment counters. - */ - pmap->pm_stats.resident_count += PTE1_SIZE / PAGE_SIZE; - - /* - * Map the section. - * - * QQQ: Why VM_PROT_WRITE is not evaluated and the mapping is - * made readonly? - */ - pa = VM_PAGE_TO_PHYS(m); - l1prot = PTE1_RO | PTE1_NM; - if (va < VM_MAXUSER_ADDRESS) - 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) { - /* - * Sync icache if exec permission and attribute PTE2_ATTR_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))); - - pmap_pte1_mappings++; - CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va, - pmap); - return (TRUE); -} - -/* - * 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, mpt2pg; - vm_pindex_t diff, psize; - - PDEBUG(6, printf("%s: pmap %p start %#x end %#x m %p prot %#x\n", - __func__, pmap, start, end, m_start, prot)); - - VM_OBJECT_ASSERT_LOCKED(m_start->object); - psize = atop(end - start); - mpt2pg = NULL; - m = m_start; - rw_wlock(&pvh_global_lock); - PMAP_LOCK(pmap); - while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { - va = start + ptoa(diff); - if ((va & PTE1_OFFSET) == 0 && va + PTE1_SIZE <= end && - m->psind == 1 && sp_enabled && - pmap_enter_pte1(pmap, va, m, prot)) - m = &m[PTE1_SIZE / PAGE_SIZE - 1]; - else - mpt2pg = pmap_enter_quick_locked(pmap, va, m, prot, - mpt2pg); - m = TAILQ_NEXT(m, listq); - } - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(pmap); -} - -/* - * 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) -{ - pt1_entry_t *pte1p; - vm_paddr_t pa, pte2_pa; - vm_page_t p; - int pat_mode; - u_int l1attr, l1prot; - - VM_OBJECT_ASSERT_WLOCKED(object); - KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG, - ("%s: non-device object", __func__)); - if ((addr & PTE1_OFFSET) == 0 && (size & PTE1_OFFSET) == 0) { - if (!vm_object_populate(object, pindex, pindex + atop(size))) - return; - p = vm_page_lookup(object, pindex); - KASSERT(p->valid == VM_PAGE_BITS_ALL, - ("%s: invalid page %p", __func__, p)); - pat_mode = p->md.pat_mode; - - /* - * Abort the mapping if the first page is not physically - * aligned to a 1MB page boundary. - */ - pte2_pa = VM_PAGE_TO_PHYS(p); - if (pte2_pa & PTE1_OFFSET) - return; - - /* - * Skip the first page. Abort the mapping if the rest of - * the pages are not physically contiguous or have differing - * memory attributes. - */ - p = TAILQ_NEXT(p, listq); - for (pa = pte2_pa + PAGE_SIZE; pa < pte2_pa + size; - pa += PAGE_SIZE) { - KASSERT(p->valid == VM_PAGE_BITS_ALL, - ("%s: invalid page %p", __func__, p)); - if (pa != VM_PAGE_TO_PHYS(p) || - pat_mode != p->md.pat_mode) - return; - p = TAILQ_NEXT(p, listq); - } - - /* - * Map using 1MB pages. - * - * QQQ: Well, we are mapping a section, so same condition must - * be hold like during promotion. It looks that only RW mapping - * 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); - PMAP_LOCK(pmap); - for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) { - pte1p = pmap_pte1(pmap, addr); - if (!pte1_is_valid(pte1_load(pte1p))) { - pte1_store(pte1p, PTE1(pa, l1prot, l1attr)); - pmap->pm_stats.resident_count += PTE1_SIZE / - PAGE_SIZE; - pmap_pte1_mappings++; - } - /* Else continue on if the PTE1 is already valid. */ - addr += PTE1_SIZE; - } - PMAP_UNLOCK(pmap); - } -} - -/* - * Do the things to protect a 1mpage in a process. - */ -static void -pmap_protect_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva, - vm_prot_t prot) -{ - pt1_entry_t npte1, opte1; - vm_offset_t eva, va; - vm_page_t m; - - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - KASSERT((sva & PTE1_OFFSET) == 0, - ("%s: sva is not 1mpage aligned", __func__)); -retry: - opte1 = npte1 = pte1_load(pte1p); - if (pte1_is_managed(opte1)) { - eva = sva + PTE1_SIZE; - for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1)); - va < eva; va += PAGE_SIZE, m++) - if (pte1_is_dirty(opte1)) - vm_page_dirty(m); - } - if ((prot & VM_PROT_WRITE) == 0) - npte1 |= PTE1_RO | PTE1_NM; - if ((prot & VM_PROT_EXECUTE) == 0) - npte1 |= PTE1_NX; - - /* - * QQQ: Herein, execute permission is never set. - * It only can be cleared. So, no icache - * syncing is needed. - */ - - if (npte1 != opte1) { - if (!pte1_cmpset(pte1p, opte1, npte1)) - goto retry; - pmap_tlb_flush(pmap, sva); - } -} - -/* - * 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) -{ - boolean_t pv_lists_locked; - vm_offset_t nextva; - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, opte2, npte2; - - KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot)); - if (prot == VM_PROT_NONE) { - pmap_remove(pmap, sva, eva); - return; - } - - if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) == - (VM_PROT_WRITE | VM_PROT_EXECUTE)) - return; - - if (pmap_is_current(pmap)) - pv_lists_locked = FALSE; - else { - pv_lists_locked = TRUE; -resume: - rw_wlock(&pvh_global_lock); - sched_pin(); - } - - PMAP_LOCK(pmap); - for (; sva < eva; sva = nextva) { - /* - * Calculate address for next L2 page table. - */ - nextva = pte1_trunc(sva + PTE1_SIZE); - if (nextva < sva) - nextva = eva; - - pte1p = pmap_pte1(pmap, sva); - pte1 = pte1_load(pte1p); - - /* - * Weed out invalid mappings. Note: we assume that L1 page - * page table is always allocated, and in kernel virtual. - */ - if (pte1 == 0) - continue; - - if (pte1_is_section(pte1)) { - /* - * Are we protecting the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + PTE1_SIZE == nextva && eva >= nextva) { - pmap_protect_pte1(pmap, pte1p, sva, prot); - continue; - } else { - if (!pv_lists_locked) { - pv_lists_locked = TRUE; - if (!rw_try_wlock(&pvh_global_lock)) { - PMAP_UNLOCK(pmap); - goto resume; - } - sched_pin(); - } - if (!pmap_demote_pte1(pmap, pte1p, sva)) { - /* - * The large page mapping - * was destroyed. - */ - continue; - } -#ifdef INVARIANTS - else { - /* Update pte1 after demotion */ - pte1 = pte1_load(pte1p); - } -#endif - } - } - - KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" - " is not link", __func__, pmap, sva, pte1, pte1p)); - - /* - * Limit our scan to either the end of the va represented - * by the current L2 page table page, or to the end of the - * range being protected. - */ - if (nextva > eva) - nextva = eva; - - for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++, - sva += PAGE_SIZE) { - vm_page_t m; -retry: - opte2 = npte2 = pte2_load(pte2p); - if (!pte2_is_valid(opte2)) - continue; - - if ((prot & VM_PROT_WRITE) == 0) { - if (pte2_is_managed(opte2) && - pte2_is_dirty(opte2)) { - m = PHYS_TO_VM_PAGE(pte2_pa(opte2)); - vm_page_dirty(m); - } - npte2 |= PTE2_RO | PTE2_NM; - } - - if ((prot & VM_PROT_EXECUTE) == 0) - npte2 |= PTE2_NX; - - /* - * QQQ: Herein, execute permission is never set. - * It only can be cleared. So, no icache - * syncing is needed. - */ - - if (npte2 != opte2) { - - if (!pte2_cmpset(pte2p, opte2, npte2)) - goto retry; - pmap_tlb_flush(pmap, sva); - } - } - } - if (pv_lists_locked) { - sched_unpin(); - rw_wunlock(&pvh_global_lock); - } - PMAP_UNLOCK(pmap); -} - -/* - * 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) -{ - pmap_t pmap; - pt1_entry_t pte1; - pt2_entry_t pte2; - pv_entry_t pv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - sched_pin(); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); - if (pte1_is_section(pte1)) { - if (pte1_is_wired(pte1)) - count++; - } else { - KASSERT(pte1_is_link(pte1), - ("%s: pte1 %#x is not link", __func__, pte1)); - pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); - if (pte2_is_wired(pte2)) - count++; - } - PMAP_UNLOCK(pmap); - } - sched_unpin(); - return (count); -} - -/* - * 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); -} - -/* - * Returns TRUE if any of the given mappings were used to modify - * physical memory. Otherwise, returns FALSE. Both page and 1mpage - * mappings are supported. - */ -static boolean_t -pmap_is_modified_pvh(struct md_page *pvh) -{ - pv_entry_t pv; - pt1_entry_t pte1; - pt2_entry_t pte2; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - sched_pin(); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); - if (pte1_is_section(pte1)) { - rv = pte1_is_dirty(pte1); - } else { - KASSERT(pte1_is_link(pte1), - ("%s: pte1 %#x is not link", __func__, pte1)); - pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); - rv = pte2_is_dirty(pte2); - } - PMAP_UNLOCK(pmap); - if (rv) - break; - } - sched_unpin(); - 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) -{ - boolean_t rv; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, 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 PTE2s can have PG_M set. - */ - 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); -} - -/* - * 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) -{ - pt1_entry_t pte1; - pt2_entry_t pte2; - boolean_t rv; - - rv = FALSE; - PMAP_LOCK(pmap); - pte1 = pte1_load(pmap_pte1(pmap, addr)); - if (pte1_is_link(pte1)) { - pte2 = pte2_load(pt2map_entry(addr)); - rv = !pte2_is_valid(pte2) ; - } - PMAP_UNLOCK(pmap); - return (rv); -} - -/* - * Returns TRUE if any of the given mappings were referenced and FALSE - * otherwise. Both page and 1mpage mappings are supported. - */ -static boolean_t -pmap_is_referenced_pvh(struct md_page *pvh) -{ - - pv_entry_t pv; - pt1_entry_t pte1; - pt2_entry_t pte2; - pmap_t pmap; - boolean_t rv; - - rw_assert(&pvh_global_lock, RA_WLOCKED); - rv = FALSE; - sched_pin(); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); - if (pte1_is_section(pte1)) { - rv = (pte1 & (PTE1_A | PTE1_V)) == (PTE1_A | PTE1_V); - } else { - pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); - rv = (pte2 & (PTE2_A | PTE2_V)) == (PTE2_A | PTE2_V); - } - PMAP_UNLOCK(pmap); - if (rv) - break; - } - sched_unpin(); - 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, - ("%s: page %p is not managed", __func__, 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); -} - -#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) -{ - struct md_page *pvh; - pv_entry_t pv, pvf; - pmap_t pmap; - pt1_entry_t *pte1p, opte1; - pt2_entry_t *pte2p; - vm_paddr_t pa; - int rtval = 0; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, m)); - pa = VM_PAGE_TO_PHYS(m); - pvh = pa_to_pvh(pa); - rw_wlock(&pvh_global_lock); - sched_pin(); - if ((m->flags & PG_FICTITIOUS) != 0 || - (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL) - goto small_mappings; - pv = pvf; - do { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, pv->pv_va); - opte1 = pte1_load(pte1p); - if ((opte1 & PTE1_A) != 0) { - /* - * Since this reference bit is shared by 256 4KB pages, - * it should not be cleared every time it is tested. - * Apply a simple "hash" function on the physical page - * number, the virtual section number, and the pmap - * address to select one 4KB page out of the 256 - * on which testing the reference bit will result - * in clearing that bit. This function is designed - * to avoid the selection of the same 4KB page - * for every 1MB page mapping. - * - * On demotion, a mapping that hasn't been referenced - * is simply destroyed. To avoid the possibility of a - * subsequent page fault on a demoted wired mapping, - * always leave its reference bit set. Moreover, - * since the section is wired, the current state of - * its reference bit won't affect page replacement. - */ - if ((((pa >> PAGE_SHIFT) ^ (pv->pv_va >> PTE1_SHIFT) ^ - (uintptr_t)pmap) & (NPTE2_IN_PG - 1)) == 0 && - !pte1_is_wired(opte1)) { - pte1_clear_bit(pte1p, PTE1_A); - pmap_tlb_flush(pmap, pv->pv_va); - } - rtval++; - } - PMAP_UNLOCK(pmap); - /* Rotate the PV list if it has more than one entry. */ - if (TAILQ_NEXT(pv, pv_next) != NULL) { - TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); - TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); - } - if (rtval >= PMAP_TS_REFERENCED_MAX) - goto out; - } while ((pv = TAILQ_FIRST(&pvh->pv_list)) != pvf); -small_mappings: - if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL) - goto out; - pv = pvf; - do { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, pv->pv_va); - KASSERT(pte1_is_link(pte1_load(pte1p)), - ("%s: not found a link in page %p's pv list", __func__, m)); - - pte2p = pmap_pte2_quick(pmap, pv->pv_va); - if ((pte2_load(pte2p) & PTE2_A) != 0) { - pte2_clear_bit(pte2p, PTE2_A); - pmap_tlb_flush(pmap, pv->pv_va); - rtval++; - } - PMAP_UNLOCK(pmap); - /* Rotate the PV list if it has more than one entry. */ - if (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); - } - } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && rtval < - PMAP_TS_REFERENCED_MAX); -out: - sched_unpin(); - rw_wunlock(&pvh_global_lock); - return (rtval); -} - -/* - * 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 nextva; - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, pte2; - boolean_t pv_lists_locked; - - if (pmap_is_current(pmap)) - pv_lists_locked = FALSE; - else { - pv_lists_locked = TRUE; -resume: - rw_wlock(&pvh_global_lock); - sched_pin(); - } - PMAP_LOCK(pmap); - for (; sva < eva; sva = nextva) { - nextva = pte1_trunc(sva + PTE1_SIZE); - if (nextva < sva) - nextva = eva; - - pte1p = pmap_pte1(pmap, sva); - pte1 = pte1_load(pte1p); - - /* - * Weed out invalid mappings. Note: we assume that L1 page - * page table is always allocated, and in kernel virtual. - */ - if (pte1 == 0) - continue; - - if (pte1_is_section(pte1)) { - if (!pte1_is_wired(pte1)) - panic("%s: pte1 %#x not wired", __func__, pte1); - - /* - * Are we unwiring the entire large page? If not, - * demote the mapping and fall through. - */ - if (sva + PTE1_SIZE == nextva && eva >= nextva) { - pte1_clear_bit(pte1p, PTE1_W); - pmap->pm_stats.wired_count -= PTE1_SIZE / - PAGE_SIZE; - continue; - } else { - if (!pv_lists_locked) { - pv_lists_locked = TRUE; - if (!rw_try_wlock(&pvh_global_lock)) { - PMAP_UNLOCK(pmap); - /* Repeat sva. */ - goto resume; - } - sched_pin(); - } - if (!pmap_demote_pte1(pmap, pte1p, sva)) - panic("%s: demotion failed", __func__); -#ifdef INVARIANTS - else { - /* Update pte1 after demotion */ - pte1 = pte1_load(pte1p); - } -#endif - } - } - - KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" - " is not link", __func__, pmap, sva, pte1, pte1p)); - - /* - * Limit our scan to either the end of the va represented - * by the current L2 page table page, or to the end of the - * range being protected. - */ - if (nextva > eva) - nextva = eva; - - for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++, - sva += PAGE_SIZE) { - pte2 = pte2_load(pte2p); - if (!pte2_is_valid(pte2)) - continue; - if (!pte2_is_wired(pte2)) - panic("%s: pte2 %#x is missing PTE2_W", - __func__, pte2); - - /* - * PTE2_W must be cleared atomically. Although the pmap - * lock synchronizes access to PTE2_W, another processor - * could be changing PTE2_NM and/or PTE2_A concurrently. - */ - pte2_clear_bit(pte2p, PTE2_W); - pmap->pm_stats.wired_count--; - } - } - if (pv_lists_locked) { - sched_unpin(); - rw_wunlock(&pvh_global_lock); - } - PMAP_UNLOCK(pmap); -} - -/* - * Clear the write and modified bits in each of the given page's mappings. - */ -void -pmap_remove_write(vm_page_t m) -{ - struct md_page *pvh; - pv_entry_t next_pv, pv; - pmap_t pmap; - pt1_entry_t *pte1p; - pt2_entry_t *pte2p, opte2; - vm_offset_t va; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, 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_wlock(&pvh_global_lock); - sched_pin(); - 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_next, next_pv) { - va = pv->pv_va; - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, va); - if (!(pte1_load(pte1p) & PTE1_RO)) - (void)pmap_demote_pte1(pmap, pte1p, va); - PMAP_UNLOCK(pmap); - } -small_mappings: - TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, pv->pv_va); - KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found" - " a section in page %p's pv list", __func__, m)); - pte2p = pmap_pte2_quick(pmap, pv->pv_va); -retry: - opte2 = pte2_load(pte2p); - if (!(opte2 & PTE2_RO)) { - if (!pte2_cmpset(pte2p, opte2, - opte2 | (PTE2_RO | PTE2_NM))) - goto retry; - if (pte2_is_dirty(opte2)) - vm_page_dirty(m); - pmap_tlb_flush(pmap, pv->pv_va); - } - PMAP_UNLOCK(pmap); - } - vm_page_aflag_clear(m, PGA_WRITEABLE); - sched_unpin(); - rw_wunlock(&pvh_global_lock); -} - -/* - * 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) -{ - pt1_entry_t *pte1p, opte1; - pt2_entry_t *pte2p, pte2; - vm_offset_t pdnxt; - vm_page_t m; - boolean_t pv_lists_locked; - - if (advice != MADV_DONTNEED && advice != MADV_FREE) - return; - if (pmap_is_current(pmap)) - pv_lists_locked = FALSE; - else { - pv_lists_locked = TRUE; -resume: - rw_wlock(&pvh_global_lock); - sched_pin(); - } - PMAP_LOCK(pmap); - for (; sva < eva; sva = pdnxt) { - pdnxt = pte1_trunc(sva + PTE1_SIZE); - if (pdnxt < sva) - pdnxt = eva; - pte1p = pmap_pte1(pmap, sva); - opte1 = pte1_load(pte1p); - if (!pte1_is_valid(opte1)) /* XXX */ - continue; - else if (pte1_is_section(opte1)) { - if (!pte1_is_managed(opte1)) - continue; - if (!pv_lists_locked) { - pv_lists_locked = TRUE; - if (!rw_try_wlock(&pvh_global_lock)) { - PMAP_UNLOCK(pmap); - goto resume; - } - sched_pin(); - } - if (!pmap_demote_pte1(pmap, pte1p, 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 page - * table is fully populated, this removal never - * frees a L2 page table page. - */ - if (!pte1_is_wired(opte1)) { - pte2p = pmap_pte2_quick(pmap, sva); - KASSERT(pte2_is_valid(pte2_load(pte2p)), - ("%s: invalid PTE2", __func__)); - pmap_remove_pte2(pmap, pte2p, sva, NULL); - } - } - if (pdnxt > eva) - pdnxt = eva; - for (pte2p = pmap_pte2_quick(pmap, sva); sva != pdnxt; pte2p++, - sva += PAGE_SIZE) { - pte2 = pte2_load(pte2p); - if (!pte2_is_valid(pte2) || !pte2_is_managed(pte2)) - continue; - else if (pte2_is_dirty(pte2)) { - if (advice == MADV_DONTNEED) { - /* - * Future calls to pmap_is_modified() - * can be avoided by making the page - * dirty now. - */ - m = PHYS_TO_VM_PAGE(pte2_pa(pte2)); - vm_page_dirty(m); - } - pte2_set_bit(pte2p, PTE2_NM); - pte2_clear_bit(pte2p, PTE2_A); - } else if ((pte2 & PTE2_A) != 0) - pte2_clear_bit(pte2p, PTE2_A); - else - continue; - pmap_tlb_flush(pmap, sva); - } - } - if (pv_lists_locked) { - sched_unpin(); - 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) -{ - struct md_page *pvh; - pv_entry_t next_pv, pv; - pmap_t pmap; - pt1_entry_t *pte1p, opte1; - pt2_entry_t *pte2p, opte2; - vm_offset_t va; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, m)); - VM_OBJECT_ASSERT_WLOCKED(m->object); - KASSERT(!vm_page_xbusied(m), - ("%s: page %p is exclusive busy", __func__, m)); - - /* - * If the page is not PGA_WRITEABLE, then no PTE2s can have PTE2_NM - * cleared. If the object containing the page is locked and the page - * is not exclusive busied, then PGA_WRITEABLE cannot be concurrently - * set. - */ - if ((m->flags & PGA_WRITEABLE) == 0) - return; - rw_wlock(&pvh_global_lock); - sched_pin(); - 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_next, next_pv) { - va = pv->pv_va; - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, va); - opte1 = pte1_load(pte1p); - if (!(opte1 & PTE1_RO)) { - if (pmap_demote_pte1(pmap, pte1p, va) && - !pte1_is_wired(opte1)) { - /* - * Write protect the mapping to a - * single page so that a subsequent - * write access may repromote. - */ - va += VM_PAGE_TO_PHYS(m) - pte1_pa(opte1); - pte2p = pmap_pte2_quick(pmap, va); - opte2 = pte2_load(pte2p); - if ((opte2 & PTE2_V)) { - pte2_set_bit(pte2p, PTE2_NM | PTE2_RO); - vm_page_dirty(m); - pmap_tlb_flush(pmap, va); - } - } - } - PMAP_UNLOCK(pmap); - } -small_mappings: - TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { - pmap = PV_PMAP(pv); - PMAP_LOCK(pmap); - pte1p = pmap_pte1(pmap, pv->pv_va); - KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found" - " a section in page %p's pv list", __func__, m)); - pte2p = pmap_pte2_quick(pmap, pv->pv_va); - if (pte2_is_dirty(pte2_load(pte2p))) { - pte2_set_bit(pte2p, PTE2_NM); - pmap_tlb_flush(pmap, pv->pv_va); - } - PMAP_UNLOCK(pmap); - } - sched_unpin(); - rw_wunlock(&pvh_global_lock); -} - - -/* - * Sets the memory attribute for the specified page. - */ -void -pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) -{ - struct sysmaps *sysmaps; - vm_memattr_t oma; - vm_paddr_t pa; - - oma = m->md.pat_mode; - m->md.pat_mode = ma; - - CTR5(KTR_PMAP, "%s: page %p - 0x%08X oma: %d, ma: %d", __func__, m, - VM_PAGE_TO_PHYS(m), oma, ma); - if ((m->flags & PG_FICTITIOUS) != 0) - return; -#if 0 - /* - * If "m" is a normal page, flush it from the cache. - * - * First, try to find an existing mapping of the page by sf - * buffer. sf_buf_invalidate_cache() modifies mapping and - * flushes the cache. - */ - if (sf_buf_invalidate_cache(m, oma)) - return; -#endif - /* - * If page is not mapped by sf buffer, map the page - * transient and do invalidation. - */ - if (ma != oma) { - pa = VM_PAGE_TO_PHYS(m); - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - if (*sysmaps->CMAP2) - panic("%s: CMAP2 busy", __func__); - pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); - dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); - } -} - -/* - * Miscellaneous support routines follow - */ - -/* - * Returns TRUE if the given page is mapped individually or as part of - * a 1mpage. 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); -} - -/* - * 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 md_page *pvh; - pv_entry_t pv; - int loops = 0; - boolean_t rv; - - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("%s: page %p is not managed", __func__, m)); - rv = FALSE; - rw_wlock(&pvh_global_lock); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { - 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_next) { - if (PV_PMAP(pv) == pmap) { - rv = TRUE; - break; - } - loops++; - if (loops >= 16) - break; - } - } - rw_wunlock(&pvh_global_lock); - return (rv); -} - -/* - * 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) -{ - struct sysmaps *sysmaps; - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - 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)); - pagezero(sysmaps->CADDR2); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -/* - * 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) -{ - struct sysmaps *sysmaps; - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - 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)); - if (off == 0 && size == PAGE_SIZE) - pagezero(sysmaps->CADDR2); - else - bzero(sysmaps->CADDR2 + off, size); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -/* - * 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) -{ - - if (pte2_load(CMAP3) != 0) - 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)); - pagezero(CADDR3); - pte2_clear(CMAP3); - tlb_flush((vm_offset_t)CADDR3); - sched_unpin(); -} - -/* - * 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 src, vm_page_t dst) -{ - struct sysmaps *sysmaps; - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - if (pte2_load(sysmaps->CMAP1) != 0) - panic("%s: CMAP1 busy", __func__); - 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_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst), - PTE2_AP_KRW, dst->md.pat_mode)); - bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); - pte2_clear(sysmaps->CMAP1); - tlb_flush((vm_offset_t)sysmaps->CADDR1); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -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) -{ - struct sysmaps *sysmaps; - vm_page_t a_pg, b_pg; - char *a_cp, *b_cp; - vm_offset_t a_pg_offset, b_pg_offset; - int cnt; - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - if (*sysmaps->CMAP1 != 0) - panic("pmap_copy_pages: CMAP1 busy"); - if (*sysmaps->CMAP2 != 0) - panic("pmap_copy_pages: CMAP2 busy"); - 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); - pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg), - PTE2_AP_KR | PTE2_NM, a_pg->md.pat_mode)); - 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)); - tlb_flush_local((vm_offset_t)sysmaps->CADDR2); - a_cp = sysmaps->CADDR1 + a_pg_offset; - b_cp = sysmaps->CADDR2 + b_pg_offset; - bcopy(a_cp, b_cp, cnt); - a_offset += cnt; - b_offset += cnt; - xfersize -= cnt; - } - pte2_clear(sysmaps->CMAP1); - tlb_flush((vm_offset_t)sysmaps->CADDR1); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -vm_offset_t -pmap_quick_enter_page(vm_page_t m) -{ - pt2_entry_t *pte2p; - vm_offset_t qmap_addr; - - critical_enter(); - qmap_addr = PCPU_GET(qmap_addr); - pte2p = pt2map_entry(qmap_addr); - - 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))); - return (qmap_addr); -} - -void -pmap_quick_remove_page(vm_offset_t addr) -{ - pt2_entry_t *pte2p; - vm_offset_t qmap_addr; - - qmap_addr = PCPU_GET(qmap_addr); - pte2p = pt2map_entry(qmap_addr); - - KASSERT(addr == qmap_addr, ("%s: invalid address", __func__)); - KASSERT(pte2_load(pte2p) != 0, ("%s: PTE2 not in use", __func__)); - - pte2_clear(pte2p); - tlb_flush(qmap_addr); - critical_exit(); -} - -/* - * 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) -{ - struct spglist free; - vm_offset_t addr; - vm_offset_t end_addr = src_addr + len; - vm_offset_t nextva; - - if (dst_addr != src_addr) - return; - - if (!pmap_is_current(src_pmap)) - return; - - rw_wlock(&pvh_global_lock); - if (dst_pmap < src_pmap) { - PMAP_LOCK(dst_pmap); - PMAP_LOCK(src_pmap); - } else { - PMAP_LOCK(src_pmap); - PMAP_LOCK(dst_pmap); - } - sched_pin(); - for (addr = src_addr; addr < end_addr; addr = nextva) { - pt2_entry_t *src_pte2p, *dst_pte2p; - vm_page_t dst_mpt2pg, src_mpt2pg; - pt1_entry_t src_pte1; - u_int pte1_idx; - - KASSERT(addr < VM_MAXUSER_ADDRESS, - ("%s: invalid to pmap_copy page tables", __func__)); - - nextva = pte1_trunc(addr + PTE1_SIZE); - if (nextva < addr) - nextva = end_addr; - - pte1_idx = pte1_index(addr); - src_pte1 = src_pmap->pm_pt1[pte1_idx]; - if (pte1_is_section(src_pte1)) { - if ((addr & PTE1_OFFSET) != 0 || - (addr + PTE1_SIZE) > end_addr) - continue; - if (dst_pmap->pm_pt1[pte1_idx] == 0 && - (!pte1_is_managed(src_pte1) || - pmap_pv_insert_pte1(dst_pmap, addr, - pte1_pa(src_pte1)))) { - dst_pmap->pm_pt1[pte1_idx] = src_pte1 & - ~PTE1_W; - dst_pmap->pm_stats.resident_count += - PTE1_SIZE / PAGE_SIZE; - pmap_pte1_mappings++; - } - continue; - } else if (!pte1_is_link(src_pte1)) - continue; - - src_mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(src_pte1)); - - /* - * We leave PT2s to be linked from PT1 even if they are not - * referenced until all PT2s in a page are without reference. - * - * QQQ: It could be changed ... - */ -#if 0 /* single_pt2_link_is_cleared */ - KASSERT(pt2_wirecount_get(src_mpt2pg, pte1_idx) > 0, - ("%s: source page table page is unused", __func__)); -#else - if (pt2_wirecount_get(src_mpt2pg, pte1_idx) == 0) - continue; -#endif - if (nextva > end_addr) - nextva = end_addr; - - src_pte2p = pt2map_entry(addr); - while (addr < nextva) { - pt2_entry_t temp_pte2; - temp_pte2 = pte2_load(src_pte2p); - /* - * we only virtual copy managed pages - */ - if (pte2_is_managed(temp_pte2)) { - dst_mpt2pg = pmap_allocpte2(dst_pmap, addr, - PMAP_ENTER_NOSLEEP); - if (dst_mpt2pg == NULL) - goto out; - dst_pte2p = pmap_pte2_quick(dst_pmap, addr); - if (!pte2_is_valid(pte2_load(dst_pte2p)) && - pmap_try_insert_pv_entry(dst_pmap, addr, - PHYS_TO_VM_PAGE(pte2_pa(temp_pte2)))) { - /* - * Clear the wired, modified, and - * accessed (referenced) bits - * during the copy. - */ - temp_pte2 &= ~(PTE2_W | PTE2_A); - temp_pte2 |= PTE2_NM; - pte2_store(dst_pte2p, temp_pte2); - dst_pmap->pm_stats.resident_count++; - } else { - SLIST_INIT(&free); - if (pmap_unwire_pt2(dst_pmap, addr, - dst_mpt2pg, &free)) { - pmap_tlb_flush(dst_pmap, addr); - pmap_free_zero_pages(&free); - } - goto out; - } - if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >= - pt2_wirecount_get(src_mpt2pg, pte1_idx)) - break; - } - addr += PAGE_SIZE; - src_pte2p++; - } - } -out: - sched_unpin(); - rw_wunlock(&pvh_global_lock); - PMAP_UNLOCK(src_pmap); - PMAP_UNLOCK(dst_pmap); -} - -/* - * Increase the starting virtual address of the given mapping if a - * different alignment might result in more section mappings. - */ -void -pmap_align_superpage(vm_object_t object, vm_ooffset_t offset, - vm_offset_t *addr, vm_size_t size) -{ - vm_offset_t pte1_offset; - - if (size < PTE1_SIZE) - return; - if (object != NULL && (object->flags & OBJ_COLORED) != 0) - offset += ptoa(object->pg_color); - pte1_offset = offset & PTE1_OFFSET; - if (size - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) < PTE1_SIZE || - (*addr & PTE1_OFFSET) == pte1_offset) - return; - if ((*addr & PTE1_OFFSET) < pte1_offset) - *addr = pte1_trunc(*addr) + pte1_offset; - else - *addr = pte1_roundup(*addr) + pte1_offset; -} - -void -pmap_activate(struct thread *td) -{ - pmap_t pmap, oldpmap; - u_int cpuid, ttb; - - PDEBUG(9, printf("%s: td = %08x\n", __func__, (uint32_t)td)); - - critical_enter(); - pmap = vmspace_pmap(td->td_proc->p_vmspace); - oldpmap = PCPU_GET(curpmap); - cpuid = PCPU_GET(cpuid); - -#if defined(SMP) - CPU_CLR_ATOMIC(cpuid, &oldpmap->pm_active); - CPU_SET_ATOMIC(cpuid, &pmap->pm_active); -#else - CPU_CLR(cpuid, &oldpmap->pm_active); - CPU_SET(cpuid, &pmap->pm_active); -#endif - - ttb = pmap_ttb_get(pmap); - - /* - * pmap_activate is for the current thread on the current cpu - */ - td->td_pcb->pcb_pagedir = ttb; - cp15_ttbr_set(ttb); - PCPU_SET(curpmap, pmap); - critical_exit(); -} - -/* - * Perform the pmap work for mincore. - */ -int -pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa) -{ - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, pte2; - vm_paddr_t pa; - boolean_t managed; - int val; - - PMAP_LOCK(pmap); -retry: - pte1p = pmap_pte1(pmap, addr); - pte1 = pte1_load(pte1p); - if (pte1_is_section(pte1)) { - pa = trunc_page(pte1_pa(pte1) | (addr & PTE1_OFFSET)); - managed = pte1_is_managed(pte1); - val = MINCORE_SUPER | MINCORE_INCORE; - if (pte1_is_dirty(pte1)) - val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; - if (pte1 & PTE1_A) - val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; - } else if (pte1_is_link(pte1)) { - pte2p = pmap_pte2(pmap, addr); - pte2 = pte2_load(pte2p); - pmap_pte2_release(pte2p); - pa = pte2_pa(pte2); - managed = pte2_is_managed(pte2); - val = MINCORE_INCORE; - if (pte2_is_dirty(pte2)) - val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; - if (pte2 & PTE2_A) - val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; - } else { - managed = FALSE; - val = 0; - } - 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 - PA_UNLOCK_COND(*locked_pa); - PMAP_UNLOCK(pmap); - return (val); -} - -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_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEVICE); - va += PAGE_SIZE; - pa += PAGE_SIZE; - size -= PAGE_SIZE; - } - tlb_flush_range(sva, va - sva); -} - -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; - } - tlb_flush_range(sva, va - sva); -} - -void -pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb) -{ - - pcb->pcb_pagedir = pmap_ttb_get(pmap); -} - - -/* - * Clean L1 data cache range by physical address. - * 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) -{ - struct sysmaps *sysmaps; - - KASSERT(((pa & PAGE_MASK) + size) <= PAGE_SIZE, - ("%s: not on single page", __func__)); - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - if (*sysmaps->CMAP3) - panic("%s: CMAP3 busy", __func__); - pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); - dcache_wb_pou((vm_offset_t)sysmaps->CADDR3 + (pa & PAGE_MASK), size); - pte2_clear(sysmaps->CMAP3); - tlb_flush((vm_offset_t)sysmaps->CADDR3); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -/* - * Sync instruction cache range which is not mapped yet. - */ -void -cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - uint32_t len, offset; - vm_page_t m; - - /* Write back d-cache on given address range. */ - offset = pa & PAGE_MASK; - for ( ; size != 0; size -= len, pa += len, offset = 0) { - len = min(PAGE_SIZE - offset, 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); - } - /* - * I-cache is VIPT. Only way how to flush all virtual mappings - * on given physical address is to invalidate all i-cache. - */ - icache_inv_all(); -} - -void -pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size) -{ - - /* Write back d-cache on given address range. */ - if (va >= VM_MIN_KERNEL_ADDRESS) { - dcache_wb_pou(va, size); - } else { - uint32_t len, offset; - vm_paddr_t pa; - vm_page_t m; - - offset = va & PAGE_MASK; - for ( ; size != 0; size -= len, va += len, offset = 0) { - pa = pmap_extract(pmap, va); /* offset is preserved */ - len = min(PAGE_SIZE - offset, 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); - } - } - /* - * I-cache is VIPT. Only way how to flush all virtual mappings - * on given physical address is to invalidate all i-cache. - */ - icache_inv_all(); -} - -/* - * The implementation of pmap_fault() uses IN_RANGE2() macro which - * depends on the fact that given range size is a power of 2. - */ -CTASSERT(powerof2(NB_IN_PT1)); -CTASSERT(powerof2(PT2MAP_SIZE)); - -#define IN_RANGE2(addr, start, size) \ - ((vm_offset_t)(start) == ((vm_offset_t)(addr) & ~((size) - 1))) - -/* - * Handle access and R/W emulation faults. - */ -int -pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode) -{ - pt1_entry_t *pte1p, pte1; - pt2_entry_t *pte2p, pte2; - - if (pmap == NULL) - pmap = kernel_pmap; - - /* - * In kernel, we should never get abort with FAR which is in range of - * pmap->pm_pt1 or PT2MAP address spaces. If it happens, stop here - * and print out a useful abort message and even get to the debugger - * otherwise it likely ends with never ending loop of aborts. - */ - if (__predict_false(IN_RANGE2(far, pmap->pm_pt1, NB_IN_PT1))) { - /* - * All L1 tables should always be mapped and present. - * However, we check only current one herein. For user mode, - * only permission abort from malicious user is not fatal. - * And alignment abort as it may have higher priority. - */ - if (!usermode || (idx != FAULT_ALIGN && idx != FAULT_PERM_L2)) { - CTR4(KTR_PMAP, "%s: pmap %#x pm_pt1 %#x far %#x", - __func__, pmap, pmap->pm_pt1, far); - panic("%s: pm_pt1 abort", __func__); - } - return (KERN_INVALID_ADDRESS); - } - if (__predict_false(IN_RANGE2(far, PT2MAP, PT2MAP_SIZE))) { - /* - * PT2MAP should be always mapped and present in current - * L1 table. However, only existing L2 tables are mapped - * in PT2MAP. For user mode, only L2 translation abort and - * permission abort from malicious user is not fatal. - * And alignment abort as it may have higher priority. - */ - if (!usermode || (idx != FAULT_ALIGN && - idx != FAULT_TRAN_L2 && idx != FAULT_PERM_L2)) { - CTR4(KTR_PMAP, "%s: pmap %#x PT2MAP %#x far %#x", - __func__, pmap, PT2MAP, far); - panic("%s: PT2MAP abort", __func__); - } - return (KERN_INVALID_ADDRESS); - } - - /* - * Accesss bits for page and section. Note that the entry - * is not in TLB yet, so TLB flush is not necessary. - * - * QQQ: This is hardware emulation, we do not call userret() - * for aborts from user mode. - * We do not lock PMAP, so cmpset() is a need. Hopefully, - * no one removes the mapping when we are here. - */ - if (idx == FAULT_ACCESS_L2) { - pte2p = pt2map_entry(far); -pte2_seta: - pte2 = pte2_load(pte2p); - if (pte2_is_valid(pte2)) { - if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_A)) { - goto pte2_seta; - } - return (KERN_SUCCESS); - } - } - if (idx == FAULT_ACCESS_L1) { - pte1p = pmap_pte1(pmap, far); -pte1_seta: - pte1 = pte1_load(pte1p); - if (pte1_is_section(pte1)) { - if (!pte1_cmpset(pte1p, pte1, pte1 | PTE1_A)) { - goto pte1_seta; - } - return (KERN_SUCCESS); - } - } - - /* - * Handle modify bits for page and section. Note that the modify - * bit is emulated by software. So PTEx_RO is software read only - * bit and PTEx_NM flag is real hardware read only bit. - * - * QQQ: This is hardware emulation, we do not call userret() - * for aborts from user mode. - * We do not lock PMAP, so cmpset() is a need. Hopefully, - * no one removes the mapping when we are here. - */ - if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L2)) { - pte2p = pt2map_entry(far); -pte2_setrw: - pte2 = pte2_load(pte2p); - if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) && - (pte2 & PTE2_NM)) { - if (!pte2_cmpset(pte2p, pte2, pte2 & ~PTE2_NM)) { - goto pte2_setrw; - } - tlb_flush(trunc_page(far)); - return (KERN_SUCCESS); - } - } - if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L1)) { - pte1p = pmap_pte1(pmap, far); -pte1_setrw: - pte1 = pte1_load(pte1p); - if (pte1_is_section(pte1) && !(pte1 & PTE1_RO) && - (pte1 & PTE1_NM)) { - if (!pte1_cmpset(pte1p, pte1, pte1 & ~PTE1_NM)) { - goto pte1_setrw; - } - tlb_flush(pte1_trunc(far)); - return (KERN_SUCCESS); - } - } - - /* - * QQQ: The previous code, mainly fast handling of access and - * modify bits aborts, could be moved to ASM. Now we are - * starting to deal with not fast aborts. - */ - -#ifdef INVARIANTS - /* - * Read an entry in PT2TAB associated with both pmap and far. - * It's safe because PT2TAB is always mapped. - * - * QQQ: We do not lock PMAP, so false positives could happen if - * the mapping is removed concurrently. - */ - pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far)); - if (pte2_is_valid(pte2)) { - /* - * Now, when we know that L2 page table is allocated, - * we can use PT2MAP to get L2 page table entry. - */ - pte2 = pte2_load(pt2map_entry(far)); - if (pte2_is_valid(pte2)) { - /* - * If L2 page table entry is valid, make sure that - * L1 page table entry is valid too. Note that we - * leave L2 page entries untouched when promoted. - */ - pte1 = pte1_load(pmap_pte1(pmap, far)); - if (!pte1_is_valid(pte1)) { - panic("%s: missing L1 page entry (%p, %#x)", - __func__, pmap, far); - } - } - } -#endif - return (KERN_FAILURE); -} - -/* !!!! REMOVE !!!! */ -void -pmap_pte_init_mmu_v6(void) -{ -} - -void vector_page_setprot(int p) -{ -} - -#if defined(PMAP_DEBUG) -/* - * Reusing of KVA used in pmap_zero_page function !!! - */ -static void -pmap_zero_page_check(vm_page_t m) -{ - uint32_t *p, *end; - struct sysmaps *sysmaps; - - sched_pin(); - sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; - mtx_lock(&sysmaps->lock); - 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)); - end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE); - for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++) - if (*p != 0) - panic("%s: page %p not zero, va: %p", __func__, m, - sysmaps->CADDR2); - pte2_clear(sysmaps->CMAP2); - tlb_flush((vm_offset_t)sysmaps->CADDR2); - sched_unpin(); - mtx_unlock(&sysmaps->lock); -} - -int -pmap_pid_dump(int pid) -{ - pmap_t pmap; - struct proc *p; - int npte2 = 0; - int i, j, index; - - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { - if (p->p_pid != pid || p->p_vmspace == NULL) - continue; - index = 0; - pmap = vmspace_pmap(p->p_vmspace); - for (i = 0; i < NPTE1_IN_PT1; i++) { - pt1_entry_t pte1; - pt2_entry_t *pte2p, pte2; - vm_offset_t base, va; - vm_paddr_t pa; - vm_page_t m; - - base = i << PTE1_SHIFT; - pte1 = pte1_load(&pmap->pm_pt1[i]); - - if (pte1_is_section(pte1)) { - /* - * QQQ: Do something here! - */ - } else if (pte1_is_link(pte1)) { - for (j = 0; j < NPTE2_IN_PT2; j++) { - va = base + (j << PAGE_SHIFT); - if (va >= VM_MIN_KERNEL_ADDRESS) { - if (index) { - index = 0; - printf("\n"); - } - sx_sunlock(&allproc_lock); - return (npte2); - } - pte2p = pmap_pte2(pmap, va); - pte2 = pte2_load(pte2p); - pmap_pte2_release(pte2p); - if (!pte2_is_valid(pte2)) - continue; - - pa = pte2_pa(pte2); - m = PHYS_TO_VM_PAGE(pa); - printf("va: 0x%x, pa: 0x%x, h: %d, w:" - " %d, f: 0x%x", va, pa, - m->hold_count, m->wire_count, - m->flags); - npte2++; - index++; - if (index >= 2) { - index = 0; - printf("\n"); - } else { - printf(" "); - } - } - } - } - } - sx_sunlock(&allproc_lock); - return (npte2); -} - -#endif - -#ifdef DDB -static pt2_entry_t * -pmap_pte2_ddb(pmap_t pmap, vm_offset_t va) -{ - pt1_entry_t pte1; - vm_paddr_t pt2pg_pa; - - pte1 = pte1_load(pmap_pte1(pmap, va)); - if (!pte1_is_link(pte1)) - return (NULL); - - if (pmap_is_current(pmap)) - return (pt2map_entry(va)); - - /* Note that L2 page table size is not equal to PAGE_SIZE. */ - pt2pg_pa = trunc_page(pte1_link_pa(pte1)); - if (pte2_pa(pte2_load(PMAP3)) != pt2pg_pa) { - pte2_store(PMAP3, PTE2_KPT(pt2pg_pa)); -#ifdef SMP - PMAP3cpu = PCPU_GET(cpuid); -#endif - tlb_flush_local((vm_offset_t)PADDR3); - } -#ifdef SMP - else if (PMAP3cpu != PCPU_GET(cpuid)) { - PMAP3cpu = PCPU_GET(cpuid); - tlb_flush_local((vm_offset_t)PADDR3); - } -#endif - return (PADDR3 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); -} - -static void -dump_pmap(pmap_t pmap) -{ - - printf("pmap %p\n", pmap); - printf(" pm_pt1: %p\n", pmap->pm_pt1); - printf(" pm_pt2tab: %p\n", pmap->pm_pt2tab); - printf(" pm_active: 0x%08lX\n", pmap->pm_active.__bits[0]); -} - -DB_SHOW_COMMAND(pmaps, pmap_list_pmaps) -{ - - pmap_t pmap; - LIST_FOREACH(pmap, &allpmaps, pm_list) { - dump_pmap(pmap); - } -} - -static int -pte2_class(pt2_entry_t pte2) -{ - int cls; - - cls = (pte2 >> 2) & 0x03; - cls |= (pte2 >> 4) & 0x04; - return (cls); -} - -static void -dump_section(pmap_t pmap, uint32_t pte1_idx) -{ -} - -static void -dump_link(pmap_t pmap, uint32_t pte1_idx, boolean_t invalid_ok) -{ - uint32_t i; - vm_offset_t va; - pt2_entry_t *pte2p, pte2; - vm_page_t m; - - va = pte1_idx << PTE1_SHIFT; - pte2p = pmap_pte2_ddb(pmap, va); - for (i = 0; i < NPTE2_IN_PT2; i++, pte2p++, va += PAGE_SIZE) { - pte2 = pte2_load(pte2p); - if (pte2 == 0) - continue; - if (!pte2_is_valid(pte2)) { - printf(" 0x%08X: 0x%08X", va, pte2); - if (!invalid_ok) - printf(" - not valid !!!"); - printf("\n"); - continue; - } - m = PHYS_TO_VM_PAGE(pte2_pa(pte2)); - printf(" 0x%08X: 0x%08X, TEX%d, s:%d, g:%d, m:%p", va , pte2, - pte2_class(pte2), !!(pte2 & PTE2_S), !(pte2 & PTE2_NG), m); - if (m != NULL) { - printf(" v:%d h:%d w:%d f:0x%04X\n", m->valid, - m->hold_count, m->wire_count, m->flags); - } else { - printf("\n"); - } - } -} - -static __inline boolean_t -is_pv_chunk_space(vm_offset_t va) -{ - - if ((((vm_offset_t)pv_chunkbase) <= va) && - (va < ((vm_offset_t)pv_chunkbase + PAGE_SIZE * pv_maxchunks))) - return (TRUE); - return (FALSE); -} - -DB_SHOW_COMMAND(pmap, pmap_pmap_print) -{ - /* XXX convert args. */ - pmap_t pmap = (pmap_t)addr; - pt1_entry_t pte1; - pt2_entry_t pte2; - vm_offset_t va, eva; - vm_page_t m; - uint32_t i; - boolean_t invalid_ok, dump_link_ok, dump_pv_chunk; - - if (have_addr) { - pmap_t pm; - - LIST_FOREACH(pm, &allpmaps, pm_list) - if (pm == pmap) break; - if (pm == NULL) { - printf("given pmap %p is not in allpmaps list\n", pmap); - return; - } - } else - pmap = PCPU_GET(curpmap); - - eva = (modif[0] == 'u') ? VM_MAXUSER_ADDRESS : 0xFFFFFFFF; - dump_pv_chunk = FALSE; /* XXX evaluate from modif[] */ - - printf("pmap: 0x%08X\n", (uint32_t)pmap); - printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP); - printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab); - - for(i = 0; i < NPTE1_IN_PT1; i++) { - pte1 = pte1_load(&pmap->pm_pt1[i]); - if (pte1 == 0) - continue; - va = i << PTE1_SHIFT; - if (va >= eva) - break; - - if (pte1_is_section(pte1)) { - printf("0x%08X: Section 0x%08X, s:%d g:%d\n", va, pte1, - !!(pte1 & PTE1_S), !(pte1 & PTE1_NG)); - dump_section(pmap, i); - } else if (pte1_is_link(pte1)) { - dump_link_ok = TRUE; - invalid_ok = FALSE; - pte2 = pte2_load(pmap_pt2tab_entry(pmap, va)); - m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); - printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X m: %p", - va, pte1, pte2, m); - if (is_pv_chunk_space(va)) { - printf(" - pv_chunk space"); - if (dump_pv_chunk) - invalid_ok = TRUE; - else - dump_link_ok = FALSE; - } - else if (m != NULL) - printf(" w:%d w2:%u", m->wire_count, - pt2_wirecount_get(m, pte1_index(va))); - if (pte2 == 0) - printf(" !!! pt2tab entry is ZERO"); - else if (pte2_pa(pte1) != pte2_pa(pte2)) - printf(" !!! pt2tab entry is DIFFERENT - m: %p", - PHYS_TO_VM_PAGE(pte2_pa(pte2))); - printf("\n"); - if (dump_link_ok) - dump_link(pmap, i, invalid_ok); - } else - printf("0x%08X: Invalid entry 0x%08X\n", va, pte1); - } -} - -static void -dump_pt2tab(pmap_t pmap) -{ - uint32_t i; - pt2_entry_t pte2; - vm_offset_t va; - vm_paddr_t pa; - vm_page_t m; - - printf("PT2TAB:\n"); - for (i = 0; i < PT2TAB_ENTRIES; i++) { - pte2 = pte2_load(&pmap->pm_pt2tab[i]); - if (!pte2_is_valid(pte2)) - continue; - va = i << PT2TAB_SHIFT; - pa = pte2_pa(pte2); - m = PHYS_TO_VM_PAGE(pa); - printf(" 0x%08X: 0x%08X, TEX%d, s:%d, m:%p", va, pte2, - pte2_class(pte2), !!(pte2 & PTE2_S), m); - if (m != NULL) - printf(" , h: %d, w: %d, f: 0x%04X pidx: %lld", - m->hold_count, m->wire_count, m->flags, m->pindex); - printf("\n"); - } -} - -DB_SHOW_COMMAND(pmap_pt2tab, pmap_pt2tab_print) -{ - /* XXX convert args. */ - pmap_t pmap = (pmap_t)addr; - pt1_entry_t pte1; - pt2_entry_t pte2; - vm_offset_t va; - uint32_t i, start; - - if (have_addr) { - printf("supported only on current pmap\n"); - return; - } - - pmap = PCPU_GET(curpmap); - printf("curpmap: 0x%08X\n", (uint32_t)pmap); - printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP); - printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab); - - start = pte1_index((vm_offset_t)PT2MAP); - for (i = start; i < (start + NPT2_IN_PT2TAB); i++) { - pte1 = pte1_load(&pmap->pm_pt1[i]); - if (pte1 == 0) - continue; - va = i << PTE1_SHIFT; - if (pte1_is_section(pte1)) { - printf("0x%08X: Section 0x%08X, s:%d\n", va, pte1, - !!(pte1 & PTE1_S)); - dump_section(pmap, i); - } else if (pte1_is_link(pte1)) { - pte2 = pte2_load(pmap_pt2tab_entry(pmap, va)); - printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X\n", va, - pte1, pte2); - if (pte2 == 0) - printf(" !!! pt2tab entry is ZERO\n"); - } else - printf("0x%08X: Invalid entry 0x%08X\n", va, pte1); - } - dump_pt2tab(pmap); -} -#endif diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 5d7021189ed7..525280c6d822 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -1,11 +1,15 @@ -/* 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. + * Copyright (c) 1991 Regents of the University of California. + * Copyright (c) 1994 John S. Dyson + * Copyright (c) 1994 David Greenman + * Copyright (c) 2005-2010 Alan L. Cox + * Copyright (c) 2014-2016 Svatopluk Kraus + * Copyright (c) 2014-2016 Michal Meloun * All rights reserved. * - * Written by Steve C. Woodford for Wasabi Systems, Inc. + * 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -15,158 +19,114 @@ * 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. + * 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 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. + * 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: FreeBSD: src/sys/arm/arm/pmap.c,v 1.113 2009/07/24 13:50:29 + * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 */ - /*- - * Copyright (c) 2002-2003 Wasabi Systems, Inc. - * Copyright (c) 2001 Richard Earnshaw - * Copyright (c) 2001-2002 Christopher Gilbert + * 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. - * 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) + * 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. */ -/*- - * 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$"); + +/* + * 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 "opt_vm.h" +#include "opt_pmap.h" +#include "opt_ddb.h" + #include #include #include #include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include #include #include +#ifdef SMP +#include +#else +#include +#endif + +#ifdef DDB +#include +#endif + +#include +#include #include -#include #include #include +#include #include #include #include @@ -175,270 +135,2563 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include +#include #include -#include #include +#include +#ifdef SMP +#include +#endif -#ifdef DEBUG -extern int last_fault_code; +#ifndef PMAP_SHPGPERPROC +#define PMAP_SHPGPERPROC 200 +#endif + +#ifndef DIAGNOSTIC +#define PMAP_INLINE __inline +#else +#define PMAP_INLINE #endif #ifdef PMAP_DEBUG -#define PDEBUG(_lev_,_stat_) \ - if (pmap_debug_level >= (_lev_)) \ - ((_stat_)) -#define dprintf printf +static void pmap_zero_page_check(vm_page_t m); +void pmap_debug(int level); +int pmap_pid_dump(int pid); -int pmap_debug_level = 0; -#define PMAP_INLINE +#define PDEBUG(_lev_,_stat_) \ + if (pmap_debug_level >= (_lev_)) \ + ((_stat_)) +#define dprintf printf +int pmap_debug_level = 1; #else /* PMAP_DEBUG */ #define PDEBUG(_lev_,_stat_) /* Nothing */ #define dprintf(x, arg...) -#define PMAP_INLINE __inline #endif /* PMAP_DEBUG */ +/* + * Level 2 page tables map definion ('max' is excluded). + */ + +#define PT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP) +#define PT2V_MAX_ADDRESS ((vm_offset_t)PT2MAP + PT2MAP_SIZE) + +#define UPT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP) +#define UPT2V_MAX_ADDRESS \ + ((vm_offset_t)(PT2MAP + (KERNBASE >> PT2MAP_SHIFT))) + +/* + * Promotion to a 1MB (PTE1) page mapping requires that the corresponding + * 4KB (PTE2) page mappings have identical settings for the following fields: + */ +#define PTE2_PROMOTE (PTE2_V | PTE2_A | PTE2_NM | PTE2_S | PTE2_NG | \ + PTE2_NX | PTE2_RO | PTE2_U | PTE2_W | \ + PTE2_ATTR_MASK) + +#define PTE1_PROMOTE (PTE1_V | PTE1_A | PTE1_NM | PTE1_S | PTE1_NG | \ + PTE1_NX | PTE1_RO | PTE1_U | PTE1_W | \ + PTE1_ATTR_MASK) + +#define ATTR_TO_L1(l2_attr) ((((l2_attr) & L2_TEX0) ? L1_S_TEX0 : 0) | \ + (((l2_attr) & L2_C) ? L1_S_C : 0) | \ + (((l2_attr) & L2_B) ? L1_S_B : 0) | \ + (((l2_attr) & PTE2_A) ? PTE1_A : 0) | \ + (((l2_attr) & PTE2_NM) ? PTE1_NM : 0) | \ + (((l2_attr) & PTE2_S) ? PTE1_S : 0) | \ + (((l2_attr) & PTE2_NG) ? PTE1_NG : 0) | \ + (((l2_attr) & PTE2_NX) ? PTE1_NX : 0) | \ + (((l2_attr) & PTE2_RO) ? PTE1_RO : 0) | \ + (((l2_attr) & PTE2_U) ? PTE1_U : 0) | \ + (((l2_attr) & PTE2_W) ? PTE1_W : 0)) + +#define ATTR_TO_L2(l1_attr) ((((l1_attr) & L1_S_TEX0) ? L2_TEX0 : 0) | \ + (((l1_attr) & L1_S_C) ? L2_C : 0) | \ + (((l1_attr) & L1_S_B) ? L2_B : 0) | \ + (((l1_attr) & PTE1_A) ? PTE2_A : 0) | \ + (((l1_attr) & PTE1_NM) ? PTE2_NM : 0) | \ + (((l1_attr) & PTE1_S) ? PTE2_S : 0) | \ + (((l1_attr) & PTE1_NG) ? PTE2_NG : 0) | \ + (((l1_attr) & PTE1_NX) ? PTE2_NX : 0) | \ + (((l1_attr) & PTE1_RO) ? PTE2_RO : 0) | \ + (((l1_attr) & PTE1_U) ? PTE2_U : 0) | \ + (((l1_attr) & PTE1_W) ? PTE2_W : 0)) + +/* + * PTE2 descriptors creation macros. + */ +#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_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_ATTR_DEFAULT) +#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_DEFAULT) + +#define PV_STATS #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 + * The boot_pt1 is used temporary in very early boot stage as L1 page table. + * We can init many things with no memory allocation thanks to its static + * allocation and this brings two main advantages: + * (1) other cores can be started very simply, + * (2) various boot loaders can be supported as its arguments can be processed + * in virtual address space and can be moved to safe location before + * first allocation happened. + * Only disadvantage is that boot_pt1 is used only in very early boot stage. + * However, the table is uninitialized and so lays in bss. Therefore kernel + * image size is not influenced. + * + * QQQ: In the future, maybe, boot_pt1 can be used for soft reset and + * CPU suspend/resume game. */ +extern pt1_entry_t boot_pt1[]; -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); +vm_paddr_t base_pt1; +pt1_entry_t *kern_pt1; +pt2_entry_t *kern_pt2tab; +pt2_entry_t *PT2MAP; -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 uint32_t ttb_flags; +static vm_memattr_t pt_memattr; +ttb_entry_t pmap_kern_ttb; -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"); +struct pmap kernel_pmap_store; +LIST_HEAD(pmaplist, pmap); +static struct pmaplist allpmaps; +static struct mtx allpmaps_lock; 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; + +static vm_offset_t kernel_vm_end_new; +vm_offset_t kernel_vm_end = KERNBASE + NKPT2PG * NPT2_IN_PG * PTE1_SIZE; +vm_offset_t vm_max_kernel_address; vm_paddr_t kernel_l1pa; -vm_offset_t kernel_vm_end = 0; - -vm_offset_t vm_max_kernel_address; - -struct pmap kernel_pmap_store; +static struct rwlock __aligned(CACHE_LINE_SIZE) pvh_global_lock; /* - * 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 + * 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 pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; +static struct md_page *pv_table; /* XXX: Is it used only the list in md_page? */ 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 */ +vm_offset_t pv_vafree; /* freelist stored in the PTE */ + +vm_paddr_t first_managed_pa; +#define pa_to_pvh(pa) (&pv_table[pte1_index(pa - first_managed_pa)]) + +/* + * All those kernel PT submaps that BSD is so fond of + */ +struct sysmaps { + struct mtx lock; + pt2_entry_t *CMAP1; + pt2_entry_t *CMAP2; + pt2_entry_t *CMAP3; + caddr_t CADDR1; + caddr_t CADDR2; + caddr_t CADDR3; +}; +static struct sysmaps sysmaps_pcpu[MAXCPU]; +static pt2_entry_t *CMAP3; +static caddr_t CADDR3; +caddr_t _tmppt = 0; + +struct msgbuf *msgbufp = 0; /* XXX move it to machdep.c */ + +/* + * Crashdump maps. + */ +static caddr_t crashdumpmap; + +static pt2_entry_t *PMAP1 = 0, *PMAP2; +static pt2_entry_t *PADDR1 = 0, *PADDR2; +#ifdef DDB +static pt2_entry_t *PMAP3; +static pt2_entry_t *PADDR3; +static int PMAP3cpu __unused; /* for SMP only */ +#endif +#ifdef SMP +static int PMAP1cpu; +static int PMAP1changedcpu; +SYSCTL_INT(_debug, OID_AUTO, PMAP1changedcpu, CTLFLAG_RD, + &PMAP1changedcpu, 0, + "Number of times pmap_pte2_quick changed CPU with same PMAP1"); +#endif +static int PMAP1changed; +SYSCTL_INT(_debug, OID_AUTO, PMAP1changed, CTLFLAG_RD, + &PMAP1changed, 0, + "Number of times pmap_pte2_quick changed PMAP1"); +static int PMAP1unchanged; +SYSCTL_INT(_debug, OID_AUTO, PMAP1unchanged, CTLFLAG_RD, + &PMAP1unchanged, 0, + "Number of times pmap_pte2_quick didn't change PMAP1"); +static struct mtx PMAP2mutex; + +static __inline void pt2_wirecount_init(vm_page_t m); +static boolean_t pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, + vm_offset_t va); +void cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size); + +/* + * 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 */ + +/* + * This table must corespond with memory attribute configuration in vm.h. + * First entry is used for normal system mapping. + * + * Device memory is always marked as shared. + * Normal memory is shared only in SMP . + * Not outer shareable bits are not used yet. + * Class 6 cannot be used on ARM11. + */ +#define TEXDEF_TYPE_SHIFT 0 +#define TEXDEF_TYPE_MASK 0x3 +#define TEXDEF_INNER_SHIFT 2 +#define TEXDEF_INNER_MASK 0x3 +#define TEXDEF_OUTER_SHIFT 4 +#define TEXDEF_OUTER_MASK 0x3 +#define TEXDEF_NOS_SHIFT 6 +#define TEXDEF_NOS_MASK 0x1 + +#define TEX(t, i, o, s) \ + ((t) << TEXDEF_TYPE_SHIFT) | \ + ((i) << TEXDEF_INNER_SHIFT) | \ + ((o) << TEXDEF_OUTER_SHIFT | \ + ((s) << TEXDEF_NOS_SHIFT)) + +static uint32_t tex_class[8] = { +/* type inner cache outer cache */ + TEX(PRRR_MEM, NMRR_WB_WA, NMRR_WB_WA, 0), /* 0 - ATTR_WB_WA */ + TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 1 - ATTR_NOCACHE */ + TEX(PRRR_DEV, NMRR_NC, NMRR_NC, 0), /* 2 - ATTR_DEVICE */ + TEX(PRRR_SO, NMRR_NC, NMRR_NC, 0), /* 3 - ATTR_SO */ + TEX(PRRR_MEM, NMRR_WT, NMRR_WT, 0), /* 4 - ATTR_WT */ + TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 5 - NOT USED YET */ + TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 6 - NOT USED YET */ + TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 7 - NOT USED YET */ +}; +#undef TEX + +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 */ + 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 +vm_memattr_to_pte2(vm_memattr_t 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 +vm_page_pte2_attr(vm_page_t m) +{ + + return (vm_memattr_to_pte2(m->md.pat_mode)); +} + +/* + * Convert TEX definition entry to TTB flags. + */ +static uint32_t +encode_ttb_flags(int idx) +{ + uint32_t inner, outer, nos, reg; + + inner = (tex_class[idx] >> TEXDEF_INNER_SHIFT) & + TEXDEF_INNER_MASK; + outer = (tex_class[idx] >> TEXDEF_OUTER_SHIFT) & + TEXDEF_OUTER_MASK; + nos = (tex_class[idx] >> TEXDEF_NOS_SHIFT) & + TEXDEF_NOS_MASK; + + reg = nos << 5; + reg |= outer << 3; + if (cpuinfo.coherent_walk) + reg |= (inner & 0x1) << 6; + reg |= (inner & 0x2) >> 1; +#ifdef SMP + reg |= 1 << 1; +#endif + return reg; +} + +/* + * Set TEX remapping registers in current CPU. + */ +void +pmap_set_tex(void) +{ + uint32_t prrr, nmrr; + uint32_t type, inner, outer, nos; + int i; + +#ifdef PMAP_PTE_NOCACHE + /* XXX fixme */ + if (cpuinfo.coherent_walk) { + pt_memattr = VM_MEMATTR_WB_WA; + ttb_flags = encode_ttb_flags(0); + } + else { + pt_memattr = VM_MEMATTR_NOCACHE; + ttb_flags = encode_ttb_flags(1); + } +#else + pt_memattr = VM_MEMATTR_WB_WA; + ttb_flags = encode_ttb_flags(0); +#endif + + prrr = 0; + nmrr = 0; + + /* Build remapping register from TEX classes. */ + for (i = 0; i < 8; i++) { + type = (tex_class[i] >> TEXDEF_TYPE_SHIFT) & + TEXDEF_TYPE_MASK; + inner = (tex_class[i] >> TEXDEF_INNER_SHIFT) & + TEXDEF_INNER_MASK; + outer = (tex_class[i] >> TEXDEF_OUTER_SHIFT) & + TEXDEF_OUTER_MASK; + nos = (tex_class[i] >> TEXDEF_NOS_SHIFT) & + TEXDEF_NOS_MASK; + + prrr |= type << (i * 2); + prrr |= nos << (i + 24); + nmrr |= inner << (i * 2); + nmrr |= outer << (i * 2 + 16); + } + /* Add shareable bits for device memory. */ + prrr |= PRRR_DS0 | PRRR_DS1; + + /* Add shareable bits for normal memory in SMP case. */ +#ifdef SMP + prrr |= PRRR_NS1; +#endif + cp15_prrr_set(prrr); + cp15_nmrr_set(nmrr); + + /* Caches are disabled, so full TLB flush should be enough. */ + tlb_flush_all_local(); +} + +/* + * KERNBASE must be multiple of NPT2_IN_PG * PTE1_SIZE. In other words, + * KERNBASE is mapped by first L2 page table in L2 page table page. It + * meets same constrain due to PT2MAP being placed just under KERNBASE. + */ +CTASSERT((KERNBASE & (NPT2_IN_PG * PTE1_SIZE - 1)) == 0); +CTASSERT((KERNBASE - VM_MAXUSER_ADDRESS) >= PT2MAP_SIZE); + +/* + * In crazy dreams, PAGE_SIZE could be a multiple of PTE2_SIZE in general. + * For now, anyhow, the following check must be fulfilled. + */ +CTASSERT(PAGE_SIZE == PTE2_SIZE); +/* + * We don't want to mess up MI code with all MMU and PMAP definitions, + * so some things, which depend on other ones, are defined independently. + * Now, it is time to check that we don't screw up something. + */ +CTASSERT(PDRSHIFT == PTE1_SHIFT); +/* + * Check L1 and L2 page table entries definitions consistency. + */ +CTASSERT(NB_IN_PT1 == (sizeof(pt1_entry_t) * NPTE1_IN_PT1)); +CTASSERT(NB_IN_PT2 == (sizeof(pt2_entry_t) * NPTE2_IN_PT2)); +/* + * Check L2 page tables page consistency. + */ +CTASSERT(PAGE_SIZE == (NPT2_IN_PG * NB_IN_PT2)); +CTASSERT((1 << PT2PG_SHIFT) == NPT2_IN_PG); +/* + * Check PT2TAB consistency. + * PT2TAB_ENTRIES is defined as a division of NPTE1_IN_PT1 by NPT2_IN_PG. + * This should be done without remainder. + */ +CTASSERT(NPTE1_IN_PT1 == (PT2TAB_ENTRIES * NPT2_IN_PG)); + +/* + * A PT2MAP magic. + * + * All level 2 page tables (PT2s) are mapped continuously and accordingly + * into PT2MAP address space. As PT2 size is less than PAGE_SIZE, this can + * be done only if PAGE_SIZE is a multiple of PT2 size. All PT2s in one page + * must be used together, but not necessary at once. The first PT2 in a page + * must map things on correctly aligned address and the others must follow + * in right order. + */ +#define NB_IN_PT2TAB (PT2TAB_ENTRIES * sizeof(pt2_entry_t)) +#define NPT2_IN_PT2TAB (NB_IN_PT2TAB / NB_IN_PT2) +#define NPG_IN_PT2TAB (NB_IN_PT2TAB / PAGE_SIZE) + +/* + * Check PT2TAB consistency. + * NPT2_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by NB_IN_PT2. + * NPG_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by PAGE_SIZE. + * The both should be done without remainder. + */ +CTASSERT(NB_IN_PT2TAB == (NPT2_IN_PT2TAB * NB_IN_PT2)); +CTASSERT(NB_IN_PT2TAB == (NPG_IN_PT2TAB * PAGE_SIZE)); +/* + * The implementation was made general, however, with the assumption + * bellow in mind. In case of another value of NPG_IN_PT2TAB, + * the code should be once more rechecked. + */ +CTASSERT(NPG_IN_PT2TAB == 1); + +/* + * Get offset of PT2 in a page + * associated with given PT1 index. + */ +static __inline u_int +page_pt2off(u_int pt1_idx) +{ + + return ((pt1_idx & PT2PG_MASK) * NB_IN_PT2); +} + +/* + * Get physical address of PT2 + * associated with given PT2s page and PT1 index. + */ +static __inline vm_paddr_t +page_pt2pa(vm_paddr_t pgpa, u_int pt1_idx) +{ + + return (pgpa + page_pt2off(pt1_idx)); +} + +/* + * Get first entry of PT2 + * associated with given PT2s page and PT1 index. + */ +static __inline pt2_entry_t * +page_pt2(vm_offset_t pgva, u_int pt1_idx) +{ + + return ((pt2_entry_t *)(pgva + page_pt2off(pt1_idx))); +} + +/* + * Get virtual address of PT2s page (mapped in PT2MAP) + * which holds PT2 which holds entry which maps given virtual address. + */ +static __inline vm_offset_t +pt2map_pt2pg(vm_offset_t va) +{ + + va &= ~(NPT2_IN_PG * PTE1_SIZE - 1); + return ((vm_offset_t)pt2map_entry(va)); +} + +/***************************************************************************** + * + * THREE pmap initialization milestones exist: + * + * locore.S + * -> fundamental init (including MMU) in ASM + * + * initarm() + * -> fundamental init continues in C + * -> first available physical address is known + * + * pmap_bootstrap_prepare() -> FIRST PMAP MILESTONE (first epoch begins) + * -> basic (safe) interface for physical address allocation is made + * -> basic (safe) interface for virtual mapping is made + * -> limited not SMP coherent work is possible + * + * -> more fundamental init continues in C + * -> locks and some more things are available + * -> all fundamental allocations and mappings are done + * + * pmap_bootstrap() -> SECOND PMAP MILESTONE (second epoch begins) + * -> phys_avail[] and virtual_avail is set + * -> control is passed to vm subsystem + * -> physical and virtual address allocation are off limit + * -> low level mapping functions, some SMP coherent, + * are available, which cannot be used before vm subsystem + * is being inited + * + * mi_startup() + * -> vm subsystem is being inited + * + * pmap_init() -> THIRD PMAP MILESTONE (third epoch begins) + * -> pmap is fully inited + * + *****************************************************************************/ + +/***************************************************************************** + * + * PMAP first stage initialization and utility functions + * for pre-bootstrap epoch. + * + * After pmap_bootstrap_prepare() is called, the following functions + * can be used: + * + * (1) strictly only for this stage functions for physical page allocations, + * virtual space allocations, and mappings: + * + * vm_paddr_t pmap_preboot_get_pages(u_int num); + * void pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num); + * 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, + * vm_prot_t prot, vm_memattr_t attr); + * + * (2) for all stages: + * + * vm_paddr_t pmap_kextract(vm_offset_t va); + * + * NOTE: This is not SMP coherent stage. + * + *****************************************************************************/ + +#define KERNEL_P2V(pa) \ + ((vm_offset_t)((pa) - arm_physmem_kernaddr + KERNVIRTADDR)) +#define KERNEL_V2P(va) \ + ((vm_paddr_t)((va) - KERNVIRTADDR + arm_physmem_kernaddr)) + +static vm_paddr_t last_paddr; + +/* + * Pre-bootstrap epoch page allocator. + */ +vm_paddr_t +pmap_preboot_get_pages(u_int num) +{ + vm_paddr_t ret; + + ret = last_paddr; + last_paddr += num * PAGE_SIZE; + + return (ret); +} + +/* + * The fundamental initalization of PMAP stuff. + * + * Some things already happened in locore.S and some things could happen + * before pmap_bootstrap_prepare() is called, so let's recall what is done: + * 1. Caches are disabled. + * 2. We are running on virtual addresses already with 'boot_pt1' + * as L1 page table. + * 3. So far, all virtual addresses can be converted to physical ones and + * vice versa by the following macros: + * KERNEL_P2V(pa) .... physical to virtual ones, + * KERNEL_V2P(va) .... virtual to physical ones. + * + * What is done herein: + * 1. The 'boot_pt1' is replaced by real kernel L1 page table 'kern_pt1'. + * 2. PT2MAP magic is brought to live. + * 3. Basic preboot functions for page allocations and mappings can be used. + * 4. Everything is prepared for L1 cache enabling. + * + * Variations: + * 1. To use second TTB register, so kernel and users page tables will be + * separated. This way process forking - pmap_pinit() - could be faster, + * it saves physical pages and KVA per a process, and it's simple change. + * However, it will lead, due to hardware matter, to the following: + * (a) 2G space for kernel and 2G space for users. + * (b) 1G space for kernel in low addresses and 3G for users above it. + * A question is: Is the case (b) really an option? Note that case (b) + * does save neither physical memory and KVA. + */ +void +pmap_bootstrap_prepare(vm_paddr_t last) +{ + vm_paddr_t pt2pg_pa, pt2tab_pa, pa, size; + vm_offset_t pt2pg_va; + pt1_entry_t *pte1p; + pt2_entry_t *pte2p; + u_int i; + uint32_t actlr_mask, actlr_set, l1_attr; + + /* + * Now, we are going to make real kernel mapping. Note that we are + * already running on some mapping made in locore.S and we expect + * that it's large enough to ensure nofault access to physical memory + * allocated herein before switch. + * + * As kernel image and everything needed before are and will be mapped + * by section mappings, we align last physical address to PTE1_SIZE. + */ + last_paddr = pte1_roundup(last); + + /* + * Allocate and zero page(s) for kernel L1 page table. + * + * Note that it's first allocation on space which was PTE1_SIZE + * aligned and as such base_pt1 is aligned to NB_IN_PT1 too. + */ + base_pt1 = pmap_preboot_get_pages(NPG_IN_PT1); + kern_pt1 = (pt1_entry_t *)KERNEL_P2V(base_pt1); + bzero((void*)kern_pt1, NB_IN_PT1); + pte1_sync_range(kern_pt1, NB_IN_PT1); + + /* Allocate and zero page(s) for kernel PT2TAB. */ + pt2tab_pa = pmap_preboot_get_pages(NPG_IN_PT2TAB); + kern_pt2tab = (pt2_entry_t *)KERNEL_P2V(pt2tab_pa); + bzero(kern_pt2tab, NB_IN_PT2TAB); + pte2_sync_range(kern_pt2tab, NB_IN_PT2TAB); + + /* Allocate and zero page(s) for kernel L2 page tables. */ + pt2pg_pa = pmap_preboot_get_pages(NKPT2PG); + pt2pg_va = KERNEL_P2V(pt2pg_pa); + size = NKPT2PG * PAGE_SIZE; + bzero((void*)pt2pg_va, size); + pte2_sync_range((pt2_entry_t *)pt2pg_va, size); + + /* + * Add a physical memory segment (vm_phys_seg) corresponding to the + * preallocated pages for kernel L2 page tables so that vm_page + * structures representing these pages will be created. The vm_page + * structures are required for promotion of the corresponding kernel + * virtual addresses to section mappings. + */ + vm_phys_add_seg(pt2tab_pa, pmap_preboot_get_pages(0)); + + /* + * Insert allocated L2 page table pages to PT2TAB and make + * link to all PT2s in L1 page table. See how kernel_vm_end + * is initialized. + * + * We play simple and safe. So every KVA will have underlaying + * L2 page table, even kernel image mapped by sections. + */ + pte2p = kern_pt2tab_entry(KERNBASE); + for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += PTE2_SIZE) + pt2tab_store(pte2p++, PTE2_KPT(pa)); + + pte1p = kern_pte1(KERNBASE); + for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += NB_IN_PT2) + pte1_store(pte1p++, PTE1_LINK(pa)); + + /* Make section mappings for kernel. */ + 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)); + + /* + * Get free and aligned space for PT2MAP and make L1 page table links + * to L2 page tables held in PT2TAB. + * + * Note that pages holding PT2s are stored in PT2TAB as pt2_entry_t + * descriptors and PT2TAB page(s) itself is(are) used as PT2s. Thus + * each entry in PT2TAB maps all PT2s in a page. This implies that + * virtual address of PT2MAP must be aligned to NPT2_IN_PG * PTE1_SIZE. + */ + PT2MAP = (pt2_entry_t *)(KERNBASE - PT2MAP_SIZE); + pte1p = kern_pte1((vm_offset_t)PT2MAP); + for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) { + pte1_store(pte1p++, PTE1_LINK(pa)); + } + + /* + * Store PT2TAB in PT2TAB itself, i.e. self reference mapping. + * Each pmap will hold own PT2TAB, so the mapping should be not global. + */ + pte2p = kern_pt2tab_entry((vm_offset_t)PT2MAP); + for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) { + pt2tab_store(pte2p++, PTE2_KPT_NG(pa)); + } + + /* + * Choose correct L2 page table and make mappings for allocations + * made herein which replaces temporary locore.S mappings after a while. + * Note that PT2MAP cannot be used until we switch to kern_pt1. + * + * Note, that these allocations started aligned on 1M section and + * kernel PT1 was allocated first. Making of mappings must follow + * order of physical allocations as we've used KERNEL_P2V() macro + * for virtual addresses resolution. + */ + pte2p = kern_pt2tab_entry((vm_offset_t)kern_pt1); + pt2pg_va = KERNEL_P2V(pte2_pa(pte2_load(pte2p))); + + pte2p = page_pt2(pt2pg_va, pte1_index((vm_offset_t)kern_pt1)); + + /* Make mapping for kernel L1 page table. */ + for (pa = base_pt1, i = 0; i < NPG_IN_PT1; i++, pa += PTE2_SIZE) + pte2_store(pte2p++, PTE2_KPT(pa)); + + /* Make mapping for kernel PT2TAB. */ + for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) + pte2_store(pte2p++, PTE2_KPT(pa)); + + /* Finally, switch from 'boot_pt1' to 'kern_pt1'. */ + pmap_kern_ttb = base_pt1 | ttb_flags; + cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set); + reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set); + /* + * Initialize the first available KVA. As kernel image is mapped by + * sections, we are leaving some gap behind. + */ + virtual_avail = (vm_offset_t)kern_pt2tab + NPG_IN_PT2TAB * PAGE_SIZE; +} + +/* + * Setup L2 page table page for given KVA. + * Used in pre-bootstrap epoch. + * + * Note that we have allocated NKPT2PG pages for L2 page tables in advance + * and used them for mapping KVA starting from KERNBASE. However, this is not + * enough. Vectors and devices need L2 page tables too. Note that they are + * even above VM_MAX_KERNEL_ADDRESS. + */ +static __inline vm_paddr_t +pmap_preboot_pt2pg_setup(vm_offset_t va) +{ + pt2_entry_t *pte2p, pte2; + vm_paddr_t pt2pg_pa; + + /* Get associated entry in PT2TAB. */ + pte2p = kern_pt2tab_entry(va); + + /* Just return, if PT2s page exists already. */ + pte2 = pt2tab_load(pte2p); + if (pte2_is_valid(pte2)) + return (pte2_pa(pte2)); + + KASSERT(va >= VM_MAX_KERNEL_ADDRESS, + ("%s: NKPT2PG too small", __func__)); + + /* + * Allocate page for PT2s and insert it to PT2TAB. + * In other words, map it into PT2MAP space. + */ + pt2pg_pa = pmap_preboot_get_pages(1); + pt2tab_store(pte2p, PTE2_KPT(pt2pg_pa)); + + /* Zero all PT2s in allocated page. */ + bzero((void*)pt2map_pt2pg(va), PAGE_SIZE); + pte2_sync_range((pt2_entry_t *)pt2map_pt2pg(va), PAGE_SIZE); + + return (pt2pg_pa); +} + +/* + * Setup L2 page table for given KVA. + * Used in pre-bootstrap epoch. + */ +static void +pmap_preboot_pt2_setup(vm_offset_t va) +{ + pt1_entry_t *pte1p; + vm_paddr_t pt2pg_pa, pt2_pa; + + /* Setup PT2's page. */ + pt2pg_pa = pmap_preboot_pt2pg_setup(va); + pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(va)); + + /* Insert PT2 to PT1. */ + pte1p = kern_pte1(va); + pte1_store(pte1p, PTE1_LINK(pt2_pa)); +} + +/* + * Get L2 page entry associated with given KVA. + * Used in pre-bootstrap epoch. + */ +static __inline pt2_entry_t* +pmap_preboot_vtopte2(vm_offset_t va) +{ + pt1_entry_t *pte1p; + + /* Setup PT2 if needed. */ + pte1p = kern_pte1(va); + if (!pte1_is_valid(pte1_load(pte1p))) /* XXX - sections ?! */ + pmap_preboot_pt2_setup(va); + + return (pt2map_entry(va)); +} + +/* + * Pre-bootstrap epoch page(s) mapping(s). + */ +void +pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num) +{ + u_int i; + pt2_entry_t *pte2p; + + /* Map all the pages. */ + for (i = 0; i < num; i++) { + pte2p = pmap_preboot_vtopte2(va); + pte2_store(pte2p, PTE2_KRW(pa)); + va += PAGE_SIZE; + pa += PAGE_SIZE; + } +} + +/* + * Pre-bootstrap epoch virtual space alocator. + */ +vm_offset_t +pmap_preboot_reserve_pages(u_int num) +{ + u_int i; + vm_offset_t start, va; + pt2_entry_t *pte2p; + + /* Allocate virtual space. */ + start = va = virtual_avail; + virtual_avail += num * PAGE_SIZE; + + /* Zero the mapping. */ + for (i = 0; i < num; i++) { + pte2p = pmap_preboot_vtopte2(va); + pte2_store(pte2p, 0); + va += PAGE_SIZE; + } + + return (start); +} + +/* + * Pre-bootstrap epoch page(s) allocation and mapping(s). + */ +vm_offset_t +pmap_preboot_get_vpages(u_int num) +{ + vm_paddr_t pa; + vm_offset_t va; + + /* Allocate physical page(s). */ + pa = pmap_preboot_get_pages(num); + + /* Allocate virtual space. */ + va = virtual_avail; + virtual_avail += num * PAGE_SIZE; + + /* Map and zero all. */ + pmap_preboot_map_pages(pa, va, num); + bzero((void *)va, num * PAGE_SIZE); + + return (va); +} + +/* + * 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, + vm_prot_t prot, vm_memattr_t attr) +{ + u_int num; + 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 = vm_memattr_to_pte2(attr); + l1_prot = ATTR_TO_L1(l2_prot); + l1_attr = ATTR_TO_L1(l2_attr); + + /* Map all the pages. */ + num = round_page(size); + while (num > 0) { + if ((((va | pa) & PTE1_OFFSET) == 0) && (num >= PTE1_SIZE)) { + pte1p = kern_pte1(va); + pte1_store(pte1p, PTE1_KERN(pa, l1_prot, l1_attr)); + va += PTE1_SIZE; + pa += PTE1_SIZE; + num -= PTE1_SIZE; + } else { + pte2p = pmap_preboot_vtopte2(va); + pte2_store(pte2p, PTE2_KERN(pa, l2_prot, l2_attr)); + va += PAGE_SIZE; + pa += PAGE_SIZE; + num -= PAGE_SIZE; + } + } +} + +/* + * Extract from the kernel page table the physical address + * that is mapped by the given virtual address "va". + */ +vm_paddr_t +pmap_kextract(vm_offset_t va) +{ + vm_paddr_t pa; + pt1_entry_t pte1; + pt2_entry_t pte2; + + pte1 = pte1_load(kern_pte1(va)); + if (pte1_is_section(pte1)) { + pa = pte1_pa(pte1) | (va & PTE1_OFFSET); + } else if (pte1_is_link(pte1)) { + /* + * We should beware of concurrent promotion that changes + * pte1 at this point. However, it's not a problem as PT2 + * page is preserved by promotion in PT2TAB. So even if + * it happens, using of PT2MAP is still safe. + * + * QQQ: However, concurrent removing is a problem which + * ends in abort on PT2MAP space. Locking must be used + * to deal with this. + */ + pte2 = pte2_load(pt2map_entry(va)); + pa = pte2_pa(pte2) | (va & PTE2_OFFSET); + } + else { + panic("%s: va %#x pte1 %#x", __func__, va, pte1); + } + return (pa); +} + +/* + * Extract from the kernel page table the physical address + * that is mapped by the given virtual address "va". Also + * return L2 page table entry which maps the address. + * + * This is only intended to be used for panic dumps. + */ +vm_paddr_t +pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) +{ + vm_paddr_t pa; + pt1_entry_t pte1; + pt2_entry_t pte2; + + pte1 = pte1_load(kern_pte1(va)); + if (pte1_is_section(pte1)) { + pa = pte1_pa(pte1) | (va & PTE1_OFFSET); + pte2 = pa | ATTR_TO_L2(pte1) | PTE2_V; + } else if (pte1_is_link(pte1)) { + pte2 = pte2_load(pt2map_entry(va)); + pa = pte2_pa(pte2); + } else { + pte2 = 0; + pa = 0; + } + if (pte2p != NULL) + *pte2p = pte2; + return (pa); +} + +/***************************************************************************** + * + * PMAP second stage initialization and utility functions + * for bootstrap epoch. + * + * After pmap_bootstrap() is called, the following functions for + * mappings can be used: + * + * void pmap_kenter(vm_offset_t va, vm_paddr_t pa); + * void pmap_kremove(vm_offset_t va); + * vm_offset_t pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, + * int prot); + * + * NOTE: This is not SMP coherent stage. And physical page allocation is not + * allowed during this stage. + * + *****************************************************************************/ + +/* + * Initialize kernel PMAP locks and lists, kernel_pmap itself, and + * reserve various virtual spaces for temporary mappings. + */ +void +pmap_bootstrap(vm_offset_t firstaddr) +{ + pt2_entry_t *unused __unused; + struct sysmaps *sysmaps; + u_int i; + + /* + * Initialize the kernel pmap (which is statically allocated). + */ + PMAP_LOCK_INIT(kernel_pmap); + kernel_l1pa = (vm_paddr_t)kern_pt1; /* for libkvm */ + kernel_pmap->pm_pt1 = kern_pt1; + kernel_pmap->pm_pt2tab = kern_pt2tab; + CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */ + TAILQ_INIT(&kernel_pmap->pm_pvchunk); + + /* + * Initialize the global pv list lock. + */ + rw_init(&pvh_global_lock, "pmap pv global"); + + LIST_INIT(&allpmaps); + + /* + * Request a spin mutex so that changes to allpmaps cannot be + * preempted by smp_rendezvous_cpus(). + */ + mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN); + mtx_lock_spin(&allpmaps_lock); + LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list); + mtx_unlock_spin(&allpmaps_lock); + + /* + * Reserve some special page table entries/VA space for temporary + * mapping of pages. + */ +#define SYSMAP(c, p, v, n) do { \ + v = (c)pmap_preboot_reserve_pages(n); \ + p = pt2map_entry((vm_offset_t)v); \ + } while (0) + + /* + * Local CMAP1/CMAP2 are used for zeroing and copying pages. + * Local CMAP3 is used for data cache cleaning. + * Global CMAP3 is used for the idle process page zeroing. + */ + for (i = 0; i < MAXCPU; i++) { + sysmaps = &sysmaps_pcpu[i]; + mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF); + SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1); + SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1); + SYSMAP(caddr_t, sysmaps->CMAP3, sysmaps->CADDR3, 1); + } + SYSMAP(caddr_t, CMAP3, CADDR3, 1); + + /* + * Crashdump maps. + */ + SYSMAP(caddr_t, unused, crashdumpmap, MAXDUMPPGS); + + /* + * _tmppt is used for reading arbitrary physical pages via /dev/mem. + */ + SYSMAP(caddr_t, unused, _tmppt, 1); + + /* + * PADDR1 and PADDR2 are used by pmap_pte2_quick() and pmap_pte2(), + * respectively. PADDR3 is used by pmap_pte2_ddb(). + */ + SYSMAP(pt2_entry_t *, PMAP1, PADDR1, 1); + SYSMAP(pt2_entry_t *, PMAP2, PADDR2, 1); +#ifdef DDB + SYSMAP(pt2_entry_t *, PMAP3, PADDR3, 1); +#endif + mtx_init(&PMAP2mutex, "PMAP2", NULL, MTX_DEF); + + /* + * Note that in very short time in initarm(), we are going to + * initialize phys_avail[] array and no futher page allocation + * can happen after that until vm subsystem will be initialized. + */ + kernel_vm_end_new = kernel_vm_end; + virtual_end = vm_max_kernel_address; +} + +static void +pmap_init_qpages(void) +{ + struct pcpu *pc; + int i; + + CPU_FOREACH(i) { + pc = pcpu_find(i); + pc->pc_qmap_addr = kva_alloc(PAGE_SIZE); + if (pc->pc_qmap_addr == 0) + panic("%s: unable to allocate KVA", __func__); + } +} +SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL); + +/* + * The function can already be use in second initialization stage. + * As such, the function DOES NOT call pmap_growkernel() where PT2 + * allocation can happen. So if used, be sure that PT2 for given + * virtual address is allocated already! + * + * Add a wired page to the kva. + * Note: not SMP coherent. + */ +static __inline void +pmap_kenter_prot_attr(vm_offset_t va, vm_paddr_t pa, uint32_t prot, + uint32_t attr) +{ + pt1_entry_t *pte1p; + pt2_entry_t *pte2p; + + pte1p = kern_pte1(va); + if (!pte1_is_valid(pte1_load(pte1p))) { /* XXX - sections ?! */ + /* + * This is a very low level function, so PT2 and particularly + * PT2PG associated with given virtual address must be already + * allocated. It's a pain mainly during pmap initialization + * stage. However, called after pmap initialization with + * virtual address not under kernel_vm_end will lead to + * the same misery. + */ + if (!pte2_is_valid(pte2_load(kern_pt2tab_entry(va)))) + panic("%s: kernel PT2 not allocated!", __func__); + } + + pte2p = pt2map_entry(va); + pte2_store(pte2p, PTE2_KERN(pa, prot, attr)); +} + +static __inline void +pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr) +{ + + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, attr); +} + +PMAP_INLINE void +pmap_kenter(vm_offset_t va, vm_paddr_t pa) +{ + + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT); +} + +/* + * Remove a page from the kernel pagetables. + * Note: not SMP coherent. + */ +PMAP_INLINE void +pmap_kremove(vm_offset_t va) +{ + pt2_entry_t *pte2p; + + pte2p = pt2map_entry(va); + pte2_clear(pte2p); +} + +/* + * Share new kernel PT2PG with all pmaps. + * The caller is responsible for maintaining TLB consistency. + */ +static void +pmap_kenter_pt2tab(vm_offset_t va, pt2_entry_t npte2) +{ + pmap_t pmap; + pt2_entry_t *pte2p; + + mtx_lock_spin(&allpmaps_lock); + LIST_FOREACH(pmap, &allpmaps, pm_list) { + pte2p = pmap_pt2tab_entry(pmap, va); + pt2tab_store(pte2p, npte2); + } + mtx_unlock_spin(&allpmaps_lock); +} + +/* + * Share new kernel PTE1 with all pmaps. + * The caller is responsible for maintaining TLB consistency. + */ +static void +pmap_kenter_pte1(vm_offset_t va, pt1_entry_t npte1) +{ + pmap_t pmap; + pt1_entry_t *pte1p; + + mtx_lock_spin(&allpmaps_lock); + LIST_FOREACH(pmap, &allpmaps, pm_list) { + pte1p = pmap_pte1(pmap, va); + pte1_store(pte1p, npte1); + } + mtx_unlock_spin(&allpmaps_lock); +} + +/* + * 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. + * + * NOTE: Read the comments above pmap_kenter_prot_attr() as + * the function is used herein! + */ +vm_offset_t +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; + 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)); + + 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); + + l2attr = PTE2_ATTR_DEFAULT; + l1attr = ATTR_TO_L1(l2attr); + + va = *virt; + /* + * Does the physical address range's size and alignment permit at + * least one section mapping to be created? + */ + pte1_offset = start & PTE1_OFFSET; + if ((end - start) - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) >= + PTE1_SIZE) { + /* + * Increase the starting virtual address so that its alignment + * does not preclude the use of section mappings. + */ + if ((va & PTE1_OFFSET) < pte1_offset) + va = pte1_trunc(va) + pte1_offset; + else if ((va & PTE1_OFFSET) > pte1_offset) + va = pte1_roundup(va) + pte1_offset; + } + sva = va; + while (start < end) { + 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, l1attr); + pmap_kenter_pte1(va, npte1); + va += PTE1_SIZE; + start += PTE1_SIZE; + } else { + pmap_kenter_prot_attr(va, start, l2prot, l2attr); + va += PAGE_SIZE; + start += PAGE_SIZE; + } + } + tlb_flush_range(sva, va - sva); + *virt = va; + return (sva); +} + +/* + * 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; + + /* QQQ: 'i' should be less or equal to MAXDUMPPGS. */ + + va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE); + pmap_kenter(va, pa); + tlb_flush_local(va); + return ((void *)crashdumpmap); +} + + +/************************************* + * + * TLB & cache maintenance routines. + * + *************************************/ + +/* + * We inline these within pmap.c for speed. + */ +PMAP_INLINE void +pmap_tlb_flush(pmap_t pmap, vm_offset_t va) +{ + + if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active)) + tlb_flush(va); +} + +PMAP_INLINE void +pmap_tlb_flush_range(pmap_t pmap, vm_offset_t sva, vm_size_t size) +{ + + if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active)) + tlb_flush_range(sva, size); +} + +/* + * Abuse the pte2 nodes for unmapped kva to thread a kva freelist through. + * Requirements: + * - Must deal with pages in order to ensure that none of the PTE2_* bits + * are ever set, PTE2_V in particular. + * - Assumes we can write to pte2s without pte2_store() atomic ops. + * - Assumes nothing will ever test these addresses for 0 to indicate + * no mapping instead of correctly checking PTE2_V. + * - Assumes a vm_offset_t will fit in a pte2 (true for arm). + * Because PTE2_V is never set, there can be no mappings to invalidate. + */ +static vm_offset_t +pmap_pte2list_alloc(vm_offset_t *head) +{ + pt2_entry_t *pte2p; + vm_offset_t va; + + va = *head; + if (va == 0) + panic("pmap_ptelist_alloc: exhausted ptelist KVA"); + pte2p = pt2map_entry(va); + *head = *pte2p; + if (*head & PTE2_V) + panic("%s: va with PTE2_V set!", __func__); + *pte2p = 0; + return (va); +} + +static void +pmap_pte2list_free(vm_offset_t *head, vm_offset_t va) +{ + pt2_entry_t *pte2p; + + if (va & PTE2_V) + panic("%s: freeing va with PTE2_V set!", __func__); + pte2p = pt2map_entry(va); + *pte2p = *head; /* virtual! PTE2_V is 0 though */ + *head = va; +} + +static void +pmap_pte2list_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_pte2list_free(head, va); + } +} + +/***************************************************************************** + * + * PMAP third and final stage initialization. + * + * After pmap_init() is called, PMAP subsystem is fully initialized. + * + *****************************************************************************/ + +SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); + +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 u_long nkpt2pg = NKPT2PG; +SYSCTL_ULONG(_vm_pmap, OID_AUTO, nkpt2pg, CTLFLAG_RD, + &nkpt2pg, 0, "Pre-allocated pages for kernel PT2s"); + +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?"); + +static SYSCTL_NODE(_vm_pmap, OID_AUTO, pte1, CTLFLAG_RD, 0, + "1MB page mapping counters"); + +static u_long pmap_pte1_demotions; +SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, demotions, CTLFLAG_RD, + &pmap_pte1_demotions, 0, "1MB page demotions"); + +static u_long pmap_pte1_mappings; +SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, mappings, CTLFLAG_RD, + &pmap_pte1_mappings, 0, "1MB page mappings"); + +static u_long pmap_pte1_p_failures; +SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, p_failures, CTLFLAG_RD, + &pmap_pte1_p_failures, 0, "1MB page promotion failures"); + +static u_long pmap_pte1_promotions; +SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, promotions, CTLFLAG_RD, + &pmap_pte1_promotions, 0, "1MB page promotions"); + +static __inline ttb_entry_t +pmap_ttb_get(pmap_t pmap) +{ + + return (vtophys(pmap->pm_pt1) | ttb_flags); +} + +/* + * Initialize a vm_page's machine-dependent fields. + * + * Variations: + * 1. Pages for L2 page tables are always not managed. So, pv_list and + * pt2_wirecount can share same physical space. However, proper + * initialization on a page alloc for page tables and reinitialization + * on the page free must be ensured. + */ +void +pmap_page_init(vm_page_t m) +{ + + TAILQ_INIT(&m->md.pv_list); + pt2_wirecount_init(m); + m->md.pat_mode = VM_MEMATTR_DEFAULT; +} + +/* + * Virtualization for faster way how to zero whole page. + */ +static __inline void +pagezero(void *page) +{ + + bzero(page, PAGE_SIZE); +} + +/* + * Zero L2 page table page. + * Use same KVA as in pmap_zero_page(). + */ +static __inline vm_paddr_t +pmap_pt2pg_zero(vm_page_t m) +{ + vm_paddr_t pa; + struct sysmaps *sysmaps; + + pa = VM_PAGE_TO_PHYS(m); + + /* + * XXX: For now, we map whole page even if it's already zero, + * to sync it even if the sync is only DSB. + */ + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + 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, + vm_page_pte2_attr(m))); + /* Even VM_ALLOC_ZERO request is only advisory. */ + if ((m->flags & PG_ZERO) == 0) + pagezero(sysmaps->CADDR2); + pte2_sync_range((pt2_entry_t *)sysmaps->CADDR2, PAGE_SIZE); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); + + return (pa); +} + +/* + * Init just allocated page as L2 page table(s) holder + * and return its physical address. + */ +static __inline vm_paddr_t +pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + vm_paddr_t pa; + pt2_entry_t *pte2p; + + /* Check page attributes. */ + if (m->md.pat_mode != pt_memattr) + pmap_page_set_memattr(m, pt_memattr); + + /* Zero page and init wire counts. */ + pa = pmap_pt2pg_zero(m); + pt2_wirecount_init(m); + + /* + * Map page to PT2MAP address space for given pmap. + * Note that PT2MAP space is shared with all pmaps. + */ + if (pmap == kernel_pmap) + pmap_kenter_pt2tab(va, PTE2_KPT(pa)); + else { + pte2p = pmap_pt2tab_entry(pmap, va); + pt2tab_store(pte2p, PTE2_KPT_NG(pa)); + } + + return (pa); +} + +/* + * 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; + pt2_entry_t *pte2p, pte2; + u_int i, pte1_idx, pv_npg; + + PDEBUG(1, printf("%s: phys_start = %#x\n", __func__, PHYSADDR)); + + /* + * Initialize the vm page array entries for kernel pmap's + * L2 page table pages allocated in advance. + */ + pte1_idx = pte1_index(KERNBASE - PT2MAP_SIZE); + pte2p = kern_pt2tab_entry(KERNBASE - PT2MAP_SIZE); + for (i = 0; i < nkpt2pg + NPG_IN_PT2TAB; i++, pte2p++) { + vm_paddr_t pa; + vm_page_t m; + + pte2 = pte2_load(pte2p); + KASSERT(pte2_is_valid(pte2), ("%s: no valid entry", __func__)); + + pa = pte2_pa(pte2); + m = PHYS_TO_VM_PAGE(pa); + KASSERT(m >= vm_page_array && + m < &vm_page_array[vm_page_array_size], + ("%s: L2 page table page is out of range", __func__)); + + m->pindex = pte1_idx; + m->phys_addr = pa; + pte1_idx += NPT2_IN_PG; + } + + /* + * Initialize the address space (zone) for the pv entries. Set a + * high water mark so that the system can recover from excessive + * numbers of pv entries. + */ + 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); + + /* + * Are large page mappings enabled? + */ + TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled); + if (sp_enabled) { + KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0, + ("%s: can't assign to pagesizes[1]", __func__)); + pagesizes[1] = PTE1_SIZE; + } + + /* + * Calculate the size of the pv head table for sections. + * Handle the possibility that "vm_phys_segs[...].end" is zero. + * Note that the table is only for sections which could be promoted. + */ + first_managed_pa = pte1_trunc(vm_phys_segs[0].start); + pv_npg = (pte1_trunc(vm_phys_segs[vm_phys_nsegs - 1].end - PAGE_SIZE) + - first_managed_pa) / PTE1_SIZE + 1; + + /* + * Allocate memory for the pv head table for sections. + */ + 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); + + pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc); + pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks); + if (pv_chunkbase == NULL) + panic("%s: not enough kvm for pv chunks", __func__); + pmap_pte2list_init(&pv_vafree, pv_chunkbase, pv_maxchunks); +} + +/* + * 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) +{ + u_int anychanged; + pt2_entry_t *epte2p, *pte2p, pte2; + vm_page_t m; + vm_paddr_t pa; + + anychanged = 0; + pte2p = pt2map_entry(sva); + epte2p = pte2p + count; + while (pte2p < epte2p) { + m = *ma++; + pa = VM_PAGE_TO_PHYS(m); + pte2 = pte2_load(pte2p); + if ((pte2_pa(pte2) != pa) || + (pte2_attr(pte2) != vm_page_pte2_attr(m))) { + anychanged++; + pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW, + vm_page_pte2_attr(m))); + } + pte2p++; + } + if (__predict_false(anychanged)) + tlb_flush_range(sva, count * PAGE_SIZE); +} + +/* + * 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) +{ + vm_offset_t va; + + va = sva; + while (count-- > 0) { + pmap_kremove(va); + va += PAGE_SIZE; + } + tlb_flush_range(sva, va - sva); +} + +/* + * Are we current address space or kernel? + */ +static __inline int +pmap_is_current(pmap_t pmap) +{ + + return (pmap == kernel_pmap || + (pmap == vmspace_pmap(curthread->td_proc->p_vmspace))); +} + +/* + * If the given pmap is not the current or kernel pmap, the returned + * pte2 must be released by passing it to pmap_pte2_release(). + */ +static pt2_entry_t * +pmap_pte2(pmap_t pmap, vm_offset_t va) +{ + pt1_entry_t pte1; + vm_paddr_t pt2pg_pa; + + pte1 = pte1_load(pmap_pte1(pmap, va)); + if (pte1_is_section(pte1)) + panic("%s: attempt to map PTE1", __func__); + if (pte1_is_link(pte1)) { + /* Are we current address space or kernel? */ + if (pmap_is_current(pmap)) + return (pt2map_entry(va)); + /* Note that L2 page table size is not equal to PAGE_SIZE. */ + pt2pg_pa = trunc_page(pte1_link_pa(pte1)); + mtx_lock(&PMAP2mutex); + if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) { + pte2_store(PMAP2, PTE2_KPT(pt2pg_pa)); + tlb_flush((vm_offset_t)PADDR2); + } + return (PADDR2 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); + } + return (NULL); +} + +/* + * Releases a pte2 that was obtained from pmap_pte2(). + * Be prepared for the pte2p being NULL. + */ +static __inline void +pmap_pte2_release(pt2_entry_t *pte2p) +{ + + if ((pt2_entry_t *)(trunc_page((vm_offset_t)pte2p)) == PADDR2) { + mtx_unlock(&PMAP2mutex); + } +} + +/* + * Super fast pmap_pte2 routine best used when scanning + * the pv lists. This eliminates many coarse-grained + * invltlb calls. Note that many of the pv list + * scans are across different pmaps. It is very wasteful + * to do an entire tlb flush for checking a single mapping. + * + * If the given pmap is not the current pmap, pvh_global_lock + * must be held and curthread pinned to a CPU. + */ +static pt2_entry_t * +pmap_pte2_quick(pmap_t pmap, vm_offset_t va) +{ + pt1_entry_t pte1; + vm_paddr_t pt2pg_pa; + + pte1 = pte1_load(pmap_pte1(pmap, va)); + if (pte1_is_section(pte1)) + panic("%s: attempt to map PTE1", __func__); + if (pte1_is_link(pte1)) { + /* Are we current address space or kernel? */ + if (pmap_is_current(pmap)) + return (pt2map_entry(va)); + rw_assert(&pvh_global_lock, RA_WLOCKED); + KASSERT(curthread->td_pinned > 0, + ("%s: curthread not pinned", __func__)); + /* Note that L2 page table size is not equal to PAGE_SIZE. */ + pt2pg_pa = trunc_page(pte1_link_pa(pte1)); + if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) { + pte2_store(PMAP1, PTE2_KPT(pt2pg_pa)); +#ifdef SMP + PMAP1cpu = PCPU_GET(cpuid); +#endif + tlb_flush_local((vm_offset_t)PADDR1); + PMAP1changed++; + } else +#ifdef SMP + if (PMAP1cpu != PCPU_GET(cpuid)) { + PMAP1cpu = PCPU_GET(cpuid); + tlb_flush_local((vm_offset_t)PADDR1); + PMAP1changedcpu++; + } else +#endif + PMAP1unchanged++; + return (PADDR1 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); + } + return (NULL); +} + +/* + * 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; + pt1_entry_t pte1; + pt2_entry_t *pte2p; + + PMAP_LOCK(pmap); + pte1 = pte1_load(pmap_pte1(pmap, va)); + if (pte1_is_section(pte1)) + pa = pte1_pa(pte1) | (va & PTE1_OFFSET); + else if (pte1_is_link(pte1)) { + pte2p = pmap_pte2(pmap, va); + pa = pte2_pa(pte2_load(pte2p)) | (va & PTE2_OFFSET); + pmap_pte2_release(pte2p); + } else + pa = 0; + 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) +{ + vm_paddr_t pa, lockpa; + pt1_entry_t pte1; + pt2_entry_t pte2, *pte2p; + vm_page_t m; + + lockpa = 0; + m = NULL; + PMAP_LOCK(pmap); +retry: + pte1 = pte1_load(pmap_pte1(pmap, va)); + if (pte1_is_section(pte1)) { + if (!(pte1 & PTE1_RO) || !(prot & VM_PROT_WRITE)) { + pa = pte1_pa(pte1) | (va & PTE1_OFFSET); + if (vm_page_pa_tryrelock(pmap, pa, &lockpa)) + goto retry; + m = PHYS_TO_VM_PAGE(pa); + vm_page_hold(m); + } + } else if (pte1_is_link(pte1)) { + pte2p = pmap_pte2(pmap, va); + pte2 = pte2_load(pte2p); + pmap_pte2_release(pte2p); + if (pte2_is_valid(pte2) && + (!(pte2 & PTE2_RO) || !(prot & VM_PROT_WRITE))) { + pa = pte2_pa(pte2); + if (vm_page_pa_tryrelock(pmap, pa, &lockpa)) + goto retry; + m = PHYS_TO_VM_PAGE(pa); + vm_page_hold(m); + } + } + PA_UNLOCK_COND(lockpa); + PMAP_UNLOCK(pmap); + return (m); +} + +/* + * Grow the number of kernel L2 page table entries, if needed. + */ +void +pmap_growkernel(vm_offset_t addr) +{ + vm_page_t m; + vm_paddr_t pt2pg_pa, pt2_pa; + pt1_entry_t pte1; + pt2_entry_t pte2; + + PDEBUG(1, printf("%s: addr = %#x\n", __func__, addr)); + /* + * All the time kernel_vm_end is first KVA for which underlying + * L2 page table is either not allocated or linked from L1 page table + * (not considering sections). Except for two possible cases: + * + * (1) in the very beginning as long as pmap_growkernel() was + * not called, it could be first unused KVA (which is not + * rounded up to PTE1_SIZE), + * + * (2) when all KVA space is mapped and kernel_map->max_offset + * address is not rounded up to PTE1_SIZE. (For example, + * it could be 0xFFFFFFFF.) + */ + kernel_vm_end = pte1_roundup(kernel_vm_end); + mtx_assert(&kernel_map->system_mtx, MA_OWNED); + addr = roundup2(addr, PTE1_SIZE); + if (addr - 1 >= kernel_map->max_offset) + addr = kernel_map->max_offset; + while (kernel_vm_end < addr) { + pte1 = pte1_load(kern_pte1(kernel_vm_end)); + if (pte1_is_valid(pte1)) { + kernel_vm_end += PTE1_SIZE; + if (kernel_vm_end - 1 >= kernel_map->max_offset) { + kernel_vm_end = kernel_map->max_offset; + break; + } + continue; + } + + /* + * kernel_vm_end_new is used in pmap_pinit() when kernel + * mappings are entered to new pmap all at once to avoid race + * between pmap_kenter_pte1() and kernel_vm_end increase. + * The same aplies to pmap_kenter_pt2tab(). + */ + kernel_vm_end_new = kernel_vm_end + PTE1_SIZE; + + pte2 = pt2tab_load(kern_pt2tab_entry(kernel_vm_end)); + if (!pte2_is_valid(pte2)) { + /* + * Install new PT2s page into kernel PT2TAB. + */ + m = vm_page_alloc(NULL, + pte1_index(kernel_vm_end) & ~PT2PG_MASK, + VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | + VM_ALLOC_WIRED | VM_ALLOC_ZERO); + if (m == NULL) + panic("%s: no memory to grow kernel", __func__); + /* + * QQQ: To link all new L2 page tables from L1 page + * table now and so pmap_kenter_pte1() them + * at once together with pmap_kenter_pt2tab() + * could be nice speed up. However, + * pmap_growkernel() does not happen so often... + * QQQ: The other TTBR is another option. + */ + pt2pg_pa = pmap_pt2pg_init(kernel_pmap, kernel_vm_end, + m); + } else + pt2pg_pa = pte2_pa(pte2); + + pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(kernel_vm_end)); + pmap_kenter_pte1(kernel_vm_end, PTE1_LINK(pt2_pa)); + + kernel_vm_end = kernel_vm_end_new; + if (kernel_vm_end - 1 >= kernel_map->max_offset) { + kernel_vm_end = kernel_map->max_offset; + break; + } + } +} + +static int +kvm_size(SYSCTL_HANDLER_ARGS) +{ + unsigned long ksize = vm_max_kernel_address - KERNBASE; + + return (sysctl_handle_long(oidp, &ksize, 0, req)); +} +SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD, + 0, 0, kvm_size, "IU", "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, "IU", "Amount of KVM free"); + +/*********************************************** + * + * Pmap allocation/deallocation routines. + * + ***********************************************/ + +/* + * Initialize the pmap for the swapper process. + */ +void +pmap_pinit0(pmap_t pmap) +{ + PDEBUG(1, printf("%s: pmap = %p\n", __func__, pmap)); + + PMAP_LOCK_INIT(pmap); + + /* + * Kernel page table directory and pmap stuff around is already + * initialized, we are using it right now and here. So, finish + * only PMAP structures initialization for process0 ... + * + * Since the L1 page table and PT2TAB is shared with the kernel pmap, + * which is already included in the list "allpmaps", this pmap does + * not need to be inserted into that list. + */ + pmap->pm_pt1 = kern_pt1; + pmap->pm_pt2tab = kern_pt2tab; + CPU_ZERO(&pmap->pm_active); + PCPU_SET(curpmap, pmap); + TAILQ_INIT(&pmap->pm_pvchunk); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); + CPU_SET(0, &pmap->pm_active); +} + +static __inline void +pte1_copy_nosync(pt1_entry_t *spte1p, pt1_entry_t *dpte1p, vm_offset_t sva, + vm_offset_t eva) +{ + u_int idx, count; + + idx = pte1_index(sva); + count = (pte1_index(eva) - idx + 1) * sizeof(pt1_entry_t); + bcopy(spte1p + idx, dpte1p + idx, count); +} + +static __inline void +pt2tab_copy_nosync(pt2_entry_t *spte2p, pt2_entry_t *dpte2p, vm_offset_t sva, + vm_offset_t eva) +{ + u_int idx, count; + + idx = pt2tab_index(sva); + count = (pt2tab_index(eva) - idx + 1) * sizeof(pt2_entry_t); + bcopy(spte2p + idx, dpte2p + idx, count); +} + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + */ +int +pmap_pinit(pmap_t pmap) +{ + pt1_entry_t *pte1p; + pt2_entry_t *pte2p; + vm_paddr_t pa, pt2tab_pa; + u_int i; + + PDEBUG(6, printf("%s: pmap = %p, pm_pt1 = %p\n", __func__, pmap, + pmap->pm_pt1)); + + /* + * No need to allocate L2 page table space yet but we do need + * a valid L1 page table and PT2TAB table. + * + * Install shared kernel mappings to these tables. It's a little + * tricky as some parts of KVA are reserved for vectors, devices, + * and whatever else. These parts are supposed to be above + * vm_max_kernel_address. Thus two regions should be installed: + * + * (1) . + * + * QQQ: The second region should be stable enough to be installed + * only once in time when the tables are allocated. + * QQQ: Maybe copy of both regions at once could be faster ... + * QQQ: Maybe the other TTBR is an option. + * + * Finally, install own PT2TAB table to these tables. + */ + + if (pmap->pm_pt1 == NULL) { + pmap->pm_pt1 = (pt1_entry_t *)kmem_alloc_contig(kernel_arena, + NB_IN_PT1, M_NOWAIT | M_ZERO, 0, -1UL, NB_IN_PT1, 0, + pt_memattr); + if (pmap->pm_pt1 == NULL) + return (0); + } + if (pmap->pm_pt2tab == NULL) { + /* + * QQQ: (1) PT2TAB must be contiguous. If PT2TAB is one page + * only, what should be the only size for 32 bit systems, + * then we could allocate it with vm_page_alloc() and all + * the stuff needed as other L2 page table pages. + * (2) Note that a process PT2TAB is special L2 page table + * page. Its mapping in kernel_arena is permanent and can + * be used no matter which process is current. Its mapping + * in PT2MAP can be used only for current process. + */ + pmap->pm_pt2tab = (pt2_entry_t *)kmem_alloc_attr(kernel_arena, + NB_IN_PT2TAB, M_NOWAIT | M_ZERO, 0, -1UL, pt_memattr); + if (pmap->pm_pt2tab == NULL) { + /* + * QQQ: As struct pmap is allocated from UMA with + * UMA_ZONE_NOFREE flag, it's important to leave + * no allocation in pmap if initialization failed. + */ + kmem_free(kernel_arena, (vm_offset_t)pmap->pm_pt1, + NB_IN_PT1); + pmap->pm_pt1 = NULL; + return (0); + } + /* + * QQQ: Each L2 page table page vm_page_t has pindex set to + * pte1 index of virtual address mapped by this page. + * It's not valid for non kernel PT2TABs themselves. + * The pindex of these pages can not be altered because + * of the way how they are allocated now. However, it + * should not be a problem. + */ + } + + mtx_lock_spin(&allpmaps_lock); + /* + * To avoid race with pmap_kenter_pte1() and pmap_kenter_pt2tab(), + * kernel_vm_end_new is used here instead of kernel_vm_end. + */ + pte1_copy_nosync(kern_pt1, pmap->pm_pt1, KERNBASE, + kernel_vm_end_new - 1); + pte1_copy_nosync(kern_pt1, pmap->pm_pt1, vm_max_kernel_address, + 0xFFFFFFFF); + pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, KERNBASE, + kernel_vm_end_new - 1); + pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, vm_max_kernel_address, + 0xFFFFFFFF); + LIST_INSERT_HEAD(&allpmaps, pmap, pm_list); + mtx_unlock_spin(&allpmaps_lock); + + /* + * Store PT2MAP PT2 pages (a.k.a. PT2TAB) in PT2TAB itself. + * I.e. self reference mapping. The PT2TAB is private, however mapped + * into shared PT2MAP space, so the mapping should be not global. + */ + pt2tab_pa = vtophys(pmap->pm_pt2tab); + pte2p = pmap_pt2tab_entry(pmap, (vm_offset_t)PT2MAP); + for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) { + pt2tab_store(pte2p++, PTE2_KPT_NG(pa)); + } + + /* Insert PT2MAP PT2s into pmap PT1. */ + pte1p = pmap_pte1(pmap, (vm_offset_t)PT2MAP); + for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) { + pte1_store(pte1p++, PTE1_LINK(pa)); + } + + /* + * Now synchronize new mapping which was made above. + */ + pte1_sync_range(pmap->pm_pt1, NB_IN_PT1); + pte2_sync_range(pmap->pm_pt2tab, NB_IN_PT2TAB); + + CPU_ZERO(&pmap->pm_active); + TAILQ_INIT(&pmap->pm_pvchunk); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); + + return (1); +} + +#ifdef INVARIANTS +static boolean_t +pt2tab_user_is_empty(pt2_entry_t *tab) +{ + u_int i, end; + + end = pt2tab_index(VM_MAXUSER_ADDRESS); + for (i = 0; i < end; i++) + if (tab[i] != 0) return (FALSE); + return (TRUE); +} +#endif +/* + * 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) +{ +#ifdef INVARIANTS + vm_offset_t start, end; +#endif + KASSERT(pmap->pm_stats.resident_count == 0, + ("%s: pmap resident count %ld != 0", __func__, + pmap->pm_stats.resident_count)); + KASSERT(pt2tab_user_is_empty(pmap->pm_pt2tab), + ("%s: has allocated user PT2(s)", __func__)); + KASSERT(CPU_EMPTY(&pmap->pm_active), + ("%s: pmap %p is active on some CPU(s)", __func__, pmap)); + + mtx_lock_spin(&allpmaps_lock); + LIST_REMOVE(pmap, pm_list); + mtx_unlock_spin(&allpmaps_lock); + +#ifdef INVARIANTS + start = pte1_index(KERNBASE) * sizeof(pt1_entry_t); + end = (pte1_index(0xFFFFFFFF) + 1) * sizeof(pt1_entry_t); + bzero((char *)pmap->pm_pt1 + start, end - start); + + start = pt2tab_index(KERNBASE) * sizeof(pt2_entry_t); + end = (pt2tab_index(0xFFFFFFFF) + 1) * sizeof(pt2_entry_t); + bzero((char *)pmap->pm_pt2tab + start, end - start); +#endif + /* + * We are leaving PT1 and PT2TAB allocated on released pmap, + * so hopefully UMA vmspace_zone will always be inited with + * UMA_ZONE_NOFREE flag. + */ +} + +/********************************************************* + * + * L2 table pages and their pages management routines. + * + *********************************************************/ + +/* + * Virtual interface for L2 page table wire counting. + * + * Each L2 page table in a page has own counter which counts a number of + * valid mappings in a table. Global page counter counts mappings in all + * tables in a page plus a single itself mapping in PT2TAB. + * + * During a promotion we leave the associated L2 page table counter + * untouched, so the table (strictly speaking a page which holds it) + * is never freed if promoted. + * + * If a page m->wire_count == 1 then no valid mappings exist in any L2 page + * table in the page and the page itself is only mapped in PT2TAB. + */ + +static __inline void +pt2_wirecount_init(vm_page_t m) +{ + u_int i; + + /* + * Note: A page m is allocated with VM_ALLOC_WIRED flag and + * m->wire_count should be already set correctly. + * So, there is no need to set it again herein. + */ + for (i = 0; i < NPT2_IN_PG; i++) + m->md.pt2_wirecount[i] = 0; +} + +static __inline void +pt2_wirecount_inc(vm_page_t m, uint32_t pte1_idx) +{ + + /* + * Note: A just modificated pte2 (i.e. already allocated) + * is acquiring one extra reference which must be + * explicitly cleared. It influences the KASSERTs herein. + * All L2 page tables in a page always belong to the same + * pmap, so we allow only one extra reference for the page. + */ + KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] < (NPTE2_IN_PT2 + 1), + ("%s: PT2 is overflowing ...", __func__)); + KASSERT(m->wire_count <= (NPTE2_IN_PG + 1), + ("%s: PT2PG is overflowing ...", __func__)); + + m->wire_count++; + m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]++; +} + +static __inline void +pt2_wirecount_dec(vm_page_t m, uint32_t pte1_idx) +{ + + KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] != 0, + ("%s: PT2 is underflowing ...", __func__)); + KASSERT(m->wire_count > 1, + ("%s: PT2PG is underflowing ...", __func__)); + + m->wire_count--; + m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]--; +} + +static __inline void +pt2_wirecount_set(vm_page_t m, uint32_t pte1_idx, uint16_t count) +{ + + KASSERT(count <= NPTE2_IN_PT2, + ("%s: invalid count %u", __func__, count)); + KASSERT(m->wire_count > m->md.pt2_wirecount[pte1_idx & PT2PG_MASK], + ("%s: PT2PG corrupting (%u, %u) ...", __func__, m->wire_count, + m->md.pt2_wirecount[pte1_idx & PT2PG_MASK])); + + m->wire_count -= m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]; + m->wire_count += count; + m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] = count; + + KASSERT(m->wire_count <= (NPTE2_IN_PG + 1), + ("%s: PT2PG is overflowed (%u) ...", __func__, m->wire_count)); +} + +static __inline uint32_t +pt2_wirecount_get(vm_page_t m, uint32_t pte1_idx) +{ + + return (m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]); +} + +static __inline boolean_t +pt2_is_empty(vm_page_t m, vm_offset_t va) +{ + + return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == 0); +} + +static __inline boolean_t +pt2_is_full(vm_page_t m, vm_offset_t va) +{ + + return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == + NPTE2_IN_PT2); +} + +static __inline boolean_t +pt2pg_is_empty(vm_page_t m) +{ + + return (m->wire_count == 1); +} + +/* + * This routine is called if the L2 page table + * is not mapped correctly. + */ +static vm_page_t +_pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags) +{ + uint32_t pte1_idx; + pt1_entry_t *pte1p; + pt2_entry_t pte2; + vm_page_t m; + vm_paddr_t pt2pg_pa, pt2_pa; + + pte1_idx = pte1_index(va); + pte1p = pmap->pm_pt1 + pte1_idx; + + KASSERT(pte1_load(pte1p) == 0, + ("%s: pm_pt1[%#x] is not zero: %#x", __func__, pte1_idx, + pte1_load(pte1p))); + + pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, va)); + if (!pte2_is_valid(pte2)) { + /* + * Install new PT2s page into pmap PT2TAB. + */ + m = vm_page_alloc(NULL, pte1_idx & ~PT2PG_MASK, + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO); + if (m == 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); + } + + /* + * Indicate the need to retry. While waiting, + * the L2 page table page may have been allocated. + */ + return (NULL); + } + pmap->pm_stats.resident_count++; + pt2pg_pa = pmap_pt2pg_init(pmap, va, m); + } else { + pt2pg_pa = pte2_pa(pte2); + m = PHYS_TO_VM_PAGE(pt2pg_pa); + } + + pt2_wirecount_inc(m, pte1_idx); + pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx); + pte1_store(pte1p, PTE1_LINK(pt2_pa)); + + return (m); +} + +static vm_page_t +pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags) +{ + u_int pte1_idx; + pt1_entry_t *pte1p, pte1; + vm_page_t m; + + pte1_idx = pte1_index(va); +retry: + pte1p = pmap->pm_pt1 + pte1_idx; + pte1 = pte1_load(pte1p); + + /* + * This supports switching from a 1MB page to a + * normal 4K page. + */ + if (pte1_is_section(pte1)) { + (void)pmap_demote_pte1(pmap, pte1p, va); + /* + * Reload pte1 after demotion. + * + * Note: Demotion can even fail as either PT2 is not find for + * the virtual address or PT2PG can not be allocated. + */ + pte1 = pte1_load(pte1p); + } + + /* + * If the L2 page table page is mapped, we just increment the + * hold count, and activate it. + */ + if (pte1_is_link(pte1)) { + m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); + pt2_wirecount_inc(m, pte1_idx); + } else { + /* + * Here if the PT2 isn't mapped, or if it has + * been deallocated. + */ + m = _pmap_allocpte2(pmap, va, flags); + if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0) + goto retry; + } + + return (m); +} + +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 L2 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) +{ + + /* + * Put page on a list so that it is released after + * *ALL* TLB shootdown is done + */ +#ifdef PMAP_DEBUG + pmap_zero_page_check(m); +#endif + m->flags |= PG_ZERO; + SLIST_INSERT_HEAD(free, m, plinks.s.ss); +} + +/* + * Unwire L2 page tables page. + */ +static void +pmap_unwire_pt2pg(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + pt1_entry_t *pte1p, opte1 __unused; + pt2_entry_t *pte2p; + uint32_t i; + + KASSERT(pt2pg_is_empty(m), + ("%s: pmap %p PT2PG %p wired", __func__, pmap, m)); + + /* + * Unmap all L2 page tables in the page from L1 page table. + * + * QQQ: Individual L2 page tables (except the last one) can be unmapped + * earlier. However, we are doing that this way. + */ + KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK), + ("%s: pmap %p va %#x PT2PG %p bad index", __func__, pmap, va, m)); + pte1p = pmap->pm_pt1 + m->pindex; + for (i = 0; i < NPT2_IN_PG; i++, pte1p++) { + KASSERT(m->md.pt2_wirecount[i] == 0, + ("%s: pmap %p PT2 %u (PG %p) wired", __func__, pmap, i, m)); + opte1 = pte1_load(pte1p); + if (pte1_is_link(opte1)) { + pte1_clear(pte1p); + /* + * Flush intermediate TLB cache. + */ + pmap_tlb_flush(pmap, (m->pindex + i) << PTE1_SHIFT); + } +#ifdef INVARIANTS + else + KASSERT((opte1 == 0) || pte1_is_section(opte1), + ("%s: pmap %p va %#x bad pte1 %x at %u", __func__, + pmap, va, opte1, i)); +#endif + } + + /* + * Unmap the page from PT2TAB. + */ + pte2p = pmap_pt2tab_entry(pmap, va); + (void)pt2tab_load_clear(pte2p); + pmap_tlb_flush(pmap, pt2map_pt2pg(va)); + + m->wire_count = 0; + pmap->pm_stats.resident_count--; + + /* + * This is a release store so that the ordinary store unmapping + * the L2 page table page is globally performed before TLB shoot- + * down is begun. + */ + atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1); +} + +/* + * Decrements a L2 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_pt2(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free) +{ + pt2_wirecount_dec(m, pte1_index(va)); + if (pt2pg_is_empty(m)) { + /* + * QQQ: Wire count is zero, so whole page should be zero and + * we can set PG_ZERO flag to it. + * Note that when promotion is enabled, it takes some + * more efforts. See pmap_unwire_pt2_all() below. + */ + pmap_unwire_pt2pg(pmap, va, m); + pmap_add_delayed_free_list(m, free); + return (TRUE); + } else + return (FALSE); +} + +/* + * Drop a L2 page table page's wire count at once, which is used to record + * the number of valid L2 page table entries within the page. If the wire + * count drops to zero, then the L2 page table page is unmapped. + */ +static __inline void +pmap_unwire_pt2_all(pmap_t pmap, vm_offset_t va, vm_page_t m, + struct spglist *free) +{ + u_int pte1_idx = pte1_index(va); + + KASSERT(m->pindex == (pte1_idx & ~PT2PG_MASK), + ("%s: PT2 page's pindex is wrong", __func__)); + KASSERT(m->wire_count > pt2_wirecount_get(m, pte1_idx), + ("%s: bad pt2 wire count %u > %u", __func__, m->wire_count, + pt2_wirecount_get(m, pte1_idx))); + + /* + * It's possible that the L2 page table was never used. + * It happened in case that a section was created without promotion. + */ + if (pt2_is_full(m, va)) { + pt2_wirecount_set(m, pte1_idx, 0); + + /* + * QQQ: We clear L2 page table now, so when L2 page table page + * is going to be freed, we can set it PG_ZERO flag ... + * This function is called only on section mappings, so + * hopefully it's not to big overload. + * + * XXX: If pmap is current, existing PT2MAP mapping could be + * used for zeroing. + */ + pmap_zero_page_area(m, page_pt2off(pte1_idx), NB_IN_PT2); + } +#ifdef INVARIANTS + else + KASSERT(pt2_is_empty(m, va), ("%s: PT2 is not empty (%u)", + __func__, pt2_wirecount_get(m, pte1_idx))); +#endif + if (pt2pg_is_empty(m)) { + pmap_unwire_pt2pg(pmap, va, m); + pmap_add_delayed_free_list(m, free); + } +} + +/* + * After removing a L2 page table entry, this routine is used to + * conditionally free the page, and manage the hold/wire counts. + */ +static boolean_t +pmap_unuse_pt2(pmap_t pmap, vm_offset_t va, struct spglist *free) +{ + pt1_entry_t pte1; + vm_page_t mpte; + + if (va >= VM_MAXUSER_ADDRESS) + return (FALSE); + pte1 = pte1_load(pmap_pte1(pmap, va)); + mpte = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); + return (pmap_unwire_pt2(pmap, va, mpte, free)); +} + +/************************************* + * + * Page management routines. + * + *************************************/ + +CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE); +CTASSERT(_NPCM == 11); +CTASSERT(_NPCPV == 336); static __inline struct pv_chunk * pv_to_chunk(pv_entry_t pv) @@ -449,28 +2702,18 @@ pv_to_chunk(pv_entry_t pv) #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 */ +#define PC_FREE0_9 0xfffffffful /* Free values for index 0 through 9 */ +#define PC_FREE10 0x0000fffful /* Free values for index 10 */ 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 + PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, + PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, + PC_FREE0_9, PC_FREE0_9, PC_FREE0_9, + PC_FREE0_9, PC_FREE10 }; -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"); + "Current number of pv entries"); #ifdef PV_STATS static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail; @@ -481,3706 +2724,85 @@ 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."); +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_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. + * Is given page managed? */ -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) +static __inline boolean_t +is_managed(vm_paddr_t pa) { - 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) + vm_offset_t pgnum; + vm_page_t m; + + pgnum = atop(pa); + if (pgnum >= first_page) { + m = PHYS_TO_VM_PAGE(pa); + if (m == NULL) + return (FALSE); + if ((m->oflags & VPO_UNMANAGED) == 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) +static __inline boolean_t +pte1_is_managed(pt1_entry_t pte1) { - struct l2_dtable *l2; - pd_entry_t *pl1pd, l1pd; - pt_entry_t *ptep; - u_short l1idx; - if (pmap->pm_l1 == NULL) - return (FALSE); + return (is_managed(pte1_pa(pte1))); +} - l1idx = L1_IDX(va); - *pdp = pl1pd = &pmap->pm_l1->l1_kva[l1idx]; - l1pd = *pl1pd; +static __inline boolean_t +pte2_is_managed(pt2_entry_t pte2) +{ - 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); + return (is_managed(pte2_pa(pte2))); } /* - * 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. + * 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; + struct md_page *pvh; + pt1_entry_t *pte1p; pmap_t pmap; - pd_entry_t *pl1pd; - pt_entry_t *ptep; + pt2_entry_t *pte2p, tpte2; pv_entry_t pv; vm_offset_t va; - vm_page_t free, m, m_pc; + vm_page_t m, m_pc; + struct spglist free; uint32_t inuse; - int bit, field, freed, idx; + int bit, field, freed; - PMAP_ASSERT_LOCKED(locked_pmap); + PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED); pmap = NULL; - free = m_pc = NULL; + m_pc = NULL; + SLIST_INIT(&free); TAILQ_INIT(&newtail); while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 || - free == NULL)) { + SLIST_EMPTY(&free))) { 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); } @@ -4203,33 +2825,41 @@ pmap_pv_reclaim(pmap_t locked_pmap) 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]; + pv = &pc->pc_pventry[field * 32 + bit]; va = pv->pv_va; - - pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)]; - if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) + pte1p = pmap_pte1(pmap, va); + if (pte1_is_section(pte1_load(pte1p))) continue; - if (pv->pv_flags & PVF_WIRED) + pte2p = pmap_pte2(pmap, va); + tpte2 = pte2_load(pte2p); + if ((tpte2 & PTE2_W) == 0) + tpte2 = pte2_load_clear(pte2p); + pmap_pte2_release(pte2p); + if ((tpte2 & PTE2_W) != 0) 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); + KASSERT(tpte2 != 0, + ("pmap_pv_reclaim: pmap %p va %#x zero pte", + pmap, va)); + pmap_tlb_flush(pmap, va); + m = PHYS_TO_VM_PAGE(pte2_pa(tpte2)); + if (pte2_is_dirty(tpte2)) + vm_page_dirty(m); + if ((tpte2 & PTE2_A) != 0) + vm_page_aflag_set(m, PGA_REFERENCED); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + if (TAILQ_EMPTY(&m->md.pv_list) && + (m->flags & PG_FICTITIOUS) == 0) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) { + vm_page_aflag_clear(m, + PGA_WRITEABLE); + } + } pc->pc_map[field] |= 1UL << bit; + pmap_unuse_pt2(pmap, va, &free); freed++; } } - if (freed == 0) { TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); continue; @@ -4261,39 +2891,62 @@ pmap_pv_reclaim(pmap_t locked_pmap) /* 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); + pmap_pte2list_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); } + if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { + m_pc = SLIST_FIRST(&free); + SLIST_REMOVE_HEAD(&free, plinks.s.ss); + /* Recycle a freed page table page. */ + m_pc->wire_count = 1; + atomic_add_int(&vm_cnt.v_wire_count, 1); + } + pmap_free_zero_pages(&free); return (m_pc); } +static void +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_pte2list_free(&pv_vafree, (vm_offset_t)pc); +} + /* - * free the pv_entry back to the free list + * Free the pv_entry back to the free list. */ static void -pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv) +free_pv_entry(pmap_t pmap, pv_entry_t pv) { struct pv_chunk *pc; - int bit, field, idx; + int idx, field, bit; rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); 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); + field = idx / 32; + bit = idx % 32; pc->pc_map[field] |= 1ul << bit; for (idx = 0; idx < _NPCM; idx++) if (pc->pc_map[idx] != pc_freemask[idx]) { @@ -4310,46 +2963,32 @@ pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv) 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); - + free_pv_chunk(pc); } +/* + * Get a new pv_entry, allocating a block from the system + * when needed. + */ static pv_entry_t -pmap_get_pv_entry(pmap_t pmap, boolean_t try) +get_pv_entry(pmap_t pmap, boolean_t try) { static const struct timeval printinterval = { 60, 0 }; static struct timeval lastprint; - struct pv_chunk *pc; + int bit, field; pv_entry_t pv; + struct pv_chunk *pc; vm_page_t m; - int bit, field, idx; rw_assert(&pvh_global_lock, RA_WLOCKED); - PMAP_ASSERT_LOCKED(pmap); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); 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__); + printf("Approaching the limit on PV entries, consider " + "increasing either the vm.pmap.shpgperproc or the " + "vm.pmap.pv_entry_max tunable.\n"); retry: pc = TAILQ_FIRST(&pmap->pm_pvchunk); if (pc != NULL) { @@ -4360,8 +2999,7 @@ pmap_get_pv_entry(pmap_t pmap, boolean_t try) } } if (field < _NPCM) { - idx = field * sizeof(pc->pc_map[field]) * NBBY + bit; - pv = &pc->pc_pventry[idx]; + pv = &pc->pc_pventry[field * 32 + bit]; pc->pc_map[field] &= ~(1ul << bit); /* If this was the last item, move it to tail */ for (field = 0; field < _NPCM; field++) @@ -4376,9 +3014,9 @@ pmap_get_pv_entry(pmap_t pmap, boolean_t try) } } /* - * Access to the ptelist "pv_vafree" is synchronized by the pvh + * Access to the pte2list "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. + * remain non-empty until pmap_pte2list_alloc() completes. */ if (pv_vafree == 0 || (m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) { @@ -4393,7 +3031,7 @@ pmap_get_pv_entry(pmap_t pmap, boolean_t try) } PV_STAT(pc_chunk_count++); PV_STAT(pc_chunk_allocs++); - pc = (struct pv_chunk *)pmap_ptelist_alloc(&pv_vafree); + pc = (struct pv_chunk *)pmap_pte2list_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 */ @@ -4407,418 +3045,1818 @@ pmap_get_pv_entry(pmap_t pmap, boolean_t try) } /* - * 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. + * Create a pv entry for page at pa for + * (pmap, va). */ -#define PMAP_REMOVE_CLEAN_LIST_SIZE 3 -void -pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +static void +pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m) { - 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; + pv_entry_t pv; + rw_assert(&pvh_global_lock, RA_WLOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + pv = get_pv_entry(pmap, FALSE); + pv->pv_va = va; + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); +} + +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_WLOCKED); + 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); + break; + } + } + 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")); + free_pv_entry(pmap, pv); +} + +static void +pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +{ + struct md_page *pvh; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + pmap_pvh_free(&m->md, pmap, va); + if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_aflag_clear(m, PGA_WRITEABLE); + } +} + +static void +pmap_pv_demote_pte1(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 & PTE1_OFFSET) == 0, + ("pmap_pv_demote_pte1: pa is not 1mpage aligned")); /* - * we lock in the pmap => pv_head direction + * Transfer the 1mpage's pv entry for this mapping to the first + * page's pv list. */ + pvh = pa_to_pvh(pa); + va = pte1_trunc(va); + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_demote_pte1: pv not found")); + m = PHYS_TO_VM_PAGE(pa); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + /* Instantiate the remaining NPTE2_IN_PT2 - 1 pv entries. */ + va_last = va + PTE1_SIZE - PAGE_SIZE; + do { + m++; + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("pmap_pv_demote_pte1: page %p is not managed", m)); + va += PAGE_SIZE; + pmap_insert_entry(pmap, va, m); + } while (va < va_last); +} + +static void +pmap_pv_promote_pte1(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 & PTE1_OFFSET) == 0, + ("pmap_pv_promote_pte1: 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 = pte1_trunc(va); + pv = pmap_pvh_remove(&m->md, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_promote_pte1: pv not found")); + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); + /* Free the remaining NPTE2_IN_PT2 - 1 pv entries. */ + va_last = va + PTE1_SIZE - PAGE_SIZE; + do { + m++; + va += PAGE_SIZE; + pmap_pvh_free(&m->md, pmap, va); + } while (va < va_last); +} + +/* + * Conditionally create a pv entry. + */ +static boolean_t +pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + pv_entry_t pv; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (pv_entry_count < pv_entry_high_water && + (pv = get_pv_entry(pmap, TRUE)) != NULL) { + pv->pv_va = va; + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + return (TRUE); + } else + return (FALSE); +} + +/* + * Create the pv entries for each of the pages within a section. + */ +static boolean_t +pmap_pv_insert_pte1(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 = get_pv_entry(pmap, TRUE)) != NULL) { + pv->pv_va = va; + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); + return (TRUE); + } else + return (FALSE); +} + +/* + * Tries to promote the NPTE2_IN_PT2, contiguous 4KB page mappings that are + * within a single page table page (PT2) to a single 1MB page 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. + * + * Managed (PG_MANAGED) mappings within the kernel address space are not + * promoted. The reason is that kernel PTE1s are replicated in each pmap but + * pmap_remove_write(), pmap_clear_modify(), and pmap_clear_reference() only + * read the PTE1 from the kernel pmap. + */ +static void +pmap_promote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) +{ + pt1_entry_t npte1; + pt2_entry_t *fpte2p, fpte2, fpte2_fav; + pt2_entry_t *pte2p, pte2; + vm_offset_t pteva __unused; + vm_page_t m __unused; + + PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__, + pmap, va, pte1_load(pte1p), pte1p)); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + /* + * Examine the first PTE2 in the specified PT2. Abort if this PTE2 is + * either invalid, unused, or does not map the first 4KB physical page + * within a 1MB page. + */ + fpte2p = pmap_pte2_quick(pmap, pte1_trunc(va)); +setpte1: + fpte2 = pte2_load(fpte2p); + if ((fpte2 & ((PTE2_FRAME & PTE1_OFFSET) | PTE2_A | PTE2_V)) != + (PTE2_A | PTE2_V)) { + pmap_pte1_p_failures++; + CTR3(KTR_PMAP, "%s: failure(1) for va %#x in pmap %p", + __func__, va, pmap); + return; + } + if (pte2_is_managed(fpte2) && pmap == kernel_pmap) { + pmap_pte1_p_failures++; + CTR3(KTR_PMAP, "%s: failure(2) for va %#x in pmap %p", + __func__, va, pmap); + return; + } + if ((fpte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) { + /* + * When page is not modified, PTE2_RO can be set without + * a TLB invalidation. + * + * Note: When modified bit is being set, then in hardware case, + * the TLB entry is re-read (updated) from PT2, and in + * software case (abort), the PTE2 is read from PT2 and + * TLB flushed if changed. The following cmpset() solves + * any race with setting this bit in both cases. + */ + if (!pte2_cmpset(fpte2p, fpte2, fpte2 | PTE2_RO)) + goto setpte1; + fpte2 |= PTE2_RO; + } + + /* + * Examine each of the other PTE2s in the specified PT2. Abort if this + * PTE2 maps an unexpected 4KB physical page or does not have identical + * characteristics to the first PTE2. + */ + fpte2_fav = (fpte2 & (PTE2_FRAME | PTE2_A | PTE2_V)); + fpte2_fav += PTE1_SIZE - PTE2_SIZE; /* examine from the end */ + for (pte2p = fpte2p + NPTE2_IN_PT2 - 1; pte2p > fpte2p; pte2p--) { +setpte2: + pte2 = pte2_load(pte2p); + if ((pte2 & (PTE2_FRAME | PTE2_A | PTE2_V)) != fpte2_fav) { + pmap_pte1_p_failures++; + CTR3(KTR_PMAP, "%s: failure(3) for va %#x in pmap %p", + __func__, va, pmap); + return; + } + if ((pte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) { + /* + * When page is not modified, PTE2_RO can be set + * without a TLB invalidation. See note above. + */ + if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_RO)) + goto setpte2; + pte2 |= PTE2_RO; + pteva = pte1_trunc(va) | (pte2 & PTE1_OFFSET & + PTE2_FRAME); + CTR3(KTR_PMAP, "%s: protect for va %#x in pmap %p", + __func__, pteva, pmap); + } + if ((pte2 & PTE2_PROMOTE) != (fpte2 & PTE2_PROMOTE)) { + pmap_pte1_p_failures++; + CTR3(KTR_PMAP, "%s: failure(4) for va %#x in pmap %p", + __func__, va, pmap); + return; + } + + fpte2_fav -= PTE2_SIZE; + } + /* + * The page table page in its current state will stay in PT2TAB + * until the PTE1 mapping the section is demoted by pmap_demote_pte1() + * or destroyed by pmap_remove_pte1(). + * + * Note that L2 page table size is not equal to PAGE_SIZE. + */ + m = PHYS_TO_VM_PAGE(trunc_page(pte1_link_pa(pte1_load(pte1p)))); + KASSERT(m >= vm_page_array && m < &vm_page_array[vm_page_array_size], + ("%s: PT2 page is out of range", __func__)); + KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK), + ("%s: PT2 page's pindex is wrong", __func__)); + + /* + * Get pte1 from pte2 format. + */ + npte1 = (fpte2 & PTE1_FRAME) | ATTR_TO_L1(fpte2) | PTE1_V; + + /* + * Promote the pv entries. + */ + if (pte2_is_managed(fpte2)) + pmap_pv_promote_pte1(pmap, va, pte1_pa(npte1)); + + /* + * Map the section. + */ + if (pmap == kernel_pmap) + pmap_kenter_pte1(va, npte1); + else + pte1_store(pte1p, npte1); + /* + * Flush old small mappings. We call single pmap_tlb_flush() in + * pmap_demote_pte1() and pmap_remove_pte1(), so we must be sure that + * no small mappings survive. We assume that given pmap is current and + * don't play game with PTE2_NG. + */ + pmap_tlb_flush_range(pmap, pte1_trunc(va), PTE1_SIZE); + + pmap_pte1_promotions++; + CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p", + __func__, va, pmap); + + PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n", + __func__, pmap, va, npte1, pte1_load(pte1p), pte1p)); +} + +/* + * Zero L2 page table page. + */ +static __inline void +pmap_clear_pt2(pt2_entry_t *fpte2p) +{ + pt2_entry_t *pte2p; + + for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) + pte2_clear(pte2p); + +} + +/* + * Removes a 1MB page mapping from the kernel pmap. + */ +static void +pmap_remove_kernel_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) +{ + vm_page_t m; + uint32_t pte1_idx; + pt2_entry_t *fpte2p; + vm_paddr_t pt2_pa; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + m = pmap_pt2_page(pmap, va); + if (m == NULL) + /* + * QQQ: Is this function called only on promoted pte1? + * We certainly do section mappings directly + * (without promotion) in kernel !!! + */ + panic("%s: missing pt2 page", __func__); + + pte1_idx = pte1_index(va); + + /* + * Initialize the L2 page table. + */ + fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx); + pmap_clear_pt2(fpte2p); + + /* + * Remove the mapping. + */ + pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(m), pte1_idx); + pmap_kenter_pte1(va, PTE1_LINK(pt2_pa)); + + /* + * QQQ: We do not need to invalidate PT2MAP mapping + * as we did not change it. I.e. the L2 page table page + * was and still is mapped the same way. + */ +} + +/* + * Do the things to unmap a section in a process + */ +static void +pmap_remove_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva, + struct spglist *free) +{ + pt1_entry_t opte1; + struct md_page *pvh; + vm_offset_t eva, va; + vm_page_t m; + + PDEBUG(6, printf("%s(%p): va %#x pte1 %#x at %p\n", __func__, pmap, sva, + pte1_load(pte1p), pte1p)); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & PTE1_OFFSET) == 0, + ("%s: sva is not 1mpage aligned", __func__)); + + /* + * Clear and invalidate the mapping. It should occupy one and only TLB + * entry. So, pmap_tlb_flush() called with aligned address should be + * sufficient. + */ + opte1 = pte1_load_clear(pte1p); + pmap_tlb_flush(pmap, sva); + + if (pte1_is_wired(opte1)) + pmap->pm_stats.wired_count -= PTE1_SIZE / PAGE_SIZE; + pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE; + if (pte1_is_managed(opte1)) { + pvh = pa_to_pvh(pte1_pa(opte1)); + pmap_pvh_free(pvh, pmap, sva); + eva = sva + PTE1_SIZE; + for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1)); + va < eva; va += PAGE_SIZE, m++) { + if (pte1_is_dirty(opte1)) + vm_page_dirty(m); + if (opte1 & PTE1_A) + 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); + } + } + if (pmap == kernel_pmap) { + /* + * L2 page table(s) can't be removed from kernel map as + * kernel counts on it (stuff around pmap_growkernel()). + */ + pmap_remove_kernel_pte1(pmap, pte1p, sva); + } else { + /* + * Get associated L2 page table page. + * It's possible that the page was never allocated. + */ + m = pmap_pt2_page(pmap, sva); + if (m != NULL) + pmap_unwire_pt2_all(pmap, sva, m, free); + } +} + +/* + * Fills L2 page table page with mappings to consecutive physical pages. + */ +static __inline void +pmap_fill_pt2(pt2_entry_t *fpte2p, pt2_entry_t npte2) +{ + pt2_entry_t *pte2p; + + for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) { + pte2_store(pte2p, npte2); + npte2 += PTE2_SIZE; + } +} + +/* + * Tries to demote a 1MB page mapping. If demotion fails, the + * 1MB page mapping is invalidated. + */ +static boolean_t +pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va) +{ + pt1_entry_t opte1, npte1; + pt2_entry_t *fpte2p, npte2; + vm_paddr_t pt2pg_pa, pt2_pa; + vm_page_t m; + struct spglist free; + uint32_t pte1_idx, isnew = 0; + + PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__, + pmap, va, pte1_load(pte1p), pte1p)); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + opte1 = pte1_load(pte1p); + KASSERT(pte1_is_section(opte1), ("%s: opte1 not a section", __func__)); + + if ((opte1 & PTE1_A) == 0 || (m = pmap_pt2_page(pmap, va)) == NULL) { + KASSERT(!pte1_is_wired(opte1), + ("%s: PT2 page for a wired mapping is missing", __func__)); + + /* + * Invalidate the 1MB page mapping and return + * "failure" if the mapping was never accessed or the + * allocation of the new page table page fails. + */ + if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL, + pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ | + VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) { + SLIST_INIT(&free); + pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free); + pmap_free_zero_pages(&free); + CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p", + __func__, va, pmap); + return (FALSE); + } + if (va < VM_MAXUSER_ADDRESS) + pmap->pm_stats.resident_count++; + + isnew = 1; + + /* + * We init all L2 page tables in the page even if + * we are going to change everything for one L2 page + * table in a while. + */ + pt2pg_pa = pmap_pt2pg_init(pmap, va, m); + } else { + if (va < VM_MAXUSER_ADDRESS) { + if (pt2_is_empty(m, va)) + isnew = 1; /* Demoting section w/o promotion. */ +#ifdef INVARIANTS + else + KASSERT(pt2_is_full(m, va), ("%s: bad PT2 wire" + " count %u", __func__, + pt2_wirecount_get(m, pte1_index(va)))); +#endif + } + } + + pt2pg_pa = VM_PAGE_TO_PHYS(m); + pte1_idx = pte1_index(va); + /* + * If the pmap is current, then the PT2MAP can provide access to + * the page table page (promoted L2 page tables are not unmapped). + * Otherwise, temporarily map the L2 page table page (m) into + * the kernel's address space at either PADDR1 or PADDR2. + * + * Note that L2 page table size is not equal to PAGE_SIZE. + */ + if (pmap_is_current(pmap)) + fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx); + else if (curthread->td_pinned > 0 && rw_wowned(&pvh_global_lock)) { + if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) { + pte2_store(PMAP1, PTE2_KPT(pt2pg_pa)); +#ifdef SMP + PMAP1cpu = PCPU_GET(cpuid); +#endif + tlb_flush_local((vm_offset_t)PADDR1); + PMAP1changed++; + } else +#ifdef SMP + if (PMAP1cpu != PCPU_GET(cpuid)) { + PMAP1cpu = PCPU_GET(cpuid); + tlb_flush_local((vm_offset_t)PADDR1); + PMAP1changedcpu++; + } else +#endif + PMAP1unchanged++; + fpte2p = page_pt2((vm_offset_t)PADDR1, pte1_idx); + } else { + mtx_lock(&PMAP2mutex); + if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) { + pte2_store(PMAP2, PTE2_KPT(pt2pg_pa)); + tlb_flush((vm_offset_t)PADDR2); + } + fpte2p = page_pt2((vm_offset_t)PADDR2, pte1_idx); + } + pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx); + npte1 = PTE1_LINK(pt2_pa); + + KASSERT((opte1 & PTE1_A) != 0, + ("%s: opte1 is missing PTE1_A", __func__)); + KASSERT((opte1 & (PTE1_NM | PTE1_RO)) != PTE1_NM, + ("%s: opte1 has PTE1_NM", __func__)); + + /* + * Get pte2 from pte1 format. + */ + npte2 = pte1_pa(opte1) | ATTR_TO_L2(opte1) | PTE2_V; + + /* + * If the L2 page table page is new, initialize it. If the mapping + * has changed attributes, update the page table entries. + */ + if (isnew != 0) { + pt2_wirecount_set(m, pte1_idx, NPTE2_IN_PT2); + pmap_fill_pt2(fpte2p, npte2); + } else if ((pte2_load(fpte2p) & PTE2_PROMOTE) != + (npte2 & PTE2_PROMOTE)) + pmap_fill_pt2(fpte2p, npte2); + + KASSERT(pte2_pa(pte2_load(fpte2p)) == pte2_pa(npte2), + ("%s: fpte2p and npte2 map different physical addresses", + __func__)); + + if (fpte2p == PADDR2) + mtx_unlock(&PMAP2mutex); + + /* + * Demote the mapping. This pmap is locked. The old PTE1 has + * PTE1_A set. If the old PTE1 has not PTE1_RO set, it also + * has not PTE1_NM set. Thus, there is no danger of a race with + * another processor changing the setting of PTE1_A and/or PTE1_NM + * between the read above and the store below. + */ + if (pmap == kernel_pmap) + pmap_kenter_pte1(va, npte1); + else + pte1_store(pte1p, npte1); + + /* + * Flush old big mapping. The mapping should occupy one and only + * TLB entry. So, pmap_tlb_flush() called with aligned address + * should be sufficient. + */ + pmap_tlb_flush(pmap, pte1_trunc(va)); + + /* + * Demote the pv entry. This depends on the earlier demotion + * of the mapping. Specifically, the (re)creation of a per- + * page pv entry might trigger the execution of pmap_pv_reclaim(), + * which might reclaim a newly (re)created per-page pv entry + * and destroy the associated mapping. In order to destroy + * the mapping, the PTE1 must have already changed from mapping + * the 1mpage to referencing the page table page. + */ + if (pte1_is_managed(opte1)) + pmap_pv_demote_pte1(pmap, va, pte1_pa(opte1)); + + pmap_pte1_demotions++; + CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p", + __func__, va, pmap); + + PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n", + __func__, pmap, va, npte1, pte1_load(pte1p), pte1p)); + return (TRUE); +} + +/* + * 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) +{ + pt1_entry_t *pte1p; + pt2_entry_t *pte2p; + pt2_entry_t npte2, opte2; + pv_entry_t pv; + vm_paddr_t opa, pa; + vm_page_t mpte2, om; + boolean_t wired; + + va = trunc_page(va); + mpte2 = NULL; + wired = (flags & PMAP_ENTER_WIRED) != 0; + + KASSERT(va <= vm_max_kernel_address, ("%s: toobig", __func__)); + KASSERT(va < UPT2V_MIN_ADDRESS || va >= UPT2V_MAX_ADDRESS, + ("%s: invalid to pmap_enter page table pages (va: 0x%x)", __func__, + va)); + if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m)) + VM_OBJECT_ASSERT_LOCKED(m->object); rw_wlock(&pvh_global_lock); PMAP_LOCK(pmap); - total = 0; - while (sva < eva) { - next_bucket = L2_NEXT_BUCKET(sva); + sched_pin(); + + /* + * In the case that a page table page is not + * resident, we are creating it here. + */ + if (va < VM_MAXUSER_ADDRESS) { + mpte2 = pmap_allocpte2(pmap, va, flags); + if (mpte2 == NULL) { + KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0, + ("pmap_allocpte2 failed with sleep allowed")); + sched_unpin(); + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + return (KERN_RESOURCE_SHORTAGE); + } + } + pte1p = pmap_pte1(pmap, va); + if (pte1_is_section(pte1_load(pte1p))) + panic("%s: attempted on 1MB page", __func__); + pte2p = pmap_pte2_quick(pmap, va); + if (pte2p == NULL) + panic("%s: invalid L1 page table entry va=%#x", __func__, va); + + om = NULL; + pa = VM_PAGE_TO_PHYS(m); + opte2 = pte2_load(pte2p); + opa = pte2_pa(opte2); + /* + * Mapping has not changed, must be protection or wiring change. + */ + if (pte2_is_valid(opte2) && (opa == pa)) { + /* + * Wiring change, just update stats. We don't worry about + * wiring PT2 pages as they remain resident as long as there + * are valid mappings in them. Hence, if a user page is wired, + * the PT2 page will be also. + */ + if (wired && !pte2_is_wired(opte2)) + pmap->pm_stats.wired_count++; + else if (!wired && pte2_is_wired(opte2)) + pmap->pm_stats.wired_count--; /* - * Check for large page. + * Remove extra pte2 reference */ - 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")); + if (mpte2) + pt2_wirecount_dec(mpte2, pte1_index(va)); + if (pte2_is_managed(opte2)) + om = m; + goto validate; + } + + /* + * QQQ: We think that changing physical address on writeable mapping + * is not safe. Well, maybe on kernel address space with correct + * locking, it can make a sense. However, we have no idea why + * anyone should do that on user address space. Are we wrong? + */ + KASSERT((opa == 0) || (opa == pa) || + !pte2_is_valid(opte2) || ((opte2 & PTE2_RO) != 0), + ("%s: pmap %p va %#x(%#x) opa %#x pa %#x - gotcha %#x %#x!", + __func__, pmap, va, opte2, opa, pa, flags, prot)); + + pv = NULL; + + /* + * Mapping has changed, invalidate old range and fall through to + * handle validating new mapping. + */ + if (opa) { + if (pte2_is_wired(opte2)) + pmap->pm_stats.wired_count--; + if (pte2_is_managed(opte2)) { + om = PHYS_TO_VM_PAGE(opa); + pv = pmap_pvh_remove(&om->md, pmap, va); + } + /* + * Remove extra pte2 reference + */ + if (mpte2 != NULL) + pt2_wirecount_dec(mpte2, va >> PTE1_SHIFT); + } else + pmap->pm_stats.resident_count++; + + /* + * Enter on the PV list if part of our managed memory. + */ + if ((m->oflags & VPO_UNMANAGED) == 0) { + KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva, + ("%s: managed mapping within the clean submap", __func__)); + if (pv == NULL) + pv = get_pv_entry(pmap, FALSE); + pv->pv_va = va; + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); + } else if (pv != NULL) + free_pv_entry(pmap, pv); + + /* + * Increment counters + */ + if (wired) + pmap->pm_stats.wired_count++; + +validate: + /* + * Now validate mapping with desired protection/wiring. + */ + 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); + } + else + npte2 |= PTE2_RO; + if ((prot & VM_PROT_EXECUTE) == 0) + npte2 |= PTE2_NX; + if (wired) + npte2 |= PTE2_W; + if (va < VM_MAXUSER_ADDRESS) + npte2 |= PTE2_U; + if (pmap != kernel_pmap) + npte2 |= PTE2_NG; + + /* + * If the mapping or permission bits are different, we need + * to update the pte2. + * + * QQQ: Think again and again what to do + * if the mapping is going to be changed! + */ + if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) { + /* + * 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. + * Don't do it for kernel memory which is mapped with exec + * permission even if the memory isn't going to hold executable + * code. The only time when icache sync is needed is after + * kernel module is loaded and the relocation info is processed. + * And it's done in elf_cpu_load_file(). + * + * QQQ: (1) Does it exist any better way where + * or how to sync icache? + * (2) Now, we do it on a page basis. + */ + if ((prot & VM_PROT_EXECUTE) && pmap != kernel_pmap && + m->md.pat_mode == VM_MEMATTR_WB_WA && + (opa != pa || (opte2 & PTE2_NX))) + cache_icache_sync_fresh(va, pa, PAGE_SIZE); + + npte2 |= PTE2_A; + if (flags & VM_PROT_WRITE) + npte2 &= ~PTE2_NM; + if (opte2 & PTE2_V) { + /* Change mapping with break-before-make approach. */ + opte2 = pte2_load_clear(pte2p); + pmap_tlb_flush(pmap, va); + pte2_store(pte2p, npte2); + if (opte2 & PTE2_A) { + if (pte2_is_managed(opte2)) + vm_page_aflag_set(om, PGA_REFERENCED); + } + if (pte2_is_dirty(opte2)) { + if (pte2_is_managed(opte2)) + vm_page_dirty(om); + } + if (pte2_is_managed(opte2) && + TAILQ_EMPTY(&om->md.pv_list) && + ((om->flags & PG_FICTITIOUS) != 0 || + TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list))) + vm_page_aflag_clear(om, PGA_WRITEABLE); + } else + pte2_store(pte2p, npte2); + } +#if 0 + else { + /* + * QQQ: In time when both access and not mofified bits are + * emulated by software, this should not happen. Some + * analysis is need, if this really happen. Missing + * tlb flush somewhere could be the reason. + */ + panic("%s: pmap %p va %#x opte2 %x npte2 %x !!", __func__, pmap, + va, opte2, npte2); + } +#endif + /* + * If both the L2 page table page and the reservation are fully + * populated, then attempt promotion. + */ + if ((mpte2 == NULL || pt2_is_full(mpte2, va)) && + sp_enabled && (m->flags & PG_FICTITIOUS) == 0 && + vm_reserv_level_iffullpop(m) == 0) + pmap_promote_pte1(pmap, pte1p, va); + sched_unpin(); + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); +} + +/* + * Do the things to unmap a page in a process. + */ +static int +pmap_remove_pte2(pmap_t pmap, pt2_entry_t *pte2p, vm_offset_t va, + struct spglist *free) +{ + pt2_entry_t opte2; + vm_page_t m; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + /* Clear and invalidate the mapping. */ + opte2 = pte2_load_clear(pte2p); + pmap_tlb_flush(pmap, va); + + KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %#x not link pte2 %#x", + __func__, pmap, va, opte2)); + + if (opte2 & PTE2_W) + pmap->pm_stats.wired_count -= 1; + pmap->pm_stats.resident_count -= 1; + if (pte2_is_managed(opte2)) { + m = PHYS_TO_VM_PAGE(pte2_pa(opte2)); + if (pte2_is_dirty(opte2)) + vm_page_dirty(m); + if (opte2 & PTE2_A) + vm_page_aflag_set(m, PGA_REFERENCED); + pmap_remove_entry(pmap, m, va); + } + return (pmap_unuse_pt2(pmap, va, free)); +} + +/* + * Remove a single page from a process address space. + */ +static void +pmap_remove_page(pmap_t pmap, vm_offset_t va, struct spglist *free) +{ + pt2_entry_t *pte2p; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + KASSERT(curthread->td_pinned > 0, + ("%s: curthread not pinned", __func__)); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if ((pte2p = pmap_pte2_quick(pmap, va)) == NULL || + !pte2_is_valid(pte2_load(pte2p))) + return; + pmap_remove_pte2(pmap, pte2p, va, 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) +{ + vm_offset_t nextva; + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, pte2; + struct spglist free; + + /* + * Perform an unsynchronized read. This is, however, safe. + */ + if (pmap->pm_stats.resident_count == 0) + return; + + SLIST_INIT(&free); + + rw_wlock(&pvh_global_lock); + sched_pin(); + PMAP_LOCK(pmap); + + /* + * Special handling of removing one page. A very common + * operation and easy to short circuit some code. + */ + if (sva + PAGE_SIZE == eva) { + pte1 = pte1_load(pmap_pte1(pmap, sva)); + if (pte1_is_link(pte1)) { + pmap_remove_page(pmap, sva, &free); + goto out; + } + } + + for (; sva < eva; sva = nextva) { + /* + * Calculate address for next L2 page table. + */ + nextva = pte1_trunc(sva + PTE1_SIZE); + if (nextva < sva) + nextva = eva; + if (pmap->pm_stats.resident_count == 0) + break; + + pte1p = pmap_pte1(pmap, sva); + pte1 = pte1_load(pte1p); + + /* + * Weed out invalid mappings. Note: we assume that the L1 page + * table is always allocated, and in kernel virtual. + */ + if (pte1 == 0) + continue; + + if (pte1_is_section(pte1)) { /* * 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; + if (sva + PTE1_SIZE == nextva && eva >= nextva) { + pmap_remove_pte1(pmap, pte1p, sva, &free); continue; - } else if (!pmap_demote_section(pmap, sva)) { + } else if (!pmap_demote_pte1(pmap, pte1p, sva)) { /* The large page mapping was destroyed. */ - sva = next_bucket; continue; } +#ifdef INVARIANTS + else { + /* Update pte1 after demotion. */ + pte1 = pte1_load(pte1p); + } +#endif } + + KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" + " is not link", __func__, pmap, sva, pte1, pte1p)); + /* - * Do one L2 bucket's worth at a time. + * Limit our scan to either the end of the va represented + * by the current L2 page table page, or to the end of the + * range being removed. */ - if (next_bucket > eva) - next_bucket = eva; + if (nextva > eva) + nextva = 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++; + for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; + pte2p++, sva += PAGE_SIZE) { + pte2 = pte2_load(pte2p); + if (!pte2_is_valid(pte2)) 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++; + if (pmap_remove_pte2(pmap, pte2p, sva, &free)) + break; } + } +out: + sched_unpin(); + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + pmap_free_zero_pages(&free); +} - pmap_free_l2_bucket(pmap, l2b, mappings); +/* + * 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; + pt2_entry_t *pte2p, opte2; + pt1_entry_t *pte1p; + vm_offset_t va; + struct spglist free; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("%s: page %p is not managed", __func__, m)); + SLIST_INIT(&free); + rw_wlock(&pvh_global_lock); + sched_pin(); + 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) { + va = pv->pv_va; + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, va); + (void)pmap_demote_pte1(pmap, pte1p, va); + PMAP_UNLOCK(pmap); + } +small_mappings: + while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pmap->pm_stats.resident_count--; + pte1p = pmap_pte1(pmap, pv->pv_va); + KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found " + "a 1mpage in page %p's pv list", __func__, m)); + pte2p = pmap_pte2_quick(pmap, pv->pv_va); + opte2 = pte2_load_clear(pte2p); + pmap_tlb_flush(pmap, pv->pv_va); + KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %x zero pte2", + __func__, pmap, pv->pv_va)); + if (pte2_is_wired(opte2)) + pmap->pm_stats.wired_count--; + if (opte2 & PTE2_A) + vm_page_aflag_set(m, PGA_REFERENCED); + + /* + * Update the vm_page_t clean and reference bits. + */ + if (pte2_is_dirty(opte2)) + vm_page_dirty(m); + pmap_unuse_pt2(pmap, pv->pv_va, &free); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + free_pv_entry(pmap, pv); + PMAP_UNLOCK(pmap); + } + vm_page_aflag_clear(m, PGA_WRITEABLE); + sched_unpin(); + rw_wunlock(&pvh_global_lock); + pmap_free_zero_pages(&free); +} + +/* + * Just subroutine for pmap_remove_pages() to reasonably satisfy + * good coding style, a.k.a. 80 character line width limit hell. + */ +static __inline void +pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv, + struct spglist *free) +{ + vm_paddr_t pa; + vm_page_t m, mt, mpt2pg; + struct md_page *pvh; + + pa = pte1_pa(pte1); + m = PHYS_TO_VM_PAGE(pa); + + KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x", + __func__, m, m->phys_addr, pa)); + KASSERT((m->flags & PG_FICTITIOUS) != 0 || + m < &vm_page_array[vm_page_array_size], + ("%s: bad pte1 %#x", __func__, pte1)); + + if (pte1_is_dirty(pte1)) { + for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++) + vm_page_dirty(mt); } - rw_wunlock(&pvh_global_lock); - if (flushall) - cpu_tlb_flushID(); - cpu_cpwait(); + pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE; + pvh = pa_to_pvh(pa); + TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); + if (TAILQ_EMPTY(&pvh->pv_list)) { + for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++) + if (TAILQ_EMPTY(&mt->md.pv_list)) + vm_page_aflag_clear(mt, PGA_WRITEABLE); + } + mpt2pg = pmap_pt2_page(pmap, pv->pv_va); + if (mpt2pg != NULL) + pmap_unwire_pt2_all(pmap, pv->pv_va, mpt2pg, free); +} +/* + * Just subroutine for pmap_remove_pages() to reasonably satisfy + * good coding style, a.k.a. 80 character line width limit hell. + */ +static __inline void +pmap_remove_pte2_quick(pmap_t pmap, pt2_entry_t pte2, pv_entry_t pv, + struct spglist *free) +{ + vm_paddr_t pa; + vm_page_t m; + struct md_page *pvh; + + pa = pte2_pa(pte2); + m = PHYS_TO_VM_PAGE(pa); + + KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x", + __func__, m, m->phys_addr, pa)); + KASSERT((m->flags & PG_FICTITIOUS) != 0 || + m < &vm_page_array[vm_page_array_size], + ("%s: bad pte2 %#x", __func__, pte2)); + + if (pte2_is_dirty(pte2)) + vm_page_dirty(m); + + pmap->pm_stats.resident_count--; + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) { + pvh = pa_to_pvh(pa); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_aflag_clear(m, PGA_WRITEABLE); + } + pmap_unuse_pt2(pmap, pv->pv_va, free); +} + +/* + * 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) +{ + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, pte2; + pv_entry_t pv; + struct pv_chunk *pc, *npc; + struct spglist free; + int field, idx; + int32_t bit; + uint32_t inuse, bitmask; + boolean_t allfree; + + /* + * Assert that the given pmap is only active on the current + * CPU. Unfortunately, we cannot block another CPU from + * activating the pmap while this function is executing. + */ + KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace), + ("%s: non-current pmap %p", __func__, pmap)); +#if defined(SMP) && defined(INVARIANTS) + { + cpuset_t other_cpus; + + sched_pin(); + other_cpus = pmap->pm_active; + CPU_CLR(PCPU_GET(cpuid), &other_cpus); + sched_unpin(); + KASSERT(CPU_EMPTY(&other_cpus), + ("%s: pmap %p active on other cpus", __func__, pmap)); + } +#endif + SLIST_INIT(&free); + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + sched_pin(); + TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) { + KASSERT(pc->pc_pmap == pmap, ("%s: wrong pmap %p %p", + __func__, pmap, pc->pc_pmap)); + allfree = TRUE; + 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 * 32 + bit; + pv = &pc->pc_pventry[idx]; + inuse &= ~bitmask; + + /* + * Note that we cannot remove wired pages + * from a process' mapping at this time + */ + pte1p = pmap_pte1(pmap, pv->pv_va); + pte1 = pte1_load(pte1p); + if (pte1_is_section(pte1)) { + if (pte1_is_wired(pte1)) { + allfree = FALSE; + continue; + } + pte1_clear(pte1p); + pmap_remove_pte1_quick(pmap, pte1, pv, + &free); + } + else if (pte1_is_link(pte1)) { + pte2p = pt2map_entry(pv->pv_va); + pte2 = pte2_load(pte2p); + + if (!pte2_is_valid(pte2)) { + printf("%s: pmap %p va %#x " + "pte2 %#x\n", __func__, + pmap, pv->pv_va, pte2); + panic("bad pte2"); + } + + if (pte2_is_wired(pte2)) { + allfree = FALSE; + continue; + } + pte2_clear(pte2p); + pmap_remove_pte2_quick(pmap, pte2, pv, + &free); + } else { + printf("%s: pmap %p va %#x pte1 %#x\n", + __func__, pmap, pv->pv_va, pte1); + panic("bad pte1"); + } + + /* 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); + free_pv_chunk(pc); + } + } + tlb_flush_all_ng_local(); + sched_unpin(); + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); + pmap_free_zero_pages(&free); +} + +/* + * This code makes some *MAJOR* assumptions: + * 1. Current pmap & pmap exists. + * 2. Not wired. + * 3. Read access. + * 4. No L2 page table pages. + * but is *MUCH* faster than pmap_enter... + */ +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 mpt2pg) +{ + pt2_entry_t *pte2p, pte2; + vm_paddr_t pa; + struct spglist free; + uint32_t l2prot; + + KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva || + (m->oflags & VPO_UNMANAGED) != 0, + ("%s: managed mapping within the clean submap", __func__)); + rw_assert(&pvh_global_lock, RA_WLOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + /* + * In the case that a L2 page table page is not + * resident, we are creating it here. + */ + if (va < VM_MAXUSER_ADDRESS) { + u_int pte1_idx; + pt1_entry_t pte1, *pte1p; + vm_paddr_t pt2_pa; + + /* + * Get L1 page table things. + */ + pte1_idx = pte1_index(va); + pte1p = pmap_pte1(pmap, va); + pte1 = pte1_load(pte1p); + + if (mpt2pg && (mpt2pg->pindex == (pte1_idx & ~PT2PG_MASK))) { + /* + * Each of NPT2_IN_PG L2 page tables on the page can + * come here. Make sure that associated L1 page table + * link is established. + * + * QQQ: It comes that we don't establish all links to + * L2 page tables for newly allocated L2 page + * tables page. + */ + KASSERT(!pte1_is_section(pte1), + ("%s: pte1 %#x is section", __func__, pte1)); + if (!pte1_is_link(pte1)) { + pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(mpt2pg), + pte1_idx); + pte1_store(pte1p, PTE1_LINK(pt2_pa)); + } + pt2_wirecount_inc(mpt2pg, pte1_idx); + } else { + /* + * If the L2 page table page is mapped, we just + * increment the hold count, and activate it. + */ + if (pte1_is_section(pte1)) { + return (NULL); + } else if (pte1_is_link(pte1)) { + mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); + pt2_wirecount_inc(mpt2pg, pte1_idx); + } else { + mpt2pg = _pmap_allocpte2(pmap, va, + PMAP_ENTER_NOSLEEP); + if (mpt2pg == NULL) + return (NULL); + } + } + } else { + mpt2pg = NULL; + } + + /* + * This call to pt2map_entry() makes the assumption that we are + * entering the page into the current pmap. In order to support + * quick entry into any pmap, one would likely use pmap_pte2_quick(). + * But that isn't as quick as pt2map_entry(). + */ + pte2p = pt2map_entry(va); + pte2 = pte2_load(pte2p); + if (pte2_is_valid(pte2)) { + if (mpt2pg != NULL) { + /* + * Remove extra pte2 reference + */ + pt2_wirecount_dec(mpt2pg, pte1_index(va)); + mpt2pg = NULL; + } + return (NULL); + } + + /* + * 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)) { + if (mpt2pg != NULL) { + SLIST_INIT(&free); + if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) { + pmap_tlb_flush(pmap, va); + pmap_free_zero_pages(&free); + } + + mpt2pg = NULL; + } + return (NULL); + } + + /* + * Increment counters + */ + pmap->pm_stats.resident_count++; + + /* + * Now validate mapping with RO protection + */ + pa = VM_PAGE_TO_PHYS(m); + l2prot = PTE2_RO | PTE2_NM; + if (va < VM_MAXUSER_ADDRESS) + l2prot |= PTE2_U | PTE2_NG; + if ((prot & VM_PROT_EXECUTE) == 0) + l2prot |= PTE2_NX; + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { + /* + * 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, vm_page_pte2_attr(m))); + + return (mpt2pg); +} + +void +pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) +{ + + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL); + rw_wunlock(&pvh_global_lock); 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. + * Tries to create 1MB page mapping. Returns TRUE if successful and + * FALSE otherwise. Fails if (1) a page table page cannot be allocated without + * blocking, (2) a mapping already exists at the specified virtual address, or + * (3) a pv entry cannot be allocated without reclaiming another pv entry. */ -static void -pmap_zero_page_gen(vm_page_t m, int off, int size) +static boolean_t +pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) { - struct czpages *czp; + pt1_entry_t *pte1p; + vm_paddr_t pa; + uint32_t l1prot; - 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; + rw_assert(&pvh_global_lock, RA_WLOCKED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + pte1p = pmap_pte1(pmap, va); + if (pte1_is_valid(pte1_load(pte1p))) { + CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", __func__, + va, pmap); + return (FALSE); } + if ((m->oflags & VPO_UNMANAGED) == 0) { + /* + * Abort this mapping if its PV entry could not be created. + */ + if (!pmap_pv_insert_pte1(pmap, va, VM_PAGE_TO_PHYS(m))) { + CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", + __func__, va, pmap); + return (FALSE); + } + } + /* + * Increment counters. + */ + pmap->pm_stats.resident_count += PTE1_SIZE / PAGE_SIZE; - mtx_unlock(&czp->lock); - sched_unpin(); -} + /* + * Map the section. + * + * QQQ: Why VM_PROT_WRITE is not evaluated and the mapping is + * made readonly? + */ + pa = VM_PAGE_TO_PHYS(m); + l1prot = PTE1_RO | PTE1_NM; + if (va < VM_MAXUSER_ADDRESS) + l1prot |= PTE1_U | PTE1_NG; + if ((prot & VM_PROT_EXECUTE) == 0) + l1prot |= PTE1_NX; + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { + /* + * 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(vm_page_pte2_attr(m)))); -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(); + pmap_pte1_mappings++; + CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va, + pmap); + return (TRUE); } /* - * this routine returns true if a physical page resides - * in the given pmap. + * 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. */ -boolean_t -pmap_page_exists_quick(pmap_t pmap, vm_page_t m) +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 md_page *pvh; - pv_entry_t pv; - int loops = 0; - boolean_t rv; + vm_offset_t va; + vm_page_t m, mpt2pg; + vm_pindex_t diff, psize; - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_page_exists_quick: page %p is not managed", m)); - rv = FALSE; + PDEBUG(6, printf("%s: pmap %p start %#x end %#x m %p prot %#x\n", + __func__, pmap, start, end, m_start, prot)); + + VM_OBJECT_ASSERT_LOCKED(m_start->object); + psize = atop(end - start); + mpt2pg = NULL; + m = m_start; 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; - } + PMAP_LOCK(pmap); + while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { + va = start + ptoa(diff); + if ((va & PTE1_OFFSET) == 0 && va + PTE1_SIZE <= end && + m->psind == 1 && sp_enabled && + pmap_enter_pte1(pmap, va, m, prot)) + m = &m[PTE1_SIZE / PAGE_SIZE - 1]; + else + mpt2pg = pmap_enter_quick_locked(pmap, va, m, prot, + mpt2pg); + m = TAILQ_NEXT(m, listq); } rw_wunlock(&pvh_global_lock); - return (rv); + PMAP_UNLOCK(pmap); +} + +/* + * 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) +{ + pt1_entry_t *pte1p; + vm_paddr_t pa, pte2_pa; + vm_page_t p; + vm_memattr_t pat_mode; + u_int l1attr, l1prot; + + VM_OBJECT_ASSERT_WLOCKED(object); + KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG, + ("%s: non-device object", __func__)); + if ((addr & PTE1_OFFSET) == 0 && (size & PTE1_OFFSET) == 0) { + if (!vm_object_populate(object, pindex, pindex + atop(size))) + return; + p = vm_page_lookup(object, pindex); + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("%s: invalid page %p", __func__, p)); + pat_mode = p->md.pat_mode; + + /* + * Abort the mapping if the first page is not physically + * aligned to a 1MB page boundary. + */ + pte2_pa = VM_PAGE_TO_PHYS(p); + if (pte2_pa & PTE1_OFFSET) + return; + + /* + * Skip the first page. Abort the mapping if the rest of + * the pages are not physically contiguous or have differing + * memory attributes. + */ + p = TAILQ_NEXT(p, listq); + for (pa = pte2_pa + PAGE_SIZE; pa < pte2_pa + size; + pa += PAGE_SIZE) { + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("%s: invalid page %p", __func__, p)); + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) + return; + p = TAILQ_NEXT(p, listq); + } + + /* + * Map using 1MB pages. + * + * QQQ: Well, we are mapping a section, so same condition must + * be hold like during promotion. It looks that only RW mapping + * 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(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); + if (!pte1_is_valid(pte1_load(pte1p))) { + pte1_store(pte1p, PTE1(pa, l1prot, l1attr)); + pmap->pm_stats.resident_count += PTE1_SIZE / + PAGE_SIZE; + pmap_pte1_mappings++; + } + /* Else continue on if the PTE1 is already valid. */ + addr += PTE1_SIZE; + } + PMAP_UNLOCK(pmap); + } +} + +/* + * Do the things to protect a 1mpage in a process. + */ +static void +pmap_protect_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva, + vm_prot_t prot) +{ + pt1_entry_t npte1, opte1; + vm_offset_t eva, va; + vm_page_t m; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & PTE1_OFFSET) == 0, + ("%s: sva is not 1mpage aligned", __func__)); +retry: + opte1 = npte1 = pte1_load(pte1p); + if (pte1_is_managed(opte1)) { + eva = sva + PTE1_SIZE; + for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1)); + va < eva; va += PAGE_SIZE, m++) + if (pte1_is_dirty(opte1)) + vm_page_dirty(m); + } + if ((prot & VM_PROT_WRITE) == 0) + npte1 |= PTE1_RO | PTE1_NM; + if ((prot & VM_PROT_EXECUTE) == 0) + npte1 |= PTE1_NX; + + /* + * QQQ: Herein, execute permission is never set. + * It only can be cleared. So, no icache + * syncing is needed. + */ + + if (npte1 != opte1) { + if (!pte1_cmpset(pte1p, opte1, npte1)) + goto retry; + pmap_tlb_flush(pmap, sva); + } +} + +/* + * 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) +{ + boolean_t pv_lists_locked; + vm_offset_t nextva; + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, opte2, npte2; + + KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot)); + if (prot == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + + if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) == + (VM_PROT_WRITE | VM_PROT_EXECUTE)) + return; + + if (pmap_is_current(pmap)) + pv_lists_locked = FALSE; + else { + pv_lists_locked = TRUE; +resume: + rw_wlock(&pvh_global_lock); + sched_pin(); + } + + PMAP_LOCK(pmap); + for (; sva < eva; sva = nextva) { + /* + * Calculate address for next L2 page table. + */ + nextva = pte1_trunc(sva + PTE1_SIZE); + if (nextva < sva) + nextva = eva; + + pte1p = pmap_pte1(pmap, sva); + pte1 = pte1_load(pte1p); + + /* + * Weed out invalid mappings. Note: we assume that L1 page + * page table is always allocated, and in kernel virtual. + */ + if (pte1 == 0) + continue; + + if (pte1_is_section(pte1)) { + /* + * Are we protecting the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + PTE1_SIZE == nextva && eva >= nextva) { + pmap_protect_pte1(pmap, pte1p, sva, prot); + continue; + } else { + if (!pv_lists_locked) { + pv_lists_locked = TRUE; + if (!rw_try_wlock(&pvh_global_lock)) { + PMAP_UNLOCK(pmap); + goto resume; + } + sched_pin(); + } + if (!pmap_demote_pte1(pmap, pte1p, sva)) { + /* + * The large page mapping + * was destroyed. + */ + continue; + } +#ifdef INVARIANTS + else { + /* Update pte1 after demotion */ + pte1 = pte1_load(pte1p); + } +#endif + } + } + + KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" + " is not link", __func__, pmap, sva, pte1, pte1p)); + + /* + * Limit our scan to either the end of the va represented + * by the current L2 page table page, or to the end of the + * range being protected. + */ + if (nextva > eva) + nextva = eva; + + for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++, + sva += PAGE_SIZE) { + vm_page_t m; +retry: + opte2 = npte2 = pte2_load(pte2p); + if (!pte2_is_valid(opte2)) + continue; + + if ((prot & VM_PROT_WRITE) == 0) { + if (pte2_is_managed(opte2) && + pte2_is_dirty(opte2)) { + m = PHYS_TO_VM_PAGE(pte2_pa(opte2)); + vm_page_dirty(m); + } + npte2 |= PTE2_RO | PTE2_NM; + } + + if ((prot & VM_PROT_EXECUTE) == 0) + npte2 |= PTE2_NX; + + /* + * QQQ: Herein, execute permission is never set. + * It only can be cleared. So, no icache + * syncing is needed. + */ + + if (npte2 != opte2) { + + if (!pte2_cmpset(pte2p, opte2, npte2)) + goto retry; + pmap_tlb_flush(pmap, sva); + } + } + } + if (pv_lists_locked) { + sched_unpin(); + rw_wunlock(&pvh_global_lock); + } + PMAP_UNLOCK(pmap); +} + +/* + * 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) +{ + pmap_t pmap; + pt1_entry_t pte1; + pt2_entry_t pte2; + pv_entry_t pv; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + sched_pin(); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); + if (pte1_is_section(pte1)) { + if (pte1_is_wired(pte1)) + count++; + } else { + KASSERT(pte1_is_link(pte1), + ("%s: pte1 %#x is not link", __func__, pte1)); + pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); + if (pte2_is_wired(pte2)) + count++; + } + PMAP_UNLOCK(pmap); + } + sched_unpin(); + return (count); } /* @@ -4838,62 +4876,136 @@ pmap_page_wired_mappings(vm_page_t m) 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); + 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. + * Returns TRUE if any of the given mappings were used to modify + * physical memory. Otherwise, returns FALSE. Both page and 1mpage + * mappings are supported. */ static boolean_t -pmap_is_referenced_pvh(struct md_page *pvh) +pmap_is_modified_pvh(struct md_page *pvh) { - struct l2_bucket *l2b; pv_entry_t pv; - pd_entry_t *pl1pd; - pt_entry_t *ptep; + pt1_entry_t pte1; + pt2_entry_t pte2; pmap_t pmap; boolean_t rv; rw_assert(&pvh_global_lock, RA_WLOCKED); rv = FALSE; - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { + sched_pin(); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { 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); + pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); + if (pte1_is_section(pte1)) { + rv = pte1_is_dirty(pte1); + } else { + KASSERT(pte1_is_link(pte1), + ("%s: pte1 %#x is not link", __func__, pte1)); + pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); + rv = pte2_is_dirty(pte2); } PMAP_UNLOCK(pmap); if (rv) break; } + sched_unpin(); + 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) +{ + boolean_t rv; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("%s: page %p is not managed", __func__, 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 PTE2s can have PG_M set. + */ + 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); +} + +/* + * 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) +{ + pt1_entry_t pte1; + pt2_entry_t pte2; + boolean_t rv; + + rv = FALSE; + PMAP_LOCK(pmap); + pte1 = pte1_load(pmap_pte1(pmap, addr)); + if (pte1_is_link(pte1)) { + pte2 = pte2_load(pt2map_entry(addr)); + rv = !pte2_is_valid(pte2) ; + } + PMAP_UNLOCK(pmap); + return (rv); +} + +/* + * Returns TRUE if any of the given mappings were referenced and FALSE + * otherwise. Both page and 1mpage mappings are supported. + */ +static boolean_t +pmap_is_referenced_pvh(struct md_page *pvh) +{ + + pv_entry_t pv; + pt1_entry_t pte1; + pt2_entry_t pte2; + pmap_t pmap; + boolean_t rv; + + rw_assert(&pvh_global_lock, RA_WLOCKED); + rv = FALSE; + sched_pin(); + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va)); + if (pte1_is_section(pte1)) { + rv = (pte1 & (PTE1_A | PTE1_V)) == (PTE1_A | PTE1_V); + } else { + pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va)); + rv = (pte2 & (PTE2_A | PTE2_V)) == (PTE2_A | PTE2_V); + } + PMAP_UNLOCK(pmap); + if (rv) + break; + } + sched_unpin(); return (rv); } @@ -4909,7 +5021,7 @@ 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)); + ("%s: page %p is not managed", __func__, m)); rw_wlock(&pvh_global_lock); rv = pmap_is_referenced_pvh(&m->md) || ((m->flags & PG_FICTITIOUS) == 0 && @@ -4918,190 +5030,382 @@ pmap_is_referenced(vm_page_t m) return (rv); } +#define PMAP_TS_REFERENCED_MAX 5 + /* * pmap_ts_referenced: * - * Return the count of reference bits for a page, clearing all of them. + * 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) { + struct md_page *pvh; + pv_entry_t pv, pvf; + pmap_t pmap; + pt1_entry_t *pte1p, opte1; + pt2_entry_t *pte2p; + vm_paddr_t pa; + int rtval = 0; KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_ts_referenced: page %p is not managed", m)); - return (pmap_clearbit(m, PVF_REF)); + ("%s: page %p is not managed", __func__, m)); + pa = VM_PAGE_TO_PHYS(m); + pvh = pa_to_pvh(pa); + rw_wlock(&pvh_global_lock); + sched_pin(); + if ((m->flags & PG_FICTITIOUS) != 0 || + (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL) + goto small_mappings; + pv = pvf; + do { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, pv->pv_va); + opte1 = pte1_load(pte1p); + if ((opte1 & PTE1_A) != 0) { + /* + * Since this reference bit is shared by 256 4KB pages, + * it should not be cleared every time it is tested. + * Apply a simple "hash" function on the physical page + * number, the virtual section number, and the pmap + * address to select one 4KB page out of the 256 + * on which testing the reference bit will result + * in clearing that bit. This function is designed + * to avoid the selection of the same 4KB page + * for every 1MB page mapping. + * + * On demotion, a mapping that hasn't been referenced + * is simply destroyed. To avoid the possibility of a + * subsequent page fault on a demoted wired mapping, + * always leave its reference bit set. Moreover, + * since the section is wired, the current state of + * its reference bit won't affect page replacement. + */ + if ((((pa >> PAGE_SHIFT) ^ (pv->pv_va >> PTE1_SHIFT) ^ + (uintptr_t)pmap) & (NPTE2_IN_PG - 1)) == 0 && + !pte1_is_wired(opte1)) { + pte1_clear_bit(pte1p, PTE1_A); + pmap_tlb_flush(pmap, pv->pv_va); + } + rtval++; + } + PMAP_UNLOCK(pmap); + /* Rotate the PV list if it has more than one entry. */ + if (TAILQ_NEXT(pv, pv_next) != NULL) { + TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next); + } + if (rtval >= PMAP_TS_REFERENCED_MAX) + goto out; + } while ((pv = TAILQ_FIRST(&pvh->pv_list)) != pvf); +small_mappings: + if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL) + goto out; + pv = pvf; + do { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, pv->pv_va); + KASSERT(pte1_is_link(pte1_load(pte1p)), + ("%s: not found a link in page %p's pv list", __func__, m)); + + pte2p = pmap_pte2_quick(pmap, pv->pv_va); + if ((pte2_load(pte2p) & PTE2_A) != 0) { + pte2_clear_bit(pte2p, PTE2_A); + pmap_tlb_flush(pmap, pv->pv_va); + rtval++; + } + PMAP_UNLOCK(pmap); + /* Rotate the PV list if it has more than one entry. */ + if (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); + } + } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && rtval < + PMAP_TS_REFERENCED_MAX); +out: + sched_unpin(); + rw_wunlock(&pvh_global_lock); + return (rtval); } /* - * 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. + * 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. */ -static boolean_t -pmap_is_modified_pvh(struct md_page *pvh) +void +pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) { - pd_entry_t *pl1pd; - struct l2_bucket *l2b; - pv_entry_t pv; - pt_entry_t *ptep; - pmap_t pmap; - boolean_t rv; + vm_offset_t nextva; + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, pte2; + boolean_t pv_lists_locked; - 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; + if (pmap_is_current(pmap)) + pv_lists_locked = FALSE; + else { + pv_lists_locked = TRUE; +resume: + rw_wlock(&pvh_global_lock); + sched_pin(); } + PMAP_LOCK(pmap); + for (; sva < eva; sva = nextva) { + nextva = pte1_trunc(sva + PTE1_SIZE); + if (nextva < sva) + nextva = eva; - return (rv); + pte1p = pmap_pte1(pmap, sva); + pte1 = pte1_load(pte1p); + + /* + * Weed out invalid mappings. Note: we assume that L1 page + * page table is always allocated, and in kernel virtual. + */ + if (pte1 == 0) + continue; + + if (pte1_is_section(pte1)) { + if (!pte1_is_wired(pte1)) + panic("%s: pte1 %#x not wired", __func__, pte1); + + /* + * Are we unwiring the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + PTE1_SIZE == nextva && eva >= nextva) { + pte1_clear_bit(pte1p, PTE1_W); + pmap->pm_stats.wired_count -= PTE1_SIZE / + PAGE_SIZE; + continue; + } else { + if (!pv_lists_locked) { + pv_lists_locked = TRUE; + if (!rw_try_wlock(&pvh_global_lock)) { + PMAP_UNLOCK(pmap); + /* Repeat sva. */ + goto resume; + } + sched_pin(); + } + if (!pmap_demote_pte1(pmap, pte1p, sva)) + panic("%s: demotion failed", __func__); +#ifdef INVARIANTS + else { + /* Update pte1 after demotion */ + pte1 = pte1_load(pte1p); + } +#endif + } + } + + KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p" + " is not link", __func__, pmap, sva, pte1, pte1p)); + + /* + * Limit our scan to either the end of the va represented + * by the current L2 page table page, or to the end of the + * range being protected. + */ + if (nextva > eva) + nextva = eva; + + for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++, + sva += PAGE_SIZE) { + pte2 = pte2_load(pte2p); + if (!pte2_is_valid(pte2)) + continue; + if (!pte2_is_wired(pte2)) + panic("%s: pte2 %#x is missing PTE2_W", + __func__, pte2); + + /* + * PTE2_W must be cleared atomically. Although the pmap + * lock synchronizes access to PTE2_W, another processor + * could be changing PTE2_NM and/or PTE2_A concurrently. + */ + pte2_clear_bit(pte2p, PTE2_W); + pmap->pm_stats.wired_count--; + } + } + if (pv_lists_locked) { + sched_unpin(); + rw_wunlock(&pvh_global_lock); + } + PMAP_UNLOCK(pmap); } -boolean_t -pmap_is_modified(vm_page_t m) +/* + * Clear the write and modified bits in each of the given page's mappings. + */ +void +pmap_remove_write(vm_page_t m) { - boolean_t rv; + struct md_page *pvh; + pv_entry_t next_pv, pv; + pmap_t pmap; + pt1_entry_t *pte1p; + pt2_entry_t *pte2p, opte2; + vm_offset_t va; KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_is_modified: page %p is not managed", m)); + ("%s: page %p is not managed", __func__, 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. + * 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 (FALSE); + return; 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)))); + sched_pin(); + 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_next, next_pv) { + va = pv->pv_va; + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, va); + if (!(pte1_load(pte1p) & PTE1_RO)) + (void)pmap_demote_pte1(pmap, pte1p, va); + PMAP_UNLOCK(pmap); + } +small_mappings: + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, pv->pv_va); + KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found" + " a section in page %p's pv list", __func__, m)); + pte2p = pmap_pte2_quick(pmap, pv->pv_va); +retry: + opte2 = pte2_load(pte2p); + if (!(opte2 & PTE2_RO)) { + if (!pte2_cmpset(pte2p, opte2, + opte2 | (PTE2_RO | PTE2_NM))) + goto retry; + if (pte2_is_dirty(opte2)) + vm_page_dirty(m); + pmap_tlb_flush(pmap, pv->pv_va); + } + PMAP_UNLOCK(pmap); + } + vm_page_aflag_clear(m, PGA_WRITEABLE); + sched_unpin(); 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. + * 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) { - struct l2_bucket *l2b; - struct pv_entry *pve; - pd_entry_t l1pd; - pt_entry_t *ptep, opte, pte; - vm_offset_t next_bucket; + pt1_entry_t *pte1p, opte1; + pt2_entry_t *pte2p, pte2; + vm_offset_t pdnxt; vm_page_t m; + boolean_t pv_lists_locked; if (advice != MADV_DONTNEED && advice != MADV_FREE) return; - rw_wlock(&pvh_global_lock); + if (pmap_is_current(pmap)) + pv_lists_locked = FALSE; + else { + pv_lists_locked = TRUE; +resume: + rw_wlock(&pvh_global_lock); + sched_pin(); + } 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()) + for (; sva < eva; sva = pdnxt) { + pdnxt = pte1_trunc(sva + PTE1_SIZE); + if (pdnxt < sva) + pdnxt = eva; + pte1p = pmap_pte1(pmap, sva); + opte1 = pte1_load(pte1p); + if (!pte1_is_valid(opte1)) /* XXX */ + continue; + else if (pte1_is_section(opte1)) { + if (!pte1_is_managed(opte1)) continue; - if (!pmap_demote_section(pmap, sva)) { + if (!pv_lists_locked) { + pv_lists_locked = TRUE; + if (!rw_try_wlock(&pvh_global_lock)) { + PMAP_UNLOCK(pmap); + goto resume; + } + sched_pin(); + } + if (!pmap_demote_pte1(pmap, pte1p, 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. + * access may repromote. Since the underlying L2 page + * table is fully populated, this removal never + * frees a L2 page table page. */ - 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 (!pte1_is_wired(opte1)) { + pte2p = pmap_pte2_quick(pmap, sva); + KASSERT(pte2_is_valid(pte2_load(pte2p)), + ("%s: invalid PTE2", __func__)); + pmap_remove_pte2(pmap, pte2p, sva, NULL); } } - 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) + if (pdnxt > eva) + pdnxt = eva; + for (pte2p = pmap_pte2_quick(pmap, sva); sva != pdnxt; pte2p++, + sva += PAGE_SIZE) { + pte2 = pte2_load(pte2p); + if (!pte2_is_valid(pte2) || !pte2_is_managed(pte2)) continue; - m = PHYS_TO_VM_PAGE(l2pte_pa(opte)); - if (m == NULL || (m->oflags & VPO_UNMANAGED) != 0) - continue; - else if (L2_S_WRITABLE(opte)) { + else if (pte2_is_dirty(pte2)) { 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. + * Future calls to pmap_is_modified() + * can be avoided by making the page + * dirty now. */ - } 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 + m = PHYS_TO_VM_PAGE(pte2_pa(pte2)); + vm_page_dirty(m); + } + pte2_set_bit(pte2p, PTE2_NM); + pte2_clear_bit(pte2p, PTE2_A); + } else if ((pte2 & PTE2_A) != 0) + pte2_clear_bit(pte2p, PTE2_A); + 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); - } + pmap_tlb_flush(pmap, sva); } } - cpu_cpwait(); - rw_wunlock(&pvh_global_lock); + if (pv_lists_locked) { + sched_unpin(); + rw_wunlock(&pvh_global_lock); + } PMAP_UNLOCK(pmap); } @@ -5111,102 +5415,602 @@ pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice) void pmap_clear_modify(vm_page_t m) { + struct md_page *pvh; + pv_entry_t next_pv, pv; + pmap_t pmap; + pt1_entry_t *pte1p, opte1; + pt2_entry_t *pte2p, opte2; + vm_offset_t va; KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_clear_modify: page %p is not managed", m)); + ("%s: page %p is not managed", __func__, m)); VM_OBJECT_ASSERT_WLOCKED(m->object); KASSERT(!vm_page_xbusied(m), - ("pmap_clear_modify: page %p is exclusive busied", m)); + ("%s: page %p is exclusive busy", __func__, 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 the page is not PGA_WRITEABLE, then no PTE2s can have PTE2_NM + * cleared. 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) + if ((m->flags & PGA_WRITEABLE) == 0) return; - if (pmap_is_modified(m)) - pmap_clearbit(m, PVF_MOD); + rw_wlock(&pvh_global_lock); + sched_pin(); + 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_next, next_pv) { + va = pv->pv_va; + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, va); + opte1 = pte1_load(pte1p); + if (!(opte1 & PTE1_RO)) { + if (pmap_demote_pte1(pmap, pte1p, va) && + !pte1_is_wired(opte1)) { + /* + * Write protect the mapping to a + * single page so that a subsequent + * write access may repromote. + */ + va += VM_PAGE_TO_PHYS(m) - pte1_pa(opte1); + pte2p = pmap_pte2_quick(pmap, va); + opte2 = pte2_load(pte2p); + if ((opte2 & PTE2_V)) { + pte2_set_bit(pte2p, PTE2_NM | PTE2_RO); + vm_page_dirty(m); + pmap_tlb_flush(pmap, va); + } + } + } + PMAP_UNLOCK(pmap); + } +small_mappings: + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pte1p = pmap_pte1(pmap, pv->pv_va); + KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found" + " a section in page %p's pv list", __func__, m)); + pte2p = pmap_pte2_quick(pmap, pv->pv_va); + if (pte2_is_dirty(pte2_load(pte2p))) { + pte2_set_bit(pte2p, PTE2_NM); + pmap_tlb_flush(pmap, pv->pv_va); + } + PMAP_UNLOCK(pmap); + } + sched_unpin(); + rw_wunlock(&pvh_global_lock); } /* - * Clear the write and modified bits in each of the given page's mappings. + * Sets the memory attribute for the specified page. */ void -pmap_remove_write(vm_page_t m) +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) { - KASSERT((m->oflags & VPO_UNMANAGED) == 0, - ("pmap_remove_write: page %p is not managed", m)); + struct sysmaps *sysmaps; + vm_memattr_t oma; + vm_paddr_t pa; + oma = m->md.pat_mode; + m->md.pat_mode = ma; + + CTR5(KTR_PMAP, "%s: page %p - 0x%08X oma: %d, ma: %d", __func__, m, + VM_PAGE_TO_PHYS(m), oma, ma); + if ((m->flags & PG_FICTITIOUS) != 0) + return; +#if 0 /* - * 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. + * If "m" is a normal page, flush it from the cache. + * + * First, try to find an existing mapping of the page by sf + * buffer. sf_buf_invalidate_cache() modifies mapping and + * flushes the cache. */ - VM_OBJECT_ASSERT_WLOCKED(m->object); - if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0) - pmap_clearbit(m, PVF_WRITE); + if (sf_buf_invalidate_cache(m, oma)) + return; +#endif + /* + * If page is not mapped by sf buffer, map the page + * transient and do invalidation. + */ + if (ma != oma) { + pa = VM_PAGE_TO_PHYS(m); + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + if (*sysmaps->CMAP2) + panic("%s: CMAP2 busy", __func__); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, + 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); + sched_unpin(); + mtx_unlock(&sysmaps->lock); + } } +/* + * Miscellaneous support routines follow + */ /* - * perform the pmap work for mincore + * Returns TRUE if the given page is mapped individually or as part of + * a 1mpage. 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); +} + +/* + * 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 md_page *pvh; + pv_entry_t pv; + int loops = 0; + boolean_t rv; + + KASSERT((m->oflags & VPO_UNMANAGED) == 0, + ("%s: page %p is not managed", __func__, m)); + rv = FALSE; + rw_wlock(&pvh_global_lock); + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { + 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_next) { + if (PV_PMAP(pv) == pmap) { + rv = TRUE; + break; + } + loops++; + if (loops >= 16) + break; + } + } + rw_wunlock(&pvh_global_lock); + return (rv); +} + +/* + * 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) +{ + struct sysmaps *sysmaps; + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + 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, + vm_page_pte2_attr(m))); + pagezero(sysmaps->CADDR2); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +/* + * 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) +{ + struct sysmaps *sysmaps; + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + 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, + vm_page_pte2_attr(m))); + if (off == 0 && size == PAGE_SIZE) + pagezero(sysmaps->CADDR2); + else + bzero(sysmaps->CADDR2 + off, size); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +/* + * 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) +{ + + if (pte2_load(CMAP3) != 0) + panic("%s: CMAP3 busy", __func__); + sched_pin(); + pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, + vm_page_pte2_attr(m))); + pagezero(CADDR3); + pte2_clear(CMAP3); + tlb_flush((vm_offset_t)CADDR3); + sched_unpin(); +} + +/* + * 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 src, vm_page_t dst) +{ + struct sysmaps *sysmaps; + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + if (pte2_load(sysmaps->CMAP1) != 0) + panic("%s: CMAP1 busy", __func__); + 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, vm_page_pte2_attr(src))); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(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); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +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) +{ + struct sysmaps *sysmaps; + vm_page_t a_pg, b_pg; + char *a_cp, *b_cp; + vm_offset_t a_pg_offset, b_pg_offset; + int cnt; + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + if (*sysmaps->CMAP1 != 0) + panic("pmap_copy_pages: CMAP1 busy"); + if (*sysmaps->CMAP2 != 0) + panic("pmap_copy_pages: CMAP2 busy"); + 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); + pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(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, 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; + bcopy(a_cp, b_cp, cnt); + a_offset += cnt; + b_offset += cnt; + xfersize -= cnt; + } + pte2_clear(sysmaps->CMAP1); + tlb_flush((vm_offset_t)sysmaps->CADDR1); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +vm_offset_t +pmap_quick_enter_page(vm_page_t m) +{ + pt2_entry_t *pte2p; + vm_offset_t qmap_addr; + + critical_enter(); + qmap_addr = PCPU_GET(qmap_addr); + pte2p = pt2map_entry(qmap_addr); + + KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__)); + + pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, + vm_page_pte2_attr(m))); + return (qmap_addr); +} + +void +pmap_quick_remove_page(vm_offset_t addr) +{ + pt2_entry_t *pte2p; + vm_offset_t qmap_addr; + + qmap_addr = PCPU_GET(qmap_addr); + pte2p = pt2map_entry(qmap_addr); + + KASSERT(addr == qmap_addr, ("%s: invalid address", __func__)); + KASSERT(pte2_load(pte2p) != 0, ("%s: PTE2 not in use", __func__)); + + pte2_clear(pte2p); + tlb_flush(qmap_addr); + critical_exit(); +} + +/* + * 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) +{ + struct spglist free; + vm_offset_t addr; + vm_offset_t end_addr = src_addr + len; + vm_offset_t nextva; + + if (dst_addr != src_addr) + return; + + if (!pmap_is_current(src_pmap)) + return; + + rw_wlock(&pvh_global_lock); + if (dst_pmap < src_pmap) { + PMAP_LOCK(dst_pmap); + PMAP_LOCK(src_pmap); + } else { + PMAP_LOCK(src_pmap); + PMAP_LOCK(dst_pmap); + } + sched_pin(); + for (addr = src_addr; addr < end_addr; addr = nextva) { + pt2_entry_t *src_pte2p, *dst_pte2p; + vm_page_t dst_mpt2pg, src_mpt2pg; + pt1_entry_t src_pte1; + u_int pte1_idx; + + KASSERT(addr < VM_MAXUSER_ADDRESS, + ("%s: invalid to pmap_copy page tables", __func__)); + + nextva = pte1_trunc(addr + PTE1_SIZE); + if (nextva < addr) + nextva = end_addr; + + pte1_idx = pte1_index(addr); + src_pte1 = src_pmap->pm_pt1[pte1_idx]; + if (pte1_is_section(src_pte1)) { + if ((addr & PTE1_OFFSET) != 0 || + (addr + PTE1_SIZE) > end_addr) + continue; + if (dst_pmap->pm_pt1[pte1_idx] == 0 && + (!pte1_is_managed(src_pte1) || + pmap_pv_insert_pte1(dst_pmap, addr, + pte1_pa(src_pte1)))) { + dst_pmap->pm_pt1[pte1_idx] = src_pte1 & + ~PTE1_W; + dst_pmap->pm_stats.resident_count += + PTE1_SIZE / PAGE_SIZE; + pmap_pte1_mappings++; + } + continue; + } else if (!pte1_is_link(src_pte1)) + continue; + + src_mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(src_pte1)); + + /* + * We leave PT2s to be linked from PT1 even if they are not + * referenced until all PT2s in a page are without reference. + * + * QQQ: It could be changed ... + */ +#if 0 /* single_pt2_link_is_cleared */ + KASSERT(pt2_wirecount_get(src_mpt2pg, pte1_idx) > 0, + ("%s: source page table page is unused", __func__)); +#else + if (pt2_wirecount_get(src_mpt2pg, pte1_idx) == 0) + continue; +#endif + if (nextva > end_addr) + nextva = end_addr; + + src_pte2p = pt2map_entry(addr); + while (addr < nextva) { + pt2_entry_t temp_pte2; + temp_pte2 = pte2_load(src_pte2p); + /* + * we only virtual copy managed pages + */ + if (pte2_is_managed(temp_pte2)) { + dst_mpt2pg = pmap_allocpte2(dst_pmap, addr, + PMAP_ENTER_NOSLEEP); + if (dst_mpt2pg == NULL) + goto out; + dst_pte2p = pmap_pte2_quick(dst_pmap, addr); + if (!pte2_is_valid(pte2_load(dst_pte2p)) && + pmap_try_insert_pv_entry(dst_pmap, addr, + PHYS_TO_VM_PAGE(pte2_pa(temp_pte2)))) { + /* + * Clear the wired, modified, and + * accessed (referenced) bits + * during the copy. + */ + temp_pte2 &= ~(PTE2_W | PTE2_A); + temp_pte2 |= PTE2_NM; + pte2_store(dst_pte2p, temp_pte2); + dst_pmap->pm_stats.resident_count++; + } else { + SLIST_INIT(&free); + if (pmap_unwire_pt2(dst_pmap, addr, + dst_mpt2pg, &free)) { + pmap_tlb_flush(dst_pmap, addr); + pmap_free_zero_pages(&free); + } + goto out; + } + if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >= + pt2_wirecount_get(src_mpt2pg, pte1_idx)) + break; + } + addr += PAGE_SIZE; + src_pte2p++; + } + } +out: + sched_unpin(); + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(src_pmap); + PMAP_UNLOCK(dst_pmap); +} + +/* + * Increase the starting virtual address of the given mapping if a + * different alignment might result in more section mappings. + */ +void +pmap_align_superpage(vm_object_t object, vm_ooffset_t offset, + vm_offset_t *addr, vm_size_t size) +{ + vm_offset_t pte1_offset; + + if (size < PTE1_SIZE) + return; + if (object != NULL && (object->flags & OBJ_COLORED) != 0) + offset += ptoa(object->pg_color); + pte1_offset = offset & PTE1_OFFSET; + if (size - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) < PTE1_SIZE || + (*addr & PTE1_OFFSET) == pte1_offset) + return; + if ((*addr & PTE1_OFFSET) < pte1_offset) + *addr = pte1_trunc(*addr) + pte1_offset; + else + *addr = pte1_roundup(*addr) + pte1_offset; +} + +void +pmap_activate(struct thread *td) +{ + pmap_t pmap, oldpmap; + u_int cpuid, ttb; + + PDEBUG(9, printf("%s: td = %08x\n", __func__, (uint32_t)td)); + + critical_enter(); + pmap = vmspace_pmap(td->td_proc->p_vmspace); + oldpmap = PCPU_GET(curpmap); + cpuid = PCPU_GET(cpuid); + +#if defined(SMP) + CPU_CLR_ATOMIC(cpuid, &oldpmap->pm_active); + CPU_SET_ATOMIC(cpuid, &pmap->pm_active); +#else + CPU_CLR(cpuid, &oldpmap->pm_active); + CPU_SET(cpuid, &pmap->pm_active); +#endif + + ttb = pmap_ttb_get(pmap); + + /* + * pmap_activate is for the current thread on the current cpu + */ + td->td_pcb->pcb_pagedir = ttb; + cp15_ttbr_set(ttb); + PCPU_SET(curpmap, pmap); + critical_exit(); +} + +/* + * 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; + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, pte2; vm_paddr_t pa; - vm_page_t m; - int val; boolean_t managed; + int val; 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); + pte1p = pmap_pte1(pmap, addr); + pte1 = pte1_load(pte1p); + if (pte1_is_section(pte1)) { + pa = trunc_page(pte1_pa(pte1) | (addr & PTE1_OFFSET)); + managed = pte1_is_managed(pte1); val = MINCORE_SUPER | MINCORE_INCORE; - if (L1_S_WRITABLE(l1pd)) + if (pte1_is_dirty(pte1)) 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; - } + if (pte1 & PTE1_A) + val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; + } else if (pte1_is_link(pte1)) { + pte2p = pmap_pte2(pmap, addr); + pte2 = pte2_load(pte2p); + pmap_pte2_release(pte2p); + pa = pte2_pa(pte2); + managed = pte2_is_managed(pte2); val = MINCORE_INCORE; - if (L2_S_WRITABLE(pte)) + if (pte2_is_dirty(pte2)) val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; + if (pte2 & PTE2_A) + val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; + } else { 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; - } + val = 0; } if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) != (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) { @@ -5214,239 +6018,648 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa) 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) +pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa) { -} + vm_offset_t sva; + uint32_t l2attr; -/* - * 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; + KASSERT((size & PAGE_MASK) == 0, + ("%s: device mapping not page-sized", __func__)); - 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)]); + sva = va; + l2attr = vm_memattr_to_pte2(VM_MEMATTR_DEVICE); + while (size != 0) { + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, l2attr); va += PAGE_SIZE; pa += PAGE_SIZE; - resid -= PAGE_SIZE; + size -= PAGE_SIZE; } -#ifdef VERBOSE_INIT_ARM - printf("\n"); -#endif - return (size); - + tlb_flush_range(sva, va - sva); } void -pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +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; + } + tlb_flush_range(sva, va - sva); +} + +void +pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb) +{ + + pcb->pcb_pagedir = pmap_ttb_get(pmap); +} + + +/* + * Clean L1 data cache range by physical address. + * The range must be within a single page. + */ +static void +pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, uint32_t attr) +{ + struct sysmaps *sysmaps; + + KASSERT(((pa & PAGE_MASK) + size) <= PAGE_SIZE, + ("%s: not on single page", __func__)); + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + if (*sysmaps->CMAP3) + panic("%s: CMAP3 busy", __func__); + 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); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +/* + * Sync instruction cache range which is not mapped yet. + */ +void +cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + uint32_t len, offset; + vm_page_t m; + + /* Write back d-cache on given address range. */ + offset = pa & PAGE_MASK; + for ( ; size != 0; size -= len, pa += len, offset = 0) { + len = min(PAGE_SIZE - offset, 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, vm_page_pte2_attr(m)); + } /* - * Remember the memattr in a field that gets used to set the appropriate - * bits in the PTEs as mappings are established. + * I-cache is VIPT. Only way how to flush all virtual mappings + * on given physical address is to invalidate all i-cache. */ - m->md.pv_memattr = ma; + icache_inv_all(); +} + +void +pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size) +{ + + /* Write back d-cache on given address range. */ + if (va >= VM_MIN_KERNEL_ADDRESS) { + dcache_wb_pou(va, size); + } else { + uint32_t len, offset; + vm_paddr_t pa; + vm_page_t m; + + offset = va & PAGE_MASK; + for ( ; size != 0; size -= len, va += len, offset = 0) { + pa = pmap_extract(pmap, va); /* offset is preserved */ + len = min(PAGE_SIZE - offset, 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, vm_page_pte2_attr(m)); + } + } + /* + * I-cache is VIPT. Only way how to flush all virtual mappings + * on given physical address is to invalidate all i-cache. + */ + icache_inv_all(); +} + +/* + * The implementation of pmap_fault() uses IN_RANGE2() macro which + * depends on the fact that given range size is a power of 2. + */ +CTASSERT(powerof2(NB_IN_PT1)); +CTASSERT(powerof2(PT2MAP_SIZE)); + +#define IN_RANGE2(addr, start, size) \ + ((vm_offset_t)(start) == ((vm_offset_t)(addr) & ~((size) - 1))) + +/* + * Handle access and R/W emulation faults. + */ +int +pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode) +{ + pt1_entry_t *pte1p, pte1; + pt2_entry_t *pte2p, pte2; + + if (pmap == NULL) + pmap = kernel_pmap; /* - * 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. + * In kernel, we should never get abort with FAR which is in range of + * pmap->pm_pt1 or PT2MAP address spaces. If it happens, stop here + * and print out a useful abort message and even get to the debugger + * otherwise it likely ends with never ending loop of aborts. */ - if (TAILQ_FIRST(&m->md.pv_list) != NULL) - panic("Can't change memattr on page with existing mappings"); + if (__predict_false(IN_RANGE2(far, pmap->pm_pt1, NB_IN_PT1))) { + /* + * All L1 tables should always be mapped and present. + * However, we check only current one herein. For user mode, + * only permission abort from malicious user is not fatal. + * And alignment abort as it may have higher priority. + */ + if (!usermode || (idx != FAULT_ALIGN && idx != FAULT_PERM_L2)) { + CTR4(KTR_PMAP, "%s: pmap %#x pm_pt1 %#x far %#x", + __func__, pmap, pmap->pm_pt1, far); + panic("%s: pm_pt1 abort", __func__); + } + return (KERN_INVALID_ADDRESS); + } + if (__predict_false(IN_RANGE2(far, PT2MAP, PT2MAP_SIZE))) { + /* + * PT2MAP should be always mapped and present in current + * L1 table. However, only existing L2 tables are mapped + * in PT2MAP. For user mode, only L2 translation abort and + * permission abort from malicious user is not fatal. + * And alignment abort as it may have higher priority. + */ + if (!usermode || (idx != FAULT_ALIGN && + idx != FAULT_TRAN_L2 && idx != FAULT_PERM_L2)) { + CTR4(KTR_PMAP, "%s: pmap %#x PT2MAP %#x far %#x", + __func__, pmap, PT2MAP, far); + panic("%s: PT2MAP abort", __func__); + } + return (KERN_INVALID_ADDRESS); + } + + /* + * Accesss bits for page and section. Note that the entry + * is not in TLB yet, so TLB flush is not necessary. + * + * QQQ: This is hardware emulation, we do not call userret() + * for aborts from user mode. + * We do not lock PMAP, so cmpset() is a need. Hopefully, + * no one removes the mapping when we are here. + */ + if (idx == FAULT_ACCESS_L2) { + pte2p = pt2map_entry(far); +pte2_seta: + pte2 = pte2_load(pte2p); + if (pte2_is_valid(pte2)) { + if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_A)) { + goto pte2_seta; + } + return (KERN_SUCCESS); + } + } + if (idx == FAULT_ACCESS_L1) { + pte1p = pmap_pte1(pmap, far); +pte1_seta: + pte1 = pte1_load(pte1p); + if (pte1_is_section(pte1)) { + if (!pte1_cmpset(pte1p, pte1, pte1 | PTE1_A)) { + goto pte1_seta; + } + return (KERN_SUCCESS); + } + } + + /* + * Handle modify bits for page and section. Note that the modify + * bit is emulated by software. So PTEx_RO is software read only + * bit and PTEx_NM flag is real hardware read only bit. + * + * QQQ: This is hardware emulation, we do not call userret() + * for aborts from user mode. + * We do not lock PMAP, so cmpset() is a need. Hopefully, + * no one removes the mapping when we are here. + */ + if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L2)) { + pte2p = pt2map_entry(far); +pte2_setrw: + pte2 = pte2_load(pte2p); + if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) && + (pte2 & PTE2_NM)) { + if (!pte2_cmpset(pte2p, pte2, pte2 & ~PTE2_NM)) { + goto pte2_setrw; + } + tlb_flush(trunc_page(far)); + return (KERN_SUCCESS); + } + } + if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L1)) { + pte1p = pmap_pte1(pmap, far); +pte1_setrw: + pte1 = pte1_load(pte1p); + if (pte1_is_section(pte1) && !(pte1 & PTE1_RO) && + (pte1 & PTE1_NM)) { + if (!pte1_cmpset(pte1p, pte1, pte1 & ~PTE1_NM)) { + goto pte1_setrw; + } + tlb_flush(pte1_trunc(far)); + return (KERN_SUCCESS); + } + } + + /* + * QQQ: The previous code, mainly fast handling of access and + * modify bits aborts, could be moved to ASM. Now we are + * starting to deal with not fast aborts. + */ + +#ifdef INVARIANTS + /* + * Read an entry in PT2TAB associated with both pmap and far. + * It's safe because PT2TAB is always mapped. + * + * QQQ: We do not lock PMAP, so false positives could happen if + * the mapping is removed concurrently. + */ + pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far)); + if (pte2_is_valid(pte2)) { + /* + * Now, when we know that L2 page table is allocated, + * we can use PT2MAP to get L2 page table entry. + */ + pte2 = pte2_load(pt2map_entry(far)); + if (pte2_is_valid(pte2)) { + /* + * If L2 page table entry is valid, make sure that + * L1 page table entry is valid too. Note that we + * leave L2 page entries untouched when promoted. + */ + pte1 = pte1_load(pmap_pte1(pmap, far)); + if (!pte1_is_valid(pte1)) { + panic("%s: missing L1 page entry (%p, %#x)", + __func__, pmap, far); + } + } + } +#endif + return (KERN_FAILURE); } + +/* !!!! REMOVE !!!! */ +void vector_page_setprot(int p) +{ +} + +#if defined(PMAP_DEBUG) +/* + * Reusing of KVA used in pmap_zero_page function !!! + */ +static void +pmap_zero_page_check(vm_page_t m) +{ + uint32_t *p, *end; + struct sysmaps *sysmaps; + + sched_pin(); + sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; + mtx_lock(&sysmaps->lock); + 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, + vm_page_pte2_attr(m))); + end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE); + for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++) + if (*p != 0) + panic("%s: page %p not zero, va: %p", __func__, m, + sysmaps->CADDR2); + pte2_clear(sysmaps->CMAP2); + tlb_flush((vm_offset_t)sysmaps->CADDR2); + sched_unpin(); + mtx_unlock(&sysmaps->lock); +} + +int +pmap_pid_dump(int pid) +{ + pmap_t pmap; + struct proc *p; + int npte2 = 0; + int i, j, index; + + sx_slock(&allproc_lock); + FOREACH_PROC_IN_SYSTEM(p) { + if (p->p_pid != pid || p->p_vmspace == NULL) + continue; + index = 0; + pmap = vmspace_pmap(p->p_vmspace); + for (i = 0; i < NPTE1_IN_PT1; i++) { + pt1_entry_t pte1; + pt2_entry_t *pte2p, pte2; + vm_offset_t base, va; + vm_paddr_t pa; + vm_page_t m; + + base = i << PTE1_SHIFT; + pte1 = pte1_load(&pmap->pm_pt1[i]); + + if (pte1_is_section(pte1)) { + /* + * QQQ: Do something here! + */ + } else if (pte1_is_link(pte1)) { + for (j = 0; j < NPTE2_IN_PT2; j++) { + va = base + (j << PAGE_SHIFT); + if (va >= VM_MIN_KERNEL_ADDRESS) { + if (index) { + index = 0; + printf("\n"); + } + sx_sunlock(&allproc_lock); + return (npte2); + } + pte2p = pmap_pte2(pmap, va); + pte2 = pte2_load(pte2p); + pmap_pte2_release(pte2p); + if (!pte2_is_valid(pte2)) + continue; + + pa = pte2_pa(pte2); + m = PHYS_TO_VM_PAGE(pa); + printf("va: 0x%x, pa: 0x%x, h: %d, w:" + " %d, f: 0x%x", va, pa, + m->hold_count, m->wire_count, + m->flags); + npte2++; + index++; + if (index >= 2) { + index = 0; + printf("\n"); + } else { + printf(" "); + } + } + } + } + } + sx_sunlock(&allproc_lock); + return (npte2); +} + +#endif + +#ifdef DDB +static pt2_entry_t * +pmap_pte2_ddb(pmap_t pmap, vm_offset_t va) +{ + pt1_entry_t pte1; + vm_paddr_t pt2pg_pa; + + pte1 = pte1_load(pmap_pte1(pmap, va)); + if (!pte1_is_link(pte1)) + return (NULL); + + if (pmap_is_current(pmap)) + return (pt2map_entry(va)); + + /* Note that L2 page table size is not equal to PAGE_SIZE. */ + pt2pg_pa = trunc_page(pte1_link_pa(pte1)); + if (pte2_pa(pte2_load(PMAP3)) != pt2pg_pa) { + pte2_store(PMAP3, PTE2_KPT(pt2pg_pa)); +#ifdef SMP + PMAP3cpu = PCPU_GET(cpuid); +#endif + tlb_flush_local((vm_offset_t)PADDR3); + } +#ifdef SMP + else if (PMAP3cpu != PCPU_GET(cpuid)) { + PMAP3cpu = PCPU_GET(cpuid); + tlb_flush_local((vm_offset_t)PADDR3); + } +#endif + return (PADDR3 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); +} + +static void +dump_pmap(pmap_t pmap) +{ + + printf("pmap %p\n", pmap); + printf(" pm_pt1: %p\n", pmap->pm_pt1); + printf(" pm_pt2tab: %p\n", pmap->pm_pt2tab); + printf(" pm_active: 0x%08lX\n", pmap->pm_active.__bits[0]); +} + +DB_SHOW_COMMAND(pmaps, pmap_list_pmaps) +{ + + pmap_t pmap; + LIST_FOREACH(pmap, &allpmaps, pm_list) { + dump_pmap(pmap); + } +} + +static int +pte2_class(pt2_entry_t pte2) +{ + int cls; + + cls = (pte2 >> 2) & 0x03; + cls |= (pte2 >> 4) & 0x04; + return (cls); +} + +static void +dump_section(pmap_t pmap, uint32_t pte1_idx) +{ +} + +static void +dump_link(pmap_t pmap, uint32_t pte1_idx, boolean_t invalid_ok) +{ + uint32_t i; + vm_offset_t va; + pt2_entry_t *pte2p, pte2; + vm_page_t m; + + va = pte1_idx << PTE1_SHIFT; + pte2p = pmap_pte2_ddb(pmap, va); + for (i = 0; i < NPTE2_IN_PT2; i++, pte2p++, va += PAGE_SIZE) { + pte2 = pte2_load(pte2p); + if (pte2 == 0) + continue; + if (!pte2_is_valid(pte2)) { + printf(" 0x%08X: 0x%08X", va, pte2); + if (!invalid_ok) + printf(" - not valid !!!"); + printf("\n"); + continue; + } + m = PHYS_TO_VM_PAGE(pte2_pa(pte2)); + printf(" 0x%08X: 0x%08X, TEX%d, s:%d, g:%d, m:%p", va , pte2, + pte2_class(pte2), !!(pte2 & PTE2_S), !(pte2 & PTE2_NG), m); + if (m != NULL) { + printf(" v:%d h:%d w:%d f:0x%04X\n", m->valid, + m->hold_count, m->wire_count, m->flags); + } else { + printf("\n"); + } + } +} + +static __inline boolean_t +is_pv_chunk_space(vm_offset_t va) +{ + + if ((((vm_offset_t)pv_chunkbase) <= va) && + (va < ((vm_offset_t)pv_chunkbase + PAGE_SIZE * pv_maxchunks))) + return (TRUE); + return (FALSE); +} + +DB_SHOW_COMMAND(pmap, pmap_pmap_print) +{ + /* XXX convert args. */ + pmap_t pmap = (pmap_t)addr; + pt1_entry_t pte1; + pt2_entry_t pte2; + vm_offset_t va, eva; + vm_page_t m; + uint32_t i; + boolean_t invalid_ok, dump_link_ok, dump_pv_chunk; + + if (have_addr) { + pmap_t pm; + + LIST_FOREACH(pm, &allpmaps, pm_list) + if (pm == pmap) break; + if (pm == NULL) { + printf("given pmap %p is not in allpmaps list\n", pmap); + return; + } + } else + pmap = PCPU_GET(curpmap); + + eva = (modif[0] == 'u') ? VM_MAXUSER_ADDRESS : 0xFFFFFFFF; + dump_pv_chunk = FALSE; /* XXX evaluate from modif[] */ + + printf("pmap: 0x%08X\n", (uint32_t)pmap); + printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP); + printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab); + + for(i = 0; i < NPTE1_IN_PT1; i++) { + pte1 = pte1_load(&pmap->pm_pt1[i]); + if (pte1 == 0) + continue; + va = i << PTE1_SHIFT; + if (va >= eva) + break; + + if (pte1_is_section(pte1)) { + printf("0x%08X: Section 0x%08X, s:%d g:%d\n", va, pte1, + !!(pte1 & PTE1_S), !(pte1 & PTE1_NG)); + dump_section(pmap, i); + } else if (pte1_is_link(pte1)) { + dump_link_ok = TRUE; + invalid_ok = FALSE; + pte2 = pte2_load(pmap_pt2tab_entry(pmap, va)); + m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1)); + printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X m: %p", + va, pte1, pte2, m); + if (is_pv_chunk_space(va)) { + printf(" - pv_chunk space"); + if (dump_pv_chunk) + invalid_ok = TRUE; + else + dump_link_ok = FALSE; + } + else if (m != NULL) + printf(" w:%d w2:%u", m->wire_count, + pt2_wirecount_get(m, pte1_index(va))); + if (pte2 == 0) + printf(" !!! pt2tab entry is ZERO"); + else if (pte2_pa(pte1) != pte2_pa(pte2)) + printf(" !!! pt2tab entry is DIFFERENT - m: %p", + PHYS_TO_VM_PAGE(pte2_pa(pte2))); + printf("\n"); + if (dump_link_ok) + dump_link(pmap, i, invalid_ok); + } else + printf("0x%08X: Invalid entry 0x%08X\n", va, pte1); + } +} + +static void +dump_pt2tab(pmap_t pmap) +{ + uint32_t i; + pt2_entry_t pte2; + vm_offset_t va; + vm_paddr_t pa; + vm_page_t m; + + printf("PT2TAB:\n"); + for (i = 0; i < PT2TAB_ENTRIES; i++) { + pte2 = pte2_load(&pmap->pm_pt2tab[i]); + if (!pte2_is_valid(pte2)) + continue; + va = i << PT2TAB_SHIFT; + pa = pte2_pa(pte2); + m = PHYS_TO_VM_PAGE(pa); + printf(" 0x%08X: 0x%08X, TEX%d, s:%d, m:%p", va, pte2, + pte2_class(pte2), !!(pte2 & PTE2_S), m); + if (m != NULL) + printf(" , h: %d, w: %d, f: 0x%04X pidx: %lld", + m->hold_count, m->wire_count, m->flags, m->pindex); + printf("\n"); + } +} + +DB_SHOW_COMMAND(pmap_pt2tab, pmap_pt2tab_print) +{ + /* XXX convert args. */ + pmap_t pmap = (pmap_t)addr; + pt1_entry_t pte1; + pt2_entry_t pte2; + vm_offset_t va; + uint32_t i, start; + + if (have_addr) { + printf("supported only on current pmap\n"); + return; + } + + pmap = PCPU_GET(curpmap); + printf("curpmap: 0x%08X\n", (uint32_t)pmap); + printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP); + printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab); + + start = pte1_index((vm_offset_t)PT2MAP); + for (i = start; i < (start + NPT2_IN_PT2TAB); i++) { + pte1 = pte1_load(&pmap->pm_pt1[i]); + if (pte1 == 0) + continue; + va = i << PTE1_SHIFT; + if (pte1_is_section(pte1)) { + printf("0x%08X: Section 0x%08X, s:%d\n", va, pte1, + !!(pte1 & PTE1_S)); + dump_section(pmap, i); + } else if (pte1_is_link(pte1)) { + pte2 = pte2_load(pmap_pt2tab_entry(pmap, va)); + printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X\n", va, + pte1, pte2); + if (pte2 == 0) + printf(" !!! pt2tab entry is ZERO\n"); + } else + printf("0x%08X: Invalid entry 0x%08X\n", va, pte1); + } + dump_pt2tab(pmap); +} +#endif diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index 3dd998429dfc..99a39a0ee522 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); @@ -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) { @@ -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/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S new file mode 100644 index 000000000000..6fdbeed197c2 --- /dev/null +++ b/sys/arm/arm/swtch-v4.S @@ -0,0 +1,377 @@ +/* $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) +.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..ef2156a4f121 --- /dev/null +++ b/sys/arm/arm/swtch-v6.S @@ -0,0 +1,482 @@ +/* $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 +#include + +__FBSDID("$FreeBSD$"); + +#if defined(SMP) +#define GET_PCPU(tmp, tmp2) \ + mrc CP15_MPIDR(tmp); \ + 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) + +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 /* 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 ee6368553bcc..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) - - -#ifndef ARM_NEW_PMAP - -#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_NEW_PMAP */ -#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_NEW_PMAP */ - ENTRY(savectx) stmfd sp!, {lr} sub sp, sp, #4 diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c index efebda32262e..b893a9028561 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 @@ -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/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 6d8015137939..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 @@ -70,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include #endif -extern char fusubailout[]; extern char cachebailout[]; #ifdef DEBUG @@ -293,7 +291,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,26 +335,23 @@ abort_handler(struct trapframe *tf, int prefetch) * they are not from KVA space. Thus, no action is needed here. */ -#ifdef ARM_NEW_PMAP + /* + * (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; -#endif - /* - * 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 @@ -419,6 +417,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. @@ -437,23 +443,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; - tf->tf_pc = (register_t)pcb->pcb_onfault; - return; - } - va = trunc_page(far); if (va >= KERNBASE) { /* @@ -488,13 +477,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/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 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/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/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/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/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/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/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/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/include/cpu-v4.h b/sys/arm/include/cpu-v4.h new file mode 100644 index 000000000000..0d66dee42bc3 --- /dev/null +++ b/sys/arm/include/cpu-v4.h @@ -0,0 +1,186 @@ +/*- + * 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 Never 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 +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 +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); +} + +static __inline void +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 */ + +#endif /* MACHINE_CPU_V4_H */ diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index bb8649ab30ba..e537c10b4d4e 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -32,19 +32,32 @@ /* 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 +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); +#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 +290,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 +584,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 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 8bbb1dd7491c..eb445b49abcf 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -60,23 +60,17 @@ 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 */ 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); @@ -85,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 @@ -110,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 @@ -136,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); @@ -155,18 +147,12 @@ struct cpu_functions { /* Other 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); /* Soft functions */ - int (*cf_dataabt_fixup) (void *arg); - int (*cf_prefetchabt_fixup) (void *arg); - void (*cf_context_switch) (void); void (*cf_setup) (void); @@ -175,70 +161,19 @@ struct cpu_functions { extern struct cpu_functions cpufuncs; extern u_int cputype; -#define cpu_ident() cpufuncs.cf_id() +#if __ARM_ARCH < 6 #define cpu_cpwait() cpufuncs.cf_cpwait() +#endif #define cpu_control(c, e) cpufuncs.cf_control(c, e) -#define cpu_domains(d) cpufuncs.cf_domains(d) +#if __ARM_ARCH < 6 #define cpu_setttb(t) cpufuncs.cf_setttb(t) -#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() -#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) -#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)) #define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all() @@ -249,25 +184,18 @@ void tlb_broadcast(int); #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() -#define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf() +#if __ARM_ARCH < 6 #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) - +#endif #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); @@ -275,15 +203,12 @@ 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 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_get_control (void); u_int cpu_pfr (int); #if defined(CPU_FA526) @@ -291,12 +216,8 @@ 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); -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); void fa526_dcache_wbinv_all (void); void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end); @@ -307,12 +228,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 -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); @@ -323,8 +245,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; @@ -334,11 +254,6 @@ extern unsigned arm9_dcache_index_inc; #endif #if defined(CPU_ARM9E) -void arm10_tlb_flushID_SE (u_int); -void arm10_tlb_flushI_SE (u_int); - -void arm10_context_switch (void); - void arm10_setup (void); u_int sheeva_control_ext (u_int, u_int); @@ -362,7 +277,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); @@ -390,8 +304,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); @@ -408,8 +320,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_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); @@ -419,7 +329,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); @@ -432,13 +341,11 @@ 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_flushI (void); void armv4_tlb_flushD (void); void armv4_tlb_flushD_SE (u_int va); @@ -446,9 +353,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); @@ -486,8 +392,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 @@ -514,9 +419,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/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/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/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/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) 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/pmap-v6.h b/sys/arm/include/pmap-v6.h index beaf638a179b..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) /* @@ -216,28 +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 ); -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); -} - -/* - * 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 *); +void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t, + vm_memattr_t); #endif /* _KERNEL */ @@ -268,40 +248,9 @@ 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); - -/* - * 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 - * 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 - - +#define PTE_DEVICE VM_MEMATTR_DEVICE #endif /* _KERNEL */ // ----------------------------------------------------------------------------- diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index a0b0d94255b8..8222652084b4 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_ @@ -58,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, @@ -102,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); /* @@ -129,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; }; @@ -162,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; @@ -174,7 +155,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) @@ -197,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; /* @@ -245,7 +223,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); } @@ -269,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 @@ -339,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 @@ -493,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 @@ -504,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) @@ -523,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 @@ -618,15 +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); -#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 */ +#endif /* ARM_MMU_GENERIC != 0 */ #if ARM_MMU_XSCALE == 1 void pmap_copy_page_xscale(vm_paddr_t, vm_paddr_t); @@ -704,4 +544,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/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 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/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); diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 8fb230e23de8..eb670256f47c 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -29,20 +29,24 @@ #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) -#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_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 */ -#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WT /* for DRM */ +#ifdef _KERNEL +/* Don't export aliased VM_MEMATTR to userland */ +#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WRITE_THROUGH /* 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/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.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..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 @@ -111,7 +112,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; /* @@ -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/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 f59d511f4d09..15751cc990b7 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 @@ -74,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/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/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 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; } 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) 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/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/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/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/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 2bd77a5f30a7..293696364a32 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 @@ -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/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/i80321/i80321_timer.c b/sys/arm/xscale/i8134x/i80321_timer.c similarity index 99% rename from sys/arm/xscale/i80321/i80321_timer.c rename to sys/arm/xscale/i8134x/i80321_timer.c index 3b4e5a11b552..ea15d920bf01 100644 --- a/sys/arm/xscale/i80321/i80321_timer.c +++ b/sys/arm/xscale/i8134x/i80321_timer.c @@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include +#include +#include #ifdef CPU_XSCALE_81342 #define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because diff --git a/sys/arm/xscale/i80321/i80321_wdog.c b/sys/arm/xscale/i8134x/i80321_wdog.c similarity index 98% rename from sys/arm/xscale/i80321/i80321_wdog.c rename to sys/arm/xscale/i8134x/i80321_wdog.c index 9be98d2f7e25..c11c78a48e33 100644 --- a/sys/arm/xscale/i80321/i80321_wdog.c +++ b/sys/arm/xscale/i8134x/i80321_wdog.c @@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include +#include +#include struct iopwdog_softc { diff --git a/sys/arm/xscale/i80321/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h similarity index 83% rename from sys/arm/xscale/i80321/i80321reg.h rename to sys/arm/xscale/i8134x/i80321reg.h index 53617f956582..b6dd4fea14da 100644 --- a/sys/arm/xscale/i80321/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_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 */ @@ -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_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 */ /* * Peripheral Bus Interface Unit diff --git a/sys/arm/xscale/i80321/i80321var.h b/sys/arm/xscale/i8134x/i80321var.h similarity index 100% rename from sys/arm/xscale/i80321/i80321var.h rename to sys/arm/xscale/i8134x/i80321var.h 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. 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); } 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/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/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) { 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); } diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 5a61c4a1f7cf..87abee18e483 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 @@ -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: 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/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] - diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S index bc2e52103416..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 @@ -166,15 +201,18 @@ 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 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..10e3f416c2a1 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) { @@ -372,16 +374,27 @@ 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: - 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/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/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/arm64/cavium/thunder_pcie.c b/sys/arm64/cavium/thunder_pcie.c index 9785739a858f..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$"); @@ -43,9 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include #include #include #include @@ -82,23 +80,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 @@ -109,39 +90,16 @@ 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_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 *); -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); -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 +125,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 +150,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) @@ -417,19 +259,19 @@ 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) { 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)); } -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) { @@ -446,7 +288,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)); }; @@ -558,8 +400,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 +421,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..58239f1eed9f 100644 --- a/sys/arm64/cavium/thunder_pcie_common.c +++ b/sys/arm64/cavium/thunder_pcie_common.c @@ -35,13 +35,18 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include + #include #include #include #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 731675b9b0b4..548a43518c68 100644 --- a/sys/arm64/cavium/thunder_pcie_common.h +++ b/sys/arm64/cavium/thunder_pcie_common.h @@ -32,6 +32,10 @@ #define RANGES_TUPLES_MAX 6 #define RANGES_TUPLES_INVALID (RANGES_TUPLES_MAX + 1) +DECLARE_CLASS(thunder_pcie_driver); + +MALLOC_DECLARE(M_THUNDER_PCIE); + struct pcie_range { uint64_t pci_base; uint64_t phys_base; @@ -39,6 +43,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 +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 new file mode 100644 index 000000000000..f1624f615484 --- /dev/null +++ b/sys/arm64/cavium/thunder_pcie_fdt.c @@ -0,0 +1,382 @@ +/* + * 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 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 +}; + +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_ofw_bus_attach(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) +{ + 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) +{ + 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); + + get_addr_size_cells(node, &pci_addr_cells, &size_cells); + + /* 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); +} + +/* 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 ((int)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 ((int)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); +} diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index f8d19960139e..0c86462376fc 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)); \ @@ -99,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/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/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 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; 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; 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 diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index f1e614331999..b7888aaed5fc 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 for " + "exclusive access\n", i); + } + 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); 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/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/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, 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/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); } 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); } 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/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 diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c index d91733760ceb..8d0b6e76958a 100644 --- a/sys/compat/cloudabi/cloudabi_proc.c +++ b/sys/compat/cloudabi/cloudabi_proc.c @@ -75,12 +75,16 @@ 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_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/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/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/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/files.arm b/sys/conf/files.arm index 33bdd94265cb..bc5d8a39fd6d 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -11,18 +11,17 @@ 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 +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 @@ -64,8 +63,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.c optional armv6 arm/arm/pmu.c optional pmu | fdt hwpmc arm/arm/sc_machdep.c optional sc arm/arm/setcpsr.S standard @@ -75,6 +73,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 diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 6168d704ed18..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 @@ -51,7 +52,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 @@ -70,6 +72,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/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.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 7860701e8440..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}) @@ -252,6 +257,8 @@ 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 .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 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/conf/options.arm b/sys/conf/options.arm index 8720ac24a168..7beae5bd6833 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 @@ -16,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 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/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/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/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); 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/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/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; } } 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; 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 c1a9ce8717df..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 */ @@ -1371,8 +1390,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); @@ -2352,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; @@ -2443,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); @@ -2862,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 @@ -2923,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: @@ -2981,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; @@ -3005,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); @@ -3601,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); } } 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/filemon/filemon.c b/sys/dev/filemon/filemon.c index 0ec83465dbed..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; @@ -223,8 +223,6 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, sx_init(&filemon->lock, "filemon"); } - filemon->pid = curproc->p_pid; - devfs_set_cdevpriv(filemon, filemon_dtr); /* Get exclusive write access. */ diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c index 9beb573966bc..1b9877a68592 100644 --- a/sys/dev/filemon/filemon_wrapper.c +++ b/sys/dev/filemon/filemon_wrapper.c @@ -29,7 +29,10 @@ #include __FBSDID("$FreeBSD$"); +#include +#include #include +#include #include "opt_compat.h" @@ -43,21 +46,21 @@ __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_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 -#define sys_sys_exit sys_exit #ifdef FILEMON_HAS_LINKAT #define sys_linkat linkat #endif #endif /* __FreeBSD_version */ +static eventhandler_tag filemon_exec_tag; +static eventhandler_tag filemon_exit_tag; +static eventhandler_tag filemon_fork_tag; + static void filemon_output(struct filemon *filemon, char *msg, size_t len) { @@ -95,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(); @@ -136,84 +139,32 @@ 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_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 @@ -485,7 +436,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,28 +445,26 @@ 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->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. */ filemon_filemon_unlock(filemon); } - - sys_sys_exit(td, uap); } static int @@ -545,27 +494,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 __unused) { - 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 @@ -578,15 +523,11 @@ 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; 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,21 +538,24 @@ 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; 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 sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat; #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, + filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST); } static void @@ -624,15 +568,11 @@ 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; 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 @@ -643,19 +583,19 @@ 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; 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 sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat; #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/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/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/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/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 8bf34a85c783..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; @@ -136,15 +133,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; @@ -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; @@ -789,8 +778,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 */ diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index c19034043e38..4f52e0d7c7f9 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; @@ -1022,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; @@ -1030,11 +1032,12 @@ 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; + u_long hn_csum_udp; u_long hn_csum_trusted; u_long hn_lro_tried; u_long hn_small_pkts; @@ -1045,6 +1048,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 ab88e367106d..be43bf413302 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 + \ @@ -167,14 +169,12 @@ struct hn_txdesc { #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. + * Only enable UDP checksum offloading when it is on 2012R2 or + * later. UDP checksum offloading doesn't work on earlier + * Windows releases. */ -#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) +#define HN_CSUM_ASSIST_WIN8 (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 @@ -212,6 +212,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; @@ -226,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 */ @@ -241,12 +256,14 @@ 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); 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) @@ -257,62 +274,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) { @@ -382,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); @@ -393,8 +359,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); @@ -444,15 +415,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) @@ -463,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 @@ -509,17 +485,30 @@ 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", 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"); + "# 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", @@ -545,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; @@ -562,6 +555,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"); @@ -572,6 +573,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); @@ -761,6 +768,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; @@ -769,35 +785,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; - 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) 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); @@ -822,236 +1039,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; - } - - /* 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; - } - - /* 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); - - if (trans_proto_type & (TYPE_IPV4 << 16)) { - csum_info->xmit.is_ipv4 = 1; - } else { - csum_info->xmit.is_ipv6 = 1; - } - - 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; - } - - 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)); - } -#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; - -pre_send: - 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); @@ -1191,7 +1189,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! */ @@ -1239,21 +1237,28 @@ 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 (NULL != csum_info) { + 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 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) && do_csum) { 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 && @@ -1284,7 +1289,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_hosttcp) { + 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 | @@ -1293,6 +1299,20 @@ 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 (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 && do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_IP)) { + sc->hn_csum_trusted++; + m_new->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED | CSUM_IP_VALID); } } } @@ -1331,18 +1351,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 } /* @@ -1506,47 +1516,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: @@ -1603,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; @@ -1614,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; @@ -1634,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 @@ -1734,6 +1743,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) { 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/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); 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.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_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..e60c55709fc0 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -86,12 +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)); + msg->monitor_page_2 = hv_get_phys_addr( + hv_vmbus_g_connection.monitor_page_2); /** * Add to list before we send the request since we may receive the @@ -164,8 +162,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", @@ -179,18 +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_NOWAIT | 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; - } + M_WAITOK | M_ZERO); hv_vmbus_g_connection.recv_interrupt_page = hv_vmbus_g_connection.interrupt_page; @@ -203,31 +190,19 @@ 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_NOWAIT | M_ZERO, - 0UL, - BUS_SPACE_MAXADDR, + hv_vmbus_g_connection.monitor_page_1 = malloc( 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; - } + 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) + 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, @@ -269,8 +244,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); @@ -282,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); @@ -305,32 +273,19 @@ 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); 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; - 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 7eac11679290..8a1e4126f13e 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; @@ -309,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)); @@ -566,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); } } diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 538ab1e7222e..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; /** @@ -362,10 +363,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 +631,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 +680,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); 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); 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/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 168fa1310f74..f0e218fab1ed 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; @@ -1011,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 @@ -1018,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; } @@ -1260,6 +1270,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 +3993,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_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; } 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 */ 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 */ 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/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/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 d0819efc26e9..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 @@ -890,7 +891,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 +921,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); @@ -2265,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/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; /* 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); 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/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)) 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]; 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.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..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 @@ -205,25 +206,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 +255,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 +1108,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. 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/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..2394b2c17c9a 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 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 */ @@ -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/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/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_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..ec6e68f64850 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 ((int)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; 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 { 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/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; 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++) { 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_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/kern/kern_fork.c b/sys/kern/kern_fork.c index e7d727619be0..9abe08c037c5 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -101,12 +101,15 @@ struct fork_args { int sys_fork(struct thread *td, struct fork_args *uap) { - int error; - struct proc *p2; + struct fork_req fr; + int error, pid; - error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC; + 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); @@ -114,22 +117,24 @@ 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) { - int error, fd; - struct proc *p2; + struct fork_req fr; + int error, fd, pid; + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; + fr.fr_pidp = &pid; + 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[0] = pid; td->td_retval[1] = 0; error = copyout(&fd, uap->fdp, sizeof(fd)); } @@ -140,13 +145,15 @@ sys_pdfork(td, uap) int sys_vfork(struct thread *td, struct vfork_args *uap) { - int error, flags; - struct proc *p2; + struct fork_req fr; + int error, pid; - 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_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); @@ -155,17 +162,20 @@ sys_vfork(struct thread *td, struct vfork_args *uap) int sys_rfork(struct thread *td, struct rfork_args *uap) { - struct proc *p2; - int error; + struct fork_req fr; + int error, pid; /* Don't allow kernel-only flags. */ if ((uap->flags & RFKERNELONLY) != 0) 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_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); @@ -366,11 +376,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; @@ -378,10 +388,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); @@ -414,7 +423,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(); @@ -422,10 +431,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 { @@ -433,7 +442,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. @@ -501,16 +510,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; @@ -543,7 +552,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; @@ -590,7 +599,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; @@ -624,7 +633,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 { @@ -652,13 +661,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); @@ -677,14 +686,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. @@ -703,9 +712,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)) { /* @@ -718,24 +732,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. @@ -747,22 +749,41 @@ 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) + while (td2->td_proc == p2 && (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); } 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 +793,15 @@ 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; + + 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) @@ -795,7 +825,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 +836,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, * certain parts of a process from itself. */ if ((flags & RFPROC) == 0) { - *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)); } @@ -845,7 +878,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,17 +967,7 @@ 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); - - /* - * Return child proc pointer to parent. - */ - *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); } @@ -962,7 +986,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/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 { 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 a864c946873c..55964398b6a1 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include /* @@ -274,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. */ @@ -292,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); @@ -320,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, @@ -333,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); @@ -350,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, @@ -364,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, @@ -378,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 @@ -678,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/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/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_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_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/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/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/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; } } 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); 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/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 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..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. @@ -149,14 +150,25 @@ #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) -#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_MIPS74KC) || defined(CPU_MIPS1004KC) -#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 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/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/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 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 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/sctp_input.c b/sys/netinet/sctp_input.c index 9edfcf67808a..a6f625d13a11 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; @@ -5684,9 +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) && (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; } @@ -5715,9 +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) && (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; } @@ -5827,9 +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) && (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; } diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 95ac97c903dd..017261000189 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 @@ -5457,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, @@ -5501,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 *, 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) { 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/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 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/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c index 82074aab868f..011b9999db99 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; @@ -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_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_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; 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/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 diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index d657244ffe56..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); } /* @@ -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); 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) 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 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/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); 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/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/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/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..814fcf67b9d8 --- /dev/null +++ b/sys/riscv/riscv/exception.S @@ -0,0 +1,461 @@ +/*- + * 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, -(TF_SIZE) + + sd ra, (TF_RA)(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) + 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 + /* 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 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, (TF_SIZE) +.endm + +.macro do_ast + /* Disable interrupts */ + csrr a4, sstatus +1: + csrci sstatus, SSTATUS_IE + + ld a1, PC_CURTHREAD(gp) + 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..bf6c8fb4c851 --- /dev/null +++ b/sys/riscv/riscv/genassym.c @@ -0,0 +1,99 @@ +/*- + * 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_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)); +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..79688e6f3009 --- /dev/null +++ b/sys/riscv/riscv/machdep.c @@ -0,0 +1,794 @@ +/*- + * 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; + + 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 */ + __asm __volatile("mv gp, %0" :: "r"(pcpup)); + + 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/arm/xscale/i80321/uart_cpu_i80321.c b/sys/riscv/riscv/minidump_machdep.c similarity index 63% rename from sys/arm/xscale/i80321/uart_cpu_i80321.c rename to sys/riscv/riscv/minidump_machdep.c index a3faec7289df..ca51cfc77e50 100644 --- a/sys/arm/xscale/i80321/uart_cpu_i80321.c +++ b/sys/riscv/riscv/minidump_machdep.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2006 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,41 +27,33 @@ #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 +#include +#include -#include -#include - -#include -#include - -bus_space_tag_t uart_bus_space_io; -bus_space_tag_t uart_bus_space_mem; +CTASSERT(sizeof(struct kerneldumpheader) == 512); +CTASSERT(sizeof(*vm_page_dump) == 8); int -uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +minidumpsys(struct dumperinfo *di) { - 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); + 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..c6336a968d15 --- /dev/null +++ b/sys/riscv/riscv/swtch.S @@ -0,0 +1,271 @@ +/*- + * 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) + /* Store the new curthread */ + sd a1, PC_CURTHREAD(gp) + /* And the new pcb */ + ld x13, TD_PCB(a1) + sd x13, PC_CURPCB(gp) + + 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) + + /* 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) + /* Store the new curthread */ + sd a1, PC_CURTHREAD(gp) + /* And the new pcb */ + ld x13, TD_PCB(a1) + sd x13, PC_CURPCB(gp) + + /* Save the old context. */ + ld x13, TD_PCB(a0) + + /* Store the callee-saved registers */ + sd ra, (PCB_RA)(x13) + sd sp, (PCB_SP)(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) + + /* 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) + + /* 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 stack */ + ld sp, (TF_SP - TF_SIZE)(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..b3f2d82be13c --- /dev/null +++ b/sys/riscv/riscv/uma_machdep.c @@ -0,0 +1,56 @@ +/*- + * 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 +#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..fef626b9f2fa --- /dev/null +++ b/sys/riscv/riscv/vm_machdep.c @@ -0,0 +1,260 @@ +/*- + * 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 + +/* + * 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( + (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe)); +} + +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/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 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 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 */ 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/event.h b/sys/sys/event.h index 0f132318c827..7897c818cb0e 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 */ @@ -221,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/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 */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index f2f4a9d17202..039fd394d34a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -907,6 +907,16 @@ 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; + int *fr_pidp; + struct proc **fr_procp; + int *fr_pd_fd; + int fr_pd_flags; + struct filecaps *fr_pd_fcaps; +}; + /* * pget() flags. */ @@ -930,8 +940,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 *); 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); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 26cf9a6721ed..f101849eb92d 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -95,16 +95,16 @@ 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 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; @@ -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/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 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 *); 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/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; 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 4600589bd06d..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 @@ -275,6 +276,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, @@ -434,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 @@ -1585,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)); @@ -3022,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); } @@ -3607,6 +3613,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 +3766,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..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 @@ -196,100 +197,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 */ 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 diff --git a/tests/sys/acl/Makefile b/tests/sys/acl/Makefile index 298b0a27c91d..d101088dcd3f 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= getfacl setfacl + .for t in 01 03 04 -TEST_METADATA.$t+= required_programs="/sbin/zpool" +TEST_METADATA.$t+= required_programs="zpool ${_ACL_PROGS}" +.endfor + +.for t in 00 02 +TEST_METADATA.$t+= required_programs="${_ACL_PROGS}" .endfor .include diff --git a/tests/sys/geom/class/gate/1_test.sh b/tests/sys/geom/class/gate/1_test.sh index 3e277349631f..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 @@ -41,6 +42,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 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(); 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/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 a1d401a03782..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,12 +689,30 @@ 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 ;; 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 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 +# 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/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], 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 }; 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 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 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 ;; diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index e0cd7e0a1d5a..f33f4df566ad 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,48 +52,73 @@ VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" ############################################################ FUNCTIONS -# f_substr "$string" $start [$length] +# f_isinteger $arg # -# Simple wrapper to awk(1)'s `substr' function. +# Returns true if argument is a positive/negative whole integer. # -f_substr() +f_isinteger() { - local string="$1" start="${2:-0}" len="${3:-0}" - echo "$string" | awk "{ print substr(\$0, $start, $len) }" + local arg="${1#-}" + [ "${arg:-x}" = "${arg%[!0-9]*}" ] } -# f_snprintf $var_to_set $size $format [$arguments ...] +# f_substr [-v $var_to_set] $string $start [$length] # -# 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. +# Similar to awk(1)'s substr(), return length substring of string that begins +# at start position counted from 1. # -f_snprintf() -{ - local __funcname=f_snprintf - local __var_to_set="$1" __size="$2" - shift 2 # var_to_set size +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 + 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 + shift $(( $OPTIND - 1 )) - if [ "$__size" -eq 0 ] 2> /dev/null; then - 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 - return ${FAILURE:-1} - fi + local __tmp="$1" __start="${2:-1}" __size="$3" + local __tbuf __tbuf_len __trim __trimq - local __f_snprintf_tmp - f_sprintf __f_snprintf_tmp "$@" + 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 - local __tmp_size=${#__f_snprintf_tmp} - local __trim=$(( $__tmp_size - $__size )) __trimq - local __tbuf __tbuf_len - local __mask __mask_len - while [ $__trim -gt 0 ]; do - __tbuf="?" - __tbuf_len=1 - if [ $__trim -le $__size ]; then + __trim=$(( $__start - 1 )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ] do __tbuf="$__tbuf?" @@ -102,43 +127,115 @@ 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" - 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 )) + done + + 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 - __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 - __f_snprintf_tmp="${__f_snprintf_tmp%"$__mask"}" + done + + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__tmp" + else + echo "$__tmp" fi - done - setvar "$__var_to_set" "$__f_snprintf_tmp" -} + } +esac # f_sprintf $var_to_set $format [$arguments ...] # # Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax # (`$format [$arguments ...]'). # -f_sprintf() +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}\" + } + ;; +*) + # 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 +# +# Similar to vsprintf(3), write a string into $var_to_set using printf(1) +# syntax (`$format $format_args'). +# +f_vsprintf() { - local __var_to_set="$1" - shift 1 # var_to_set - eval "$__var_to_set"=\$\( printf -- \"\$@\" \) + 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 +# 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 @@ -176,140 +273,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 -# 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_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 -# 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 @@ -493,6 +456,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 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") 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); +} 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 . 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 diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc index e384dff93f6c..1da537fd5992 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 @@ -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 @@ -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 dbd0e4b3c326..075fc3bd8a1e 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 " " Qc or Qo , Qc . For example, in the following statement: .Bl -item -offset indent .It @@ -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 @@ -312,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" @@ -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