diff --git a/bin/ls/print.c b/bin/ls/print.c index 08701c05134f..70f53ba70663 100644 --- a/bin/ls/print.c +++ b/bin/ls/print.c @@ -192,7 +192,7 @@ printlong(const DISPLAY *dp) if (f_numericonly) { xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {td:user/%-*s}{e:user/%ju} {td:group/%-*s}{e:group/%ju} ", buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, - dp->s_user, np->user, sp->st_uid, dp->s_group, np->group, sp->st_gid); + dp->s_user, np->user, (uintmax_t)sp->st_uid, dp->s_group, np->group, (uintmax_t)sp->st_gid); } else { xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {t:user/%-*s} {t:group/%-*s} ", buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, @@ -456,7 +456,7 @@ printtime(const char *field, time_t ftime) snprintf(fmt, sizeof(fmt), "{d:%s/%%hs} ", field); xo_attr("value", "%ld", (long) ftime); xo_emit(fmt, longstring); - snprintf(fmt, sizeof(fmt), "{en:%s/%%ld} ", field); + snprintf(fmt, sizeof(fmt), "{en:%s/%%ld}", field); xo_emit(fmt, (long) ftime); } @@ -486,7 +486,7 @@ printtype(u_int mode) xo_emit("{D:=}{e:type/socket}"); return (1); case S_IFWHT: - xo_emit("{D:%}{e:type/whiteout}"); + xo_emit("{D:%%}{e:type/whiteout}"); return (1); default: break; diff --git a/contrib/elftoolchain/common/elfdefinitions.h b/contrib/elftoolchain/common/elfdefinitions.h index 58554fef2ebf..21b415bb0693 100644 --- a/contrib/elftoolchain/common/elfdefinitions.h +++ b/contrib/elftoolchain/common/elfdefinitions.h @@ -813,7 +813,8 @@ _ELF_DEFINE_EM(EM_KM32, 210, "KM211 KM32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX32, 211, "KM211 KMX32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX16, 212, "KM211 KMX16 16-bit processor") \ _ELF_DEFINE_EM(EM_KMX8, 213, "KM211 KMX8 8-bit processor") \ -_ELF_DEFINE_EM(EM_KVARC, 214, "KM211 KMX32 KVARC processor") +_ELF_DEFINE_EM(EM_KVARC, 214, "KM211 KMX32 KVARC processor") \ +_ELF_DEFINE_EM(EM_RISCV, 243, "RISC-V") #undef _ELF_DEFINE_EM #define _ELF_DEFINE_EM(N, V, DESCR) N = V , diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index b1b81a34d4f7..f56aa28ba391 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -314,6 +315,7 @@ static const char *dwarf_reg(unsigned int mach, unsigned int reg); static const char *dwarf_regname(struct readelf *re, unsigned int num); static struct dumpop *find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); +static int get_ent_count(struct section *s, int *ent_count); static char *get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off); static const char *get_string(struct readelf *re, int strtab, size_t off); @@ -532,6 +534,7 @@ elf_machine(unsigned int mach) case EM_ARCA: return "Arca RISC Microprocessor"; case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd"; case EM_AARCH64: return "AArch64"; + case EM_RISCV: return "RISC-V"; default: snprintf(s_mach, sizeof(s_mach), "", mach); return (s_mach); @@ -2900,6 +2903,24 @@ dump_shdr(struct readelf *re) #undef ST_CTL } +/* + * Return number of entries in the given section. We'd prefer ent_count be a + * size_t *, but libelf APIs already use int for section indices. + */ +static int +get_ent_count(struct section *s, int *ent_count) +{ + if (s->entsize == 0) { + warnx("section %s has entry size 0", s->name); + return (0); + } else if (s->sz / s->entsize > INT_MAX) { + warnx("section %s has invalid section count", s->name); + return (0); + } + *ent_count = (int)(s->sz / s->entsize); + return (1); +} + static void dump_dynamic(struct readelf *re) { @@ -2928,8 +2949,8 @@ dump_dynamic(struct readelf *re) /* Determine the actual number of table entries. */ nentries = 0; - jmax = (int) (s->sz / s->entsize); - + if (!get_ent_count(s, &jmax)) + continue; for (j = 0; j < jmax; j++) { if (gelf_getdyn(d, j, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", @@ -3175,7 +3196,9 @@ dump_rel(struct readelf *re, struct section *s, Elf_Data *d) else printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrel(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); @@ -3231,7 +3254,9 @@ dump_rela(struct readelf *re, struct section *s, Elf_Data *d) else printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrela(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); @@ -3296,7 +3321,7 @@ dump_symtab(struct readelf *re, int i) Elf_Data *d; GElf_Sym sym; const char *name; - int elferr, stab, j; + int elferr, stab, j, len; s = &re->sl[i]; stab = s->link; @@ -3309,12 +3334,14 @@ dump_symtab(struct readelf *re, int i) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; printf("Symbol table (%s)", s->name); - printf(" contains %ju entries:\n", s->sz / s->entsize); + printf(" contains %d entries:\n", len); printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name"); - for (j = 0; (uint64_t)j < s->sz / s->entsize; j++) { + for (j = 0; j < len; j++) { if (gelf_getsym(d, j, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; @@ -3352,7 +3379,7 @@ dump_symtabs(struct readelf *re) Elf_Data *d; struct section *s; uint64_t dyn_off; - int elferr, i; + int elferr, i, len; /* * If -D is specified, only dump the symbol table specified by @@ -3377,8 +3404,10 @@ dump_symtabs(struct readelf *re) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { + for (i = 0; i < len; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); continue; @@ -3566,7 +3595,8 @@ dump_gnu_hash(struct readelf *re, struct section *s) maskwords = buf[2]; buf += 4; ds = &re->sl[s->link]; - dynsymcount = ds->sz / ds->entsize; + if (!get_ent_count(ds, &dynsymcount)) + return; nchain = dynsymcount - symndx; if (d->d_size != 4 * sizeof(uint32_t) + maskwords * (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + @@ -3995,7 +4025,7 @@ dump_liblist(struct readelf *re) char tbuf[20]; Elf_Data *d; Elf_Lib *lib; - int i, j, k, elferr, first; + int i, j, k, elferr, first, len; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; @@ -4012,8 +4042,10 @@ dump_liblist(struct readelf *re) if (d->d_size <= 0) continue; lib = d->d_buf; + if (!get_ent_count(s, &len)) + continue; printf("\nLibrary list section '%s' ", s->name); - printf("contains %ju entries:\n", s->sz / s->entsize); + printf("contains %d entries:\n", len); printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", "Checksum", "Version", "Flags"); for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) { @@ -4398,7 +4430,7 @@ static void dump_mips_reginfo(struct readelf *re, struct section *s) { Elf_Data *d; - int elferr; + int elferr, len; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { @@ -4410,9 +4442,10 @@ dump_mips_reginfo(struct readelf *re, struct section *s) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - printf("\nSection '%s' contains %ju entries:\n", s->name, - s->sz / s->entsize); + printf("\nSection '%s' contains %d entries:\n", s->name, len); dump_mips_odk_reginfo(re, d->d_buf, d->d_size); } diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index 3c3cd345a046..4f1d92f80695 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -5433,6 +5433,15 @@ nomatch 32 { action "kldload -n umodem"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0xff"; + action "kldload -n if_urndis"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5576,5 +5585,5 @@ nomatch 32 { action "kldload -n umass"; }; -# 2687 USB entries processed +# 2688 USB entries processed diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index a8634362286b..d16bb4759f1f 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -528,6 +528,8 @@ .. gzip .. + ident + .. join .. jot diff --git a/gnu/usr.bin/rcs/Makefile b/gnu/usr.bin/rcs/Makefile index 4a9fd0838a07..d6a960b729f2 100644 --- a/gnu/usr.bin/rcs/Makefile +++ b/gnu/usr.bin/rcs/Makefile @@ -1,3 +1,5 @@ -SUBDIR= lib ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog rcsfreeze +# $FreeBSD$ + +SUBDIR= lib ci co merge rcs rcsclean rcsdiff rcsmerge rlog rcsfreeze .include diff --git a/gnu/usr.bin/rcs/ident/Makefile b/gnu/usr.bin/rcs/ident/Makefile deleted file mode 100644 index f28f8d3c5b71..000000000000 --- a/gnu/usr.bin/rcs/ident/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -PROG= ident -SRCS= ident.c -CFLAGS+= -I${.CURDIR}/../lib -LDADD= ${LIBRCS} -DPADD= ${LIBRCS} - -.include "../../Makefile.inc" -.include diff --git a/gnu/usr.bin/rcs/ident/Makefile.depend b/gnu/usr.bin/rcs/ident/Makefile.depend deleted file mode 100644 index cab8f8fe15db..000000000000 --- a/gnu/usr.bin/rcs/ident/Makefile.depend +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - gnu/lib/libgcc \ - gnu/usr.bin/rcs/lib \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/gnu/usr.bin/rcs/ident/ident.1 b/gnu/usr.bin/rcs/ident/ident.1 deleted file mode 100644 index 253a2ce72724..000000000000 --- a/gnu/usr.bin/rcs/ident/ident.1 +++ /dev/null @@ -1,182 +0,0 @@ -.de Id -.ds Rv \\$3 -.ds Dt \\$4 -.ds iD \\$3 \\$4 \\$5 \\$6 \\$7 -.. -.Id $FreeBSD$ -.ds r \&\s-1RCS\s0 -.ds u \&\s-1UTC\s0 -.if n .ds - \%-- -.if t .ds - \(em -.TH IDENT 1 \*(Dt GNU -.SH NAME -ident \- identify RCS keyword strings in files -.SH SYNOPSIS -.B ident -[ -.B \-q -] [ -.B \-V -] [ -.I file -\&.\|.\|. ] -.SH DESCRIPTION -.B ident -searches for all instances of the pattern -.BI $ keyword : "\ text\ " $ -in the named files or, if no files are named, the standard input. -.PP -These patterns are normally inserted automatically by the \*r command -.BR co (1), -but can also be inserted manually. -The option -.B \-q -suppresses -the warning given if there are no patterns in a file. -The option -.B \-V -prints -.BR ident 's -version number. -.PP -.B ident -works on text files as well as object files and dumps. -For example, if the C program in -.B f.c -contains -.IP -.ft 3 -#include -.br -static char const rcsid[] = -.br - \&"$\&Id: f.c,v \*(iD $\&"; -.br -int main() { return printf(\&"%s\en\&", rcsid) == EOF; } -.ft P -.LP -and -.B f.c -is compiled into -.BR f.o , -then the command -.IP -.B "ident f.c f.o" -.LP -will output -.nf -.IP -.ft 3 -f.c: - $\&Id: f.c,v \*(iD $ -f.o: - $\&Id: f.c,v \*(iD $ -.ft -.fi -.PP -If a C program defines a string like -.B rcsid -above but does not use it, -.BR lint (1) -may complain, and some C compilers will optimize away the string. -The most reliable solution is to have the program use the -.B rcsid -string, as shown in the example above. -.PP -.B ident -finds all instances of the -.BI $ keyword : "\ text\ " $ -pattern, even if -.I keyword -is not actually an \*r-supported keyword. -This gives you information about nonstandard keywords like -.BR $\&XConsortium$ . -.SH KEYWORDS -Here is the list of keywords currently maintained by -.BR co (1). -All times are given in Coordinated Universal Time (\*u, -sometimes called \&\s-1GMT\s0) by default, but if the files -were checked out with -.BR co 's -.BI \-z zone -option, times are given with a numeric time zone indication appended. -.TP -.B $\&Author$ -The login name of the user who checked in the revision. -.TP -.B $\&Date$ -The date and time the revision was checked in. -.TP -.B $\&Header$ -A standard header containing the full pathname of the \*r file, the -revision number, the date and time, the author, the state, -and the locker (if locked). -.TP -.B $\&Id$ -Same as -.BR $\&Header$ , -except that the \*r filename is without a path. -.TP -.B $\&Locker$ -The login name of the user who locked the revision (empty if not locked). -.TP -.B $\&Log$ -The log message supplied during checkin. -For -.BR ident 's -purposes, this is equivalent to -.BR $\&RCSfile$ . -.TP -.B $\&Name$ -The symbolic name used to check out the revision, if any. -.TP -.B $\&RCSfile$ -The name of the \*r file without a path. -.TP -.B $\&Revision$ -The revision number assigned to the revision. -.TP -.B $\&Source$ -The full pathname of the \*r file. -.TP -.B $\&State$ -The state assigned to the revision with the -.B \-s -option of -.BR rcs (1) -or -.BR ci (1). -.PP -.BR co (1) -represents the following characters in keyword values by escape sequences -to keep keyword strings well-formed. -.LP -.RS -.nf -.ne 6 -.ta \w'newline 'u -\f2char escape sequence\fP -tab \f3\et\fP -newline \f3\en\fP -space \f3\e040 -$ \e044 -\e \e\e\fP -.fi -.RE -.SH IDENTIFICATION -Author: Walter F. Tichy. -.br -Manual Page Revision: \*(Rv; Release Date: \*(Dt. -.br -Copyright \(co 1982, 1988, 1989 Walter F. Tichy. -.br -Copyright \(co 1990, 1992, 1993 Paul Eggert. -.SH "SEE ALSO" -ci(1), co(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1), -rcsfile(5) -.br -Walter F. Tichy, -\*r\*-A System for Version Control, -.I "Software\*-Practice & Experience" -.BR 15 , -7 (July 1985), 637-654. diff --git a/gnu/usr.bin/rcs/ident/ident.c b/gnu/usr.bin/rcs/ident/ident.c deleted file mode 100644 index 9b8bf57365ec..000000000000 --- a/gnu/usr.bin/rcs/ident/ident.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Identify RCS keyword strings in files. */ - -/* Copyright 1982, 1988, 1989 Walter Tichy - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert - Distributed under license by the Free Software Foundation, Inc. - -This file is part of RCS. - -RCS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -RCS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with RCS; see the file COPYING. -If not, write to the Free Software Foundation, -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Report problems and direct all questions to: - - rcs-bugs@cs.purdue.edu - -*/ - -/* - * Revision 5.9 1995/06/16 06:19:24 eggert - * Update FSF address. - * - * Revision 5.8 1995/06/01 16:23:43 eggert - * (exiterr, reportError): New functions, needed for DOS and OS/2 ports. - * (scanfile): Use them. - * - * Revision 5.7 1994/03/20 04:52:58 eggert - * Remove `exiting' from identExit. - * - * Revision 5.6 1993/11/09 17:40:15 eggert - * Add -V. - * - * Revision 5.5 1993/11/03 17:42:27 eggert - * Test for char == EOF, not char < 0. - * - * Revision 5.4 1992/01/24 18:44:19 eggert - * lint -> RCS_lint - * - * Revision 5.3 1991/09/10 22:15:46 eggert - * Open files with FOPEN_R, not FOPEN_R_WORK, - * because they might be executables, not working files. - * - * Revision 5.2 1991/08/19 03:13:55 eggert - * Report read errors immediately. - * - * Revision 5.1 1991/02/25 07:12:37 eggert - * Don't report empty keywords. Check for I/O errors. - * - * Revision 5.0 1990/08/22 08:12:37 eggert - * Don't limit output to known keywords. - * Remove arbitrary limits and lint. Ansify and Posixate. - * - * Revision 4.5 89/05/01 15:11:54 narten - * changed copyright header to reflect current distribution rules - * - * Revision 4.4 87/10/23 17:09:57 narten - * added exit(0) so exit return code would be non random - * - * Revision 4.3 87/10/18 10:23:55 narten - * Updating version numbers. Changes relative to 1.1 are actually relative - * to 4.1 - * - * Revision 1.3 87/07/09 09:20:52 trinkle - * Added check to make sure there is at least one arg before comparing argv[1] - * with "-q". This necessary on machines that don't allow dereferncing null - * pointers (i.e. Suns). - * - * Revision 1.2 87/03/27 14:21:47 jenkins - * Port to suns - * - * Revision 4.1 83/05/10 16:31:02 wft - * Added option -q and input from reading stdin. - * Marker matching is now done with trymatch() (independent of keywords). - * - * Revision 3.4 83/02/18 17:37:49 wft - * removed printing of new line after last file. - * - * Revision 3.3 82/12/04 12:48:55 wft - * Added LOCKER. - * - * Revision 3.2 82/11/28 18:24:17 wft - * removed Suffix; added ungetc to avoid skipping over trailing KDELIM. - * - * Revision 3.1 82/10/13 15:58:51 wft - * fixed type of variables receiving from getc() (char-->int). -*/ - -#include "rcsbase.h" - -static int match P((FILE*)); -static int scanfile P((FILE*,char const*,int)); -static void reportError P((char const*)); - -mainProg(identId, "ident", "$FreeBSD$") -/* Ident searches the named files for all occurrences - * of the pattern $@: text $ where @ is a keyword. - */ - -{ - FILE *fp; - int quiet = 0; - int status = EXIT_SUCCESS; - char const *a; - - while ((a = *++argv) && *a=='-') - while (*++a) - switch (*a) { - case 'q': - quiet = 1; - break; - - case 'V': - VOID printf("RCS version %s\n", RCS_version_string); - quiet = -1; - break; - - default: - VOID fprintf(stderr, - "ident: usage: ident -{qV} [file...]\n" - ); - exitmain(EXIT_FAILURE); - break; - } - - if (0 <= quiet) - if (!a) - VOID scanfile(stdin, (char*)0, quiet); - else - do { - if (!(fp = fopen(a, FOPEN_RB))) { - reportError(a); - status = EXIT_FAILURE; - } else if ( - scanfile(fp, a, quiet) != 0 - || (argv[1] && putchar('\n') == EOF) - ) - break; - } while ((a = *++argv)); - - if (ferror(stdout) || fclose(stdout)!=0) { - reportError("standard output"); - status = EXIT_FAILURE; - } - exitmain(status); -} - -#if RCS_lint -# define exiterr identExit -#endif - void -exiterr() -{ - _exit(EXIT_FAILURE); -} - - static void -reportError(s) - char const *s; -{ - int e = errno; - VOID fprintf(stderr, "%s error: ", cmdid); - errno = e; - perror(s); -} - - - static int -scanfile(file, name, quiet) - register FILE *file; - char const *name; - int quiet; -/* Function: scan an open file with descriptor file for keywords. - * Return -1 if there's a write error; exit immediately on a read error. - */ -{ - register int c; - - if (name) { - VOID printf("%s:\n", name); - if (ferror(stdout)) - return -1; - } else - name = "standard input"; - c = 0; - while (c != EOF || ! (feof(file)|ferror(file))) { - if (c == KDELIM) { - if ((c = match(file))) - continue; - if (ferror(stdout)) - return -1; - quiet = true; - } - c = getc(file); - } - if (ferror(file) || fclose(file) != 0) { - reportError(name); - /* - * The following is equivalent to exit(EXIT_FAILURE), but we invoke - * exiterr to keep lint happy. The DOS and OS/2 ports need exiterr. - */ - VOID fflush(stderr); - VOID fflush(stdout); - exiterr(); - } - if (!quiet) - VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name); - return 0; -} - - - - static int -match(fp) /* group substring between two KDELIM's; then do pattern match */ - register FILE *fp; -{ - char line[BUFSIZ]; - register int c; - register char * tp; - - tp = line; - while ((c = getc(fp)) != VDELIM) { - if (c == EOF && feof(fp) | ferror(fp)) - return c; - switch (ctab[c]) { - case LETTER: case Letter: case DIGIT: - *tp++ = c; - if (tp < line+sizeof(line)-4) - break; - /* fall into */ - default: - return c ? c : '\n'/* anything but 0 or KDELIM or EOF */; - } - } - if (tp == line) - return c; - *tp++ = c; - if ((c = getc(fp)) != ' ') - return c ? c : '\n'; - *tp++ = c; - while( (c = getc(fp)) != KDELIM ) { - if (c == EOF && feof(fp) | ferror(fp)) - return c; - switch (ctab[c]) { - default: - *tp++ = c; - if (tp < line+sizeof(line)-2) - break; - /* fall into */ - case NEWLN: case UNKN: - return c ? c : '\n'; - } - } - if (tp[-1] != ' ') - return c; - *tp++ = c; /*append trailing KDELIM*/ - *tp = '\0'; - VOID printf(" %c%s\n", KDELIM, line); - return 0; -} diff --git a/lib/libc/posix1e/mac.3 b/lib/libc/posix1e/mac.3 index af162f8a5a46..5d2d5c4f49df 100644 --- a/lib/libc/posix1e/mac.3 +++ b/lib/libc/posix1e/mac.3 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 7, 2009 +.Dd July 25, 2015 .Dt MAC 3 .Os .Sh NAME @@ -163,14 +163,3 @@ Support for Mandatory Access Control was introduced in as part of the .Tn TrustedBSD Project. -.Sh BUGS -The -.Tn TrustedBSD -MAC Framework and associated policies, interfaces, and -applications are considered to be an experimental feature in -.Fx . -Sites considering production deployment should keep the experimental -status of these services in mind during any deployment process. -See also -.Xr mac 9 -for related considerations regarding the kernel framework. diff --git a/lib/libc/posix1e/mac.conf.5 b/lib/libc/posix1e/mac.conf.5 index a8dfba214393..3946be18db16 100644 --- a/lib/libc/posix1e/mac.conf.5 +++ b/lib/libc/posix1e/mac.conf.5 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 19, 2003 +.Dd July 25, 2015 .Dt MAC.CONF 5 .Os .Sh NAME @@ -110,14 +110,3 @@ Support for Mandatory Access Control was introduced in as part of the .Tn TrustedBSD Project. -.Sh BUGS -The -.Tn TrustedBSD -MAC Framework and associated policies, interfaces, and -applications are considered to be an experimental feature in -.Fx . -Sites considering production deployment should keep the experimental -status of these services in mind during any deployment process. -See also -.Xr mac 9 -for related considerations regarding the kernel framework. diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3 index 3cea71ec79a9..4fd61bcda233 100644 --- a/lib/libc/stdlib/system.3 +++ b/lib/libc/stdlib/system.3 @@ -32,7 +32,7 @@ .\" @(#)system.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd July 25, 2015 .Dt SYSTEM 3 .Os .Sh NAME @@ -87,7 +87,8 @@ failed. .Xr execve 2 , .Xr fork 2 , .Xr waitpid 2 , -.Xr popen 3 +.Xr popen 3 , +.Xr posix_spawn 3 .Sh STANDARDS The .Fn system @@ -97,3 +98,14 @@ conforms to and is expected to be .St -p1003.2 compatible. +.Sh SECURITY CONSIDERATIONS +The +.Fn system +function is easily misused in a manner that enables a malicious +user to run arbitrary command, +because all meta-characters supported by +.Xr sh 1 +would be honored. +User supplied parameters should always be carefully santized +before they appear in +.Fa string. diff --git a/lib/libc/sys/reboot.2 b/lib/libc/sys/reboot.2 index f5571ae76b2b..caaba5848bc4 100644 --- a/lib/libc/sys/reboot.2 +++ b/lib/libc/sys/reboot.2 @@ -82,7 +82,7 @@ Dump kernel memory before rebooting; see .Xr savecore 8 for more information. .It Dv RB_HALT -the processor is simply halted; no reboot takes place. +The processor is simply halted; no reboot takes place. This option should be used with caution. .It Dv RB_POWEROFF After halting, the shutdown code will do what it can to turn diff --git a/lib/libc/sys/shutdown.2 b/lib/libc/sys/shutdown.2 index e8a434b23955..35c464e9fe2e 100644 --- a/lib/libc/sys/shutdown.2 +++ b/lib/libc/sys/shutdown.2 @@ -29,7 +29,7 @@ .\" @(#)shutdown.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd March 5, 2007 +.Dd July 27, 2015 .Dt SHUTDOWN 2 .Os .Sh NAME @@ -79,40 +79,26 @@ The following protocol specific actions apply to the use of based on the properties of the socket associated with the file descriptor .Fa s . .Bl -column ".Dv PF_INET6" ".Dv SOCK_STREAM" ".Dv IPPROTO_SCTP" -.It Sy Domain Ta Sy Type Ta Sy Protocol Ta Sy Return value and action +.It Sy Domain Ta Sy Type Ta Sy Protocol Ta Sy Action .It Dv PF_INET Ta Dv SOCK_DGRAM Ta Dv IPPROTO_SCTP Ta -Return \-1. -The global variable -.Va errno -will be set to -.Er EOPNOTSUPP . +Failure, +as socket is not connected. .It Dv PF_INET Ta Dv SOCK_DGRAM Ta Dv IPPROTO_UDP Ta -Return 0. -ICMP messages will -.Em not -be generated. +Failure, +as socket is not connected. .It Dv PF_INET Ta Dv SOCK_STREAM Ta Dv IPPROTO_SCTP Ta -Return 0. Send queued data and tear down association. .It Dv PF_INET Ta Dv SOCK_STREAM Ta Dv IPPROTO_TCP Ta -Return 0. Send queued data, wait for ACK, then send FIN. .It Dv PF_INET6 Ta Dv SOCK_DGRAM Ta Dv IPPROTO_SCTP Ta -Return \-1. -The global variable -.Va errno -will be set to -.Er EOPNOTSUPP . +Failure, +as socket is not connected. .It Dv PF_INET6 Ta Dv SOCK_DGRAM Ta Dv IPPROTO_UDP Ta -Return 0. -ICMP messages will -.Em not -be generated. +Failure, +as socket is not connected. .It Dv PF_INET6 Ta Dv SOCK_STREAM Ta Dv IPPROTO_SCTP Ta -Return 0. Send queued data and tear down association. .It Dv PF_INET6 Ta Dv SOCK_STREAM Ta Dv IPPROTO_TCP Ta -Return 0. Send queued data, wait for ACK, then send FIN. .El .\" @@ -131,16 +117,10 @@ argument is not a valid file descriptor. The .Fa how argument is invalid. -.It Bq Er EOPNOTSUPP -The socket associated with the file descriptor -.Fa s -does not support this operation. .It Bq Er ENOTCONN The .Fa s -argument specifies a -.Dv SOCK_STREAM -socket which is not connected. +argument specifies a socket which is not connected. .It Bq Er ENOTSOCK The .Fa s diff --git a/lib/libiconv_modules/BIG5/Makefile b/lib/libiconv_modules/BIG5/Makefile index cdaf9ddf1889..34ff9ebaa220 100644 --- a/lib/libiconv_modules/BIG5/Makefile +++ b/lib/libiconv_modules/BIG5/Makefile @@ -2,6 +2,6 @@ SHLIB= BIG5 SRCS+= citrus_big5.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/lib/libiconv_modules/EUC/Makefile b/lib/libiconv_modules/EUC/Makefile index aeceff40d230..b2f02ee3b920 100644 --- a/lib/libiconv_modules/EUC/Makefile +++ b/lib/libiconv_modules/EUC/Makefile @@ -2,6 +2,6 @@ SHLIB= EUC SRCS+= citrus_euc.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/lib/libiconv_modules/EUCTW/Makefile b/lib/libiconv_modules/EUCTW/Makefile index 4808ca3ac58b..c719a1aa1f8c 100644 --- a/lib/libiconv_modules/EUCTW/Makefile +++ b/lib/libiconv_modules/EUCTW/Makefile @@ -2,6 +2,6 @@ SHLIB= EUCTW SRCS+= citrus_euctw.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/lib/libiconv_modules/UTF1632/Makefile b/lib/libiconv_modules/UTF1632/Makefile index 485d0702b40d..b42e58c7d15f 100644 --- a/lib/libiconv_modules/UTF1632/Makefile +++ b/lib/libiconv_modules/UTF1632/Makefile @@ -2,6 +2,6 @@ SHLIB= UTF1632 SRCS+= citrus_utf1632.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/lib/libiconv_modules/UTF7/Makefile b/lib/libiconv_modules/UTF7/Makefile index 733cb26e3d43..e191fb9afd30 100644 --- a/lib/libiconv_modules/UTF7/Makefile +++ b/lib/libiconv_modules/UTF7/Makefile @@ -2,6 +2,6 @@ SHLIB= UTF7 SRCS+= citrus_utf7.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/lib/libiconv_modules/iconv_std/Makefile b/lib/libiconv_modules/iconv_std/Makefile index 88d68aafc77b..f6eeb76d20cb 100644 --- a/lib/libiconv_modules/iconv_std/Makefile +++ b/lib/libiconv_modules/iconv_std/Makefile @@ -2,6 +2,6 @@ SHLIB= iconv_std SRCS+= citrus_iconv_std.c -CFLAGS.gcc+= --param max-inline-insns-single=32 +CFLAGS.gcc+= --param max-inline-insns-single=64 .include diff --git a/release/doc/en_US.ISO8859-1/hardware/article.xml b/release/doc/en_US.ISO8859-1/hardware/article.xml index 467d5cf4af32..bc51b3d16524 100644 --- a/release/doc/en_US.ISO8859-1/hardware/article.xml +++ b/release/doc/en_US.ISO8859-1/hardware/article.xml @@ -731,6 +731,8 @@ &hwlist.nsp; + &hwlist.pms; + &hwlist.pst; &hwlist.siis; diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 4a6e577305ef..f00a2686fc07 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -511,6 +511,11 @@ OpenSSL has been updated to version 1.0.1p. + + The + &man.ssh.1; utility has been updated to re-implement hostname + canonicalization before locating the host in + known_hosts. @@ -540,6 +545,24 @@ The &man.bsdinstall.8; utility has been updated to use the new &man.dpv.3; library to display progress when extracting the &os; distributions. + + Support for detecting and implementing + aligning partitions on 1Mb boundaries has been added to + &man.bsdinstall.8;. + + Support for detecting and implementing + a workaround for various laptops and motherboards that do not + boot properly from GPT-partitioned disks + has been added to &man.bsdinstall.8;. Additionally, the + active flag will be set on the partition + when needed. + + Support for selecting the partitioning + scheme when installing on the UFS + filesystem has been added to &man.bsdinstall.8;. @@ -803,7 +826,19 @@ The PAE_TABLES kernel configuration option has been added for &os;/&arch.i386;, which instructs &man.pmap.9; - to use PAE format for page tables. + to use PAE format for page tables while + maintaining a 32-bit physical address size elsewhere in the + kernel. The use of this option can enhance application-level + security by enabling the creation of no execute + mappings on modern &arch.i386; processors. Unlike the + PAE option, PAE_TABLES + preserves kernel binary interface (KBI) + compatibility with non-PAE kernels, + allowing non-PAE kernel modules and drivers + to work with a PAE_TABLES-enabled kernel. + Additionally, system limits are tuned for 4GB maximum + RAM, avoiding kernel virtual address space + (KVA) exhaustion. The SIFTR kernel configuration has been added, allowing building &man.siftr.4; diff --git a/release/doc/share/xml/sponsor.ent b/release/doc/share/xml/sponsor.ent index 6d954f6f6f33..d5d4653b54a8 100644 --- a/release/doc/share/xml/sponsor.ent +++ b/release/doc/share/xml/sponsor.ent @@ -19,6 +19,7 @@ + diff --git a/sbin/init/init.8 b/sbin/init/init.8 index a7488a93ed82..13659e36ec2d 100644 --- a/sbin/init/init.8 +++ b/sbin/init/init.8 @@ -31,7 +31,7 @@ .\" @(#)init.8 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd March 14, 2012 +.Dd July 24, 2015 .Dt INIT 8 .Os .Sh NAME @@ -284,6 +284,7 @@ will signal the original as follows: .Bl -column Run-level SIGTERM .It Sy "Run-level Signal Action" +.It Cm 0 Ta Dv SIGUSR1 Ta "Halt" .It Cm 0 Ta Dv SIGUSR2 Ta "Halt and turn the power off" .It Cm 1 Ta Dv SIGTERM Ta "Go to single-user mode" .It Cm 6 Ta Dv SIGINT Ta "Reboot the machine" diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c index 836bc87daa48..810cf59da0c4 100644 --- a/sbin/mount_nfs/mount_nfs.c +++ b/sbin/mount_nfs/mount_nfs.c @@ -476,7 +476,8 @@ main(int argc, char *argv[]) build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); if (nmount(iov, iovlen, 0)) - err(1, "%s, %s", mntpath, errmsg); + err(1, "nmount: %s%s%s", mntpath, errmsg[0] ? ", " : "", + errmsg); exit(0); } diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c index e3309885e39f..ac443bbe15b1 100644 --- a/sbin/nvmecontrol/logpage.c +++ b/sbin/nvmecontrol/logpage.c @@ -298,6 +298,8 @@ logpage(int argc, char *argv[]) open_dev(argv[optind], &fd, 1, 1); } + read_controller_data(fd, &cdata); + /* * The log page attribtues indicate whether or not the controller * supports the SMART/Health information log page on a per @@ -307,7 +309,6 @@ logpage(int argc, char *argv[]) if (log_page != NVME_LOG_HEALTH_INFORMATION) errx(1, "log page %d valid only at controller level", log_page); - read_controller_data(fd, &cdata); if (cdata.lpa.ns_smart == 0) errx(1, "controller does not support per namespace " diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index cd4c91b466b6..fc7370494c2c 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -107,6 +107,7 @@ MAN= aac.4 \ cxgb.4 \ cxgbe.4 \ cy.4 \ + cyapa.4 \ da.4 \ dc.4 \ dcons.4 \ @@ -215,6 +216,7 @@ MAN= aac.4 \ ipw.4 \ ipwfw.4 \ isci.4 \ + isl.4 \ ismt.4 \ isp.4 \ ispfw.4 \ @@ -388,6 +390,7 @@ MAN= aac.4 \ ${_pflog.4} \ ${_pfsync.4} \ pim.4 \ + pms.4 \ polling.4 \ ppbus.4 \ ppc.4 \ diff --git a/share/man/man4/capsicum.4 b/share/man/man4/capsicum.4 index 9290cbcf0328..1d208b04a94c 100644 --- a/share/man/man4/capsicum.4 +++ b/share/man/man4/capsicum.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 19, 2013 +.Dd July 25, 2015 .Dt CAPSICUM 4 .Os .Sh NAME @@ -125,7 +125,3 @@ and .An Kris Kennaway Aq Mt kris@FreeBSD.org at Google, Inc., and .An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net . -.Sh BUGS -.Nm -is considered experimental in -.Fx . diff --git a/share/man/man4/cyapa.4 b/share/man/man4/cyapa.4 new file mode 100644 index 000000000000..5ecc9d757a1f --- /dev/null +++ b/share/man/man4/cyapa.4 @@ -0,0 +1,200 @@ +.\" Copyright (c) 2015 Michael Gmelin +.\" 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$ +.\" +.Dd July 25, 2015 +.Dt CYAPA 4 +.Os +.Sh NAME +.Nm cyapa +.Nd Cypress APA trackpad with I2C interface driver +.Sh SYNOPSIS +To compile this driver into the kernel, place the following lines into +the kernel configuration file: +.Bd -ragged -offset indent +.Cd "device cyapa" +.Cd "device ig4" +.Cd "device smbus" +.Ed +.Pp +Alternatively, to load the driver as a module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +cyapa_load="YES" +ig4_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for the Cypress APA trackpad. +It emulates the IntelliMouse PS/2 protocol. +It supports basic mouse ioctls, so that +.Xr moused 8 +is supported properly. +.Ss Trackpad layout +.Bd -literal + 2/3 1/3 + +--------------------+------------+ + | | Middle | + | | Button | + | Left | | + | Button +------------+ + | | Right | + | | Button | + +--------------------+............| + | Thumb/Button Area | 15% + +---------------------------------+ +.Ed +.Ss Trackpad features +.Bl -tag -width 8n +.It Va Two finger scrolling +Use two fingers for Z axis scrolling. +.It Va Button down/second finger +While one finger clicks and holds down the touchpad, the second finger can be +used to move the mouse cursor. +This can be useful for drawing or selecting text. +.It Va Thumb/Button area +The lower 15% of the trackpad will not affect the mouse cursor position. +This allows for high precision clicking, by controlling the cursor with the +index finger and pushing/holding the pad down with the thumb. +.It Va Trackpad button +Push physical button. +The left two thirds of the pad issues a LEFT button event. +The upper right corner issues a MIDDLE button event. +The lower right corner issues a RIGHT button. +Optionally, tap to click can be enabled (see below). +.El +.Sh SYSCTL VARIABLES +These +.Xr sysctl 8 +variables are available: +.Bl -tag -width 8n +.It Va debug.cyapa_idle_freq +Scan frequency in idle mode, the default is 1. +.It Va debug.cyapa_slow_freq +Scan frequency in slow mode, the default is 20. +.It Va debug.cyapa_norm_freq +Scan frequency in normal mode, the default is 100. +.It Va debug.cyapa_minpressure +Minimum pressure to detect a finger, the default is 12. +.It Va debug.cyapa_enable_tapclick +Controls tap to click. +Possible values: +.Bl -tag -width 8n +.It 0 +Tap to click is disabled. +This is the default value. +.It 1 +Tap to click always generates a left mouse button event. +.It 2 +Tap to click generates left mouse button event if the left 2/3rds of the pad +are tapped and a right mouse button event otherwise. +.It 3 +Tap to click generates mouse button events as if the physical button was +pressed (see +.Sx DESCRIPTION +above). +.El +.It Va debug.cyapa_tapclick_min_ticks +Minimum tap duration in ticks to create a click, the default is 1. +.It Va debug.cyapa_tapclick_max_ticks +Maximum tap duration in ticks to create a click, the default is 8. +.It Va debug.cyapa_move_min_ticks +Minimum ticks before cursor movement occurs, the default is 4. +.It Va debug.cyapa_scroll_wait_ticks +Ticks to wait before starting to scroll, the default is 0. +.It Va debug.cyapa_scroll_stick_ticks +Ticks while preventing cursor movement on single finger after scroll, +the default is 15. +.It Va debug.cyapa_thumbarea_percent +Size of bottom thumb area in percent, the default is 15. +.It Va debug.cyapa_debug +Setting this to a non-zero value enables debug output to console and syslog, +the default is 0. +.It Va debug.cyapa_reset +Setting this to a non-zero value reinitializes the device. +The sysctl resets to zero immediately. +.El +.Sh FILES +.Nm +creates +.Pa /dev/cyapa0 , +which presents the mouse as an +.Ar IntelliMouse PS/2 +device. +It supports +.Xr moused 8 +levels 0 through 2, level 1 is used by default. +.Sh EXAMPLES +To use +.Nm +with +.Xr moused 8 , +add the following lines to the +.Xr rc.conf 5 +file: +.Pp +.Dl moused_enable="YES" +.Dl moused_port="/dev/cyapa0" +.Pp +If vertical scrolling is not desired, add +.Pp +.Dl moused_flags="-l0" +.Pp +to +.Xr rc.conf 5 . +.Pp +Enable tap to click for the left and the right mouse button and +disable the thumb area by adding these lines to the +.Xr sysctl.conf 5 +file: +.Pp +.Dl debug.cyapa_thumbarea_percent=0 +.Dl debug.cyapa_enable_tapclick=2 +.Sh SEE ALSO +.Xr ig4 4 , +.Xr moused 4 , +.Xr smbus 4 , +.Xr sysmouse 4 +.Sh AUTHORS +.An -nosplit +The original +.Nm +driver was written for DragonFly BSD by +.An Matthew Dillon . +.Pp +It has been ported, modified, and enhanced for +.Fx +by +.An Michael Gmelin Aq Mt freebsd@grem.de . +.Pp +This manual page was written by +.An Michael Gmelin Aq Mt freebsd@grem.de . +.Sh BUGS +The +.Nm +driver detects the device based on its I2C address (0x67). +This might have unforeseen consequences if the initialization sequence +is sent to an unknown device at that address. diff --git a/share/man/man4/isl.4 b/share/man/man4/isl.4 new file mode 100644 index 000000000000..56a0cc3c6dcf --- /dev/null +++ b/share/man/man4/isl.4 @@ -0,0 +1,104 @@ +.\" Copyright (c) 2015 Michael Gmelin +.\" 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$ +.\" +.Dd July 25, 2015 +.Dt ISL 4 +.Os +.Sh NAME +.Nm isl +.Nd Intersil(TM) I2C ISL29018 sensor driver +.Sh SYNOPSIS +To compile this driver into the kernel, place the following lines into +the kernel configuration file: +.Bd -ragged -offset indent +.Cd "device isl" +.Cd "device ig4" +.Cd "device smbus" +.Ed +.Pp +Alternatively, to load the driver as a module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +isl_load="YES" +ig4_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides access to sensor data provided by the Intersil(TM) I2C +ISL29018 Digital Ambient Light Sensor and Proximity Sensor with Interrupt +Function. +Functionality is basic and provided through the +.Xr sysctl 8 +interface. +.Sh SYSCTL VARIABLES +The following +.Xr sysctl 8 +variables are available: +.Bl -tag -width "dev.isl.X.resolution" +.It Va dev.isl.X.als +Current ALS (Ambient Light Sensor) readout. +.It Va dev.isl.X.ir +Current IR (InfraRed) sensor readout. +.It Va dev.isl.X.prox +Current proximity sensor readout. +.It Va dev.isl.X.resolution +Current sensor resolution. +.It Va dev.isl.X.range +Current sensor range. +.El +.Sh EXAMPLES +.Ss Ambient light sensor read out +.Bd -literal +$ sysctl dev.isl.0.als +dev.isl.0.als: 64 +.Ed +.Ss Automatically adjust brightness +This requires the port +.Pa graphics/intel-backlight +and only works with laptops using a supported Intel(R) GPU. +.Bd -literal +$ pkg install intel-backlight +$ sh /usr/local/share/examples/intel-backlight/isl_backlight.sh +.Ed +.Sh SEE ALSO +.Xr ig4 4 , +.Xr smbus 4 +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Michael Gmelin Aq Mt freebsd@grem.de . +.Pp +This manual page was written by +.An Michael Gmelin Aq Mt freebsd@grem.de . +.Sh BUGS +The +.Nm +driver detects the device based on its I2C address (0x44). +This might have unforeseen consequences if the initialization sequence +is sent to an unknown device at that address. diff --git a/share/man/man4/mac.4 b/share/man/man4/mac.4 index b1ff1d951d8e..0c143139d7e0 100644 --- a/share/man/man4/mac.4 +++ b/share/man/man4/mac.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 30, 2007 +.Dd July 25, 2015 .Dt MAC 4 .Os .Sh NAME @@ -239,14 +239,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_ifoff.4 b/share/man/man4/mac_ifoff.4 index 87c73b250888..3800eeaf4cb4 100644 --- a/share/man/man4/mac_ifoff.4 +++ b/share/man/man4/mac_ifoff.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 10, 2002 +.Dd July 25, 2015 .Dt MAC_IFOFF 4 .Os .Sh NAME @@ -118,14 +118,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_mls.4 b/share/man/man4/mac_mls.4 index b314fb5ca3a9..9f98c465bd37 100644 --- a/share/man/man4/mac_mls.4 +++ b/share/man/man4/mac_mls.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 1, 2002 +.Dd July 25, 2015 .Dt MAC_MLS 4 .Os .Sh NAME @@ -236,14 +236,6 @@ Inc.\& under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_none.4 b/share/man/man4/mac_none.4 index ed13ca6f6dc7..ea5b75b34f53 100644 --- a/share/man/man4/mac_none.4 +++ b/share/man/man4/mac_none.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 1, 2002 +.Dd July 25, 2015 .Dt MAC_NONE 4 .Os .Sh NAME @@ -98,14 +98,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_partition.4 b/share/man/man4/mac_partition.4 index 296635edaf06..e19b1bc49731 100644 --- a/share/man/man4/mac_partition.4 +++ b/share/man/man4/mac_partition.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 9, 2002 +.Dd July 25, 2015 .Dt MAC_PARTITION 4 .Os .Sh NAME @@ -118,14 +118,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_seeotheruids.4 b/share/man/man4/mac_seeotheruids.4 index c870ca00d3ed..7cc3e8880915 100644 --- a/share/man/man4/mac_seeotheruids.4 +++ b/share/man/man4/mac_seeotheruids.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 6, 2005 +.Dd July 25, 2015 .Dt MAC_SEEOTHERUIDS 4 .Os .Sh NAME @@ -116,14 +116,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_stub.4 b/share/man/man4/mac_stub.4 index 89491f1605c2..77896876470e 100644 --- a/share/man/man4/mac_stub.4 +++ b/share/man/man4/mac_stub.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 1, 2002 +.Dd July 25, 2015 .Dt MAC_STUB 4 .Os .Sh NAME @@ -101,14 +101,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/mac_test.4 b/share/man/man4/mac_test.4 index e86d4bd0f140..6f14792faee7 100644 --- a/share/man/man4/mac_test.4 +++ b/share/man/man4/mac_test.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 1, 2002 +.Dd July 25, 2015 .Dt MAC_TEST 4 .Os .Sh NAME @@ -102,14 +102,6 @@ under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. .Sh BUGS -See -.Xr mac 9 -concerning appropriateness for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/share/man/man4/pms.4 b/share/man/man4/pms.4 new file mode 100644 index 000000000000..7684051213c5 --- /dev/null +++ b/share/man/man4/pms.4 @@ -0,0 +1,128 @@ +.\" Copyright (c) 2015 Christian Brueffer +.\" 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$ +.\" +.Dd July 23, 2015 +.Dt PMS 4 +.Os +.Sh NAME +.Nm pms +.Nd "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 SAS/SATA HBA Controller driver" +.Sh SYNOPSIS +To compile the driver into the kernel, +place the following line in the +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device pms" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +pms_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for the PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 +range of SAS/SATA HBA controllers. +.Sh HARDWARE +The +.Nm +driver supports the following hardware: +.Pp +.Bl -bullet -compact +.It +Tachyon TS Fibre Channel Card +.It +Tachyon TL Fibre Channel Card +.It +Tachyon XL2 Fibre Channel Card +.It +Tachyon DX2 Fibre Channel Card +.It +Tachyon DX2+ Fibre Channel Card +.It +Tachyon DX4+ Fibre Channel Card +.It +Tachyon QX2 Fibre Channel Card +.It +Tachyon QX4 Fibre Channel Card +.It +Tachyon DE4 Fibre Channel Card +.It +Tachyon QE4 Fibre Channel Card +.It +Tachyon XL10 Fibre Channel Card +.It +PMC Sierra SPC SAS-SATA Card +.It +PMC Sierra SPC-V SAS-SATA Card +.It +PMC Sierra SPC-VE SAS-SATA Card +.It +PMC Sierra SPC-V 16 Port SAS-SATA Card +.It +PMC Sierra SPC-VE 16 Port SAS-SATA Card +.It +PMC Sierra SPC-V SAS-SATA Card 12Gig +.It +PMC Sierra SPC-VE SAS-SATA Card 12Gig +.It +PMC Sierra SPC-V 16 Port SAS-SATA Card 12Gig +.It +PMC Sierra SPC-VE 16 Port SAS-SATA Card 12Gig +.It +Adaptec Hialeah 4/8 Port SAS-SATA HBA Card 6Gig +.It +Adaptec Hialeah 4/8 Port SAS-SATA RAID Card 6Gig +.It +Adaptec Hialeah 8/16 Port SAS-SATA HBA Card 6Gig +.It +Adaptec Hialeah 8/16 Port SAS-SATA RAID Card 6Gig +.It +Adaptec Hialeah 8/16 Port SAS-SATA HBA Encryption Card 6Gig +.It +Adaptec Hialeah 8/16 Port SAS-SATA RAID Encryption Card 6Gig +.It +Adaptec Delray 8 Port SAS-SATA HBA Card 12Gig +.It +Adaptec Delray 8 Port SAS-SATA HBA Encryption Card 12Gig +.It +Adaptec Delray 16 Port SAS-SATA HBA Card 12Gig +.It +Adaptec Delray 16 Port SAS-SATA HBA Encryption Card 12Gig +.El +.Sh SEE ALSO +.Xr cam 4 , +.Xr camcontrol 8 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 10.2 . +.Sh AUTHORS +.An Achim Leubner Aq Mt Achim.Leubner@pmcs.com diff --git a/share/man/man4/procdesc.4 b/share/man/man4/procdesc.4 index ec8c827f29ec..ce32a24646da 100644 --- a/share/man/man4/procdesc.4 +++ b/share/man/man4/procdesc.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 21, 2013 +.Dd July 25, 2015 .Dt PROCDESC 4 .Os .Sh NAME @@ -85,7 +85,3 @@ at the University of Cambridge, and and .An Kris Kennaway Aq Mt kris@FreeBSD.org at Google, Inc. -.Sh BUGS -.Nm -is considered experimental in -.Fx . diff --git a/share/man/man5/device.hints.5 b/share/man/man5/device.hints.5 index 16d462738e2c..4f33e3518aeb 100644 --- a/share/man/man5/device.hints.5 +++ b/share/man/man5/device.hints.5 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 11, 2009 +.Dd July 23, 2015 .Dt DEVICE.HINTS 5 .Os .Sh NAME @@ -41,9 +41,8 @@ passed to the kernel. It contains various variables to control the boot behavior of the kernel. These variables are typically -.Dq device hints . -.\" .Dq device hints , -.\" and other control variables. +.Dq device hints , +but can include any kernel tunable values. .Pp The file contains one variable per line. Lines starting with the @@ -152,12 +151,11 @@ The following example disables the ACPI driver: .Bd -literal -offset indent hint.acpi.0.disabled="1" .Ed -.\" .Pp -.\" A control variable may look like: -.\" .Pp -.\" .Bd -literal -offset indent -.\" debug.acpi.layer="ACPI_RESOURCES" -.\" .Ed +.Pp +Setting a tunable variable: +.Bd -literal -offset indent +vm.pmap.pg_ps_enabled=1 +.Ed .Sh SEE ALSO .Xr kenv 1 , .Xr loader.conf 5 , diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index 4ed941c40cfc..02cd3414335d 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -28,7 +28,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 29, 2012 +.Dd July 25, 2015 .Dt PF.CONF 5 .Os .Sh NAME @@ -2381,8 +2381,10 @@ Once this limit is reached, fragments that would have to be cached are dropped until other entries time out. The timeout value can also be adjusted. .Pp -Currently, only IPv4 fragments are supported and IPv6 fragments -are blocked unconditionally. +When forwarding reassembled IPv6 packets, pf refragments them with +the original maximum fragment size. +This allows the sender to determine the optimal fragment size by +path MTU discovery. .Sh ANCHORS Besides the main ruleset, .Xr pfctl 8 diff --git a/share/man/man9/mac.9 b/share/man/man9/mac.9 index cc05c5a1f323..d1e86ad79234 100644 --- a/share/man/man9/mac.9 +++ b/share/man/man9/mac.9 @@ -33,7 +33,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 10, 2006 +.Dd July 25, 2015 .Dt MAC 9 .Os .Sh NAME @@ -62,14 +62,6 @@ opportunity to modify security behavior at those MAC API entry points. Both consumers of the API (normal kernel services) and security modules must be aware of the semantics of the API calls, particularly with respect to synchronization primitives (such as locking). -.Ss Note on Appropriateness for Production Use -The -.Tn TrustedBSD -MAC Framework included in -.Fx 5.0 -is considered experimental, and should not be deployed in production -environments without careful consideration of the risks associated with -the use of experimental operating system features. .Ss Kernel Objects Supported by the Framework The MAC framework manages labels on a variety of types of in-kernel objects, including process credentials, vnodes, devfs_dirents, mount @@ -232,13 +224,6 @@ Additional contributors include: and .An Tim Robbins . .Sh BUGS -See the earlier section in this document concerning appropriateness -for production use. -The -.Tn TrustedBSD -MAC Framework is considered experimental in -.Fx . -.Pp While the MAC Framework design is intended to support the containment of the root user, not all attack channels are currently protected by entry point checks. diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h index 7892d51ec19c..016aa70e04b0 100644 --- a/sys/amd64/include/atomic.h +++ b/sys/amd64/include/atomic.h @@ -32,6 +32,25 @@ #error this file needs sys/cdefs.h as a prerequisite #endif +/* + * To express interprocessor (as opposed to processor and device) memory + * ordering constraints, use the atomic_*() functions with acquire and release + * semantics rather than the *mb() functions. An architecture's memory + * ordering (or memory consistency) model governs the order in which a + * program's accesses to different locations may be performed by an + * implementation of that architecture. In general, for memory regions + * defined as writeback cacheable, the memory ordering implemented by amd64 + * processors preserves the program ordering of a load followed by a load, a + * load followed by a store, and a store followed by a store. Only a store + * followed by a load to a different memory location may be reordered. + * Therefore, except for special cases, like non-temporal memory accesses or + * memory regions defined as write combining, the memory ordering effects + * provided by the sfence instruction in the wmb() function and the lfence + * instruction in the rmb() function are redundant. In contrast, the + * atomic_*() functions with acquire and release semantics do not perform + * redundant instructions for ordinary cases of interprocessor memory + * ordering on any architecture. + */ #define mb() __asm __volatile("mfence;" : : : "memory") #define wmb() __asm __volatile("sfence;" : : : "memory") #define rmb() __asm __volatile("lfence;" : : : "memory") diff --git a/sys/arm/ti/am335x/am335x_lcd.c b/sys/arm/ti/am335x/am335x_lcd.c index 1f3866454a69..c1c91b3d5a7c 100644 --- a/sys/arm/ti/am335x/am335x_lcd.c +++ b/sys/arm/ti/am335x/am335x_lcd.c @@ -998,8 +998,11 @@ am335x_lcd_attach(device_t dev) PWM_PERIOD, PWM_PERIOD) == 0) sc->sc_backlight = 100; - sc->sc_hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event, - am335x_lcd_hdmi_event, sc, 0); + if (panel_node != 0) + am335x_lcd_configure(sc); + else + sc->sc_hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event, + am335x_lcd_hdmi_event, sc, 0); return (0); } diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.h b/sys/arm/ti/am335x/am335x_scm_padconf.h index 35adc57f1605..2d0cd4b9ccec 100644 --- a/sys/arm/ti/am335x/am335x_scm_padconf.h +++ b/sys/arm/ti/am335x/am335x_scm_padconf.h @@ -34,8 +34,9 @@ #define PULLTYPESEL (0x01 << 4) /* Pad pullup/pulldown type selection */ #define PULLUDEN (0x01 << 3) /* Pullup/pulldown disabled */ -#define PADCONF_OUTPUT (0) +#define PADCONF_OUTPUT (PULLUDEN) #define PADCONF_OUTPUT_PULLUP (PULLTYPESEL) +#define PADCONF_OUTPUT_PULLDOWN (0) #define PADCONF_INPUT (RXACTIVE | PULLUDEN) #define PADCONF_INPUT_PULLUP (RXACTIVE | PULLTYPESEL) #define PADCONF_INPUT_PULLDOWN (RXACTIVE) diff --git a/sys/arm/ti/am335x/tda19988.c b/sys/arm/ti/am335x/tda19988.c index 83dcf4364893..18bc18b73068 100644 --- a/sys/arm/ti/am335x/tda19988.c +++ b/sys/arm/ti/am335x/tda19988.c @@ -715,8 +715,8 @@ tda19988_start(void *xdev) /* Default values for RGB 4:4:4 mapping */ tda19988_reg_write(sc, TDA_VIP_CNTRL_0, 0x23); - tda19988_reg_write(sc, TDA_VIP_CNTRL_1, 0x45); - tda19988_reg_write(sc, TDA_VIP_CNTRL_2, 0x01); + tda19988_reg_write(sc, TDA_VIP_CNTRL_1, 0x01); + tda19988_reg_write(sc, TDA_VIP_CNTRL_2, 0x45); done: config_intrhook_disestablish(&sc->enum_hook); diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8 index 03a648802a8a..7d5a561e31cc 100644 --- a/sys/boot/common/loader.8 +++ b/sys/boot/common/loader.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 22, 2014 +.Dd July 25, 2015 .Dt LOADER 8 .Os .Sh NAME @@ -207,12 +207,18 @@ returns an error itself (see .Op Fl t Ar type .Ar file Cm ... .Xc -Loads a kernel, kernel loadable module (kld), or file of opaque -contents tagged as being of the type +Loads a kernel, kernel loadable module (kld), disk image, +or file of opaque contents tagged as being of the type .Ar type . Kernel and modules can be either in a.out or ELF format. Any arguments passed after the name of the file to be loaded will be passed as arguments to that file. +Use the +.Li md_image +type to make the kernel create a file-backed +.Xr md 4 +disk. +This is useful for booting from a temporary rootfs. Currently, argument passing does not work for the kernel. .Pp .It Ic load_geli Xo diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index a844889cbc73..caafcc65ba90 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -39,7 +39,7 @@ bitmap_type="splash_image_data" # and place it on the module_path ############################################################## -### Random number generator configuration ################### +### Random number generator configuration ################## ############################################################## # See rc.conf(5). The entropy_boot_file config variable must agree with the @@ -53,8 +53,9 @@ entropy_cache_type="/boot/entropy" # Required for the kernel to find # must not change value even if the # _name above does change! + ############################################################## -### RAM Blacklist configuration ############################# +### RAM Blacklist configuration ############################ ############################################################## ram_blacklist_load="NO" # Set this to YES to load a file @@ -64,6 +65,17 @@ ram_blacklist_name="/boot/blacklist.txt" # Set this to the name of the file ram_blacklist_type="ram_blacklist" # Required for the kernel to find # the blacklist module + +############################################################## +### Initial memory disk settings ########################### +############################################################## + +#initmd_load="YES" # The "initmd" prefix is arbitrary. +#initmd_type="md_image" # Create md(4) disk at boot. +#initmd_name="/boot/root.img" # Path to a file containing the image. +#rootdev="ufs:/dev/md0" # Set the root filesystem to md(4) device. + + ############################################################## ### Loader settings ######################################## ############################################################## @@ -161,7 +173,7 @@ module_path="/boot/modules" # Set the module search path ############################################################## -### ATA modules ############################################## +### ATA modules ############################################ ############################################################## ataacard_load="NO" # ACARD @@ -381,6 +393,7 @@ if_xe_load="NO" # Xircom CreditCard PCMCIA if_xl_load="NO" # 3Com Etherlink XL (3c900, 3c905, 3c905B) utopia_load="NO" # ATM PHY driver + ############################################################## ### Netgraph modules ####################################### ############################################################## @@ -422,6 +435,7 @@ ng_tty_load="NO" # Netgraph node type that is also a line ng_vjc_load="NO" # Van Jacobsen compression netgraph node type ng_vlan_load="NO" # IEEE 802.1Q VLAN tagging netgraph node type + ############################################################## ### Sound modules ########################################## ############################################################## @@ -458,6 +472,7 @@ snd_via82c686_load="NO" # via82c686 snd_vibes_load="NO" # vibes snd_driver_load="NO" # All sound drivers + ############################################################## ### USB modules ############################################ ############################################################## @@ -490,6 +505,7 @@ if_ural_load="NO" # Ralink RT2500USB 802.11 wireless adapter if_zyd_load="NO" # ZyDAS ZD1211(B) USB 802.11 wireless adapter snd_uaudio_load="NO" # USB audio + ############################################################## ### Other modules ########################################## ############################################################## @@ -514,6 +530,7 @@ amdtemp_load="NO" # AMD K8/K10/K11 temperature monitor tpm_load="NO" # Trusted Platform Module wbwd_load="NO" # Winbond watchdog + ############################################################## ### ACPI settings ########################################## ############################################################## @@ -524,8 +541,9 @@ acpi_dsdt_name="/boot/acpi_dsdt.aml" # Override DSDT in BIOS by this file acpi_video_load="NO" # Load the ACPI video extension driver + ############################################################## -### TrustedBSD MAC settings ################################## +### TrustedBSD MAC settings ################################ ############################################################## mac_biba_load="NO" # Biba MAC policy @@ -536,6 +554,7 @@ mac_none_load="NO" # Null MAC policy mac_partition_load="NO" # Partition MAC policy mac_seeotheruids_load="NO" # UID visbility MAC policy + ############################################################## ### Module loading syntax example ########################## ############################################################## diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 53454f815c21..956e5d0a7a25 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -855,12 +855,12 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) */ mapinfo->bp[i] = getpbuf(NULL); - /* save the buffer's data address */ - mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data; - /* put our pointer in the data slot */ mapinfo->bp[i]->b_data = *data_ptrs[i]; + /* save the user's data address */ + mapinfo->bp[i]->b_caller1 = *data_ptrs[i]; + /* set the transfer length, we know it's < MAXPHYS */ mapinfo->bp[i]->b_bufsize = lengths[i]; @@ -877,7 +877,7 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) */ if (vmapbuf(mapinfo->bp[i], 1) < 0) { for (j = 0; j < i; ++j) { - *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr; + *data_ptrs[j] = mapinfo->bp[j]->b_caller1; vunmapbuf(mapinfo->bp[j]); relpbuf(mapinfo->bp[j], NULL); } @@ -958,7 +958,7 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) for (i = 0; i < numbufs; i++) { /* Set the user's pointer back to the original value */ - *data_ptrs[i] = mapinfo->bp[i]->b_saveaddr; + *data_ptrs[i] = mapinfo->bp[i]->b_caller1; /* unmap the buffer */ vunmapbuf(mapinfo->bp[i]); diff --git a/sys/compat/cloudabi/cloudabi_clock.c b/sys/compat/cloudabi/cloudabi_clock.c index 8462f233b738..ed32cf611f72 100644 --- a/sys/compat/cloudabi/cloudabi_clock.c +++ b/sys/compat/cloudabi/cloudabi_clock.c @@ -80,6 +80,24 @@ cloudabi_convert_timespec(const struct timespec *in, cloudabi_timestamp_t *out) return (0); } +/* Fetches the time value of a clock. */ +int +cloudabi_clock_time_get(struct thread *td, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t *ret) +{ + struct timespec ts; + int error; + clockid_t clockid; + + error = cloudabi_convert_clockid(clock_id, &clockid); + if (error != 0) + return (error); + error = kern_clock_gettime(td, clockid, &ts); + if (error != 0) + return (error); + return (cloudabi_convert_timespec(&ts, ret)); +} + int cloudabi_sys_clock_res_get(struct thread *td, struct cloudabi_sys_clock_res_get_args *uap) @@ -106,20 +124,10 @@ int cloudabi_sys_clock_time_get(struct thread *td, struct cloudabi_sys_clock_time_get_args *uap) { - struct timespec ts; - cloudabi_timestamp_t cts; + cloudabi_timestamp_t ts; int error; - clockid_t clockid; - error = cloudabi_convert_clockid(uap->clock_id, &clockid); - if (error != 0) - return (error); - error = kern_clock_gettime(td, clockid, &ts); - if (error != 0) - return (error); - error = cloudabi_convert_timespec(&ts, &cts); - if (error != 0) - return (error); - td->td_retval[0] = cts; - return (0); + error = cloudabi_clock_time_get(td, uap->clock_id, &ts); + td->td_retval[0] = ts; + return (error); } diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c index da3c0da59305..8b72c19cdf6f 100644 --- a/sys/compat/cloudabi/cloudabi_fd.c +++ b/sys/compat/cloudabi/cloudabi_fd.c @@ -46,18 +46,51 @@ int cloudabi_sys_fd_create1(struct thread *td, struct cloudabi_sys_fd_create1_args *uap) { + struct socket_args socket_args = { + .domain = AF_UNIX, + }; - /* Not implemented. */ - return (ENOSYS); + switch (uap->type) { + case CLOUDABI_FILETYPE_SOCKET_DGRAM: + socket_args.type = SOCK_DGRAM; + return (sys_socket(td, &socket_args)); + case CLOUDABI_FILETYPE_SOCKET_SEQPACKET: + socket_args.type = SOCK_SEQPACKET; + return (sys_socket(td, &socket_args)); + case CLOUDABI_FILETYPE_SOCKET_STREAM: + socket_args.type = SOCK_STREAM; + return (sys_socket(td, &socket_args)); + default: + return (EINVAL); + } } int cloudabi_sys_fd_create2(struct thread *td, struct cloudabi_sys_fd_create2_args *uap) { + int fds[2]; + int error; - /* Not implemented. */ - return (ENOSYS); + switch (uap->type) { + case CLOUDABI_FILETYPE_SOCKET_DGRAM: + error = kern_socketpair(td, AF_UNIX, SOCK_DGRAM, 0, fds); + break; + case CLOUDABI_FILETYPE_SOCKET_SEQPACKET: + error = kern_socketpair(td, AF_UNIX, SOCK_SEQPACKET, 0, fds); + break; + case CLOUDABI_FILETYPE_SOCKET_STREAM: + error = kern_socketpair(td, AF_UNIX, SOCK_STREAM, 0, fds); + break; + default: + return (EINVAL); + } + + if (error == 0) { + td->td_retval[0] = fds[0]; + td->td_retval[1] = fds[1]; + } + return (0); } int diff --git a/sys/compat/cloudabi/cloudabi_file.c b/sys/compat/cloudabi/cloudabi_file.c index 034cf0159479..b5085173811a 100644 --- a/sys/compat/cloudabi/cloudabi_file.c +++ b/sys/compat/cloudabi/cloudabi_file.c @@ -28,11 +28,67 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include #include #include #include +static MALLOC_DEFINE(M_CLOUDABI_PATH, "cloudabipath", "CloudABI pathnames"); + +/* + * Copying pathnames from userspace to kernelspace. + * + * Unlike most operating systems, CloudABI doesn't use null-terminated + * pathname strings. Processes always pass pathnames to the kernel by + * providing a base pointer and a length. This has a couple of reasons: + * + * - It makes it easier to use CloudABI in combination with programming + * languages other than C, that may use non-null terminated strings. + * - It allows for calling system calls on individual components of the + * pathname without modifying the input string. + * + * The function below copies in pathname strings and null-terminates it. + * It also ensure that the string itself does not contain any null + * bytes. + * + * TODO(ed): Add an abstraction to vfs_lookup.c that allows us to pass + * in unterminated pathname strings, so we can do away with + * the copying. + */ + +static int +copyin_path(const char *uaddr, size_t len, char **result) +{ + char *buf; + int error; + + if (len >= PATH_MAX) + return (ENAMETOOLONG); + buf = malloc(len + 1, M_CLOUDABI_PATH, M_WAITOK); + error = copyin(uaddr, buf, len); + if (error != 0) { + free(buf, M_CLOUDABI_PATH); + return (error); + } + if (memchr(buf, '\0', len) != NULL) { + free(buf, M_CLOUDABI_PATH); + return (EINVAL); + } + buf[len] = '\0'; + *result = buf; + return (0); +} + +static void +cloudabi_freestr(char *buf) +{ + + free(buf, M_CLOUDABI_PATH); +} + int cloudabi_sys_file_advise(struct thread *td, struct cloudabi_sys_file_advise_args *uap) @@ -86,9 +142,24 @@ int cloudabi_sys_file_link(struct thread *td, struct cloudabi_sys_file_link_args *uap) { + char *path1, *path2; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->path1, uap->path1len, &path1); + if (error != 0) + return (error); + error = copyin_path(uap->path2, uap->path2len, &path2); + if (error != 0) { + cloudabi_freestr(path1); + return (error); + } + + error = kern_linkat(td, uap->fd1, uap->fd2, path1, path2, + UIO_SYSSPACE, (uap->fd1 & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ? + FOLLOW : NOFOLLOW); + cloudabi_freestr(path1); + cloudabi_freestr(path2); + return (error); } int @@ -113,18 +184,40 @@ int cloudabi_sys_file_readlink(struct thread *td, struct cloudabi_sys_file_readlink_args *uap) { + char *path; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->path, uap->pathlen, &path); + if (error != 0) + return (error); + + error = kern_readlinkat(td, uap->fd, path, UIO_SYSSPACE, + uap->buf, UIO_USERSPACE, uap->bufsize); + cloudabi_freestr(path); + return (error); } int cloudabi_sys_file_rename(struct thread *td, struct cloudabi_sys_file_rename_args *uap) { + char *old, *new; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->old, uap->oldlen, &old); + if (error != 0) + return (error); + error = copyin_path(uap->new, uap->newlen, &new); + if (error != 0) { + cloudabi_freestr(old); + return (error); + } + + error = kern_renameat(td, uap->oldfd, old, uap->newfd, new, + UIO_SYSSPACE); + cloudabi_freestr(old); + cloudabi_freestr(new); + return (error); } int @@ -167,16 +260,39 @@ int cloudabi_sys_file_symlink(struct thread *td, struct cloudabi_sys_file_symlink_args *uap) { + char *path1, *path2; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->path1, uap->path1len, &path1); + if (error != 0) + return (error); + error = copyin_path(uap->path2, uap->path2len, &path2); + if (error != 0) { + cloudabi_freestr(path1); + return (error); + } + + error = kern_symlinkat(td, path1, uap->fd, path2, UIO_SYSSPACE); + cloudabi_freestr(path1); + cloudabi_freestr(path2); + return (error); } int cloudabi_sys_file_unlink(struct thread *td, struct cloudabi_sys_file_unlink_args *uap) { + char *path; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->path, uap->pathlen, &path); + if (error != 0) + return (error); + + if (uap->flag & CLOUDABI_UNLINK_REMOVEDIR) + error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE); + else + error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0); + cloudabi_freestr(path); + return (error); } diff --git a/sys/compat/cloudabi/cloudabi_futex.c b/sys/compat/cloudabi/cloudabi_futex.c index 9d4fdf84f4e2..802509062e67 100644 --- a/sys/compat/cloudabi/cloudabi_futex.c +++ b/sys/compat/cloudabi/cloudabi_futex.c @@ -26,22 +26,1197 @@ #include __FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + #include +#include +#include + +/* + * Futexes for CloudABI. + * + * On most systems, futexes are implemented as objects of a single type + * on which a set of operations can be performed. CloudABI makes a clear + * distinction between locks and condition variables. A lock may have + * zero or more associated condition variables. A condition variable is + * always associated with exactly one lock. There is a strict topology. + * This approach has two advantages: + * + * - This topology is guaranteed to be acyclic. Requeueing of threads + * only happens in one direction (from condition variables to locks). + * This eases locking. + * - It means that a futex object for a lock exists when it is unlocked, + * but has threads waiting on associated condition variables. Threads + * can be requeued to a lock even if the thread performing the wakeup + * does not have the lock mapped in its address space. + * + * This futex implementation only implements a single lock type, namely + * a read-write lock. A regular mutex type would not be necessary, as + * the read-write lock is as efficient as a mutex if used as such. + * Userspace futex locks are 32 bits in size: + * + * - 1 bit: has threads waiting in kernel-space. + * - 1 bit: is write-locked. + * - 30 bits: + * - if write-locked: thread ID of owner. + * - if not write-locked: number of read locks held. + * + * Condition variables are also 32 bits in size. Its value is modified + * by kernel-space exclusively. Zero indicates that it has no waiting + * threads. Non-zero indicates the opposite. + * + * This implementation is optimal, in the sense that it only wakes up + * threads if they can actually continue execution. It does not suffer + * from the thundering herd problem. If multiple threads waiting on a + * condition variable need to be woken up, only a single thread is + * scheduled. All other threads are 'donated' to this thread. After the + * thread manages to reacquire the lock, it requeues its donated threads + * to the lock. + * + * TODO(ed): Integrate this functionality into kern_umtx.c instead. + * TODO(ed): Store futex objects in a hash table. + * TODO(ed): Add actual priority inheritance. + * TODO(ed): Let futex_queue also take priorities into account. + * TODO(ed): Make locking fine-grained. + * TODO(ed): Perform sleeps until an actual absolute point in time, + * instead of converting the timestamp to a relative value. + */ + +struct futex_address; +struct futex_condvar; +struct futex_lock; +struct futex_queue; +struct futex_waiter; + +/* Identifier of a location in memory. */ +struct futex_address { + /* For process-private objects: address space of the process. */ + struct vmspace * fa_vmspace; + /* For process-shared objects: VM object containing the object. */ + struct vm_object * fa_vmobject; + + /* Memory address within address space or offset within VM object. */ + uintptr_t fa_offset; +}; + +/* A set of waiting threads. */ +struct futex_queue { + STAILQ_HEAD(, futex_waiter) fq_list; + unsigned int fq_count; +}; + +/* Condition variables. */ +struct futex_condvar { + /* Address of the condition variable. */ + struct futex_address fc_address; + + /* The lock the waiters should be moved to when signalled. */ + struct futex_lock * fc_lock; + + /* Threads waiting on the condition variable. */ + struct futex_queue fc_waiters; + /* + * Number of threads blocked on this condition variable, or + * being blocked on the lock after being requeued. + */ + unsigned int fc_waitcount; + + /* Global list pointers. */ + LIST_ENTRY(futex_condvar) fc_next; +}; + +/* Read-write locks. */ +struct futex_lock { + /* Address of the lock. */ + struct futex_address fl_address; + + /* + * Current owner of the lock. LOCK_UNMANAGED if the lock is + * currently not owned by the kernel. LOCK_OWNER_UNKNOWN in case + * the owner is not known (e.g., when the lock is read-locked). + */ + cloudabi_tid_t fl_owner; +#define LOCK_UNMANAGED 0x0 +#define LOCK_OWNER_UNKNOWN 0x1 + + /* Writers blocked on the lock. */ + struct futex_queue fl_writers; + /* Readers blocked on the lock. */ + struct futex_queue fl_readers; + /* Number of threads blocked on this lock + condition variables. */ + unsigned int fl_waitcount; + + /* Global list pointers. */ + LIST_ENTRY(futex_lock) fl_next; +}; + +/* Information associated with a thread blocked on an object. */ +struct futex_waiter { + /* Thread ID. */ + cloudabi_tid_t fw_tid; + /* Condition variable used for waiting. */ + struct cv fw_wait; + + /* Queue this waiter is currently placed in. */ + struct futex_queue * fw_queue; + /* List pointers of fw_queue. */ + STAILQ_ENTRY(futex_waiter) fw_next; + + /* Lock has been acquired. */ + bool fw_locked; + /* If not locked, threads that should block after acquiring. */ + struct futex_queue fw_donated; +}; + +/* Global data structures. */ +static MALLOC_DEFINE(M_FUTEX, "futex", "CloudABI futex"); + +static struct sx futex_global_lock; +SX_SYSINIT(futex_global_lock, &futex_global_lock, "CloudABI futex global lock"); + +static LIST_HEAD(, futex_lock) futex_lock_list = + LIST_HEAD_INITIALIZER(&futex_lock_list); +static LIST_HEAD(, futex_condvar) futex_condvar_list = + LIST_HEAD_INITIALIZER(&futex_condvar_list); + +/* Utility functions. */ +static void futex_lock_assert(const struct futex_lock *); +static struct futex_lock *futex_lock_lookup_locked(struct futex_address *); +static void futex_lock_release(struct futex_lock *); +static int futex_lock_tryrdlock(struct futex_lock *, cloudabi_lock_t *); +static int futex_lock_unmanage(struct futex_lock *, cloudabi_lock_t *); +static int futex_lock_update_owner(struct futex_lock *, cloudabi_lock_t *); +static int futex_lock_wake_up_next(struct futex_lock *, cloudabi_lock_t *); +static unsigned int futex_queue_count(const struct futex_queue *); +static void futex_queue_init(struct futex_queue *); +static void futex_queue_requeue(struct futex_queue *, struct futex_queue *, + unsigned int); +static int futex_queue_sleep(struct futex_queue *, struct futex_lock *, + struct futex_waiter *, struct thread *, cloudabi_clockid_t, + cloudabi_timestamp_t, cloudabi_timestamp_t); +static cloudabi_tid_t futex_queue_tid_best(const struct futex_queue *); +static void futex_queue_wake_up_all(struct futex_queue *); +static void futex_queue_wake_up_best(struct futex_queue *); +static void futex_queue_wake_up_donate(struct futex_queue *, unsigned int); +static int futex_user_load(uint32_t *, uint32_t *); +static int futex_user_store(uint32_t *, uint32_t); +static int futex_user_cmpxchg(uint32_t *, uint32_t, uint32_t *, uint32_t); + +/* + * futex_address operations. + */ + +static int +futex_address_create(struct futex_address *fa, struct thread *td, + const void *object, cloudabi_mflags_t scope) +{ + struct vmspace *vs; + struct vm_object *vo; + vm_map_t map; + vm_map_entry_t entry; + vm_pindex_t pindex; + vm_prot_t prot; + boolean_t wired; + + /* + * Most of the time objects are stored in privately mapped + * anonymous memory. For these objects we wouldn't need to look + * up the corresponding VM object. The scope hint provided by + * userspace allows us to skip the VM map lookup for the common + * case. + * + * POSIX does permit enabling PTHREAD_PROCESS_SHARED on a lock + * stored in a private mapping, at the cost of additional + * performance overhead. Fall back to identifying the object by + * virtual memory address if the mapping isn't shared. + */ + vs = td->td_proc->p_vmspace; + switch (scope) { + case CLOUDABI_MAP_SHARED: + map = &vs->vm_map; + if (vm_map_lookup(&map, (vm_offset_t)object, + VM_PROT_COPY | VM_PROT_WRITE, &entry, &vo, &pindex, &prot, + &wired) != KERN_SUCCESS) + return (EFAULT); + + if (entry->inheritance == VM_INHERIT_SHARE) { + /* + * Address corresponds to a shared mapping. + * Identify the address by its VM object. + */ + fa->fa_vmspace = NULL; + fa->fa_vmobject = vo; + vm_object_reference(vo); + fa->fa_offset = entry->offset - entry->start + + (vm_offset_t)object; + vm_map_lookup_done(map, entry); + return (0); + } + vm_map_lookup_done(map, entry); + /* FALLTHROUGH */ + case CLOUDABI_MAP_PRIVATE: + /* + * Address corresponds to a private mapping. Never + * identify the address by its VM object, as shadow + * objects may get inserted if another thread forks. + * Simply use the VM space instead. + */ + fa->fa_vmspace = vs; + fa->fa_vmobject = NULL; + fa->fa_offset = (uintptr_t)object; + return (0); + default: + return (EINVAL); + } +} + +static void +futex_address_free(struct futex_address *fa) +{ + + if (fa->fa_vmobject != NULL) + vm_object_deallocate(fa->fa_vmobject); +} + +static bool +futex_address_match(const struct futex_address *fa1, + const struct futex_address *fa2) +{ + + /* Either fa_vmspace or fa_vmobject is NULL. */ + return (fa1->fa_vmspace == fa2->fa_vmspace && + fa1->fa_vmobject == fa2->fa_vmobject && + fa1->fa_offset == fa2->fa_offset); +} + +/* + * futex_condvar operations. + */ + +static void +futex_condvar_assert(const struct futex_condvar *fc) +{ + + KASSERT(fc->fc_waitcount >= futex_queue_count(&fc->fc_waiters), + ("Total number of waiters cannot be smaller than the wait queue")); + futex_lock_assert(fc->fc_lock); +} + +static int +futex_condvar_lookup(struct thread *td, const cloudabi_condvar_t *address, + cloudabi_mflags_t scope, struct futex_condvar **fcret) +{ + struct futex_address fa_condvar; + struct futex_condvar *fc; + int error; + + error = futex_address_create(&fa_condvar, td, address, scope); + if (error != 0) + return (error); + + sx_xlock(&futex_global_lock); + LIST_FOREACH(fc, &futex_condvar_list, fc_next) { + if (futex_address_match(&fc->fc_address, &fa_condvar)) { + /* Found matching lock object. */ + futex_address_free(&fa_condvar); + futex_condvar_assert(fc); + *fcret = fc; + return (0); + } + } + sx_xunlock(&futex_global_lock); + futex_address_free(&fa_condvar); + return (ENOENT); +} + +static int +futex_condvar_lookup_or_create(struct thread *td, + const cloudabi_condvar_t *condvar, cloudabi_mflags_t condvar_scope, + const cloudabi_lock_t *lock, cloudabi_mflags_t lock_scope, + struct futex_condvar **fcret) +{ + struct futex_address fa_condvar, fa_lock; + struct futex_condvar *fc; + struct futex_lock *fl; + int error; + + error = futex_address_create(&fa_condvar, td, condvar, condvar_scope); + if (error != 0) + return (error); + error = futex_address_create(&fa_lock, td, lock, lock_scope); + if (error != 0) { + futex_address_free(&fa_condvar); + return (error); + } + + sx_xlock(&futex_global_lock); + LIST_FOREACH(fc, &futex_condvar_list, fc_next) { + if (!futex_address_match(&fc->fc_address, &fa_condvar)) + continue; + fl = fc->fc_lock; + if (!futex_address_match(&fl->fl_address, &fa_lock)) { + /* Condition variable is owned by a different lock. */ + futex_address_free(&fa_condvar); + futex_address_free(&fa_lock); + sx_xunlock(&futex_global_lock); + return (EINVAL); + } + + /* Found fully matching condition variable. */ + futex_address_free(&fa_condvar); + futex_address_free(&fa_lock); + futex_condvar_assert(fc); + *fcret = fc; + return (0); + } + + /* None found. Create new condition variable object. */ + fc = malloc(sizeof(*fc), M_FUTEX, M_WAITOK); + fc->fc_address = fa_condvar; + fc->fc_lock = futex_lock_lookup_locked(&fa_lock); + futex_queue_init(&fc->fc_waiters); + fc->fc_waitcount = 0; + LIST_INSERT_HEAD(&futex_condvar_list, fc, fc_next); + *fcret = fc; + return (0); +} + +static void +futex_condvar_release(struct futex_condvar *fc) +{ + struct futex_lock *fl; + + futex_condvar_assert(fc); + fl = fc->fc_lock; + if (fc->fc_waitcount == 0) { + /* Condition variable has no waiters. Deallocate it. */ + futex_address_free(&fc->fc_address); + LIST_REMOVE(fc, fc_next); + free(fc, M_FUTEX); + } + futex_lock_release(fl); +} + +static int +futex_condvar_unmanage(struct futex_condvar *fc, + cloudabi_condvar_t *condvar) +{ + + if (futex_queue_count(&fc->fc_waiters) != 0) + return (0); + return (futex_user_store(condvar, CLOUDABI_CONDVAR_HAS_NO_WAITERS)); +} + +/* + * futex_lock operations. + */ + +static void +futex_lock_assert(const struct futex_lock *fl) +{ + + /* + * A futex lock can only be kernel-managed if it has waiters. + * Vice versa: if a futex lock has waiters, it must be + * kernel-managed. + */ + KASSERT((fl->fl_owner == LOCK_UNMANAGED) == + (futex_queue_count(&fl->fl_readers) == 0 && + futex_queue_count(&fl->fl_writers) == 0), + ("Managed locks must have waiting threads")); + KASSERT(fl->fl_waitcount != 0 || fl->fl_owner == LOCK_UNMANAGED, + ("Lock with no waiters must be unmanaged")); +} + +static int +futex_lock_lookup(struct thread *td, const cloudabi_lock_t *address, + cloudabi_mflags_t scope, struct futex_lock **flret) +{ + struct futex_address fa; + int error; + + error = futex_address_create(&fa, td, address, scope); + if (error != 0) + return (error); + + sx_xlock(&futex_global_lock); + *flret = futex_lock_lookup_locked(&fa); + return (0); +} + +static struct futex_lock * +futex_lock_lookup_locked(struct futex_address *fa) +{ + struct futex_lock *fl; + + LIST_FOREACH(fl, &futex_lock_list, fl_next) { + if (futex_address_match(&fl->fl_address, fa)) { + /* Found matching lock object. */ + futex_address_free(fa); + futex_lock_assert(fl); + return (fl); + } + } + + /* None found. Create new lock object. */ + fl = malloc(sizeof(*fl), M_FUTEX, M_WAITOK); + fl->fl_address = *fa; + fl->fl_owner = LOCK_UNMANAGED; + futex_queue_init(&fl->fl_readers); + futex_queue_init(&fl->fl_writers); + fl->fl_waitcount = 0; + LIST_INSERT_HEAD(&futex_lock_list, fl, fl_next); + return (fl); +} + +static int +futex_lock_rdlock(struct futex_lock *fl, struct thread *td, + cloudabi_lock_t *lock, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision) +{ + struct futex_waiter fw; + int error; + + error = futex_lock_tryrdlock(fl, lock); + if (error == EBUSY) { + /* Suspend execution. */ + KASSERT(fl->fl_owner != LOCK_UNMANAGED, + ("Attempted to sleep on an unmanaged lock")); + error = futex_queue_sleep(&fl->fl_readers, fl, &fw, td, + clock_id, timeout, precision); + KASSERT((error == 0) == fw.fw_locked, + ("Should have locked write lock on success")); + KASSERT(futex_queue_count(&fw.fw_donated) == 0, + ("Lock functions cannot receive threads")); + } + if (error != 0) + futex_lock_unmanage(fl, lock); + return (error); +} + +static void +futex_lock_release(struct futex_lock *fl) +{ + + futex_lock_assert(fl); + if (fl->fl_waitcount == 0) { + /* Lock object is unreferenced. Deallocate it. */ + KASSERT(fl->fl_owner == LOCK_UNMANAGED, + ("Attempted to free a managed lock")); + futex_address_free(&fl->fl_address); + LIST_REMOVE(fl, fl_next); + free(fl, M_FUTEX); + } + sx_xunlock(&futex_global_lock); +} + +static int +futex_lock_unmanage(struct futex_lock *fl, cloudabi_lock_t *lock) +{ + cloudabi_lock_t cmp, old; + int error; + + if (futex_queue_count(&fl->fl_readers) == 0 && + futex_queue_count(&fl->fl_writers) == 0) { + /* Lock should be unmanaged. */ + fl->fl_owner = LOCK_UNMANAGED; + + /* Clear kernel-managed bit. */ + error = futex_user_load(lock, &old); + if (error != 0) + return (error); + for (;;) { + cmp = old; + error = futex_user_cmpxchg(lock, cmp, &old, + cmp & ~CLOUDABI_LOCK_KERNEL_MANAGED); + if (error != 0) + return (error); + if (old == cmp) + break; + } + } + return (0); +} + +/* Sets an owner of a lock, based on a userspace lock value. */ +static void +futex_lock_set_owner(struct futex_lock *fl, cloudabi_lock_t lock) +{ + + /* Lock has no explicit owner. */ + if ((lock & ~CLOUDABI_LOCK_WRLOCKED) == 0) { + fl->fl_owner = LOCK_OWNER_UNKNOWN; + return; + } + lock &= ~(CLOUDABI_LOCK_WRLOCKED | CLOUDABI_LOCK_KERNEL_MANAGED); + + /* Don't allow userspace to silently unlock. */ + if (lock == LOCK_UNMANAGED) { + fl->fl_owner = LOCK_OWNER_UNKNOWN; + return; + } + fl->fl_owner = lock; +} + +static int +futex_lock_unlock(struct futex_lock *fl, struct thread *td, + cloudabi_lock_t *lock) +{ + int error; + + /* Validate that this thread is allowed to unlock. */ + error = futex_lock_update_owner(fl, lock); + if (error != 0) + return (error); + if (fl->fl_owner != LOCK_UNMANAGED && fl->fl_owner != td->td_tid) + return (EPERM); + return (futex_lock_wake_up_next(fl, lock)); +} + +/* Syncs in the owner of the lock from userspace if needed. */ +static int +futex_lock_update_owner(struct futex_lock *fl, cloudabi_lock_t *address) +{ + cloudabi_lock_t lock; + int error; + + if (fl->fl_owner == LOCK_OWNER_UNKNOWN) { + error = futex_user_load(address, &lock); + if (error != 0) + return (error); + futex_lock_set_owner(fl, lock); + } + return (0); +} + +static int +futex_lock_tryrdlock(struct futex_lock *fl, cloudabi_lock_t *address) +{ + cloudabi_lock_t old, cmp; + int error; + + if (fl->fl_owner != LOCK_UNMANAGED) { + /* Lock is already acquired. */ + return (EBUSY); + } + + old = CLOUDABI_LOCK_UNLOCKED; + for (;;) { + if ((old & CLOUDABI_LOCK_KERNEL_MANAGED) != 0) { + /* + * Userspace lock is kernel-managed, even though + * the kernel disagrees. + */ + return (EINVAL); + } + + if ((old & CLOUDABI_LOCK_WRLOCKED) == 0) { + /* + * Lock is not write-locked. Attempt to acquire + * it by increasing the read count. + */ + cmp = old; + error = futex_user_cmpxchg(address, cmp, &old, cmp + 1); + if (error != 0) + return (error); + if (old == cmp) { + /* Success. */ + return (0); + } + } else { + /* Lock is write-locked. Make it kernel-managed. */ + cmp = old; + error = futex_user_cmpxchg(address, cmp, &old, + cmp | CLOUDABI_LOCK_KERNEL_MANAGED); + if (error != 0) + return (error); + if (old == cmp) { + /* Success. */ + futex_lock_set_owner(fl, cmp); + return (EBUSY); + } + } + } +} + +static int +futex_lock_trywrlock(struct futex_lock *fl, cloudabi_lock_t *address, + cloudabi_tid_t tid, bool force_kernel_managed) +{ + cloudabi_lock_t old, new, cmp; + int error; + + if (fl->fl_owner == tid) { + /* Attempted to acquire lock recursively. */ + return (EDEADLK); + } + if (fl->fl_owner != LOCK_UNMANAGED) { + /* Lock is already acquired. */ + return (EBUSY); + } + + old = CLOUDABI_LOCK_UNLOCKED; + for (;;) { + if ((old & CLOUDABI_LOCK_KERNEL_MANAGED) != 0) { + /* + * Userspace lock is kernel-managed, even though + * the kernel disagrees. + */ + return (EINVAL); + } + if (old == (tid | CLOUDABI_LOCK_WRLOCKED)) { + /* Attempted to acquire lock recursively. */ + return (EDEADLK); + } + + if (old == CLOUDABI_LOCK_UNLOCKED) { + /* Lock is unlocked. Attempt to acquire it. */ + new = tid | CLOUDABI_LOCK_WRLOCKED; + if (force_kernel_managed) + new |= CLOUDABI_LOCK_KERNEL_MANAGED; + error = futex_user_cmpxchg(address, + CLOUDABI_LOCK_UNLOCKED, &old, new); + if (error != 0) + return (error); + if (old == CLOUDABI_LOCK_UNLOCKED) { + /* Success. */ + if (force_kernel_managed) + fl->fl_owner = tid; + return (0); + } + } else { + /* Lock is still locked. Make it kernel-managed. */ + cmp = old; + error = futex_user_cmpxchg(address, cmp, &old, + cmp | CLOUDABI_LOCK_KERNEL_MANAGED); + if (error != 0) + return (error); + if (old == cmp) { + /* Success. */ + futex_lock_set_owner(fl, cmp); + return (EBUSY); + } + } + } +} + +static int +futex_lock_wake_up_next(struct futex_lock *fl, cloudabi_lock_t *lock) +{ + cloudabi_tid_t tid; + int error; + + /* + * Determine which thread(s) to wake up. Prefer waking up + * writers over readers to prevent write starvation. + */ + if (futex_queue_count(&fl->fl_writers) > 0) { + /* Transfer ownership to a single write-locker. */ + if (futex_queue_count(&fl->fl_writers) > 1 || + futex_queue_count(&fl->fl_readers) > 0) { + /* Lock should remain managed afterwards. */ + tid = futex_queue_tid_best(&fl->fl_writers); + error = futex_user_store(lock, + tid | CLOUDABI_LOCK_WRLOCKED | + CLOUDABI_LOCK_KERNEL_MANAGED); + if (error != 0) + return (error); + + futex_queue_wake_up_best(&fl->fl_writers); + fl->fl_owner = tid; + } else { + /* Lock can become unmanaged afterwards. */ + error = futex_user_store(lock, + futex_queue_tid_best(&fl->fl_writers) | + CLOUDABI_LOCK_WRLOCKED); + if (error != 0) + return (error); + + futex_queue_wake_up_best(&fl->fl_writers); + fl->fl_owner = LOCK_UNMANAGED; + } + } else { + /* Transfer ownership to all read-lockers (if any). */ + error = futex_user_store(lock, + futex_queue_count(&fl->fl_readers)); + if (error != 0) + return (error); + + /* Wake up all threads. */ + futex_queue_wake_up_all(&fl->fl_readers); + fl->fl_owner = LOCK_UNMANAGED; + } + return (0); +} + +static int +futex_lock_wrlock(struct futex_lock *fl, struct thread *td, + cloudabi_lock_t *lock, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision, + struct futex_queue *donated) +{ + struct futex_waiter fw; + int error; + + error = futex_lock_trywrlock(fl, lock, td->td_tid, + futex_queue_count(donated) > 0); + + if (error == 0 || error == EBUSY) { + /* Put donated threads in queue before suspending. */ + KASSERT(futex_queue_count(donated) == 0 || + fl->fl_owner != LOCK_UNMANAGED, + ("Lock should be managed if we are going to donate")); + futex_queue_requeue(donated, &fl->fl_writers, UINT_MAX); + } else { + /* + * This thread cannot deal with the donated threads. + * Wake up the next thread and let it try it by itself. + */ + futex_queue_wake_up_donate(donated, UINT_MAX); + } + + if (error == EBUSY) { + /* Suspend execution if the lock was busy. */ + KASSERT(fl->fl_owner != LOCK_UNMANAGED, + ("Attempted to sleep on an unmanaged lock")); + error = futex_queue_sleep(&fl->fl_writers, fl, &fw, td, + clock_id, timeout, precision); + KASSERT((error == 0) == fw.fw_locked, + ("Should have locked write lock on success")); + KASSERT(futex_queue_count(&fw.fw_donated) == 0, + ("Lock functions cannot receive threads")); + } + if (error != 0) + futex_lock_unmanage(fl, lock); + return (error); +} + +/* + * futex_queue operations. + */ + +static cloudabi_tid_t +futex_queue_tid_best(const struct futex_queue *fq) +{ + + return (STAILQ_FIRST(&fq->fq_list)->fw_tid); +} + +static unsigned int +futex_queue_count(const struct futex_queue *fq) +{ + + return (fq->fq_count); +} + +static void +futex_queue_init(struct futex_queue *fq) +{ + + STAILQ_INIT(&fq->fq_list); + fq->fq_count = 0; +} + +/* Converts a relative timestamp to an sbintime. */ +static sbintime_t +futex_queue_convert_timestamp_relative(cloudabi_timestamp_t ts) +{ + cloudabi_timestamp_t s, ns; + + s = ts / 1000000000; + ns = ts % 1000000000; + if (s > INT32_MAX) + return (INT64_MAX); + return ((s << 32) + (ns << 32) / 1000000000); +} + +/* Converts an absolute timestamp and precision to a pair of sbintime values. */ +static int +futex_queue_convert_timestamp(struct thread *td, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision, + sbintime_t *sbttimeout, sbintime_t *sbtprecision) +{ + cloudabi_timestamp_t now; + int error; + + /* Make the time relative. */ + error = cloudabi_clock_time_get(td, clock_id, &now); + if (error != 0) + return (error); + timeout = timeout < now ? 0 : timeout - now; + + *sbttimeout = futex_queue_convert_timestamp_relative(timeout); + *sbtprecision = futex_queue_convert_timestamp_relative(precision); + return (0); +} + +static int +futex_queue_sleep(struct futex_queue *fq, struct futex_lock *fl, + struct futex_waiter *fw, struct thread *td, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision) +{ + sbintime_t sbttimeout, sbtprecision; + int error; + + /* Initialize futex_waiter object. */ + fw->fw_tid = td->td_tid; + fw->fw_locked = false; + futex_queue_init(&fw->fw_donated); + + if (timeout != UINT64_MAX) { + /* Convert timeout duration. */ + error = futex_queue_convert_timestamp(td, clock_id, timeout, + precision, &sbttimeout, &sbtprecision); + if (error != 0) + return (error); + } + + /* Place object in the queue. */ + fw->fw_queue = fq; + STAILQ_INSERT_TAIL(&fq->fq_list, fw, fw_next); + ++fq->fq_count; + + cv_init(&fw->fw_wait, "futex"); + ++fl->fl_waitcount; + + futex_lock_assert(fl); + if (timeout == UINT64_MAX) { + /* Wait without a timeout. */ + error = cv_wait_sig(&fw->fw_wait, &futex_global_lock); + } else { + /* Wait respecting the timeout. */ + error = cv_timedwait_sig_sbt(&fw->fw_wait, &futex_global_lock, + sbttimeout, sbtprecision, 0); + futex_lock_assert(fl); + if (error == EWOULDBLOCK && + fw->fw_queue != NULL && fw->fw_queue != fq) { + /* + * We got signalled on a condition variable, but + * observed a timeout while waiting to reacquire + * the lock. In other words, we didn't actually + * time out. Go back to sleep and wait for the + * lock to be reacquired. + */ + error = cv_wait_sig(&fw->fw_wait, &futex_global_lock); + } + } + futex_lock_assert(fl); + + --fl->fl_waitcount; + cv_destroy(&fw->fw_wait); + + fq = fw->fw_queue; + if (fq == NULL) { + /* Thread got dequeued, so we've slept successfully. */ + return (0); + } + + /* Thread is still enqueued. Remove it. */ + KASSERT(error != 0, ("Woken up thread is still enqueued")); + STAILQ_REMOVE(&fq->fq_list, fw, futex_waiter, fw_next); + --fq->fq_count; + return (error == EWOULDBLOCK ? ETIMEDOUT : error); +} + +/* Moves up to nwaiters waiters from one queue to another. */ +static void +futex_queue_requeue(struct futex_queue *fqfrom, struct futex_queue *fqto, + unsigned int nwaiters) +{ + struct futex_waiter *fw; + + /* Move waiters to the target queue. */ + while (nwaiters-- > 0 && !STAILQ_EMPTY(&fqfrom->fq_list)) { + fw = STAILQ_FIRST(&fqfrom->fq_list); + STAILQ_REMOVE_HEAD(&fqfrom->fq_list, fw_next); + --fqfrom->fq_count; + + fw->fw_queue = fqto; + STAILQ_INSERT_TAIL(&fqto->fq_list, fw, fw_next); + ++fqto->fq_count; + } +} + +/* Wakes up all waiters in a queue. */ +static void +futex_queue_wake_up_all(struct futex_queue *fq) +{ + struct futex_waiter *fw; + + STAILQ_FOREACH(fw, &fq->fq_list, fw_next) { + fw->fw_locked = true; + fw->fw_queue = NULL; + cv_signal(&fw->fw_wait); + } + + STAILQ_INIT(&fq->fq_list); + fq->fq_count = 0; +} + +/* + * Wakes up the best waiter (i.e., the waiter having the highest + * priority) in a queue. + */ +static void +futex_queue_wake_up_best(struct futex_queue *fq) +{ + struct futex_waiter *fw; + + fw = STAILQ_FIRST(&fq->fq_list); + fw->fw_locked = true; + fw->fw_queue = NULL; + cv_signal(&fw->fw_wait); + + STAILQ_REMOVE_HEAD(&fq->fq_list, fw_next); + --fq->fq_count; +} + +static void +futex_queue_wake_up_donate(struct futex_queue *fq, unsigned int nwaiters) +{ + struct futex_waiter *fw; + + fw = STAILQ_FIRST(&fq->fq_list); + if (fw == NULL) + return; + fw->fw_locked = false; + fw->fw_queue = NULL; + cv_signal(&fw->fw_wait); + + STAILQ_REMOVE_HEAD(&fq->fq_list, fw_next); + --fq->fq_count; + futex_queue_requeue(fq, &fw->fw_donated, nwaiters); +} + +/* + * futex_user operations. Used to adjust values in userspace. + */ + +static int +futex_user_load(uint32_t *obj, uint32_t *val) +{ + + return (fueword32(obj, val) != 0 ? EFAULT : 0); +} + +static int +futex_user_store(uint32_t *obj, uint32_t val) +{ + + return (suword32(obj, val) != 0 ? EFAULT : 0); +} + +static int +futex_user_cmpxchg(uint32_t *obj, uint32_t cmp, uint32_t *old, uint32_t new) +{ + + return (casueword32(obj, cmp, old, new) != 0 ? EFAULT : 0); +} + +/* + * Blocking calls: acquiring locks, waiting on condition variables. + */ + +int +cloudabi_futex_condvar_wait(struct thread *td, cloudabi_condvar_t *condvar, + cloudabi_mflags_t condvar_scope, cloudabi_lock_t *lock, + cloudabi_mflags_t lock_scope, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision) +{ + struct futex_condvar *fc; + struct futex_lock *fl; + struct futex_waiter fw; + int error, error2; + + /* Lookup condition variable object. */ + error = futex_condvar_lookup_or_create(td, condvar, condvar_scope, lock, + lock_scope, &fc); + if (error != 0) + return (error); + fl = fc->fc_lock; + + /* + * Set the condition variable to something other than + * CLOUDABI_CONDVAR_HAS_NO_WAITERS to make userspace threads + * call into the kernel to perform wakeups. + */ + error = futex_user_store(condvar, ~CLOUDABI_CONDVAR_HAS_NO_WAITERS); + if (error != 0) { + futex_condvar_release(fc); + return (error); + } + + /* Drop the lock. */ + error = futex_lock_unlock(fl, td, lock); + if (error != 0) { + futex_condvar_unmanage(fc, condvar); + futex_condvar_release(fc); + return (error); + } + + /* Go to sleep. */ + ++fc->fc_waitcount; + error = futex_queue_sleep(&fc->fc_waiters, fc->fc_lock, &fw, td, + clock_id, timeout, precision); + if (fw.fw_locked) { + /* Waited and got the lock assigned to us. */ + KASSERT(futex_queue_count(&fw.fw_donated) == 0, + ("Received threads while being locked")); + } else if (error == 0 || error == ETIMEDOUT) { + if (error != 0) + futex_condvar_unmanage(fc, condvar); + /* + * Got woken up without having the lock assigned to us. + * This can happen in two cases: + * + * 1. We observed a timeout on a condition variable. + * 2. We got signalled on a condition variable while the + * associated lock is unlocked. We are the first + * thread that gets woken up. This thread is + * responsible for reacquiring the userspace lock. + */ + error2 = futex_lock_wrlock(fl, td, lock, + CLOUDABI_CLOCK_MONOTONIC, UINT64_MAX, 0, &fw.fw_donated); + if (error2 != 0) + error = error2; + } else { + KASSERT(futex_queue_count(&fw.fw_donated) == 0, + ("Received threads on error")); + futex_condvar_unmanage(fc, condvar); + futex_lock_unmanage(fl, lock); + } + --fc->fc_waitcount; + futex_condvar_release(fc); + return (error); +} + +int +cloudabi_futex_lock_rdlock(struct thread *td, cloudabi_lock_t *lock, + cloudabi_mflags_t scope, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision) +{ + struct futex_lock *fl; + int error; + + /* Look up lock object. */ + error = futex_lock_lookup(td, lock, scope, &fl); + if (error != 0) + return (error); + + error = futex_lock_rdlock(fl, td, lock, clock_id, timeout, + precision); + futex_lock_release(fl); + return (error); +} + +int +cloudabi_futex_lock_wrlock(struct thread *td, cloudabi_lock_t *lock, + cloudabi_mflags_t scope, cloudabi_clockid_t clock_id, + cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision) +{ + struct futex_lock *fl; + struct futex_queue fq; + int error; + + /* Look up lock object. */ + error = futex_lock_lookup(td, lock, scope, &fl); + if (error != 0) + return (error); + + futex_queue_init(&fq); + error = futex_lock_wrlock(fl, td, lock, clock_id, timeout, + precision, &fq); + futex_lock_release(fl); + return (error); +} + +/* + * Non-blocking calls: releasing locks, signalling condition variables. + */ int cloudabi_sys_condvar_signal(struct thread *td, struct cloudabi_sys_condvar_signal_args *uap) { + struct futex_condvar *fc; + struct futex_lock *fl; + cloudabi_nthreads_t nwaiters; + int error; - /* Not implemented. */ - return (ENOSYS); + nwaiters = uap->nwaiters; + if (nwaiters == 0) { + /* No threads to wake up. */ + return (0); + } + + /* Look up futex object. */ + error = futex_condvar_lookup(td, uap->condvar, uap->scope, &fc); + if (error != 0) { + /* Race condition: condition variable with no waiters. */ + return (error == ENOENT ? 0 : error); + } + fl = fc->fc_lock; + + if (fl->fl_owner == LOCK_UNMANAGED) { + /* + * The lock is currently not managed by the kernel, + * meaning we must attempt to acquire the userspace lock + * first. We cannot requeue threads to an unmanaged lock, + * as these threads will then never be scheduled. + * + * Unfortunately, the memory address of the lock is + * unknown from this context, meaning that we cannot + * acquire the lock on behalf of the first thread to be + * scheduled. The lock may even not be mapped within the + * address space of the current thread. + * + * To solve this, wake up a single waiter that will + * attempt to acquire the lock. Donate all of the other + * waiters that need to be woken up to this waiter, so + * it can requeue them after acquiring the lock. + */ + futex_queue_wake_up_donate(&fc->fc_waiters, nwaiters - 1); + } else { + /* + * Lock is already managed by the kernel. This makes it + * easy, as we can requeue the threads from the + * condition variable directly to the associated lock. + */ + futex_queue_requeue(&fc->fc_waiters, &fl->fl_writers, nwaiters); + } + + /* Clear userspace condition variable if all waiters are gone. */ + error = futex_condvar_unmanage(fc, uap->condvar); + futex_condvar_release(fc); + return (error); } int cloudabi_sys_lock_unlock(struct thread *td, struct cloudabi_sys_lock_unlock_args *uap) { + struct futex_lock *fl; + int error; - /* Not implemented. */ - return (ENOSYS); + error = futex_lock_lookup(td, uap->lock, uap->scope, &fl); + if (error != 0) + return (error); + error = futex_lock_unlock(fl, td, uap->lock); + futex_lock_release(fl); + return (error); } diff --git a/sys/compat/cloudabi/cloudabi_sock.c b/sys/compat/cloudabi/cloudabi_sock.c index 38aa4fedbd93..877571c144c0 100644 --- a/sys/compat/cloudabi/cloudabi_sock.c +++ b/sys/compat/cloudabi/cloudabi_sock.c @@ -26,12 +26,38 @@ #include __FBSDID("$FreeBSD$"); +#include #include +#include #include +#include +#include #include #include +/* Copies a pathname into a UNIX socket address structure. */ +static int +copyin_sockaddr_un(const char *path, size_t pathlen, struct sockaddr_un *sun) +{ + int error; + + /* Copy in pathname string if there's enough space. */ + if (pathlen >= sizeof(sun->sun_path)) + return (ENAMETOOLONG); + error = copyin(path, &sun->sun_path, pathlen); + if (error != 0) + return (error); + if (memchr(sun->sun_path, '\0', pathlen) != NULL) + return (EINVAL); + + /* Initialize the rest of the socket address. */ + sun->sun_path[pathlen] = '\0'; + sun->sun_family = AF_UNIX; + sun->sun_len = sizeof(*sun); + return (0); +} + int cloudabi_sys_sock_accept(struct thread *td, struct cloudabi_sys_sock_accept_args *uap) @@ -45,18 +71,26 @@ int cloudabi_sys_sock_bind(struct thread *td, struct cloudabi_sys_sock_bind_args *uap) { + struct sockaddr_un sun; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_sockaddr_un(uap->path, uap->pathlen, &sun); + if (error != 0) + return (error); + return (kern_bindat(td, uap->fd, uap->s, (struct sockaddr *)&sun)); } int cloudabi_sys_sock_connect(struct thread *td, struct cloudabi_sys_sock_connect_args *uap) { + struct sockaddr_un sun; + int error; - /* Not implemented. */ - return (ENOSYS); + error = copyin_sockaddr_un(uap->path, uap->pathlen, &sun); + if (error != 0) + return (error); + return (kern_connectat(td, uap->fd, uap->s, (struct sockaddr *)&sun)); } int diff --git a/sys/compat/cloudabi/cloudabi_syscalldefs.h b/sys/compat/cloudabi/cloudabi_syscalldefs.h index 3a20c81796cb..64b7ea9495fa 100644 --- a/sys/compat/cloudabi/cloudabi_syscalldefs.h +++ b/sys/compat/cloudabi/cloudabi_syscalldefs.h @@ -29,6 +29,7 @@ #define _CLOUDABI_SYSCALLDEFS_H_ #include +#include #define alignas _Alignas #define alignof _Alignof diff --git a/sys/compat/cloudabi/cloudabi_thread.c b/sys/compat/cloudabi/cloudabi_thread.c index 4b9eb54b57e5..8aee708de948 100644 --- a/sys/compat/cloudabi/cloudabi_thread.c +++ b/sys/compat/cloudabi/cloudabi_thread.c @@ -29,16 +29,30 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include int cloudabi_sys_thread_exit(struct thread *td, struct cloudabi_sys_thread_exit_args *uap) { + struct cloudabi_sys_lock_unlock_args cloudabi_sys_lock_unlock_args = { + .lock = uap->lock, + .scope = uap->scope, + }; - /* Not implemented. */ - return (ENOSYS); + /* Wake up joining thread. */ + cloudabi_sys_lock_unlock(td, &cloudabi_sys_lock_unlock_args); + + /* + * Attempt to terminate the thread. Terminate the process if + * it's the last thread. + */ + kern_thr_exit(td); + exit1(td, 0, 0); + /* NOTREACHED */ } int diff --git a/sys/compat/cloudabi/cloudabi_util.h b/sys/compat/cloudabi/cloudabi_util.h index d9e6f127eb97..5350d24c082c 100644 --- a/sys/compat/cloudabi/cloudabi_util.h +++ b/sys/compat/cloudabi/cloudabi_util.h @@ -30,12 +30,33 @@ #include +struct thread; struct timespec; +/* Fetches the time value of a clock. */ +int cloudabi_clock_time_get(struct thread *, cloudabi_clockid_t, + cloudabi_timestamp_t *); + /* Converts a FreeBSD errno to a CloudABI errno. */ cloudabi_errno_t cloudabi_convert_errno(int); /* Converts a struct timespec to a CloudABI timestamp. */ int cloudabi_convert_timespec(const struct timespec *, cloudabi_timestamp_t *); +/* + * Blocking futex functions. + * + * These functions are called by CloudABI's polling system calls to + * sleep on a lock or condition variable. + */ +int cloudabi_futex_condvar_wait(struct thread *, cloudabi_condvar_t *, + cloudabi_mflags_t, cloudabi_lock_t *, cloudabi_mflags_t, cloudabi_clockid_t, + cloudabi_timestamp_t, cloudabi_timestamp_t); +int cloudabi_futex_lock_rdlock(struct thread *, cloudabi_lock_t *, + cloudabi_mflags_t, cloudabi_clockid_t, cloudabi_timestamp_t, + cloudabi_timestamp_t); +int cloudabi_futex_lock_wrlock(struct thread *, cloudabi_lock_t *, + cloudabi_mflags_t, cloudabi_clockid_t, cloudabi_timestamp_t, + cloudabi_timestamp_t); + #endif diff --git a/sys/compat/cloudabi64/cloudabi64_proto.h b/sys/compat/cloudabi64/cloudabi64_proto.h index 2dbf1cbb1e19..dd86bc982cc1 100644 --- a/sys/compat/cloudabi64/cloudabi64_proto.h +++ b/sys/compat/cloudabi64/cloudabi64_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285790 2015-07-22 10:04:53Z ed + * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed */ #ifndef _CLOUDABI64_SYSPROTO_H_ @@ -43,7 +43,7 @@ struct cloudabi_sys_clock_time_get_args { }; struct cloudabi_sys_condvar_signal_args { char condvar_l_[PADL_(cloudabi_condvar_t *)]; cloudabi_condvar_t * condvar; char condvar_r_[PADR_(cloudabi_condvar_t *)]; - char scope_l_[PADL_(cloudabi_futexscope_t)]; cloudabi_futexscope_t scope; char scope_r_[PADR_(cloudabi_futexscope_t)]; + char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)]; char nwaiters_l_[PADL_(cloudabi_nthreads_t)]; cloudabi_nthreads_t nwaiters; char nwaiters_r_[PADR_(cloudabi_nthreads_t)]; }; struct cloudabi_sys_fd_close_args { @@ -194,7 +194,7 @@ struct cloudabi_sys_file_unlink_args { }; struct cloudabi_sys_lock_unlock_args { char lock_l_[PADL_(cloudabi_lock_t *)]; cloudabi_lock_t * lock; char lock_r_[PADR_(cloudabi_lock_t *)]; - char scope_l_[PADL_(cloudabi_futexscope_t)]; cloudabi_futexscope_t scope; char scope_r_[PADR_(cloudabi_futexscope_t)]; + char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)]; }; struct cloudabi_sys_mem_advise_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; @@ -302,7 +302,7 @@ struct cloudabi64_sys_thread_create_args { }; struct cloudabi_sys_thread_exit_args { char lock_l_[PADL_(cloudabi_lock_t *)]; cloudabi_lock_t * lock; char lock_r_[PADR_(cloudabi_lock_t *)]; - char scope_l_[PADL_(cloudabi_futexscope_t)]; cloudabi_futexscope_t scope; char scope_r_[PADR_(cloudabi_futexscope_t)]; + char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)]; }; struct cloudabi_sys_thread_tcb_set_args { char tcb_l_[PADL_(void *)]; void * tcb; char tcb_r_[PADR_(void *)]; diff --git a/sys/compat/cloudabi64/cloudabi64_syscall.h b/sys/compat/cloudabi64/cloudabi64_syscall.h index a3dce677ef1f..176519053e7b 100644 --- a/sys/compat/cloudabi64/cloudabi64_syscall.h +++ b/sys/compat/cloudabi64/cloudabi64_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285790 2015-07-22 10:04:53Z ed + * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed */ #define CLOUDABI64_SYS_cloudabi_sys_clock_res_get 0 diff --git a/sys/compat/cloudabi64/cloudabi64_syscalls.c b/sys/compat/cloudabi64/cloudabi64_syscalls.c index e92fa14c23f8..e44e6eaecb3f 100644 --- a/sys/compat/cloudabi64/cloudabi64_syscalls.c +++ b/sys/compat/cloudabi64/cloudabi64_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285790 2015-07-22 10:04:53Z ed + * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed */ const char *cloudabi64_syscallnames[] = { diff --git a/sys/compat/cloudabi64/cloudabi64_sysent.c b/sys/compat/cloudabi64/cloudabi64_sysent.c index 380d0fa73ce9..1048e4e7d136 100644 --- a/sys/compat/cloudabi64/cloudabi64_sysent.c +++ b/sys/compat/cloudabi64/cloudabi64_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285790 2015-07-22 10:04:53Z ed + * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed */ #include diff --git a/sys/compat/cloudabi64/cloudabi64_systrace_args.c b/sys/compat/cloudabi64/cloudabi64_systrace_args.c index 9c3241226e40..311a14c20b1d 100644 --- a/sys/compat/cloudabi64/cloudabi64_systrace_args.c +++ b/sys/compat/cloudabi64/cloudabi64_systrace_args.c @@ -30,7 +30,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) case 2: { struct cloudabi_sys_condvar_signal_args *p = params; uarg[0] = (intptr_t) p->condvar; /* cloudabi_condvar_t * */ - iarg[1] = p->scope; /* cloudabi_futexscope_t */ + iarg[1] = p->scope; /* cloudabi_mflags_t */ iarg[2] = p->nwaiters; /* cloudabi_nthreads_t */ *n_args = 3; break; @@ -297,7 +297,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) case 31: { struct cloudabi_sys_lock_unlock_args *p = params; uarg[0] = (intptr_t) p->lock; /* cloudabi_lock_t * */ - iarg[1] = p->scope; /* cloudabi_futexscope_t */ + iarg[1] = p->scope; /* cloudabi_mflags_t */ *n_args = 2; break; } @@ -495,7 +495,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) case 54: { struct cloudabi_sys_thread_exit_args *p = params; uarg[0] = (intptr_t) p->lock; /* cloudabi_lock_t * */ - iarg[1] = p->scope; /* cloudabi_futexscope_t */ + iarg[1] = p->scope; /* cloudabi_mflags_t */ *n_args = 2; break; } @@ -551,7 +551,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) p = "cloudabi_condvar_t *"; break; case 1: - p = "cloudabi_futexscope_t"; + p = "cloudabi_mflags_t"; break; case 2: p = "cloudabi_nthreads_t"; @@ -1033,7 +1033,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) p = "cloudabi_lock_t *"; break; case 1: - p = "cloudabi_futexscope_t"; + p = "cloudabi_mflags_t"; break; default: break; @@ -1373,7 +1373,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) p = "cloudabi_lock_t *"; break; case 1: - p = "cloudabi_futexscope_t"; + p = "cloudabi_mflags_t"; break; default: break; diff --git a/sys/compat/cloudabi64/syscalls.master b/sys/compat/cloudabi64/syscalls.master index ba1df9a4fa21..21deffb24ee4 100644 --- a/sys/compat/cloudabi64/syscalls.master +++ b/sys/compat/cloudabi64/syscalls.master @@ -21,7 +21,7 @@ 2 AUE_NULL STD { void cloudabi_sys_condvar_signal( \ cloudabi_condvar_t *condvar, \ - cloudabi_futexscope_t scope, \ + cloudabi_mflags_t scope, \ cloudabi_nthreads_t nwaiters); } 3 AUE_NULL STD { void cloudabi_sys_fd_close( \ @@ -132,7 +132,7 @@ 31 AUE_NULL STD { void cloudabi_sys_lock_unlock( \ cloudabi_lock_t *lock, \ - cloudabi_futexscope_t scope); } + cloudabi_mflags_t scope); } 32 AUE_NULL STD { void cloudabi_sys_mem_advise( \ void *addr, size_t len, \ @@ -209,6 +209,6 @@ cloudabi64_threadattr_t *attr); } 54 AUE_NULL STD { void cloudabi_sys_thread_exit( \ cloudabi_lock_t *lock, \ - cloudabi_futexscope_t scope); } + cloudabi_mflags_t scope); } 55 AUE_NULL STD { void cloudabi_sys_thread_tcb_set(void *tcb); } 56 AUE_NULL STD { void cloudabi_sys_thread_yield(); } diff --git a/sys/conf/files b/sys/conf/files index 65cf92322332..99cef6dab2c2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -284,6 +284,7 @@ contrib/dev/acpica/components/debugger/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbinput.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbmethod.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbnames.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbobject.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbstats.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbtest.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbutils.c optional acpi acpi_debug @@ -293,7 +294,6 @@ contrib/dev/acpica/components/disassembler/dmcstyle.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmdeferred.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmnames.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmopcode.c optional acpi acpi_debug -contrib/dev/acpica/components/disassembler/dmobject.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrcl2.c optional acpi acpi_debug @@ -302,6 +302,7 @@ contrib/dev/acpica/components/disassembler/dmutils.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/components/dispatcher/dsargs.c optional acpi contrib/dev/acpica/components/dispatcher/dscontrol.c optional acpi +contrib/dev/acpica/components/dispatcher/dsdebug.c optional acpi contrib/dev/acpica/components/dispatcher/dsfield.c optional acpi contrib/dev/acpica/components/dispatcher/dsinit.c optional acpi contrib/dev/acpica/components/dispatcher/dsmethod.c optional acpi @@ -437,6 +438,7 @@ contrib/dev/acpica/components/utilities/utlock.c optional acpi contrib/dev/acpica/components/utilities/utmath.c optional acpi contrib/dev/acpica/components/utilities/utmisc.c optional acpi contrib/dev/acpica/components/utilities/utmutex.c optional acpi +contrib/dev/acpica/components/utilities/utnonansi.c optional acpi contrib/dev/acpica/components/utilities/utobject.c optional acpi contrib/dev/acpica/components/utilities/utosi.c optional acpi contrib/dev/acpica/components/utilities/utownerid.c optional acpi diff --git a/sys/contrib/cloudabi/syscalldefs_md.h b/sys/contrib/cloudabi/syscalldefs_md.h index 272360edcdbe..a7045c2d7e6b 100644 --- a/sys/contrib/cloudabi/syscalldefs_md.h +++ b/sys/contrib/cloudabi/syscalldefs_md.h @@ -193,8 +193,8 @@ typedef struct { struct { MEMBER(PTR(_Atomic(cloudabi_condvar_t))) condvar; MEMBER(PTR(_Atomic(cloudabi_lock_t))) lock; - MEMBER(cloudabi_futexscope_t) condvar_scope; - MEMBER(cloudabi_futexscope_t) lock_scope; + MEMBER(cloudabi_mflags_t) condvar_scope; + MEMBER(cloudabi_mflags_t) lock_scope; } condvar; // CLOUDABI_EVENTTYPE_FD_READ and CLOUDABI_EVENTTYPE_FD_WRITE: @@ -208,7 +208,7 @@ typedef struct { // and acquire a read or write lock. struct { MEMBER(PTR(_Atomic(cloudabi_lock_t))) lock; - MEMBER(cloudabi_futexscope_t) lock_scope; + MEMBER(cloudabi_mflags_t) lock_scope; } lock; // CLOUDABI_EVENTTYPE_PROC_TERMINATE: Wait for a process to terminate. diff --git a/sys/contrib/cloudabi/syscalldefs_mi.h b/sys/contrib/cloudabi/syscalldefs_mi.h index 23aa58c87a42..151a3dcc59b9 100644 --- a/sys/contrib/cloudabi/syscalldefs_mi.h +++ b/sys/contrib/cloudabi/syscalldefs_mi.h @@ -189,10 +189,6 @@ #define CLOUDABI_FILETYPE_SOCKET_STREAM 0x82 #define CLOUDABI_FILETYPE_SYMBOLIC_LINK 0x90 -// Futex object scopes. -#define CLOUDABI_FUTEXSCOPE_GLOBAL 1 -#define CLOUDABI_FUTEXSCOPE_PROCESS_LOCAL 2 - // Read-write lock related constants. #define CLOUDABI_LOCK_UNLOCKED 0 // Lock is unlocked. #define CLOUDABI_LOCK_WRLOCKED 0x40000000 // Lock is write locked. @@ -354,7 +350,6 @@ typedef int64_t cloudabi_filedelta_t; // lseek(). typedef uint64_t cloudabi_filesize_t; // ftruncate(), struct stat::st_size. typedef uint8_t cloudabi_filetype_t; // struct stat::st_mode. typedef uint16_t cloudabi_fsflags_t; // file_stat_put(). -typedef uint8_t cloudabi_futexscope_t; // Scope of lock or condition variable. typedef uint64_t cloudabi_inode_t; // struct stat::st_ino. typedef uint32_t cloudabi_linkcount_t; // struct stat::st_nlink. typedef uint32_t cloudabi_lock_t; // pthread_{mutex,rwlock}_*(). diff --git a/sys/contrib/dev/acpica/acpica_prep.sh b/sys/contrib/dev/acpica/acpica_prep.sh index e6bf5758613b..a7f32e79e9df 100755 --- a/sys/contrib/dev/acpica/acpica_prep.sh +++ b/sys/contrib/dev/acpica/acpica_prep.sh @@ -20,10 +20,10 @@ fulldirs="common compiler components include os_specific" stripdirs="generate libraries tests tools" stripfiles="Makefile README accygwin.h acdragonfly.h acdragonflyex.h \ acefi.h acefiex.h achaiku.h acintel.h aclinux.h aclinuxex.h \ - acmacosx.h acmsvc.h acnetbsd.h acos2.h acwin.h acwin64.h \ - new_table.txt osbsdtbl.c osefitbl.c osefixf.c osfreebsdtbl.c \ - oslinuxtbl.c osunixdir.c osunixmap.c oswindir.c oswintbl.c \ - oswinxf.c readme.txt utclib.c" + acmacosx.h acmsvc.h acmsvcex.h acnetbsd.h acos2.h acwin.h \ + acwin64.h acwinex.h new_table.txt osbsdtbl.c osefitbl.c \ + osefixf.c osfreebsdtbl.c oslinuxtbl.c osunixdir.c osunixmap.c \ + oswindir.c oswintbl.c oswinxf.c readme.txt utclib.c" # include files to canonify src_headers="acapps.h acbuffer.h acclib.h accommon.h acconfig.h \ diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt index 9abe7355c582..4a4f07359e73 100644 --- a/sys/contrib/dev/acpica/changes.txt +++ b/sys/contrib/dev/acpica/changes.txt @@ -1,3 +1,86 @@ +---------------------------------------- +17 July 2015. Summary of changes for version 20150717: + +1) ACPICA kernel-resident subsystem: + +Improved the partitioning between the Debugger and Disassembler +components. This allows the Debugger to be used standalone within kernel +code without the Disassembler (which is used for single stepping also). +This renames and moves one file, dmobject.c to dbobject.c. Lv Zheng. + +Debugger: Implemented a new command to trace the execution of control +methods (Trace). This is especially useful for the in-kernel version of +the debugger when file I/O may not be available for method trace output. +See the ACPICA reference for more information. Lv Zheng. + +Moved all C library prototypes (used for the local versions of these +functions when requested) to a new header, acclib.h +Cleaned up the use of non-ANSI C library functions. These functions are +implemented locally in ACPICA. Moved all such functions to a common +source file, utnonansi.c + +Debugger: Fixed a problem with the "!!" command (get last command +executed) where the debugger could enter an infinite loop and eventually +crash. + +Removed the use of local macros that were used for some of the standard C +library functions to automatically cast input parameters. This mostly +affected the is* functions where the input parameter is defined to be an +int. This required a few modifications to the main ACPICA source code to +provide casting for these functions and eliminate possible compiler +warnings for these parameters. + +Across the source code, added additional status/error checking to resolve +issues discovered by static source code analysis tools such as Coverity. + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The +debug version of the code includes the debug output trace mechanism and +has a much larger code and data size. + + Current Release: + Non-Debug Version: 100.9K Code, 24.5K Data, 125.4K Total + Debug Version: 197.8K Code, 81.5K Data, 279.3K Total + Previous Release: + Non-Debug Version: 100.6K Code, 27.6K Data, 128.2K Total + Debug Version: 196.2K Code, 81.0K Data, 277.2K Total + + +2) iASL Compiler/Disassembler and Tools: + +iASL: Fixed a regression where the device map file feature no longer +worked properly when used in conjunction with the disassembler. It only +worked properly with the compiler itself. + +iASL: Implemented a new warning for method LocalX variables that are set +but never used (similar to a C compiler such as gcc). This also applies +to ArgX variables that are not defined by the parent method, and are +instead (legally) used as local variables. + +iASL/Preprocessor: Finished the pass-through of line numbers from the +preprocessor to the compiler. This ensures that compiler errors/warnings +have the correct original line numbers and filenames, regardless of any +#include files. + +iASL/Preprocessor: Fixed a couple of issues with comment handling and the +pass-through of comments to the preprocessor output file (which becomes +the compiler input file). Also fixed a problem with // comments that +appear after a math expression. + +iASL: Added support for the TCPA server table to the table compiler and +template generator. (The client table was already previously supported) + +iASL/Preprocessor: Added a permanent #define of the symbol "__IASL__" to +identify the iASL compiler. + +Cleaned up the use of the macros NEGATIVE and POSITIVE which were defined +multiple times. The new names are ACPI_SIGN_NEGATIVE and +ACPI_SIGN_POSITIVE. + +AcpiHelp: Update to expand help messages for the iASL preprocessor +directives. + + ---------------------------------------- 19 June 2015. Summary of changes for version 20150619: diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c index 59424766c1a1..a2cd226ed355 100644 --- a/sys/contrib/dev/acpica/common/adisasm.c +++ b/sys/contrib/dev/acpica/common/adisasm.c @@ -187,6 +187,7 @@ AdInitialize ( AcpiGbl_RootTableList.CurrentTableCount = 0; AcpiGbl_RootTableList.Tables = LocalTables; + AcpiGbl_PreviousOp = NULL; return (Status); } @@ -796,8 +797,8 @@ AdStoreTable ( AcpiTbInitTableDescriptor (TableDesc, ACPI_PTR_TO_PHYSADDR (Table), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table); - AcpiTbValidateTable (TableDesc); - return (AE_OK); + Status = AcpiTbValidateTable (TableDesc); + return (Status); } @@ -892,7 +893,7 @@ AdParseTable ( /* Create the root object */ - AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (); + AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (AmlStart); if (!AcpiGbl_ParseOpRoot) { return (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/common/dmrestag.c b/sys/contrib/dev/acpica/common/dmrestag.c index 429603906650..51d8ba3e3ce7 100644 --- a/sys/contrib/dev/acpica/common/dmrestag.c +++ b/sys/contrib/dev/acpica/common/dmrestag.c @@ -650,7 +650,7 @@ AcpiGetTagPathname ( /* Get the full pathname to the parent buffer */ - RequiredSize = AcpiNsGetPathnameLength (BufferNode); + RequiredSize = AcpiNsBuildNormalizedPath (BufferNode, NULL, 0, FALSE); if (!RequiredSize) { return (NULL); @@ -662,12 +662,8 @@ AcpiGetTagPathname ( return (NULL); } - Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname); - if (ACPI_FAILURE (Status)) - { - ACPI_FREE (Pathname); - return (NULL); - } + (void) AcpiNsBuildNormalizedPath (BufferNode, Pathname, + RequiredSize, FALSE); /* * Create the full path to the resource and tag by: remove the buffer name, diff --git a/sys/contrib/dev/acpica/common/dmtable.c b/sys/contrib/dev/acpica/common/dmtable.c index 0b1f68e24b2d..1e97658243fb 100644 --- a/sys/contrib/dev/acpica/common/dmtable.c +++ b/sys/contrib/dev/acpica/common/dmtable.c @@ -368,7 +368,7 @@ const ACPI_DMTABLE_DATA AcpiDmTableData[] = {ACPI_SIG_SPMI, AcpiDmTableInfoSpmi, NULL, NULL, TemplateSpmi}, {ACPI_SIG_SRAT, NULL, AcpiDmDumpSrat, DtCompileSrat, TemplateSrat}, {ACPI_SIG_STAO, NULL, AcpiDmDumpStao, DtCompileStao, TemplateStao}, - {ACPI_SIG_TCPA, AcpiDmTableInfoTcpa, NULL, NULL, TemplateTcpa}, + {ACPI_SIG_TCPA, NULL, AcpiDmDumpTcpa, DtCompileTcpa, TemplateTcpa}, {ACPI_SIG_TPM2, AcpiDmTableInfoTpm2, NULL, NULL, TemplateTpm2}, {ACPI_SIG_UEFI, AcpiDmTableInfoUefi, NULL, DtCompileUefi, TemplateUefi}, {ACPI_SIG_VRTC, AcpiDmTableInfoVrtc, AcpiDmDumpVrtc, DtCompileVrtc, TemplateVrtc}, @@ -500,7 +500,11 @@ AcpiDmDumpDataTable ( if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FACS)) { Length = Table->Length; - AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoFacs); + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoFacs); + if (ACPI_FAILURE (Status)) + { + return; + } } else if (ACPI_VALIDATE_RSDP_SIG (Table->Signature)) { @@ -561,7 +565,11 @@ AcpiDmDumpDataTable ( { /* Simple table, just walk the info table */ - AcpiDmDumpTable (Length, 0, Table, 0, TableData->TableInfo); + Status = AcpiDmDumpTable (Length, 0, Table, 0, TableData->TableInfo); + if (ACPI_FAILURE (Status)) + { + return; + } } } @@ -720,6 +728,7 @@ AcpiDmDumpTable ( const AH_TABLE *TableData; const char *Name; BOOLEAN LastOutputBlankLine = FALSE; + ACPI_STATUS Status; char RepairedName[8]; @@ -1114,8 +1123,13 @@ AcpiDmDumpTable ( /* Generic Address Structure */ AcpiOsPrintf (STRING_FORMAT, "Generic Address Structure"); - AcpiDmDumpTable (TableLength, CurrentOffset, Target, + Status = AcpiDmDumpTable (TableLength, CurrentOffset, Target, sizeof (ACPI_GENERIC_ADDRESS), AcpiDmTableInfoGas); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + AcpiOsPrintf ("\n"); LastOutputBlankLine = TRUE; break; @@ -1250,8 +1264,13 @@ AcpiDmDumpTable ( AcpiOsPrintf (STRING_FORMAT, "Hardware Error Notification Structure"); - AcpiDmDumpTable (TableLength, CurrentOffset, Target, + Status = AcpiDmDumpTable (TableLength, CurrentOffset, Target, sizeof (ACPI_HEST_NOTIFY), AcpiDmTableInfoHestNotify); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + AcpiOsPrintf ("\n"); LastOutputBlankLine = TRUE; break; @@ -1275,8 +1294,13 @@ AcpiDmDumpTable ( AcpiOsPrintf (STRING_FORMAT, "IORT Memory Access Properties"); - AcpiDmDumpTable (TableLength, CurrentOffset, Target, + Status = AcpiDmDumpTable (TableLength, CurrentOffset, Target, sizeof (ACPI_IORT_MEMORY_ACCESS), AcpiDmTableInfoIortAcc); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + LastOutputBlankLine = TRUE; break; diff --git a/sys/contrib/dev/acpica/common/dmtbdump.c b/sys/contrib/dev/acpica/common/dmtbdump.c index 67d0f1c637d2..50d5d21230e9 100644 --- a/sys/contrib/dev/acpica/common/dmtbdump.c +++ b/sys/contrib/dev/acpica/common/dmtbdump.c @@ -208,11 +208,16 @@ AcpiDmDumpRsdp ( ACPI_TABLE_RSDP *Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table); UINT32 Length = sizeof (ACPI_RSDP_COMMON); UINT8 Checksum; + ACPI_STATUS Status; /* Dump the common ACPI 1.0 portion */ - AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1); + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1); + if (ACPI_FAILURE (Status)) + { + return (Length); + } /* Validate the first checksum */ @@ -229,7 +234,11 @@ AcpiDmDumpRsdp ( if (Rsdp->Revision > 0) { Length = Rsdp->Length; - AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2); + Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2); + if (ACPI_FAILURE (Status)) + { + return (Length); + } /* Validate the extended checksum over entire RSDP */ @@ -347,37 +356,59 @@ void AcpiDmDumpFadt ( ACPI_TABLE_HEADER *Table) { + ACPI_STATUS Status; + /* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */ - AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt1); + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt1); + if (ACPI_FAILURE (Status)) + { + return; + } /* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */ if ((Table->Length > ACPI_FADT_V1_SIZE) && (Table->Length <= ACPI_FADT_V2_SIZE)) { - AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt2); + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt2); + if (ACPI_FAILURE (Status)) + { + return; + } } /* Check for FADT revision 3/4 fields and up (ACPI 2.0+ extended data) */ else if (Table->Length > ACPI_FADT_V2_SIZE) { - AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt3); + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt3); + if (ACPI_FAILURE (Status)) + { + return; + } /* Check for FADT revision 5 fields and up (ACPI 5.0+) */ if (Table->Length > ACPI_FADT_V3_SIZE) { - AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt5); + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt5); + if (ACPI_FAILURE (Status)) + { + return; + } } /* Check for FADT revision 6 fields and up (ACPI 6.0+) */ if (Table->Length > ACPI_FADT_V3_SIZE) { - AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt6); + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt6); + if (ACPI_FAILURE (Status)) + { + return; + } } } @@ -1136,7 +1167,7 @@ AcpiDmDumpDrtm ( AcpiDmTableInfoDrtm1); if (ACPI_FAILURE (Status)) { - return; + return; } Offset += ACPI_OFFSET (ACPI_DRTM_RESOURCE_LIST, Resources); @@ -1164,13 +1195,9 @@ AcpiDmDumpDrtm ( DrtmDps = ACPI_ADD_PTR (ACPI_DRTM_DPS_ID, Table, Offset); AcpiOsPrintf ("\n"); - Status = AcpiDmDumpTable (Table->Length, Offset, + (void) AcpiDmDumpTable (Table->Length, Offset, DrtmDps, sizeof (ACPI_DRTM_DPS_ID), AcpiDmTableInfoDrtm2); - if (ACPI_FAILURE (Status)) - { - return; - } } @@ -1794,6 +1821,10 @@ AcpiDmDumpIort ( Status = AcpiDmDumpTable (Table->Length, Offset + NodeOffset, ACPI_ADD_PTR (ACPI_IORT_NODE, IortNode, NodeOffset), Length, AcpiDmTableInfoIort3a); + if (ACPI_FAILURE (Status)) + { + return; + } NodeOffset = IortSmmu->ContextInterruptOffset; for (i = 0; i < IortSmmu->ContextInterruptCount; i++) @@ -1801,6 +1832,10 @@ AcpiDmDumpIort ( Status = AcpiDmDumpTable (Table->Length, Offset + NodeOffset, ACPI_ADD_PTR (ACPI_IORT_NODE, IortNode, NodeOffset), 8, AcpiDmTableInfoIort3b); + if (ACPI_FAILURE (Status)) + { + return; + } NodeOffset += 8; } @@ -1810,6 +1845,10 @@ AcpiDmDumpIort ( Status = AcpiDmDumpTable (Table->Length, Offset + NodeOffset, ACPI_ADD_PTR (ACPI_IORT_NODE, IortNode, NodeOffset), 8, AcpiDmTableInfoIort3c); + if (ACPI_FAILURE (Status)) + { + return; + } NodeOffset += 8; } } @@ -1830,6 +1869,10 @@ AcpiDmDumpIort ( Status = AcpiDmDumpTable (Table->Length, Offset + NodeOffset, ACPI_ADD_PTR (ACPI_IORT_NODE, IortNode, NodeOffset), Length, AcpiDmTableInfoIortMap); + if (ACPI_FAILURE (Status)) + { + return; + } NodeOffset += Length; } @@ -2004,6 +2047,10 @@ AcpiDmDumpIvrs ( Status = AcpiDmDumpTable (Table->Length, EntryOffset, DeviceEntry, EntryLength, InfoTable); + if (ACPI_FAILURE (Status)) + { + return; + } EntryOffset += EntryLength; DeviceEntry = ACPI_ADD_PTR (ACPI_IVRS_DE_HEADER, DeviceEntry, @@ -2687,6 +2734,11 @@ AcpiDmDumpNfit ( Status = AcpiDmDumpTable (Table->Length, Offset + FieldOffset, &Interleave->LineOffset[i], sizeof (UINT32), AcpiDmTableInfoNfit2a); + if (ACPI_FAILURE (Status)) + { + return; + } + FieldOffset += sizeof (UINT32); } break; @@ -2715,6 +2767,11 @@ AcpiDmDumpNfit ( Status = AcpiDmDumpTable (Table->Length, Offset + FieldOffset, &Hint->HintAddress[i], sizeof (UINT64), AcpiDmTableInfoNfit6a); + if (ACPI_FAILURE (Status)) + { + return; + } + FieldOffset += sizeof (UINT64); } break; @@ -3126,7 +3183,7 @@ void AcpiDmDumpSlic ( ACPI_TABLE_HEADER *Table) { - AcpiDmDumpTable (Table->Length, sizeof (ACPI_TABLE_HEADER), Table, + (void) AcpiDmDumpTable (Table->Length, sizeof (ACPI_TABLE_HEADER), Table, Table->Length - sizeof (*Table), AcpiDmTableInfoSlic); } @@ -3356,6 +3413,77 @@ AcpiDmDumpStao ( } +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpTcpa + * + * PARAMETERS: Table - A TCPA table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a TCPA. + * + * NOTE: There are two versions of the table with the same signature: + * the client version and the server version. The common + * PlatformClass field is used to differentiate the two types of + * tables. + * + ******************************************************************************/ + +void +AcpiDmDumpTcpa ( + ACPI_TABLE_HEADER *Table) +{ + UINT32 Offset = sizeof (ACPI_TABLE_TCPA_HDR); + ACPI_TABLE_TCPA_HDR *CommonHeader = ACPI_CAST_PTR ( + ACPI_TABLE_TCPA_HDR, Table); + ACPI_TABLE_TCPA_HDR *SubTable = ACPI_ADD_PTR ( + ACPI_TABLE_TCPA_HDR, Table, Offset); + ACPI_STATUS Status; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, + 0, AcpiDmTableInfoTcpaHdr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* + * Examine the PlatformClass field to determine the table type. + * Either a client or server table. Only one. + */ + switch (CommonHeader->PlatformClass) + { + case ACPI_TCPA_CLIENT_TABLE: + + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + Table->Length - Offset, AcpiDmTableInfoTcpaClient); + break; + + case ACPI_TCPA_SERVER_TABLE: + + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + Table->Length - Offset, AcpiDmTableInfoTcpaServer); + break; + + default: + + AcpiOsPrintf ("\n**** Unknown TCPA Platform Class 0x%X\n", + CommonHeader->PlatformClass); + Status = AE_ERROR; + break; + } + + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("\n**** Cannot disassemble TCPA table\n"); + } +} + + /******************************************************************************* * * FUNCTION: AcpiDmDumpVrtc @@ -3497,10 +3625,6 @@ AcpiDmDumpWpbt ( /* Dump the arguments buffer */ - AcpiDmDumpTable (Table->Length, 0, Table, ArgumentsLength, + (void) AcpiDmDumpTable (Table->Length, 0, Table, ArgumentsLength, AcpiDmTableInfoWpbt0); - if (ACPI_FAILURE (Status)) - { - return; - } } diff --git a/sys/contrib/dev/acpica/common/dmtbinfo.c b/sys/contrib/dev/acpica/common/dmtbinfo.c index af67d43d79d9..fc4a254f3096 100644 --- a/sys/contrib/dev/acpica/common/dmtbinfo.c +++ b/sys/contrib/dev/acpica/common/dmtbinfo.c @@ -113,7 +113,7 @@ #define ACPI_SPMI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPMI,f) #define ACPI_SRAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SRAT,f) #define ACPI_STAO_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_STAO,f) -#define ACPI_TCPA_CLIENT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_CLIENT,f) +#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_HDR,f) #define ACPI_TPM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM2,f) #define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f) #define ACPI_WAET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WAET,f) @@ -230,6 +230,8 @@ #define ACPI_SRAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_MEM_AFFINITY,f) #define ACPI_SRAT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_X2APIC_CPU_AFFINITY,f) #define ACPI_SRAT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_GICC_AFFINITY,f) +#define ACPI_TCPA_CLIENT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_CLIENT,f) +#define ACPI_TCPA_SERVER_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_SERVER,f) #define ACPI_VRTC0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VRTC_ENTRY,f) #define ACPI_WDAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WDAT_ENTRY,f) @@ -2613,16 +2615,53 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoStaoStr[] = * * TCPA - Trusted Computing Platform Alliance table (Client) * + * NOTE: There are two versions of the table with the same signature -- + * the client version and the server version. The common PlatformClass + * field is used to differentiate the two types of tables. + * ******************************************************************************/ -ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] = +ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaHdr[] = +{ + {ACPI_DMT_UINT16, ACPI_TCPA_OFFSET (PlatformClass), "Platform Class", 0}, + ACPI_DMT_TERMINATOR +}; + +ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaClient[] = { - {ACPI_DMT_UINT16, ACPI_TCPA_CLIENT_OFFSET (PlatformClass), "Platform Class", 0}, {ACPI_DMT_UINT32, ACPI_TCPA_CLIENT_OFFSET (MinimumLogLength), "Min Event Log Length", 0}, {ACPI_DMT_UINT64, ACPI_TCPA_CLIENT_OFFSET (LogAddress), "Event Log Address", 0}, ACPI_DMT_TERMINATOR }; +ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaServer[] = +{ + {ACPI_DMT_UINT16, ACPI_TCPA_SERVER_OFFSET (Reserved), "Reserved", 0}, + {ACPI_DMT_UINT64, ACPI_TCPA_SERVER_OFFSET (MinimumLogLength), "Min Event Log Length", 0}, + {ACPI_DMT_UINT64, ACPI_TCPA_SERVER_OFFSET (LogAddress), "Event Log Address", 0}, + {ACPI_DMT_UINT16, ACPI_TCPA_SERVER_OFFSET (SpecRevision), "Specification Revision", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (DeviceFlags), "Device Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_TCPA_SERVER_OFFSET (DeviceFlags), "Pci Device", 0}, + {ACPI_DMT_FLAG1, ACPI_TCPA_SERVER_OFFSET (DeviceFlags), "Bus is Pnp", 0}, + {ACPI_DMT_FLAG2, ACPI_TCPA_SERVER_OFFSET (DeviceFlags), "Address Valid", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (InterruptFlags), "Interrupt Flags (decoded below)", DT_FLAG}, + {ACPI_DMT_FLAG0, ACPI_TCPA_SERVER_OFFSET (InterruptFlags), "Mode", 0}, + {ACPI_DMT_FLAG1, ACPI_TCPA_SERVER_OFFSET (InterruptFlags), "Polarity", 0}, + {ACPI_DMT_FLAG2, ACPI_TCPA_SERVER_OFFSET (InterruptFlags), "GPE SCI Triggered", 0}, + {ACPI_DMT_FLAG3, ACPI_TCPA_SERVER_OFFSET (InterruptFlags), "Global System Interrupt", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (GpeNumber), "Gpe Number", 0}, + {ACPI_DMT_UINT24, ACPI_TCPA_SERVER_OFFSET (Reserved2[0]), "Reserved", 0}, + {ACPI_DMT_UINT32, ACPI_TCPA_SERVER_OFFSET (GlobalInterrupt), "Global Interrupt", 0}, + {ACPI_DMT_GAS, ACPI_TCPA_SERVER_OFFSET (Address), "Address", 0}, + {ACPI_DMT_UINT32, ACPI_TCPA_SERVER_OFFSET (Reserved3), "Reserved", 0}, + {ACPI_DMT_GAS, ACPI_TCPA_SERVER_OFFSET (ConfigAddress), "Configuration Address", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (Group), "Pci Group", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (Bus), "Pci Bus", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (Device), "Pci Device", 0}, + {ACPI_DMT_UINT8, ACPI_TCPA_SERVER_OFFSET (Function), "Pci Function", 0}, + ACPI_DMT_TERMINATOR +}; + /******************************************************************************* * diff --git a/sys/contrib/dev/acpica/compiler/aslascii.c b/sys/contrib/dev/acpica/compiler/aslascii.c index 1583dc3a5f5a..67184ede01d3 100644 --- a/sys/contrib/dev/acpica/compiler/aslascii.c +++ b/sys/contrib/dev/acpica/compiler/aslascii.c @@ -177,6 +177,11 @@ FlCheckForAscii ( /* Open file in text mode so file offset is always accurate */ Handle = fopen (Filename, "rb"); + if (!Handle) + { + perror ("Could not open input file"); + return (AE_ERROR); + } Status.Line = 1; Status.Offset = 0; diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c index 9aaac3b8c291..cda158361ee0 100644 --- a/sys/contrib/dev/acpica/compiler/aslcompile.c +++ b/sys/contrib/dev/acpica/compiler/aslcompile.c @@ -100,6 +100,10 @@ CmDoCompile ( Event = UtBeginEvent ("Preprocess input file"); if (Gbl_PreprocessFlag) { + /* Enter compiler name as a #define */ + + PrAddDefine (ASL_DEFINE, "", FALSE); + /* Preprocessor */ PrDoPreprocess (); diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h index 0b5f614a6481..9e42ddf8b248 100644 --- a/sys/contrib/dev/acpica/compiler/asldefine.h +++ b/sys/contrib/dev/acpica/compiler/asldefine.h @@ -52,6 +52,7 @@ #define AML_DISASSEMBLER_NAME "AML/ASL+ Disassembler" #define ASL_INVOCATION_NAME "iasl" #define ASL_CREATOR_ID "INTL" +#define ASL_DEFINE "__IASL__" #define ASL_COMPLIANCE "Supports ACPI Specification Revision 6.0" @@ -155,12 +156,6 @@ #define ACPI_COMPILER_RESERVED_NAME (ACPI_UINT32_MAX - 3) -/* String to Integer conversion */ - -#define NEGATIVE 1 -#define POSITIVE 0 - - /* Helper macros for resource tag creation */ #define RsCreateMultiBitField \ diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c index 37043cb5cbdb..762abcd02767 100644 --- a/sys/contrib/dev/acpica/compiler/aslfiles.c +++ b/sys/contrib/dev/acpica/compiler/aslfiles.c @@ -546,6 +546,26 @@ FlOpenMiscOutputFiles ( char *Filename; + /* Create/Open a map file if requested */ + + if (Gbl_MapfileFlag) + { + Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_MAP); + if (!Filename) + { + AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, + 0, 0, 0, 0, NULL, NULL); + return (AE_ERROR); + } + + /* Open the hex file, text mode (closed at compiler exit) */ + + FlOpenFile (ASL_FILE_MAP_OUTPUT, Filename, "w+t"); + + AslCompilerSignon (ASL_FILE_MAP_OUTPUT); + AslCompilerFileHeader (ASL_FILE_MAP_OUTPUT); + } + /* All done for disassembler */ if (Gbl_FileType == ASL_INPUT_TYPE_ACPI_TABLE) @@ -812,26 +832,6 @@ FlOpenMiscOutputFiles ( AslCompilerFileHeader (ASL_FILE_NAMESPACE_OUTPUT); } - /* Create/Open a map file if requested */ - - if (Gbl_MapfileFlag) - { - Filename = FlGenerateFilename (FilenamePrefix, FILE_SUFFIX_MAP); - if (!Filename) - { - AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME, - 0, 0, 0, 0, NULL, NULL); - return (AE_ERROR); - } - - /* Open the hex file, text mode (closed at compiler exit) */ - - FlOpenFile (ASL_FILE_MAP_OUTPUT, Filename, "w+t"); - - AslCompilerSignon (ASL_FILE_MAP_OUTPUT); - AslCompilerFileHeader (ASL_FILE_MAP_OUTPUT); - } - return (AE_OK); } diff --git a/sys/contrib/dev/acpica/compiler/asllookup.c b/sys/contrib/dev/acpica/compiler/asllookup.c index a527a383dc58..0937abe96050 100644 --- a/sys/contrib/dev/acpica/compiler/asllookup.c +++ b/sys/contrib/dev/acpica/compiler/asllookup.c @@ -119,8 +119,73 @@ LkIsObjectUsed ( { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ACPI_NAMESPACE_NODE *Next; + ASL_METHOD_LOCAL *MethodLocals; + ASL_METHOD_LOCAL *MethodArgs; + UINT32 i; + if (Node->Type == ACPI_TYPE_METHOD) + { + if (!Node->Op || !Node->MethodLocals) + { + return (AE_OK); + } + + MethodLocals = (ASL_METHOD_LOCAL *) Node->MethodLocals; + MethodArgs = (ASL_METHOD_LOCAL *) Node->MethodArgs; + + /* + * Analysis of LocalX variables + */ + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) + { + /* Warn for Locals that are set but never referenced */ + + if ((MethodLocals[i].Flags & ASL_LOCAL_INITIALIZED) && + (!(MethodLocals[i].Flags & ASL_LOCAL_REFERENCED))) + { + sprintf (MsgBuffer, "Local%u", i); + AslError (ASL_WARNING, ASL_MSG_LOCAL_NOT_USED, + MethodLocals[i].Op, MsgBuffer); + } + } + + /* + * Analysis of ArgX variables (standard method arguments, + * and remaining unused ArgX can also be used as locals) + */ + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + if (MethodArgs[i].Flags & ASL_ARG_IS_LOCAL) + { + /* Warn if ArgX is being used as a local, but not referenced */ + + if ((MethodArgs[i].Flags & ASL_ARG_INITIALIZED) && + (!(MethodArgs[i].Flags & ASL_ARG_REFERENCED))) + { + sprintf (MsgBuffer, "Arg%u", i); + AslError (ASL_WARNING, ASL_MSG_ARG_AS_LOCAL_NOT_USED, + MethodArgs[i].Op, MsgBuffer); + } + } + else + { + /* + * Remark if a normal method ArgX is not referenced. + * We ignore the predefined methods since often, not + * all arguments are needed or used. + */ + if ((Node->Name.Ascii[0] != '_') && + (!(MethodArgs[i].Flags & ASL_ARG_REFERENCED))) + { + sprintf (MsgBuffer, "Arg%u", i); + AslError (ASL_REMARK, ASL_MSG_ARG_NOT_USED, + MethodArgs[i].Op, MsgBuffer); + } + } + } + } + /* Referenced flag is set during the namespace xref */ if (Node->Flags & ANOBJ_IS_REFERENCED) diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.c b/sys/contrib/dev/acpica/compiler/aslmessages.c index c57fd2d3f0a2..cf09d7de2f67 100644 --- a/sys/contrib/dev/acpica/compiler/aslmessages.c +++ b/sys/contrib/dev/acpica/compiler/aslmessages.c @@ -235,7 +235,11 @@ const char *AslCompilerMsgs [] = /* ASL_MSG_BUFFER_ALLOCATION */ "Could not allocate line buffer", /* ASL_MSG_MISSING_DEPENDENCY */ "Missing dependency", /* ASL_MSG_ILLEGAL_FORWARD_REF */ "Illegal forward reference within a method", -/* ASL_MSG_ILLEGAL_METHOD_REF */ "Illegal reference across two methods" +/* ASL_MSG_ILLEGAL_METHOD_REF */ "Illegal reference across two methods", +/* ASL_MSG_LOCAL_NOT_USED */ "Method Local is set but never used", +/* ASL_MSG_ARG_AS_LOCAL_NOT_USED */ "Method Argument (as a local) is set but never used", +/* ASL_MSG_ARG_NOT_USED */ "Method Argument is never used" + }; /* Table compiler */ diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.h b/sys/contrib/dev/acpica/compiler/aslmessages.h index 9837d540698f..d7e3dd06e8b6 100644 --- a/sys/contrib/dev/acpica/compiler/aslmessages.h +++ b/sys/contrib/dev/acpica/compiler/aslmessages.h @@ -238,6 +238,9 @@ typedef enum ASL_MSG_MISSING_DEPENDENCY, ASL_MSG_ILLEGAL_FORWARD_REF, ASL_MSG_ILLEGAL_METHOD_REF, + ASL_MSG_LOCAL_NOT_USED, + ASL_MSG_ARG_AS_LOCAL_NOT_USED, + ASL_MSG_ARG_NOT_USED, /* These messages are used by the Data Table compiler only */ diff --git a/sys/contrib/dev/acpica/compiler/aslmethod.c b/sys/contrib/dev/acpica/compiler/aslmethod.c index bee488f3c328..227ce370459f 100644 --- a/sys/contrib/dev/acpica/compiler/aslmethod.c +++ b/sys/contrib/dev/acpica/compiler/aslmethod.c @@ -255,7 +255,7 @@ MtMethodAnalysisWalkBegin ( return (AE_ERROR); } - RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); + RegisterNumber = (Op->Asl.AmlOpcode & 0x0007); /* * If the local is being used as a target, mark the local diff --git a/sys/contrib/dev/acpica/compiler/aslnamesp.c b/sys/contrib/dev/acpica/compiler/aslnamesp.c index 720d39483652..1e65ab70e527 100644 --- a/sys/contrib/dev/acpica/compiler/aslnamesp.c +++ b/sys/contrib/dev/acpica/compiler/aslnamesp.c @@ -409,7 +409,7 @@ NsDoOnePathname ( TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (Node, &TargetPath); + Status = AcpiNsHandleToPathname (Node, &TargetPath, FALSE); if (ACPI_FAILURE (Status)) { return (Status); diff --git a/sys/contrib/dev/acpica/compiler/asloffset.c b/sys/contrib/dev/acpica/compiler/asloffset.c index 14f7e9569df0..afc62585e441 100644 --- a/sys/contrib/dev/acpica/compiler/asloffset.c +++ b/sys/contrib/dev/acpica/compiler/asloffset.c @@ -363,7 +363,7 @@ LsEmitOffsetTableEntry ( /* Get the full pathname to the namespace node */ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (Node, &TargetPath); + Status = AcpiNsHandleToPathname (Node, &TargetPath, FALSE); if (ACPI_FAILURE (Status)) { return; diff --git a/sys/contrib/dev/acpica/compiler/aslopcodes.c b/sys/contrib/dev/acpica/compiler/aslopcodes.c index 43628f96e694..8ee89abf1cae 100644 --- a/sys/contrib/dev/acpica/compiler/aslopcodes.c +++ b/sys/contrib/dev/acpica/compiler/aslopcodes.c @@ -789,43 +789,6 @@ OpcEncodePldBuffer ( } -/******************************************************************************* - * - * FUNCTION: OpcStrupr (strupr) - * - * PARAMETERS: SrcString - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -static void -OpcStrupr ( - char *SrcString) -{ - char *String; - - - if (!SrcString) - { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (String = SrcString; *String; String++) - { - *String = (char) toupper ((int) *String); - } - - return; -} - - /******************************************************************************* * * FUNCTION: OpcFindName @@ -851,7 +814,7 @@ OpcFindName ( UINT32 i; - OpcStrupr (Name); + AcpiUtStrupr (Name); for (i = 0, Str = List[0]; Str; i++, Str = List[i]) { @@ -900,13 +863,6 @@ OpcDoPld ( return; } - Buffer = UtLocalCalloc (ACPI_PLD_BUFFER_SIZE); - if (!Buffer) - { - AslError(ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION, Op, NULL); - return; - } - memset (&PldInfo, 0, sizeof (ACPI_PLD_INFO)); Node = Op->Asl.Child; diff --git a/sys/contrib/dev/acpica/compiler/aslopt.c b/sys/contrib/dev/acpica/compiler/aslopt.c index a65a25ee8624..b2d8d8bf1517 100644 --- a/sys/contrib/dev/acpica/compiler/aslopt.c +++ b/sys/contrib/dev/acpica/compiler/aslopt.c @@ -655,7 +655,7 @@ OptOptimizeNamePath ( * format -- something we can easily manipulate */ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (TargetNode, &TargetPath); + Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Target NamePath", @@ -667,7 +667,7 @@ OptOptimizeNamePath ( /* CurrentPath is the path to this scope (where we are in the namespace) */ CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath); + Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Current NamePath", diff --git a/sys/contrib/dev/acpica/compiler/asloptions.c b/sys/contrib/dev/acpica/compiler/asloptions.c index 4cff853bcc81..89d42ceba1d6 100644 --- a/sys/contrib/dev/acpica/compiler/asloptions.c +++ b/sys/contrib/dev/acpica/compiler/asloptions.c @@ -286,6 +286,11 @@ AslDoOptions ( AcpiGbl_CstyleDisassembly = FALSE; break; + case 'v': + + AcpiGbl_DbOpt_Verbose = TRUE; + break; + default: printf ("Unknown option: -d%s\n", AcpiGbl_Optarg); diff --git a/sys/contrib/dev/acpica/compiler/aslstartup.c b/sys/contrib/dev/acpica/compiler/aslstartup.c index 211658ba5387..d20cc1f5a8ba 100644 --- a/sys/contrib/dev/acpica/compiler/aslstartup.c +++ b/sys/contrib/dev/acpica/compiler/aslstartup.c @@ -246,6 +246,11 @@ AslDoDisassembly ( return (Status); } + /* Handle additional output files for disassembler */ + + Gbl_FileType = ASL_INPUT_TYPE_ACPI_TABLE; + Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); + /* This is where the disassembly happens */ AcpiGbl_DbOpt_Disasm = TRUE; @@ -261,13 +266,6 @@ AslDoDisassembly ( AcpiDmUnresolvedWarning (0); -#if 0 - /* TBD: Handle additional output files for disassembler */ - - Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); - NsDisplayNamespace (); -#endif - /* Shutdown compiler and ACPICA subsystem */ AeClearErrorLog (); diff --git a/sys/contrib/dev/acpica/compiler/aslstubs.c b/sys/contrib/dev/acpica/compiler/aslstubs.c index 2259255d498b..b0b4010f2780 100644 --- a/sys/contrib/dev/acpica/compiler/aslstubs.c +++ b/sys/contrib/dev/acpica/compiler/aslstubs.c @@ -165,15 +165,6 @@ AcpiEvInitializeRegion ( return (AE_OK); } -void -AcpiExDoDebugObject ( - ACPI_OPERAND_OBJECT *SourceDesc, - UINT32 Level, - UINT32 Index) -{ - return; -} - ACPI_STATUS AcpiExReadDataFromField ( ACPI_WALK_STATE *WalkState, @@ -216,6 +207,60 @@ AcpiExLoadOp ( return (AE_SUPPORT); } +void +AcpiExDoDebugObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + UINT32 Level, + UINT32 Index) +{ + return; +} + +void +AcpiExStartTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + return; +} + +void +AcpiExStopTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + return; +} + +void +AcpiExStartTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + return; +} + +void +AcpiExStopTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) + +{ + return; +} + +void +AcpiExTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname) +{ + return; +} + ACPI_STATUS AcpiTbFindTable ( char *Signature, diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h index 343c364c49ff..ce2f75888ff5 100644 --- a/sys/contrib/dev/acpica/compiler/asltypes.h +++ b/sys/contrib/dev/acpica/compiler/asltypes.h @@ -302,5 +302,19 @@ typedef struct acpi_serial_info } ACPI_SERIAL_INFO; +typedef struct asl_method_local +{ + ACPI_PARSE_OBJECT *Op; + UINT8 Flags; + +} ASL_METHOD_LOCAL; + +/* Values for Flags field above */ + +#define ASL_LOCAL_INITIALIZED (1) +#define ASL_LOCAL_REFERENCED (1<<1) +#define ASL_ARG_IS_LOCAL (1<<2) +#define ASL_ARG_INITIALIZED (1<<3) +#define ASL_ARG_REFERENCED (1<<4) #endif /* __ASLTYPES_H */ diff --git a/sys/contrib/dev/acpica/compiler/aslutils.c b/sys/contrib/dev/acpica/compiler/aslutils.c index e0511a4bdf3d..956a488a8c87 100644 --- a/sys/contrib/dev/acpica/compiler/aslutils.c +++ b/sys/contrib/dev/acpica/compiler/aslutils.c @@ -1008,17 +1008,17 @@ stroul64 ( */ if (*String == '-') { - Sign = NEGATIVE; + Sign = ACPI_SIGN_NEGATIVE; ++String; } else if (*String == '+') { ++String; - Sign = POSITIVE; + Sign = ACPI_SIGN_POSITIVE; } else { - Sign = POSITIVE; + Sign = ACPI_SIGN_POSITIVE; } /* @@ -1106,7 +1106,7 @@ stroul64 ( /* If a minus sign was present, then "the conversion is negated": */ - if (Sign == NEGATIVE) + if (Sign == ACPI_SIGN_NEGATIVE) { ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; } diff --git a/sys/contrib/dev/acpica/compiler/aslxref.c b/sys/contrib/dev/acpica/compiler/aslxref.c index cda7ccf68b39..910a1132b3bc 100644 --- a/sys/contrib/dev/acpica/compiler/aslxref.c +++ b/sys/contrib/dev/acpica/compiler/aslxref.c @@ -66,6 +66,10 @@ XfNamespaceLocateEnd ( UINT32 Level, void *Context); +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op); + static BOOLEAN XfObjectExists ( char *Name); @@ -280,59 +284,16 @@ XfCheckFieldRange ( } -#ifdef __UNDER_DEVELOPMENT -/******************************************************************************* - * - * FUNCTION: XfIsObjectParental - * - * PARAMETERS: ChildOp - Op to be checked - * PossibleParentOp - Determine if this op is in the family - * - * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp - * - * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to - * detect if a method is declared within another method. - * - ******************************************************************************/ - -static BOOLEAN -XfIsObjectParental ( - ACPI_PARSE_OBJECT *ChildOp, - ACPI_PARSE_OBJECT *PossibleParentOp) -{ - ACPI_PARSE_OBJECT *ParentOp; - - - /* Search upwards through the tree for possible parent */ - - ParentOp = ChildOp; - while (ParentOp) - { - if (ParentOp == PossibleParentOp) - { - return (TRUE); - } - - ParentOp = ParentOp->Asl.Parent; - } - - return (FALSE); -} - - /******************************************************************************* * * FUNCTION: XfGetParentMethod * - * PARAMETERS: Op - Op to be checked + * PARAMETERS: Op - Parse Op to be checked * - * RETURN: Op for parent method. NULL if object is not within a method. + * RETURN: Control method Op if found. NULL otherwise * - * DESCRIPTION: Determine if an object is within a control method. Used to - * implement special rules for named references from within a - * control method. - * - * NOTE: It would be better to have the parser set a flag in the Op if possible. + * DESCRIPTION: Find the control method parent of a parse op. Returns NULL if + * the input Op is not within a control method. * ******************************************************************************/ @@ -340,121 +301,23 @@ static ACPI_PARSE_OBJECT * XfGetParentMethod ( ACPI_PARSE_OBJECT *Op) { - ACPI_PARSE_OBJECT *ParentOp; + ACPI_PARSE_OBJECT *NextOp; - if (!Op) + NextOp = Op->Asl.Parent; + while (NextOp) { - return (NULL); - } - - if (Op->Asl.ParseOpcode == PARSEOP_METHOD) - { - return (NULL); - } - - /* Walk upwards through the parse tree, up to the root if necessary */ - - ParentOp = Op; - while (ParentOp) - { - if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) + if (NextOp->Asl.AmlOpcode == AML_METHOD_OP) { - return (ParentOp); + return (NextOp); } - ParentOp = ParentOp->Asl.Parent; + NextOp = NextOp->Asl.Parent; } - /* Object is not within a method */ - - return (NULL); + return (NULL); /* No parent method found */ } - -/******************************************************************************* - * - * FUNCTION: XfCheckIllegalReference - * - * PARAMETERS: Op - Op referring to the target - * TargetNode - Target of the reference - * - * RETURN: None. Emits error message for an illegal reference - * - * DESCRIPTION: Determine if a named reference is legal. A "named" reference - * is something like: Store(ABCD, ...), where ABCD is an AML - * Nameseg or Namepath. - * - * NOTE: Caller must ensure that the name Op is in fact a reference, and not - * an actual name declaration (creation of a named object). - * - ******************************************************************************/ - -static void -XfCheckIllegalReference ( - ACPI_PARSE_OBJECT *Op, - ACPI_NAMESPACE_NODE *TargetNode) -{ - ACPI_PARSE_OBJECT *MethodOp1; - ACPI_PARSE_OBJECT *MethodOp2; - ACPI_PARSE_OBJECT *TargetOp; - - - /* - * Check for an illegal reference to a named object: - * - * 1) References from one control method to another, non-parent - * method are not allowed, they will fail at runtime. - * - * 2) Forward references within a control method are not allowed. - * AML interpreters use a one-pass parse of control methods - * so these forward references will fail at runtime. - */ - TargetOp = TargetNode->Op; - - MethodOp1 = XfGetParentMethod (Op); - MethodOp2 = XfGetParentMethod (TargetOp); - - /* Are both objects within control method(s)? */ - - if (!MethodOp1 || !MethodOp2) - { - return; - } - - /* Objects not in the same method? */ - - if (MethodOp1 != MethodOp2) - { - /* - * 1) Cross-method named reference - * - * This is OK if and only if the target reference is within in a - * method that is a parent of current method - */ - if (!XfIsObjectParental (MethodOp1, MethodOp2)) - { - AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, - Op->Asl.ExternalName); - } - } - - /* - * 2) Both reference and target are in the same method. Check if this is - * an (illegal) forward reference by examining the exact source code - * location of each (the referenced object and the object declaration). - * This is a bit nasty, yet effective. - */ - else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) - { - AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, - Op->Asl.ExternalName); - } - -} -#endif - - /******************************************************************************* * * FUNCTION: XfNamespaceLocateBegin @@ -496,10 +359,67 @@ XfNamespaceLocateBegin ( UINT8 Message = 0; const ACPI_OPCODE_INFO *OpInfo; UINT32 Flags; + ASL_METHOD_LOCAL *MethodLocals = NULL; + ASL_METHOD_LOCAL *MethodArgs = NULL; + int RegisterNumber; + UINT32 i; ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op); + + if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node) + { + Node = Op->Asl.Node; + + /* Support for method LocalX/ArgX analysis */ + + if (!Node->MethodLocals) + { + /* Create local/arg info blocks */ + + MethodLocals = UtLocalCalloc ( + sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS); + Node->MethodLocals = MethodLocals; + + MethodArgs = UtLocalCalloc ( + sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS); + Node->MethodArgs = MethodArgs; + + /* + * Get the method argument count + * First, get the name node + */ + NextOp = Op->Asl.Child; + + /* Get the NumArguments node */ + + NextOp = NextOp->Asl.Next; + Node->ArgCount = (UINT8) + (((UINT8) NextOp->Asl.Value.Integer) & 0x07); + + /* We will track all posible ArgXs */ + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + if (i < Node->ArgCount) + { + /* Real Args are always "initialized" */ + + MethodArgs[i].Flags = ASL_ARG_INITIALIZED; + } + else + { + /* Other ArgXs can be used as locals */ + + MethodArgs[i].Flags = ASL_ARG_IS_LOCAL; + } + + MethodArgs[i].Op = Op; + } + } + } + /* * If this node is the actual declaration of a name * [such as the XXXX name in "Method (XXXX)"], @@ -512,10 +432,88 @@ XfNamespaceLocateBegin ( return_ACPI_STATUS (AE_OK); } - /* We are only interested in opcodes that have an associated name */ - OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + /* Check method LocalX variables */ + + if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE) + { + /* Find parent method Op */ + + NextOp = XfGetParentMethod (Op); + if (!NextOp) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get method node */ + + Node = NextOp->Asl.Node; + + RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */ + MethodLocals = Node->MethodLocals; + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + /* Local is being initialized */ + + MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED; + MethodLocals[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Mark this Local as referenced */ + + MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED; + MethodLocals[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Check method ArgX variables */ + + if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT) + { + /* Find parent method Op */ + + NextOp = XfGetParentMethod (Op); + if (!NextOp) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get method node */ + + Node = NextOp->Asl.Node; + + /* Get Arg # */ + + RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */ + MethodArgs = Node->MethodArgs; + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + /* Arg is being initialized */ + + MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED; + MethodArgs[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Mark this Arg as referenced */ + + MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED; + MethodArgs[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* + * After method ArgX and LocalX, we are only interested in opcodes + * that have an associated name + */ if ((!(OpInfo->Flags & AML_NAMED)) && (!(OpInfo->Flags & AML_CREATE)) && (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && @@ -1094,3 +1092,178 @@ XfNamespaceLocateEnd ( return_ACPI_STATUS (AE_OK); } + + +#ifdef __UNDER_DEVELOPMENT +/******************************************************************************* + * + * FUNCTION: XfIsObjectParental + * + * PARAMETERS: ChildOp - Op to be checked + * PossibleParentOp - Determine if this op is in the family + * + * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp + * + * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to + * detect if a method is declared within another method. + * + ******************************************************************************/ + +static BOOLEAN +XfIsObjectParental ( + ACPI_PARSE_OBJECT *ChildOp, + ACPI_PARSE_OBJECT *PossibleParentOp) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + /* Search upwards through the tree for possible parent */ + + ParentOp = ChildOp; + while (ParentOp) + { + if (ParentOp == PossibleParentOp) + { + return (TRUE); + } + + ParentOp = ParentOp->Asl.Parent; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: XfGetParentMethod + * + * PARAMETERS: Op - Op to be checked + * + * RETURN: Op for parent method. NULL if object is not within a method. + * + * DESCRIPTION: Determine if an object is within a control method. Used to + * implement special rules for named references from within a + * control method. + * + * NOTE: It would be better to have the parser set a flag in the Op if possible. + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + if (!Op) + { + return (NULL); + } + + if (Op->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (NULL); + } + + /* Walk upwards through the parse tree, up to the root if necessary */ + + ParentOp = Op; + while (ParentOp) + { + if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (ParentOp); + } + + ParentOp = ParentOp->Asl.Parent; + } + + /* Object is not within a method */ + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: XfCheckIllegalReference + * + * PARAMETERS: Op - Op referring to the target + * TargetNode - Target of the reference + * + * RETURN: None. Emits error message for an illegal reference + * + * DESCRIPTION: Determine if a named reference is legal. A "named" reference + * is something like: Store(ABCD, ...), where ABCD is an AML + * Nameseg or Namepath. + * + * NOTE: Caller must ensure that the name Op is in fact a reference, and not + * an actual name declaration (creation of a named object). + * + ******************************************************************************/ + +static void +XfCheckIllegalReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *TargetNode) +{ + ACPI_PARSE_OBJECT *MethodOp1; + ACPI_PARSE_OBJECT *MethodOp2; + ACPI_PARSE_OBJECT *TargetOp; + + + /* + * Check for an illegal reference to a named object: + * + * 1) References from one control method to another, non-parent + * method are not allowed, they will fail at runtime. + * + * 2) Forward references within a control method are not allowed. + * AML interpreters use a one-pass parse of control methods + * so these forward references will fail at runtime. + */ + TargetOp = TargetNode->Op; + + MethodOp1 = XfGetParentMethod (Op); + MethodOp2 = XfGetParentMethod (TargetOp); + + /* Are both objects within control method(s)? */ + + if (!MethodOp1 || !MethodOp2) + { + return; + } + + /* Objects not in the same method? */ + + if (MethodOp1 != MethodOp2) + { + /* + * 1) Cross-method named reference + * + * This is OK if and only if the target reference is within in a + * method that is a parent of current method + */ + if (!XfIsObjectParental (MethodOp1, MethodOp2)) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, + Op->Asl.ExternalName); + } + } + + /* + * 2) Both reference and target are in the same method. Check if this is + * an (illegal) forward reference by examining the exact source code + * location of each (the referenced object and the object declaration). + * This is a bit nasty, yet effective. + */ + else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, + Op->Asl.ExternalName); + } + +} +#endif diff --git a/sys/contrib/dev/acpica/compiler/dtcompiler.h b/sys/contrib/dev/acpica/compiler/dtcompiler.h index daff7aa3921f..be52b1696136 100644 --- a/sys/contrib/dev/acpica/compiler/dtcompiler.h +++ b/sys/contrib/dev/acpica/compiler/dtcompiler.h @@ -536,6 +536,10 @@ ACPI_STATUS DtCompileStao ( void **PFieldList); +ACPI_STATUS +DtCompileTcpa ( + void **PFieldList); + ACPI_STATUS DtCompileUefi ( void **PFieldList); diff --git a/sys/contrib/dev/acpica/compiler/dttable.c b/sys/contrib/dev/acpica/compiler/dttable.c index 1c32fe0f933c..7987328fe978 100644 --- a/sys/contrib/dev/acpica/compiler/dttable.c +++ b/sys/contrib/dev/acpica/compiler/dttable.c @@ -3120,6 +3120,77 @@ DtCompileStao ( } +/****************************************************************************** + * + * FUNCTION: DtCompileTcpa + * + * PARAMETERS: PFieldList - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile TCPA. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileTcpa ( + void **List) +{ + DT_FIELD **PFieldList = (DT_FIELD **) List; + DT_SUBTABLE *Subtable; + ACPI_TABLE_TCPA_HDR *TcpaHeader; + DT_SUBTABLE *ParentTable; + ACPI_STATUS Status; + + + /* Compile the main table */ + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaHdr, + &Subtable, TRUE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + /* + * Examine the PlatformClass field to determine the table type. + * Either a client or server table. Only one. + */ + TcpaHeader = ACPI_CAST_PTR (ACPI_TABLE_TCPA_HDR, ParentTable->Buffer); + + switch (TcpaHeader->PlatformClass) + { + case ACPI_TCPA_CLIENT_TABLE: + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaClient, + &Subtable, TRUE); + break; + + case ACPI_TCPA_SERVER_TABLE: + + Status = DtCompileTable (PFieldList, AcpiDmTableInfoTcpaServer, + &Subtable, TRUE); + break; + + default: + + AcpiOsPrintf ("\n**** Unknown TCPA Platform Class 0x%X\n", + TcpaHeader->PlatformClass); + Status = AE_ERROR; + break; + } + + + ParentTable = DtPeekSubtable (); + DtInsertSubtable (ParentTable, Subtable); + + return (Status); +} + + /****************************************************************************** * * FUNCTION: DtGetGenericTableInfo diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.h b/sys/contrib/dev/acpica/compiler/dttemplate.h index 6d76f4d64b9c..6f3ed6407012 100644 --- a/sys/contrib/dev/acpica/compiler/dttemplate.h +++ b/sys/contrib/dev/acpica/compiler/dttemplate.h @@ -1144,13 +1144,19 @@ const unsigned char TemplateStao[] = const unsigned char TemplateTcpa[] = { - 0x54,0x43,0x50,0x41,0x32,0x00,0x00,0x00, /* 00000000 "TCPA2..." */ - 0x01,0x67,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".gINTEL " */ - 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x54,0x43,0x50,0x41,0x64,0x00,0x00,0x00, /* 00000000 "TCPAd..." */ + 0x02,0xFF,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65, /* 00000010 "Template" */ 0x80,0x31,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 ".1..INTL" */ - 0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.. ...." */ - 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ - 0x00,0x00 /* 00000030 ".." */ + 0x19,0x06,0x15,0x20,0x01,0x00,0x00,0x00, /* 00000020 "... ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x11,0x00,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA, /* 00000030 "........" */ + 0x02,0x01,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x03, /* 00000040 "..... .." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048 "........" */ + 0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x03, /* 00000050 "..... .." */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058 "........" */ + 0x01,0x01,0x01,0x01 /* 00000060 "...." */ }; const unsigned char TemplateTpm2[] = diff --git a/sys/contrib/dev/acpica/compiler/prparser.l b/sys/contrib/dev/acpica/compiler/prparser.l index 3150b69c01fa..ed77a05fb43a 100644 --- a/sys/contrib/dev/acpica/compiler/prparser.l +++ b/sys/contrib/dev/acpica/compiler/prparser.l @@ -50,14 +50,22 @@ #define STRING_SETUP strcpy (StringBuffer, PrParsertext);\ PrParserlval.str = StringBuffer -#define YY_NO_INPUT /* No file input, we use strings only */ - #define _COMPONENT ACPI_COMPILER ACPI_MODULE_NAME ("prscanner") + + +/* Local prototypes */ + +static char +PrDoCommentType1 ( + void); + +static char +PrDoCommentType2 ( + void); %} %option noyywrap -%option nounput Number [0-9a-fA-F]+ HexNumber 0[xX][0-9a-fA-F]+ @@ -66,6 +74,8 @@ NewLine [\n] Identifier [a-zA-Z][0-9a-zA-Z]* %% +"/*" { if (!PrDoCommentType1 ()) {yyterminate ();} } +"//" { if (!PrDoCommentType2 ()) {yyterminate ();} } \( return (EXPOP_PAREN_OPEN); \) return (EXPOP_PAREN_CLOSE); @@ -151,3 +161,76 @@ PrTerminateLexer ( yy_delete_buffer (LexBuffer); } + + +/******************************************************************************** + * + * FUNCTION: PrDoCommentType1 + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Process a new legacy comment. Just toss it. + * + ******************************************************************************/ + +static char +PrDoCommentType1 ( + void) +{ + int c; + + +Loop: + while (((c = input ()) != '*') && (c != EOF)) + { + } + if (c == EOF) + { + return (FALSE); + } + + if (((c = input ()) != '/') && (c != EOF)) + { + unput (c); + goto Loop; + } + if (c == EOF) + { + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************** + * + * FUNCTION: PrDoCommentType2 + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Process a new "//" comment. Just toss it. + * + ******************************************************************************/ + +static char +PrDoCommentType2 ( + void) +{ + int c; + + + while (((c = input ()) != '\n') && (c != EOF)) + { + } + if (c == EOF) + { + return (FALSE); + } + + return (TRUE); +} diff --git a/sys/contrib/dev/acpica/compiler/prparser.y b/sys/contrib/dev/acpica/compiler/prparser.y index f0c5f9bff2c4..ce9391615b77 100644 --- a/sys/contrib/dev/acpica/compiler/prparser.y +++ b/sys/contrib/dev/acpica/compiler/prparser.y @@ -213,8 +213,11 @@ void PrParsererror ( char const *Message) { + + sprintf (StringBuffer, "Preprocessor Parser : %s (near line %u)", + Message, Gbl_CurrentLineNumber); DtError (ASL_ERROR, ASL_MSG_SYNTAX, - NULL, (char *) Message); + NULL, (char *) StringBuffer); } diff --git a/sys/contrib/dev/acpica/compiler/prscan.c b/sys/contrib/dev/acpica/compiler/prscan.c index cbf82a94907e..1fb7f6fbb454 100644 --- a/sys/contrib/dev/acpica/compiler/prscan.c +++ b/sys/contrib/dev/acpica/compiler/prscan.c @@ -120,7 +120,6 @@ static const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] = {"include", 0}, /* Argument is not standard format, so just use 0 here */ {"includebuffer", 0}, /* Argument is not standard format, so just use 0 here */ {"line", 1}, - {"loadbuffer", 0}, {"pragma", 1}, {"undef", 1}, {"warning", 1}, @@ -144,7 +143,7 @@ enum Gbl_DirectiveIndexes PR_DIRECTIVE_LINE, PR_DIRECTIVE_PRAGMA, PR_DIRECTIVE_UNDEF, - PR_DIRECTIVE_WARNING, + PR_DIRECTIVE_WARNING }; #define ASL_DIRECTIVE_NOT_FOUND -1 @@ -328,7 +327,7 @@ PrPreprocessInputFile ( PrGetNextLineInit (); - /* Scan line-by-line. Comments and blank lines are skipped by this function */ + /* Scan source line-by-line and process directives. Then write the .i file */ while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) { @@ -478,6 +477,16 @@ PrDoDirective ( return; } + /* + * Emit a line directive into the preprocessor file (.pre) after + * every matched directive. This is passed through to the compiler + * so that error/warning messages are kept in sync with the + * original source file. + */ + FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\" // #%s\n", + Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename, + Gbl_DirectiveInfo[Directive].Name); + /* * If we are currently ignoring this block and we encounter a #else or * #elif, we must ignore their blocks also if the parent block is also @@ -825,6 +834,9 @@ PrDoDirective ( PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE, THIS_TOKEN_OFFSET (Token)); + + Gbl_SourceLine = 0; + Gbl_NextError = Gbl_ErrorLog; break; default: @@ -863,7 +875,9 @@ PrDoDirective ( ******************************************************************************/ #define PR_NORMAL_TEXT 0 -#define PR_WITHIN_COMMENT 1 +#define PR_MULTI_LINE_COMMENT 1 +#define PR_SINGLE_LINE_COMMENT 2 +#define PR_QUOTED_STRING 3 static UINT8 AcpiGbl_LineScanState = PR_NORMAL_TEXT; @@ -904,22 +918,55 @@ PrGetNextLine ( return (ASL_EOF); } - /* We need to worry about multi-line slash-asterisk comments */ + /* Update state machine as necessary */ - /* Check for comment open */ - - if ((AcpiGbl_LineScanState == PR_NORMAL_TEXT) && - (PreviousChar == '/') && (c == '*')) + switch (AcpiGbl_LineScanState) { - AcpiGbl_LineScanState = PR_WITHIN_COMMENT; - } + case PR_NORMAL_TEXT: - /* Check for comment close */ + /* Check for multi-line comment start */ - if ((AcpiGbl_LineScanState == PR_WITHIN_COMMENT) && - (PreviousChar == '*') && (c == '/')) - { - AcpiGbl_LineScanState = PR_NORMAL_TEXT; + if ((PreviousChar == '/') && (c == '*')) + { + AcpiGbl_LineScanState = PR_MULTI_LINE_COMMENT; + } + + /* Check for single-line comment start */ + + else if ((PreviousChar == '/') && (c == '/')) + { + AcpiGbl_LineScanState = PR_SINGLE_LINE_COMMENT; + } + + /* Check for quoted string start */ + + else if (PreviousChar == '"') + { + AcpiGbl_LineScanState = PR_QUOTED_STRING; + } + break; + + case PR_QUOTED_STRING: + + if (PreviousChar == '"') + { + AcpiGbl_LineScanState = PR_NORMAL_TEXT; + } + break; + + case PR_MULTI_LINE_COMMENT: + + /* Check for multi-line comment end */ + + if ((PreviousChar == '*') && (c == '/')) + { + AcpiGbl_LineScanState = PR_NORMAL_TEXT; + } + break; + + case PR_SINGLE_LINE_COMMENT: /* Just ignore text until EOL */ + default: + break; } /* Always copy the character into line buffer */ @@ -933,10 +980,21 @@ PrGetNextLine ( { /* Handle multi-line comments */ - if (AcpiGbl_LineScanState == PR_WITHIN_COMMENT) + if (AcpiGbl_LineScanState == PR_MULTI_LINE_COMMENT) { return (ASL_WITHIN_COMMENT); } + + /* End of single-line comment */ + + if (AcpiGbl_LineScanState == PR_SINGLE_LINE_COMMENT) + { + AcpiGbl_LineScanState = PR_NORMAL_TEXT; + return (AE_OK); + } + + /* Blank line */ + if (i == 1) { return (ASL_BLANK_LINE); diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c index 0f236d2480a6..fd982815c5d1 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c +++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c @@ -86,6 +86,8 @@ AcpiDbDoOneSleepState ( UINT8 SleepState); +static char *AcpiDbTraceMethodName = NULL; + /******************************************************************************* * * FUNCTION: AcpiDbConvertToNode @@ -1226,4 +1228,88 @@ AcpiDbGenerateSci ( #endif /* !ACPI_REDUCED_HARDWARE */ + +/******************************************************************************* + * + * FUNCTION: AcpiDbTrace + * + * PARAMETERS: EnableArg - ENABLE/AML to enable tracer + * DISABLE to disable tracer + * MethodArg - Method to trace + * OnceArg - Whether trace once + * + * RETURN: None + * + * DESCRIPTION: Control method tracing facility + * + ******************************************************************************/ + +void +AcpiDbTrace ( + char *EnableArg, + char *MethodArg, + char *OnceArg) +{ + UINT32 DebugLevel = 0; + UINT32 DebugLayer = 0; + UINT32 Flags = 0; + + + if (EnableArg) + { + AcpiUtStrupr (EnableArg); + } + if (OnceArg) + { + AcpiUtStrupr (OnceArg); + } + if (MethodArg) + { + if (AcpiDbTraceMethodName) + { + ACPI_FREE (AcpiDbTraceMethodName); + AcpiDbTraceMethodName = NULL; + } + AcpiDbTraceMethodName = ACPI_ALLOCATE (strlen (MethodArg) + 1); + if (!AcpiDbTraceMethodName) + { + AcpiOsPrintf ("Failed to allocate method name (%s)\n", MethodArg); + return; + } + strcpy (AcpiDbTraceMethodName, MethodArg); + } + if (!strcmp (EnableArg, "ENABLE") || + !strcmp (EnableArg, "METHOD") || + !strcmp (EnableArg, "OPCODE")) + { + if (!strcmp (EnableArg, "ENABLE")) + { + /* Inherit current console settings */ + + DebugLevel = AcpiGbl_DbConsoleDebugLevel; + DebugLayer = AcpiDbgLayer; + } + else + { + /* Restrict console output to trace points only */ + + DebugLevel = ACPI_LV_TRACE_POINT; + DebugLayer = ACPI_EXECUTER; + } + + Flags = ACPI_TRACE_ENABLED; + if (!strcmp (EnableArg, "OPCODE")) + { + Flags |= ACPI_TRACE_OPCODE; + } + if (OnceArg && !strcmp (OnceArg, "ONCE")) + { + Flags |= ACPI_TRACE_ONESHOT; + } + } + + (void) AcpiDebugTrace (AcpiDbTraceMethodName, + DebugLevel, DebugLayer, Flags); +} + #endif /* ACPI_DEBUGGER */ diff --git a/sys/contrib/dev/acpica/components/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c index d71d21d62a8f..94080f39e010 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbdisply.c +++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c @@ -49,7 +49,6 @@ #include #include #include -#include #ifdef ACPI_DEBUGGER @@ -513,7 +512,7 @@ AcpiDbDisplayLocals ( return; } - AcpiDmDisplayLocals (WalkState); + AcpiDbDecodeLocals (WalkState); } @@ -543,7 +542,7 @@ AcpiDbDisplayArguments ( return; } - AcpiDmDisplayArguments (WalkState); + AcpiDbDecodeArguments (WalkState); } @@ -599,7 +598,7 @@ AcpiDbDisplayResults ( { ObjDesc = Frame->Results.ObjDesc[Index]; AcpiOsPrintf ("Result%u: ", i); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); if (Index == 0) { Frame = Frame->Results.Next; @@ -763,7 +762,7 @@ AcpiDbDisplayResultObject ( } AcpiOsPrintf ("ResultObj: "); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); AcpiOsPrintf ("\n"); } @@ -793,7 +792,7 @@ AcpiDbDisplayArgumentObject ( } AcpiOsPrintf ("ArgObj: "); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); } diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c index f7e59d8ae1a2..630f39920960 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbinput.c +++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c @@ -218,7 +218,7 @@ static const ACPI_DB_COMMAND_INFO AcpiGbl_DbCommands[] = {"TABLES", 0}, {"TEMPLATE", 1}, {"TERMINATE", 0}, - {"TEST", 1}, + {"TEST", 1}, {"THREADS", 3}, {"TRACE", 1}, {"TREE", 0}, @@ -270,7 +270,7 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] = {1, " Owner [Depth]", "Display loaded namespace by object owner\n"}, {1, " Paths", "Display full pathnames of namespace objects\n"}, {1, " Predefined", "Check all predefined names\n"}, - {1, " Prefix []", "Set or Get current execution prefix\n"}, + {1, " Prefix []", "Set or Get current execution prefix\n"}, {1, " References ", "Find all references to object at addr\n"}, {1, " Resources [DeviceName]", "Display Device resources (no arg = all devices)\n"}, {1, " Set N ", "Set value for named integer\n"}, @@ -297,8 +297,12 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] = {1, " Results", "Display method result stack\n"}, {1, " Set <#> ", "Set method data (Arguments/Locals)\n"}, {1, " Stop", "Terminate control method\n"}, - {1, " Thread ", "Spawn threads to execute method(s)\n"}, - {1, " Trace ", "Trace method execution\n"}, + {1, " Thread ", "Spawn threads to execute method(s)\n"}, + {5, " Trace [] [Once]", "Trace control method execution\n"}, + {1, " Enable", "Enable all messages\n"}, + {1, " Disable", "Disable tracing\n"}, + {1, " Method", "Enable method execution messages\n"}, + {1, " Opcode", "Enable opcode execution messages\n"}, {1, " Tree", "Display control method calling tree\n"}, {1, " ", "Single step next AML opcode (over calls)\n"}, @@ -749,15 +753,22 @@ AcpiDbCommandDispatch ( return (AE_CTRL_TERMINATE); } - - /* Add all commands that come here to the history buffer */ - - AcpiDbAddToHistory (InputBuffer); + /* Find command and add to the history buffer */ ParamCount = AcpiDbGetLine (InputBuffer); CommandIndex = AcpiDbMatchCommand (AcpiGbl_DbArgs[0]); Temp = 0; + /* + * We don't want to add the !! command to the history buffer. It + * would cause an infinite loop because it would always be the + * previous command. + */ + if (CommandIndex != CMD_HISTORY_LAST) + { + AcpiDbAddToHistory (InputBuffer); + } + /* Verify that we have the minimum number of params */ if (ParamCount < AcpiGbl_DbCommands[CommandIndex].MinArgs) @@ -1110,7 +1121,7 @@ AcpiDbCommandDispatch ( case CMD_TRACE: - (void) AcpiDebugTrace (AcpiGbl_DbArgs[1],0,0,1); + AcpiDbTrace (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2], AcpiGbl_DbArgs[3]); break; case CMD_TREE: diff --git a/sys/contrib/dev/acpica/components/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c index 65266c14517a..13b7bdd8fd92 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbmethod.c +++ b/sys/contrib/dev/acpica/components/debugger/dbmethod.c @@ -46,7 +46,9 @@ #include #include #include +#ifdef ACPI_DISASSEMBLER #include +#endif #include #include @@ -79,6 +81,7 @@ AcpiDbSetMethodBreakpoint ( ACPI_PARSE_OBJECT *Op) { UINT32 Address; + UINT32 AmlOffset; if (!Op) @@ -90,10 +93,12 @@ AcpiDbSetMethodBreakpoint ( /* Get and verify the breakpoint address */ Address = strtoul (Location, NULL, 16); - if (Address <= Op->Common.AmlOffset) + AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml, + WalkState->ParserState.AmlStart); + if (Address <= AmlOffset) { AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", - Address, Op->Common.AmlOffset); + Address, AmlOffset); } /* Save breakpoint in current walk */ @@ -238,7 +243,7 @@ AcpiDbSetMethodData ( ObjDesc = WalkState->Arguments[Index].Object; AcpiOsPrintf ("Arg%u: ", Index); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); break; case 'L': @@ -261,7 +266,7 @@ AcpiDbSetMethodData ( ObjDesc = WalkState->LocalVariables[Index].Object; AcpiOsPrintf ("Local%u: ", Index); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); break; default: @@ -352,7 +357,7 @@ AcpiDbDisassembleMethod ( ObjDesc = Method->Object; - Op = AcpiPsCreateScopeOp (); + Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart); if (!Op) { return (AE_NO_MEMORY); @@ -392,15 +397,16 @@ AcpiDbDisassembleMethod ( WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; Status = AcpiPsParseAml (WalkState); + +#ifdef ACPI_DISASSEMBER (void) AcpiDmParseDeferredOps (Op); /* Now we can disassemble the method */ AcpiGbl_DbOpt_Verbose = FALSE; -#ifdef ACPI_DISASSEMBLER AcpiDmDisassemble (NULL, Op, 0); -#endif AcpiGbl_DbOpt_Verbose = TRUE; +#endif AcpiPsDeleteParseTree (Op); diff --git a/sys/contrib/dev/acpica/components/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c index 67cf517b3cdd..e52064c99151 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbnames.c +++ b/sys/contrib/dev/acpica/components/debugger/dbnames.c @@ -385,7 +385,7 @@ AcpiDbWalkAndMatchName ( /* Get the full pathname to this object */ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); @@ -582,7 +582,7 @@ AcpiDbWalkForSpecificObjects ( /* Get and display the full pathname to this object */ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); @@ -886,7 +886,7 @@ AcpiDbBusWalk ( /* Get the full path to this device object */ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); diff --git a/sys/contrib/dev/acpica/components/disassembler/dmobject.c b/sys/contrib/dev/acpica/components/debugger/dbobject.c similarity index 80% rename from sys/contrib/dev/acpica/components/disassembler/dmobject.c rename to sys/contrib/dev/acpica/components/debugger/dbobject.c index 6559ec04bfec..f9f05e45c491 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmobject.c +++ b/sys/contrib/dev/acpica/components/debugger/dbobject.c @@ -1,6 +1,6 @@ /******************************************************************************* * - * Module Name: dmobject - ACPI object decode and display + * Module Name: dbobject - ACPI object decode and display * ******************************************************************************/ @@ -44,28 +44,30 @@ #include #include #include -#include - - +#include #ifdef ACPI_DISASSEMBLER +#include +#endif + + +#ifdef ACPI_DEBUGGER #define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dmnames") + ACPI_MODULE_NAME ("dbobject") /* Local prototypes */ static void -AcpiDmDecodeNode ( +AcpiDbDecodeNode ( ACPI_NAMESPACE_NODE *Node); /******************************************************************************* * - * FUNCTION: AcpiDmDumpMethodInfo + * FUNCTION: AcpiDbDumpMethodInfo * * PARAMETERS: Status - Method execution status * WalkState - Current state of the parse tree walk - * Op - Executing parse op * * RETURN: None * @@ -76,15 +78,11 @@ AcpiDmDecodeNode ( ******************************************************************************/ void -AcpiDmDumpMethodInfo ( +AcpiDbDumpMethodInfo ( ACPI_STATUS Status, - ACPI_WALK_STATE *WalkState, - ACPI_PARSE_OBJECT *Op) + ACPI_WALK_STATE *WalkState) { - ACPI_PARSE_OBJECT *Next; ACPI_THREAD_STATE *Thread; - ACPI_WALK_STATE *NextWalkState; - ACPI_NAMESPACE_NODE *PreviousMethod = NULL; /* Ignore control codes, they are not errors */ @@ -113,68 +111,19 @@ AcpiDmDumpMethodInfo ( return; } - /* Display exception and method name */ - - AcpiOsPrintf ("\n**** Exception %s during execution of method ", - AcpiFormatException (Status)); - AcpiNsPrintNodePathname (WalkState->MethodNode, NULL); - - /* Display stack of executing methods */ - - AcpiOsPrintf ("\n\nMethod Execution Stack:\n"); - NextWalkState = Thread->WalkStateList; - - /* Walk list of linked walk states */ - - while (NextWalkState) - { - AcpiOsPrintf (" Method [%4.4s] executing: ", - AcpiUtGetNodeName (NextWalkState->MethodNode)); - - /* First method is the currently executing method */ - - if (NextWalkState == WalkState) - { - if (Op) - { - /* Display currently executing ASL statement */ - - Next = Op->Common.Next; - Op->Common.Next = NULL; - - AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); - Op->Common.Next = Next; - } - } - else - { - /* - * This method has called another method - * NOTE: the method call parse subtree is already deleted at this - * point, so we cannot disassemble the method invocation. - */ - AcpiOsPrintf ("Call to method "); - AcpiNsPrintNodePathname (PreviousMethod, NULL); - } - - PreviousMethod = NextWalkState->MethodNode; - NextWalkState = NextWalkState->Next; - AcpiOsPrintf ("\n"); - } - /* Display the method locals and arguments */ AcpiOsPrintf ("\n"); - AcpiDmDisplayLocals (WalkState); + AcpiDbDecodeLocals (WalkState); AcpiOsPrintf ("\n"); - AcpiDmDisplayArguments (WalkState); + AcpiDbDecodeArguments (WalkState); AcpiOsPrintf ("\n"); } /******************************************************************************* * - * FUNCTION: AcpiDmDecodeInternalObject + * FUNCTION: AcpiDbDecodeInternalObject * * PARAMETERS: ObjDesc - Object to be displayed * @@ -185,7 +134,7 @@ AcpiDmDumpMethodInfo ( ******************************************************************************/ void -AcpiDmDecodeInternalObject ( +AcpiDbDecodeInternalObject ( ACPI_OPERAND_OBJECT *ObjDesc) { UINT32 i; @@ -247,7 +196,7 @@ AcpiDmDecodeInternalObject ( /******************************************************************************* * - * FUNCTION: AcpiDmDecodeNode + * FUNCTION: AcpiDbDecodeNode * * PARAMETERS: Node - Object to be displayed * @@ -258,7 +207,7 @@ AcpiDmDecodeInternalObject ( ******************************************************************************/ static void -AcpiDmDecodeNode ( +AcpiDbDecodeNode ( ACPI_NAMESPACE_NODE *Node) { @@ -290,7 +239,7 @@ AcpiDmDecodeNode ( default: - AcpiDmDecodeInternalObject (AcpiNsGetAttachedObject (Node)); + AcpiDbDecodeInternalObject (AcpiNsGetAttachedObject (Node)); break; } } @@ -298,7 +247,7 @@ AcpiDmDecodeNode ( /******************************************************************************* * - * FUNCTION: AcpiDmDisplayInternalObject + * FUNCTION: AcpiDbDisplayInternalObject * * PARAMETERS: ObjDesc - Object to be displayed * WalkState - Current walk state @@ -310,7 +259,7 @@ AcpiDmDecodeNode ( ******************************************************************************/ void -AcpiDmDisplayInternalObject ( +AcpiDbDisplayInternalObject ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { @@ -336,7 +285,7 @@ AcpiDmDisplayInternalObject ( case ACPI_DESC_TYPE_NAMED: - AcpiDmDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc); + AcpiDbDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc); break; case ACPI_DESC_TYPE_OPERAND: @@ -368,7 +317,7 @@ AcpiDmDisplayInternalObject ( ObjDesc = WalkState->LocalVariables [ObjDesc->Reference.Value].Object; AcpiOsPrintf ("%p", ObjDesc); - AcpiDmDecodeInternalObject (ObjDesc); + AcpiDbDecodeInternalObject (ObjDesc); } break; @@ -380,7 +329,7 @@ AcpiDmDisplayInternalObject ( ObjDesc = WalkState->Arguments [ObjDesc->Reference.Value].Object; AcpiOsPrintf ("%p", ObjDesc); - AcpiDmDecodeInternalObject (ObjDesc); + AcpiDbDecodeInternalObject (ObjDesc); } break; @@ -391,7 +340,7 @@ AcpiDmDisplayInternalObject ( case ACPI_TYPE_BUFFER_FIELD: AcpiOsPrintf ("%p", ObjDesc->Reference.Object); - AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); + AcpiDbDecodeInternalObject (ObjDesc->Reference.Object); break; case ACPI_TYPE_PACKAGE: @@ -403,7 +352,7 @@ AcpiDmDisplayInternalObject ( } else { - AcpiDmDecodeInternalObject ( + AcpiDbDecodeInternalObject ( *(ObjDesc->Reference.Where)); } break; @@ -428,11 +377,11 @@ AcpiDmDisplayInternalObject ( switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object)) { case ACPI_DESC_TYPE_NAMED: - AcpiDmDecodeNode (ObjDesc->Reference.Object); + AcpiDbDecodeNode (ObjDesc->Reference.Object); break; case ACPI_DESC_TYPE_OPERAND: - AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); + AcpiDbDecodeInternalObject (ObjDesc->Reference.Object); break; default: @@ -442,7 +391,7 @@ AcpiDmDisplayInternalObject ( case ACPI_REFCLASS_NAME: - AcpiDmDecodeNode (ObjDesc->Reference.Node); + AcpiDbDecodeNode (ObjDesc->Reference.Node); break; case ACPI_REFCLASS_DEBUG: @@ -461,7 +410,7 @@ AcpiDmDisplayInternalObject ( default: AcpiOsPrintf (" "); - AcpiDmDecodeInternalObject (ObjDesc); + AcpiDbDecodeInternalObject (ObjDesc); break; } break; @@ -479,7 +428,7 @@ AcpiDmDisplayInternalObject ( /******************************************************************************* * - * FUNCTION: AcpiDmDisplayLocals + * FUNCTION: AcpiDbDecodeLocals * * PARAMETERS: WalkState - State for current method * @@ -490,7 +439,7 @@ AcpiDmDisplayInternalObject ( ******************************************************************************/ void -AcpiDmDisplayLocals ( +AcpiDbDecodeLocals ( ACPI_WALK_STATE *WalkState) { UINT32 i; @@ -520,14 +469,14 @@ AcpiDmDisplayLocals ( { ObjDesc = WalkState->LocalVariables[i].Object; AcpiOsPrintf (" Local%X: ", i); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); } } /******************************************************************************* * - * FUNCTION: AcpiDmDisplayArguments + * FUNCTION: AcpiDbDecodeArguments * * PARAMETERS: WalkState - State for current method * @@ -538,7 +487,7 @@ AcpiDmDisplayLocals ( ******************************************************************************/ void -AcpiDmDisplayArguments ( +AcpiDbDecodeArguments ( ACPI_WALK_STATE *WalkState) { UINT32 i; @@ -569,7 +518,7 @@ AcpiDmDisplayArguments ( { ObjDesc = WalkState->Arguments[i].Object; AcpiOsPrintf (" Arg%u: ", i); - AcpiDmDisplayInternalObject (ObjDesc, WalkState); + AcpiDbDisplayInternalObject (ObjDesc, WalkState); } } diff --git a/sys/contrib/dev/acpica/components/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c index eeb5f82a7819..16ec190b0386 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbutils.c +++ b/sys/contrib/dev/acpica/components/debugger/dbutils.c @@ -45,7 +45,6 @@ #include #include #include -#include #ifdef ACPI_DEBUGGER @@ -223,7 +222,7 @@ AcpiDbDumpExternalObject ( case ACPI_TYPE_LOCAL_REFERENCE: AcpiOsPrintf ("[Object Reference] = "); - AcpiDmDisplayInternalObject (ObjDesc->Reference.Handle, NULL); + AcpiDbDisplayInternalObject (ObjDesc->Reference.Handle, NULL); break; case ACPI_TYPE_PROCESSOR: diff --git a/sys/contrib/dev/acpica/components/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c index 6609962105ad..2425929c3c55 100644 --- a/sys/contrib/dev/acpica/components/debugger/dbxface.c +++ b/sys/contrib/dev/acpica/components/debugger/dbxface.c @@ -45,7 +45,9 @@ #include #include #include +#ifdef ACPI_DISASSEMBLER #include +#endif #ifdef ACPI_DEBUGGER @@ -179,6 +181,7 @@ AcpiDbSingleStep ( UINT32 OriginalDebugLevel; ACPI_PARSE_OBJECT *DisplayOp; ACPI_PARSE_OBJECT *ParentOp; + UINT32 AmlOffset; ACPI_FUNCTION_ENTRY (); @@ -192,15 +195,18 @@ AcpiDbSingleStep ( return (AE_ABORT_METHOD); } + AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml, + WalkState->ParserState.AmlStart); + /* Check for single-step breakpoint */ if (WalkState->MethodBreakpoint && - (WalkState->MethodBreakpoint <= Op->Common.AmlOffset)) + (WalkState->MethodBreakpoint <= AmlOffset)) { /* Check if the breakpoint has been reached or passed */ /* Hit the breakpoint, resume single step, reset breakpoint */ - AcpiOsPrintf ("***Break*** at AML offset %X\n", Op->Common.AmlOffset); + AcpiOsPrintf ("***Break*** at AML offset %X\n", AmlOffset); AcpiGbl_CmSingleStep = TRUE; AcpiGbl_StepToNextCall = FALSE; WalkState->MethodBreakpoint = 0; @@ -209,10 +215,10 @@ AcpiDbSingleStep ( /* Check for user breakpoint (Must be on exact Aml offset) */ else if (WalkState->UserBreakpoint && - (WalkState->UserBreakpoint == Op->Common.AmlOffset)) + (WalkState->UserBreakpoint == AmlOffset)) { AcpiOsPrintf ("***UserBreakpoint*** at AML offset %X\n", - Op->Common.AmlOffset); + AmlOffset); AcpiGbl_CmSingleStep = TRUE; AcpiGbl_StepToNextCall = FALSE; WalkState->MethodBreakpoint = 0; @@ -425,7 +431,7 @@ AcpiDbInitialize ( AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; AcpiGbl_DbOpt_Disasm = FALSE; -#ifdef ACPI_DISASSEMBLER +#ifndef _KERNEL AcpiGbl_DbOpt_Verbose = TRUE; #endif AcpiGbl_DbOpt_NoIniMethods = FALSE; @@ -476,7 +482,7 @@ AcpiDbInitialize ( } } -#ifdef ACPI_DISASSEMBLER +#ifndef _KERNEL if (!AcpiGbl_DbOpt_Verbose) { AcpiGbl_DbOpt_Disasm = TRUE; diff --git a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c index 9bf7451ed951..f1597e35bf7a 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c @@ -165,7 +165,6 @@ AcpiDmDeferredParse ( ACPI_STATUS Status; ACPI_PARSE_OBJECT *SearchOp; ACPI_PARSE_OBJECT *StartOp; - UINT32 BaseAmlOffset; ACPI_PARSE_OBJECT *NewRootOp; ACPI_PARSE_OBJECT *ExtraOp; @@ -202,19 +201,10 @@ AcpiDmDeferredParse ( WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; Status = AcpiPsParseAml (WalkState); - /* - * We need to update all of the AML offsets, since the parser thought - * that the method began at offset zero. In reality, it began somewhere - * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that - * was just created and update the AmlOffset in each Op. - */ - BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1; StartOp = (Op->Common.Value.Arg)->Common.Next; SearchOp = StartOp; - while (SearchOp) { - SearchOp->Common.AmlOffset += BaseAmlOffset; SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); } diff --git a/sys/contrib/dev/acpica/components/disassembler/dmnames.c b/sys/contrib/dev/acpica/components/disassembler/dmnames.c index 07a90ffd9992..98d4679defbb 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmnames.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmnames.c @@ -179,7 +179,7 @@ AcpiPsDisplayObjectPathname ( /* Convert NamedDesc/handle to a full pathname */ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (Node, &Buffer); + Status = AcpiNsHandleToPathname (Node, &Buffer, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("****Could not get pathname****)"); diff --git a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c index 6b7c1f5ac7fa..f76e42081168 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c @@ -48,6 +48,7 @@ #include #include #include +#include #ifdef ACPI_DISASSEMBLER @@ -967,7 +968,7 @@ AcpiDmDisassembleOneOp ( (WalkState->Results) && (WalkState->ResultCount)) { - AcpiDmDecodeInternalObject ( + AcpiDbDecodeInternalObject ( WalkState->Results->Results.ObjDesc [ (WalkState->ResultCount - 1) % ACPI_RESULTS_FRAME_OBJ_NUM]); diff --git a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c index 2dbaa8488150..da8c88b41b9a 100644 --- a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c @@ -313,6 +313,8 @@ AcpiDmBlockType ( return (BLOCK_NONE); } + /*lint -fallthrough */ + default: OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); @@ -410,8 +412,24 @@ AcpiDmDescendingOp ( const ACPI_OPCODE_INFO *OpInfo; UINT32 Name; ACPI_PARSE_OBJECT *NextOp; + UINT32 AmlOffset; + if (AcpiGbl_DbOpt_Verbose && AcpiGbl_PreviousOp) + { + /* Dump the entire statement in AML byte code */ + + if (Op->Common.Aml > AcpiGbl_PreviousOp->Common.Aml) + { + AcpiOsPrintf ("\n"); + AcpiUtDumpBuffer (AcpiGbl_PreviousOp->Common.Aml, + (Op->Common.Aml - AcpiGbl_PreviousOp->Common.Aml), + DB_BYTE_DISPLAY, 0); + AcpiDmIndent (Level); + } + } + AcpiGbl_PreviousOp = Op; + if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) { /* Ignore this op -- it was handled elsewhere */ @@ -427,10 +445,12 @@ AcpiDmDescendingOp ( if (Info->WalkState) { + AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml, + Info->WalkState->ParserState.AmlStart); VERBOSE_PRINT ((DB_FULL_OP_INFO, (Info->WalkState->MethodNode ? Info->WalkState->MethodNode->Name.Ascii : " "), - Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode)); + AmlOffset, (UINT32) Op->Common.AmlOpcode)); } if (Op->Common.AmlOpcode == AML_SCOPE_OP) diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c index 254f704c96a7..a3be06b8d7f3 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c @@ -94,7 +94,7 @@ AcpiDsExecuteArguments ( /* Allocate a new parser op to be the root of the parsed tree */ - Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); + Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP, AmlStart); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -141,7 +141,7 @@ AcpiDsExecuteArguments ( /* Evaluate the deferred arguments */ - Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); + Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP, AmlStart); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c b/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c new file mode 100644 index 000000000000..9fab3da87a74 --- /dev/null +++ b/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c @@ -0,0 +1,249 @@ +/****************************************************************************** + * + * Module Name: dsdebug - Parser/Interpreter interface - debugging + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsdebug") + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Local prototypes */ + +static void +AcpiDsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Message); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsPrintNodePathname + * + * PARAMETERS: Node - Object + * Message - Prefix message + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +static void +AcpiDsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Message) +{ + ACPI_BUFFER Buffer; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (DsPrintNodePathname); + + if (!Node) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[NULL NAME]")); + return_VOID; + } + + /* Convert handle to full pathname and print it (with supplied message) */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + Status = AcpiNsHandleToPathname (Node, &Buffer, FALSE); + if (ACPI_SUCCESS (Status)) + { + if (Message) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "%s ", Message)); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[%s] (Node %p)", + (char *) Buffer.Pointer, Node)); + ACPI_FREE (Buffer.Pointer); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsDumpMethodStack + * + * PARAMETERS: Status - Method execution status + * WalkState - Current state of the parse tree walk + * Op - Executing parse op + * + * RETURN: None + * + * DESCRIPTION: Called when a method has been aborted because of an error. + * Dumps the method execution stack. + * + ******************************************************************************/ + +void +AcpiDsDumpMethodStack ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *Next; + ACPI_THREAD_STATE *Thread; + ACPI_WALK_STATE *NextWalkState; + ACPI_NAMESPACE_NODE *PreviousMethod = NULL; + ACPI_OPERAND_OBJECT *MethodDesc; + + + ACPI_FUNCTION_TRACE (DsDumpMethodStack); + + /* Ignore control codes, they are not errors */ + + if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL) + { + return_VOID; + } + + /* We may be executing a deferred opcode */ + + if (WalkState->DeferredNode) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Executing subtree for Buffer/Package/Region\n")); + return_VOID; + } + + /* + * If there is no Thread, we are not actually executing a method. + * This can happen when the iASL compiler calls the interpreter + * to perform constant folding. + */ + Thread = WalkState->Thread; + if (!Thread) + { + return_VOID; + } + + /* Display exception and method name */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "\n**** Exception %s during execution of method ", + AcpiFormatException (Status))); + AcpiDsPrintNodePathname (WalkState->MethodNode, NULL); + + /* Display stack of executing methods */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, + "\n\nMethod Execution Stack:\n")); + NextWalkState = Thread->WalkStateList; + + /* Walk list of linked walk states */ + + while (NextWalkState) + { + MethodDesc = NextWalkState->MethodDesc; + if (MethodDesc) + { + AcpiExStopTraceMethod ( + (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, + MethodDesc, WalkState); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + " Method [%4.4s] executing: ", + AcpiUtGetNodeName (NextWalkState->MethodNode))); + + /* First method is the currently executing method */ + + if (NextWalkState == WalkState) + { + if (Op) + { + /* Display currently executing ASL statement */ + + Next = Op->Common.Next; + Op->Common.Next = NULL; + +#ifdef ACPI_DISASSEMBLER + AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); +#endif + Op->Common.Next = Next; + } + } + else + { + /* + * This method has called another method + * NOTE: the method call parse subtree is already deleted at this + * point, so we cannot disassemble the method invocation. + */ + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method ")); + AcpiDsPrintNodePathname (PreviousMethod, NULL); + } + + PreviousMethod = NextWalkState->MethodNode; + NextWalkState = NextWalkState->Next; + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n")); + } + + return_VOID; +} + +#else + +void +AcpiDsDumpMethodStack ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + return; +} + +#endif diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c index 9845025da0e1..eafe1a5383a8 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c @@ -46,9 +46,9 @@ #include #include #include -#include #include #include +#include #define _COMPONENT ACPI_DISPATCHER @@ -109,7 +109,7 @@ AcpiDsAutoSerializeMethod ( /* Create/Init a root op for the method parse tree */ - Op = AcpiPsAllocOp (AML_METHOD_OP); + Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -213,7 +213,7 @@ AcpiDsDetectNamedOpcodes ( * RETURN: Status * * DESCRIPTION: Called on method error. Invoke the global exception handler if - * present, dump the method data if the disassembler is configured + * present, dump the method data if the debugger is configured * * Note: Allows the exception handler to change the status code * @@ -224,6 +224,9 @@ AcpiDsMethodError ( ACPI_STATUS Status, ACPI_WALK_STATE *WalkState) { + UINT32 AmlOffset; + + ACPI_FUNCTION_ENTRY (); @@ -247,23 +250,28 @@ AcpiDsMethodError ( * Handler can map the exception code to anything it wants, including * AE_OK, in which case the executing method will not be aborted. */ + AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, + WalkState->ParserState.AmlStart); + Status = AcpiGbl_ExceptionHandler (Status, WalkState->MethodNode ? WalkState->MethodNode->Name.Integer : 0, - WalkState->Opcode, WalkState->AmlOffset, NULL); + WalkState->Opcode, AmlOffset, NULL); AcpiExEnterInterpreter (); } AcpiDsClearImplicitReturn (WalkState); -#ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE (Status)) { - /* Display method locals/args if disassembler is present */ + AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op); - AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op); - } + /* Display method locals/args if debugger is present */ + +#ifdef ACPI_DEBUGGER + AcpiDbDumpMethodInfo (Status, WalkState); #endif + } return (Status); } @@ -349,6 +357,8 @@ AcpiDsBeginMethodExecution ( return_ACPI_STATUS (AE_NULL_ENTRY); } + AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState); + /* Prevent wraparound of thread count */ if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) @@ -610,10 +620,7 @@ AcpiDsCallControlMethod ( /* On error, we must terminate the method properly */ AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); - if (NextWalkState) - { - AcpiDsDeleteWalkState (NextWalkState); - } + AcpiDsDeleteWalkState (NextWalkState); return_ACPI_STATUS (Status); } @@ -870,5 +877,8 @@ AcpiDsTerminateControlMethod ( } } + AcpiExStopTraceMethod ((ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, + MethodDesc, WalkState); + return_VOID; } diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c index 755b15ef296d..c9b512453a20 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dswload.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dswload.c @@ -398,7 +398,7 @@ AcpiDsLoad1BeginOp ( { /* Create a new op */ - Op = AcpiPsAllocOp (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c index 472877494bb3..b244263d12de 100644 --- a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c +++ b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c @@ -344,7 +344,7 @@ AcpiDsLoad2BeginOp ( { /* Create a new op */ - Op = AcpiPsAllocOp (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/components/executer/excreate.c b/sys/contrib/dev/acpica/components/executer/excreate.c index a855f200a86d..9f3f2cca2d04 100644 --- a/sys/contrib/dev/acpica/components/executer/excreate.c +++ b/sys/contrib/dev/acpica/components/executer/excreate.c @@ -526,6 +526,7 @@ AcpiExCreateMethod ( ObjDesc->Method.AmlStart = AmlStart; ObjDesc->Method.AmlLength = AmlLength; + ObjDesc->Method.Node = Operand[0]; /* * Disassemble the method flags. Split off the ArgCount, Serialized diff --git a/sys/contrib/dev/acpica/components/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c index d174ccdde2c4..6acda901188d 100644 --- a/sys/contrib/dev/acpica/components/executer/exdebug.c +++ b/sys/contrib/dev/acpica/components/executer/exdebug.c @@ -43,13 +43,26 @@ #include #include +#include #include +#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exdebug") +static ACPI_OPERAND_OBJECT *AcpiGbl_TraceMethodObject = NULL; + +/* Local prototypes */ + +#ifdef ACPI_DEBUG_OUTPUT +static const char * +AcpiExGetTraceEventName ( + ACPI_TRACE_EVENT_TYPE Type); +#endif + + #ifndef ACPI_NO_ERROR_MESSAGES /******************************************************************************* * @@ -314,3 +327,362 @@ AcpiExDoDebugObject ( return_VOID; } #endif + + +/******************************************************************************* + * + * FUNCTION: AcpiExInterpreterTraceEnabled + * + * PARAMETERS: Name - Whether method name should be matched, + * this should be checked before starting + * the tracer + * + * RETURN: TRUE if interpreter trace is enabled. + * + * DESCRIPTION: Check whether interpreter trace is enabled + * + ******************************************************************************/ + +static BOOLEAN +AcpiExInterpreterTraceEnabled ( + char *Name) +{ + + /* Check if tracing is enabled */ + + if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED)) + { + return (FALSE); + } + + /* + * Check if tracing is filtered: + * + * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have + * been filled by the trace starter + * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be + * matched if it is specified + * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should + * not be cleared by the trace stopper during the first match + */ + if (AcpiGbl_TraceMethodObject) + { + return (TRUE); + } + if (Name && + (AcpiGbl_TraceMethodName && + strcmp (AcpiGbl_TraceMethodName, Name))) + { + return (FALSE); + } + if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) && + !AcpiGbl_TraceMethodName) + { + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExGetTraceEventName + * + * PARAMETERS: Type - Trace event type + * + * RETURN: Trace event name. + * + * DESCRIPTION: Used to obtain the full trace event name. + * + ******************************************************************************/ + +#ifdef ACPI_DEBUG_OUTPUT + +static const char * +AcpiExGetTraceEventName ( + ACPI_TRACE_EVENT_TYPE Type) +{ + switch (Type) + { + case ACPI_TRACE_AML_METHOD: + + return "Method"; + + case ACPI_TRACE_AML_OPCODE: + + return "Opcode"; + + case ACPI_TRACE_AML_REGION: + + return "Region"; + + default: + + return ""; + } +} + +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiExTracePoint + * + * PARAMETERS: Type - Trace event type + * Begin - TRUE if before execution + * Aml - Executed AML address + * Pathname - Object path + * + * RETURN: None + * + * DESCRIPTION: Internal interpreter execution trace. + * + ******************************************************************************/ + +void +AcpiExTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname) +{ + + ACPI_FUNCTION_NAME (ExTracePoint); + + + if (Pathname) + { + ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, + "%s %s [0x%p:%s] execution.\n", + AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", + Aml, Pathname)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, + "%s %s [0x%p] execution.\n", + AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", + Aml)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStartTraceMethod + * + * PARAMETERS: MethodNode - Node of the method + * ObjDesc - The method object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +void +AcpiExStartTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + char *Pathname = NULL; + BOOLEAN Enabled = FALSE; + + + ACPI_FUNCTION_NAME (ExStartTraceMethod); + + + if (MethodNode) + { + Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + Enabled = AcpiExInterpreterTraceEnabled (Pathname); + if (Enabled && !AcpiGbl_TraceMethodObject) + { + AcpiGbl_TraceMethodObject = ObjDesc; + AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; + AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; + AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL; + AcpiDbgLayer = ACPI_TRACE_LAYER_ALL; + + if (AcpiGbl_TraceDbgLevel) + { + AcpiDbgLevel = AcpiGbl_TraceDbgLevel; + } + if (AcpiGbl_TraceDbgLayer) + { + AcpiDbgLayer = AcpiGbl_TraceDbgLayer; + } + } + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + +Exit: + if (Enabled) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE, + ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); + } + if (Pathname) + { + ACPI_FREE (Pathname); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStopTraceMethod + * + * PARAMETERS: MethodNode - Node of the method + * ObjDesc - The method object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +void +AcpiExStopTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + char *Pathname = NULL; + BOOLEAN Enabled; + + + ACPI_FUNCTION_NAME (ExStopTraceMethod); + + + if (MethodNode) + { + Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto ExitPath; + } + + Enabled = AcpiExInterpreterTraceEnabled (NULL); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + if (Enabled) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, + ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + goto ExitPath; + } + + /* Check whether the tracer should be stopped */ + + if (AcpiGbl_TraceMethodObject == ObjDesc) + { + /* Disable further tracing if type is one-shot */ + + if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) + { + AcpiGbl_TraceMethodName = NULL; + } + + AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; + AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; + AcpiGbl_TraceMethodObject = NULL; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + +ExitPath: + if (Pathname) + { + ACPI_FREE (Pathname); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStartTraceOpcode + * + * PARAMETERS: Op - The parser opcode object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start opcode execution trace + * + ******************************************************************************/ + +void +AcpiExStartTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_NAME (ExStartTraceOpcode); + + + if (AcpiExInterpreterTraceEnabled (NULL) && + (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE, + Op->Common.Aml, Op->Common.AmlOpName); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStopTraceOpcode + * + * PARAMETERS: Op - The parser opcode object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop opcode execution trace + * + ******************************************************************************/ + +void +AcpiExStopTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_NAME (ExStopTraceOpcode); + + + if (AcpiExInterpreterTraceEnabled (NULL) && + (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE, + Op->Common.Aml, Op->Common.AmlOpName); + } +} diff --git a/sys/contrib/dev/acpica/components/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c index 1a14d384c05f..bfb66a6f3818 100644 --- a/sys/contrib/dev/acpica/components/executer/exdump.c +++ b/sys/contrib/dev/acpica/components/executer/exdump.c @@ -1039,7 +1039,8 @@ AcpiExDumpReferenceObj ( { AcpiOsPrintf (" %p ", ObjDesc->Reference.Node); - Status = AcpiNsHandleToPathname (ObjDesc->Reference.Node, &RetBuf); + Status = AcpiNsHandleToPathname (ObjDesc->Reference.Node, + &RetBuf, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf (" Could not convert name to pathname\n"); diff --git a/sys/contrib/dev/acpica/components/namespace/nsnames.c b/sys/contrib/dev/acpica/components/namespace/nsnames.c index edd651745a53..047cc8db9a3e 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsnames.c +++ b/sys/contrib/dev/acpica/components/namespace/nsnames.c @@ -51,82 +51,6 @@ ACPI_MODULE_NAME ("nsnames") -/******************************************************************************* - * - * FUNCTION: AcpiNsBuildExternalPath - * - * PARAMETERS: Node - NS node whose pathname is needed - * Size - Size of the pathname - * *NameBuffer - Where to return the pathname - * - * RETURN: Status - * Places the pathname into the NameBuffer, in external format - * (name segments separated by path separators) - * - * DESCRIPTION: Generate a full pathaname - * - ******************************************************************************/ - -ACPI_STATUS -AcpiNsBuildExternalPath ( - ACPI_NAMESPACE_NODE *Node, - ACPI_SIZE Size, - char *NameBuffer) -{ - ACPI_SIZE Index; - ACPI_NAMESPACE_NODE *ParentNode; - - - ACPI_FUNCTION_ENTRY (); - - - /* Special case for root */ - - Index = Size - 1; - if (Index < ACPI_NAME_SIZE) - { - NameBuffer[0] = AML_ROOT_PREFIX; - NameBuffer[1] = 0; - return (AE_OK); - } - - /* Store terminator byte, then build name backwards */ - - ParentNode = Node; - NameBuffer[Index] = 0; - - while ((Index > ACPI_NAME_SIZE) && (ParentNode != AcpiGbl_RootNode)) - { - Index -= ACPI_NAME_SIZE; - - /* Put the name into the buffer */ - - ACPI_MOVE_32_TO_32 ((NameBuffer + Index), &ParentNode->Name); - ParentNode = ParentNode->Parent; - - /* Prefix name with the path separator */ - - Index--; - NameBuffer[Index] = ACPI_PATH_SEPARATOR; - } - - /* Overwrite final separator with the root prefix character */ - - NameBuffer[Index] = AML_ROOT_PREFIX; - - if (Index != 0) - { - ACPI_ERROR ((AE_INFO, - "Could not construct external pathname; index=%u, size=%u, Path=%s", - (UINT32) Index, (UINT32) Size, &NameBuffer[Size])); - - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - - /******************************************************************************* * * FUNCTION: AcpiNsGetExternalPathname @@ -146,39 +70,13 @@ char * AcpiNsGetExternalPathname ( ACPI_NAMESPACE_NODE *Node) { - ACPI_STATUS Status; char *NameBuffer; - ACPI_SIZE Size; ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname, Node); - /* Calculate required buffer size based on depth below root */ - - Size = AcpiNsGetPathnameLength (Node); - if (!Size) - { - return_PTR (NULL); - } - - /* Allocate a buffer to be returned to caller */ - - NameBuffer = ACPI_ALLOCATE_ZEROED (Size); - if (!NameBuffer) - { - ACPI_ERROR ((AE_INFO, "Could not allocate %u bytes", (UINT32) Size)); - return_PTR (NULL); - } - - /* Build the path in the allocated buffer */ - - Status = AcpiNsBuildExternalPath (Node, Size, NameBuffer); - if (ACPI_FAILURE (Status)) - { - ACPI_FREE (NameBuffer); - return_PTR (NULL); - } + NameBuffer = AcpiNsGetNormalizedPathname (Node, FALSE); return_PTR (NameBuffer); } @@ -201,38 +99,14 @@ AcpiNsGetPathnameLength ( ACPI_NAMESPACE_NODE *Node) { ACPI_SIZE Size; - ACPI_NAMESPACE_NODE *NextNode; ACPI_FUNCTION_ENTRY (); - /* - * Compute length of pathname as 5 * number of name segments. - * Go back up the parent tree to the root - */ - Size = 0; - NextNode = Node; + Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, FALSE); - while (NextNode && (NextNode != AcpiGbl_RootNode)) - { - if (ACPI_GET_DESCRIPTOR_TYPE (NextNode) != ACPI_DESC_TYPE_NAMED) - { - ACPI_ERROR ((AE_INFO, - "Invalid Namespace Node (%p) while traversing namespace", - NextNode)); - return (0); - } - Size += ACPI_PATH_SEGMENT_LENGTH; - NextNode = NextNode->Parent; - } - - if (!Size) - { - Size = 1; /* Root node case */ - } - - return (Size + 1); /* +1 for null string terminator */ + return (Size); } @@ -243,6 +117,8 @@ AcpiNsGetPathnameLength ( * PARAMETERS: TargetHandle - Handle of named object whose name is * to be found * Buffer - Where the pathname is returned + * NoTrailing - Remove trailing '_' for each name + * segment * * RETURN: Status, Buffer is filled with pathname if status is AE_OK * @@ -253,7 +129,8 @@ AcpiNsGetPathnameLength ( ACPI_STATUS AcpiNsHandleToPathname ( ACPI_HANDLE TargetHandle, - ACPI_BUFFER *Buffer) + ACPI_BUFFER *Buffer, + BOOLEAN NoTrailing) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; @@ -271,7 +148,7 @@ AcpiNsHandleToPathname ( /* Determine size required for the caller buffer */ - RequiredSize = AcpiNsGetPathnameLength (Node); + RequiredSize = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); if (!RequiredSize) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -287,7 +164,8 @@ AcpiNsHandleToPathname ( /* Build the path in the caller buffer */ - Status = AcpiNsBuildExternalPath (Node, RequiredSize, Buffer->Pointer); + (void) AcpiNsBuildNormalizedPath (Node, Buffer->Pointer, + RequiredSize, NoTrailing); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); @@ -297,3 +175,169 @@ AcpiNsHandleToPathname ( (char *) Buffer->Pointer, (UINT32) RequiredSize)); return_ACPI_STATUS (AE_OK); } + + +/******************************************************************************* + * + * FUNCTION: AcpiNsBuildNormalizedPath + * + * PARAMETERS: Node - Namespace node + * FullPath - Where the path name is returned + * PathSize - Size of returned path name buffer + * NoTrailing - Remove trailing '_' from each name segment + * + * RETURN: Return 1 if the AML path is empty, otherwise returning (length + * of pathname + 1) which means the 'FullPath' contains a trailing + * null. + * + * DESCRIPTION: Build and return a full namespace pathname. + * Note that if the size of 'FullPath' isn't large enough to + * contain the namespace node's path name, the actual required + * buffer length is returned, and it should be greater than + * 'PathSize'. So callers are able to check the returning value + * to determine the buffer size of 'FullPath'. + * + ******************************************************************************/ + +UINT32 +AcpiNsBuildNormalizedPath ( + ACPI_NAMESPACE_NODE *Node, + char *FullPath, + UINT32 PathSize, + BOOLEAN NoTrailing) +{ + UINT32 Length = 0, i; + char Name[ACPI_NAME_SIZE]; + BOOLEAN DoNoTrailing; + char c, *Left, *Right; + ACPI_NAMESPACE_NODE *NextNode; + + + ACPI_FUNCTION_TRACE_PTR (NsBuildNormalizedPath, Node); + + +#define ACPI_PATH_PUT8(Path, Size, Byte, Length) \ + do { \ + if ((Length) < (Size)) \ + { \ + (Path)[(Length)] = (Byte); \ + } \ + (Length)++; \ + } while (0) + + /* + * Make sure the PathSize is correct, so that we don't need to + * validate both FullPath and PathSize. + */ + if (!FullPath) + { + PathSize = 0; + } + + if (!Node) + { + goto BuildTrailingNull; + } + + NextNode = Node; + while (NextNode && NextNode != AcpiGbl_RootNode) + { + if (NextNode != Node) + { + ACPI_PATH_PUT8(FullPath, PathSize, AML_DUAL_NAME_PREFIX, Length); + } + ACPI_MOVE_32_TO_32 (Name, &NextNode->Name); + DoNoTrailing = NoTrailing; + for (i = 0; i < 4; i++) + { + c = Name[4-i-1]; + if (DoNoTrailing && c != '_') + { + DoNoTrailing = FALSE; + } + if (!DoNoTrailing) + { + ACPI_PATH_PUT8(FullPath, PathSize, c, Length); + } + } + NextNode = NextNode->Parent; + } + ACPI_PATH_PUT8(FullPath, PathSize, AML_ROOT_PREFIX, Length); + + /* Reverse the path string */ + + if (Length <= PathSize) + { + Left = FullPath; + Right = FullPath+Length-1; + while (Left < Right) + { + c = *Left; + *Left++ = *Right; + *Right-- = c; + } + } + + /* Append the trailing null */ + +BuildTrailingNull: + ACPI_PATH_PUT8(FullPath, PathSize, '\0', Length); + +#undef ACPI_PATH_PUT8 + + return_UINT32 (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNormalizedPathname + * + * PARAMETERS: Node - Namespace node whose pathname is needed + * NoTrailing - Remove trailing '_' from each name segment + * + * RETURN: Pointer to storage containing the fully qualified name of + * the node, In external format (name segments separated by path + * separators.) + * + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. All trailing '_' will be + * removed from the full pathname if 'NoTrailing' is specified.. + * + ******************************************************************************/ + +char * +AcpiNsGetNormalizedPathname ( + ACPI_NAMESPACE_NODE *Node, + BOOLEAN NoTrailing) +{ + char *NameBuffer; + ACPI_SIZE Size; + + + ACPI_FUNCTION_TRACE_PTR (NsGetNormalizedPathname, Node); + + + /* Calculate required buffer size based on depth below root */ + + Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); + if (!Size) + { + return_PTR (NULL); + } + + /* Allocate a buffer to be returned to caller */ + + NameBuffer = ACPI_ALLOCATE_ZEROED (Size); + if (!NameBuffer) + { + ACPI_ERROR ((AE_INFO, "Could not allocate %u bytes", (UINT32) Size)); + return_PTR (NULL); + } + + /* Build the path in the allocated buffer */ + + (void) AcpiNsBuildNormalizedPath (Node, NameBuffer, Size, NoTrailing); + + return_PTR (NameBuffer); +} diff --git a/sys/contrib/dev/acpica/components/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c index 7c6d29ad13dd..a05567ff1356 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsparse.c +++ b/sys/contrib/dev/acpica/components/namespace/nsparse.c @@ -84,6 +84,22 @@ AcpiNsOneCompleteParse ( ACPI_FUNCTION_TRACE (NsOneCompleteParse); + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Table must consist of at least a complete header */ + + if (Table->Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_BAD_HEADER); + } + + AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER); + AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); if (ACPI_FAILURE (Status)) { @@ -92,7 +108,7 @@ AcpiNsOneCompleteParse ( /* Create and init a Root Node */ - ParseRoot = AcpiPsCreateScopeOp (); + ParseRoot = AcpiPsCreateScopeOp (AmlStart); if (!ParseRoot) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -107,26 +123,12 @@ AcpiNsOneCompleteParse ( return_ACPI_STATUS (AE_NO_MEMORY); } - Status = AcpiGetTableByIndex (TableIndex, &Table); + Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL, + AmlStart, AmlLength, NULL, (UINT8) PassNumber); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); - AcpiPsFreeOp (ParseRoot); - return_ACPI_STATUS (Status); - } - - /* Table must consist of at least a complete header */ - - if (Table->Length < sizeof (ACPI_TABLE_HEADER)) - { - Status = AE_BAD_HEADER; - } - else - { - AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER); - AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); - Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL, - AmlStart, AmlLength, NULL, (UINT8) PassNumber); + goto Cleanup; } /* Found OSDT table, enable the namespace override feature */ @@ -137,12 +139,6 @@ AcpiNsOneCompleteParse ( WalkState->NamespaceOverride = TRUE; } - if (ACPI_FAILURE (Status)) - { - AcpiDsDeleteWalkState (WalkState); - goto Cleanup; - } - /* StartNode is the default location to load the table */ if (StartNode && StartNode != AcpiGbl_RootNode) diff --git a/sys/contrib/dev/acpica/components/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c index 4a597842bd9f..0c794cfad113 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsutils.c +++ b/sys/contrib/dev/acpica/components/namespace/nsutils.c @@ -90,7 +90,7 @@ AcpiNsPrintNodePathname ( Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (Node, &Buffer); + Status = AcpiNsHandleToPathname (Node, &Buffer, FALSE); if (ACPI_SUCCESS (Status)) { if (Message) diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c index 7ee3fdd9c9b1..24eca77b0d86 100644 --- a/sys/contrib/dev/acpica/components/namespace/nsxfname.c +++ b/sys/contrib/dev/acpica/components/namespace/nsxfname.c @@ -193,11 +193,13 @@ AcpiGetName ( return (Status); } - if (NameType == ACPI_FULL_PATHNAME) + if (NameType == ACPI_FULL_PATHNAME || + NameType == ACPI_FULL_PATHNAME_NO_TRAILING) { /* Get the full pathname (From the namespace root) */ - Status = AcpiNsHandleToPathname (Handle, Buffer); + Status = AcpiNsHandleToPathname (Handle, Buffer, + NameType == ACPI_FULL_PATHNAME ? FALSE : TRUE); return (Status); } diff --git a/sys/contrib/dev/acpica/components/parser/psargs.c b/sys/contrib/dev/acpica/components/parser/psargs.c index b2a86fe2b997..5bf8a1a3b55c 100644 --- a/sys/contrib/dev/acpica/components/parser/psargs.c +++ b/sys/contrib/dev/acpica/components/parser/psargs.c @@ -316,7 +316,7 @@ AcpiPsGetNextNamepath ( ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p Desc %p Path=%p\n", Node, MethodDesc, Path)); - NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Start); if (!NameOp) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -524,7 +524,7 @@ static ACPI_PARSE_OBJECT * AcpiPsGetNextField ( ACPI_PARSE_STATE *ParserState) { - UINT32 AmlOffset; + UINT8 *Aml; ACPI_PARSE_OBJECT *Field; ACPI_PARSE_OBJECT *Arg = NULL; UINT16 Opcode; @@ -540,8 +540,7 @@ AcpiPsGetNextField ( ACPI_FUNCTION_TRACE (PsGetNextField); - AmlOffset = (UINT32) ACPI_PTR_DIFF ( - ParserState->Aml, ParserState->AmlStart); + Aml = ParserState->Aml; /* Determine field type */ @@ -579,14 +578,12 @@ AcpiPsGetNextField ( /* Allocate a new field op */ - Field = AcpiPsAllocOp (Opcode); + Field = AcpiPsAllocOp (Opcode, Aml); if (!Field) { return_PTR (NULL); } - Field->Common.AmlOffset = AmlOffset; - /* Decode the field type */ switch (Opcode) @@ -650,6 +647,7 @@ AcpiPsGetNextField ( * Argument for Connection operator can be either a Buffer * (resource descriptor), or a NameString. */ + Aml = ParserState->Aml; if (ACPI_GET8 (ParserState->Aml) == AML_BUFFER_OP) { ParserState->Aml++; @@ -662,7 +660,7 @@ AcpiPsGetNextField ( { /* Non-empty list */ - Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); + Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP, Aml); if (!Arg) { AcpiPsFreeOp (Field); @@ -712,7 +710,7 @@ AcpiPsGetNextField ( } else { - Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Aml); if (!Arg) { AcpiPsFreeOp (Field); @@ -784,7 +782,7 @@ AcpiPsGetNextArg ( /* Constants, strings, and namestrings are all the same size */ - Arg = AcpiPsAllocOp (AML_BYTE_OP); + Arg = AcpiPsAllocOp (AML_BYTE_OP, ParserState->Aml); if (!Arg) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -836,7 +834,8 @@ AcpiPsGetNextArg ( { /* Non-empty list */ - Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP); + Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP, + ParserState->Aml); if (!Arg) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -866,7 +865,7 @@ AcpiPsGetNextArg ( { /* NullName or NameString */ - Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP); + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml); if (!Arg) { return_ACPI_STATUS (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/components/parser/psloop.c b/sys/contrib/dev/acpica/components/parser/psloop.c index 63b64abe66f1..b31a573a133b 100644 --- a/sys/contrib/dev/acpica/components/parser/psloop.c +++ b/sys/contrib/dev/acpica/components/parser/psloop.c @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -134,8 +135,7 @@ AcpiPsGetArguments ( */ while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) { - WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, - WalkState->ParserState.AmlStart); + WalkState->Aml = WalkState->ParserState.Aml; Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); @@ -146,7 +146,6 @@ AcpiPsGetArguments ( if (Arg) { - Arg->Common.AmlOffset = WalkState->AmlOffset; AcpiPsAppendArg (Op, Arg); } @@ -502,15 +501,7 @@ AcpiPsParseLoop ( continue; } - Op->Common.AmlOffset = WalkState->AmlOffset; - - if (WalkState->OpInfo) - { - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", - (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, - Op, ParserState->Aml, Op->Common.AmlOffset)); - } + AcpiExStartTraceOpcode (Op, WalkState); } diff --git a/sys/contrib/dev/acpica/components/parser/psobject.c b/sys/contrib/dev/acpica/components/parser/psobject.c index 0ad37b97fd97..07a6b2802113 100644 --- a/sys/contrib/dev/acpica/components/parser/psobject.c +++ b/sys/contrib/dev/acpica/components/parser/psobject.c @@ -73,12 +73,13 @@ static ACPI_STATUS AcpiPsGetAmlOpcode ( ACPI_WALK_STATE *WalkState) { + UINT32 AmlOffset; + ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); - WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, - WalkState->ParserState.AmlStart); + WalkState->Aml = WalkState->ParserState.Aml; WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); /* @@ -107,10 +108,13 @@ AcpiPsGetAmlOpcode ( if (WalkState->PassNumber == 2) { + AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, + WalkState->ParserState.AmlStart); + ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", WalkState->Opcode, - (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)))); + (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER)))); ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48); @@ -122,13 +126,13 @@ AcpiPsGetAmlOpcode ( AcpiOsPrintf ( "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", WalkState->Opcode, - (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))); + (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER))); /* Dump the context surrounding the invalid opcode */ AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16), 48, DB_BYTE_DISPLAY, - (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); + (AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); AcpiOsPrintf (" */\n"); #endif } @@ -313,7 +317,7 @@ AcpiPsCreateOp ( /* Create Op structure and append to parent's argument list */ WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); - Op = AcpiPsAllocOp (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode, AmlOpStart); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); diff --git a/sys/contrib/dev/acpica/components/parser/psparse.c b/sys/contrib/dev/acpica/components/parser/psparse.c index aa978cc57cd4..7d160a478d47 100644 --- a/sys/contrib/dev/acpica/components/parser/psparse.c +++ b/sys/contrib/dev/acpica/components/parser/psparse.c @@ -161,6 +161,8 @@ AcpiPsCompleteThisOp ( return_ACPI_STATUS (AE_OK); /* OK for now */ } + AcpiExStopTraceOpcode (Op, WalkState); + /* Delete this op and the subtree below it if asked to */ if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || @@ -198,7 +200,8 @@ AcpiPsCompleteThisOp ( * These opcodes contain TermArg operands. The current * op must be replaced by a placeholder return op */ - ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP, + Op->Common.Aml); if (!ReplacementOp) { Status = AE_NO_MEMORY; @@ -217,7 +220,8 @@ AcpiPsCompleteThisOp ( (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { - ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP, + Op->Common.Aml); if (!ReplacementOp) { Status = AE_NO_MEMORY; @@ -230,7 +234,8 @@ AcpiPsCompleteThisOp ( (Op->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { - ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode); + ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode, + Op->Common.Aml); if (!ReplacementOp) { Status = AE_NO_MEMORY; @@ -246,7 +251,8 @@ AcpiPsCompleteThisOp ( default: - ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); + ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP, + Op->Common.Aml); if (!ReplacementOp) { Status = AE_NO_MEMORY; diff --git a/sys/contrib/dev/acpica/components/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c index 8581a942cf1c..d4b5dc5c212f 100644 --- a/sys/contrib/dev/acpica/components/parser/psutils.c +++ b/sys/contrib/dev/acpica/components/parser/psutils.c @@ -64,12 +64,12 @@ ACPI_PARSE_OBJECT * AcpiPsCreateScopeOp ( - void) + UINT8 *Aml) { ACPI_PARSE_OBJECT *ScopeOp; - ScopeOp = AcpiPsAllocOp (AML_SCOPE_OP); + ScopeOp = AcpiPsAllocOp (AML_SCOPE_OP, Aml); if (!ScopeOp) { return (NULL); @@ -115,6 +115,7 @@ AcpiPsInitOp ( * FUNCTION: AcpiPsAllocOp * * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * Aml - Address of the opcode * * RETURN: Pointer to the new Op, null on failure * @@ -126,7 +127,8 @@ AcpiPsInitOp ( ACPI_PARSE_OBJECT* AcpiPsAllocOp ( - UINT16 Opcode) + UINT16 Opcode, + UINT8 *Aml) { ACPI_PARSE_OBJECT *Op; const ACPI_OPCODE_INFO *OpInfo; @@ -173,6 +175,7 @@ AcpiPsAllocOp ( if (Op) { AcpiPsInitOp (Op, Opcode); + Op->Common.Aml = Aml; Op->Common.Flags = Flags; } diff --git a/sys/contrib/dev/acpica/components/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c index 2927f4c677f6..8195a56f20ed 100644 --- a/sys/contrib/dev/acpica/components/parser/psxface.c +++ b/sys/contrib/dev/acpica/components/parser/psxface.c @@ -47,6 +47,7 @@ #include #include #include +#include #define _COMPONENT ACPI_PARSER @@ -54,14 +55,6 @@ /* Local Prototypes */ -static void -AcpiPsStartTrace ( - ACPI_EVALUATE_INFO *Info); - -static void -AcpiPsStopTrace ( - ACPI_EVALUATE_INFO *Info); - static void AcpiPsUpdateParameterList ( ACPI_EVALUATE_INFO *Info, @@ -86,7 +79,7 @@ AcpiPsUpdateParameterList ( ACPI_STATUS AcpiDebugTrace ( - char *Name, + const char *Name, UINT32 DebugLevel, UINT32 DebugLayer, UINT32 Flags) @@ -100,128 +93,14 @@ AcpiDebugTrace ( return (Status); } - /* TBDs: Validate name, allow full path or just nameseg */ - - AcpiGbl_TraceMethodName = *ACPI_CAST_PTR (UINT32, Name); + AcpiGbl_TraceMethodName = Name; AcpiGbl_TraceFlags = Flags; - - if (DebugLevel) - { - AcpiGbl_TraceDbgLevel = DebugLevel; - } - if (DebugLayer) - { - AcpiGbl_TraceDbgLayer = DebugLayer; - } + AcpiGbl_TraceDbgLevel = DebugLevel; + AcpiGbl_TraceDbgLayer = DebugLayer; + Status = AE_OK; (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiPsStartTrace - * - * PARAMETERS: Info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Start control method execution trace - * - ******************************************************************************/ - -static void -AcpiPsStartTrace ( - ACPI_EVALUATE_INFO *Info) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_ENTRY (); - - - Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (Status)) - { - return; - } - - if ((!AcpiGbl_TraceMethodName) || - (AcpiGbl_TraceMethodName != Info->Node->Name.Integer)) - { - goto Exit; - } - - AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; - AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; - - AcpiDbgLevel = 0x00FFFFFF; - AcpiDbgLayer = ACPI_UINT32_MAX; - - if (AcpiGbl_TraceDbgLevel) - { - AcpiDbgLevel = AcpiGbl_TraceDbgLevel; - } - if (AcpiGbl_TraceDbgLayer) - { - AcpiDbgLayer = AcpiGbl_TraceDbgLayer; - } - - -Exit: - (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiPsStopTrace - * - * PARAMETERS: Info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Stop control method execution trace - * - ******************************************************************************/ - -static void -AcpiPsStopTrace ( - ACPI_EVALUATE_INFO *Info) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_ENTRY (); - - - Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (Status)) - { - return; - } - - if ((!AcpiGbl_TraceMethodName) || - (AcpiGbl_TraceMethodName != Info->Node->Name.Integer)) - { - goto Exit; - } - - /* Disable further tracing if type is one-shot */ - - if (AcpiGbl_TraceFlags & 1) - { - AcpiGbl_TraceMethodName = 0; - AcpiGbl_TraceDbgLevel = 0; - AcpiGbl_TraceDbgLayer = 0; - } - - AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; - AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; - -Exit: - (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); } @@ -284,10 +163,6 @@ AcpiPsExecuteMethod ( */ AcpiPsUpdateParameterList (Info, REF_INCREMENT); - /* Begin tracing if requested */ - - AcpiPsStartTrace (Info); - /* * Execute the method. Performs parse simultaneously */ @@ -297,7 +172,7 @@ AcpiPsExecuteMethod ( /* Create and init a Root Node */ - Op = AcpiPsCreateScopeOp (); + Op = AcpiPsCreateScopeOp (Info->ObjDesc->Method.AmlStart); if (!Op) { Status = AE_NO_MEMORY; @@ -370,10 +245,6 @@ AcpiPsExecuteMethod ( Cleanup: AcpiPsDeleteParseTree (Op); - /* End optional tracing */ - - AcpiPsStopTrace (Info); - /* Take away the extra reference that we gave the parameters above */ AcpiPsUpdateParameterList (Info, REF_DECREMENT); diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c index 6225590563e5..2461bb446fee 100644 --- a/sys/contrib/dev/acpica/components/resources/rscreate.c +++ b/sys/contrib/dev/acpica/components/resources/rscreate.c @@ -370,7 +370,8 @@ AcpiRsCreatePciRoutingTable ( (UINT8 *) OutputBuffer->Pointer); PathBuffer.Pointer = UserPrt->Source; - Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, &PathBuffer); + Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, + &PathBuffer, FALSE); /* +1 to include null terminator */ diff --git a/sys/contrib/dev/acpica/components/utilities/utdebug.c b/sys/contrib/dev/acpica/components/utilities/utdebug.c index 544450d37f52..e91cc4d662e1 100644 --- a/sys/contrib/dev/acpica/components/utilities/utdebug.c +++ b/sys/contrib/dev/acpica/components/utilities/utdebug.c @@ -45,6 +45,7 @@ #include #include +#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utdebug") @@ -634,6 +635,42 @@ AcpiUtPtrExit ( } } + +/******************************************************************************* + * + * FUNCTION: AcpiTracePoint + * + * PARAMETERS: Type - Trace event type + * Begin - TRUE if before execution + * Aml - Executed AML address + * Pathname - Object path + * Pointer - Pointer to the related object + * + * RETURN: None + * + * DESCRIPTION: Interpreter execution trace. + * + ******************************************************************************/ + +void +AcpiTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname) +{ + + ACPI_FUNCTION_ENTRY (); + + AcpiExTracePoint (Type, Begin, Aml, Pathname); + +#ifdef ACPI_USE_SYSTEM_TRACER + AcpiOsTracePoint (Type, Begin, Aml, Pathname); +#endif +} + +ACPI_EXPORT_SYMBOL (AcpiTracePoint) + #endif diff --git a/sys/contrib/dev/acpica/components/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c index bc9ab70c7d98..837a3f1966ef 100644 --- a/sys/contrib/dev/acpica/components/utilities/utdelete.c +++ b/sys/contrib/dev/acpica/components/utilities/utdelete.c @@ -220,6 +220,10 @@ AcpiUtDeleteInternalObj ( AcpiUtDeleteObjectDesc (Object->Method.Mutex); Object->Method.Mutex = NULL; } + if (Object->Method.Node) + { + Object->Method.Node = NULL; + } break; case ACPI_TYPE_REGION: diff --git a/sys/contrib/dev/acpica/components/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c index fd7fba291201..ee2851c03329 100644 --- a/sys/contrib/dev/acpica/components/utilities/utinit.c +++ b/sys/contrib/dev/acpica/components/utilities/utinit.c @@ -224,8 +224,6 @@ AcpiUtInitGlobals ( AcpiGbl_AcpiHardwarePresent = TRUE; AcpiGbl_LastOwnerIdIndex = 0; AcpiGbl_NextOwnerIdOffset = 0; - AcpiGbl_TraceDbgLevel = 0; - AcpiGbl_TraceDbgLayer = 0; AcpiGbl_DebuggerConfiguration = DEBUGGER_THREADING; AcpiGbl_OsiMutex = NULL; AcpiGbl_RegMethodsExecuted = FALSE; diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c index 1aa02b824cb7..912949fd0f22 100644 --- a/sys/contrib/dev/acpica/components/utilities/utmisc.c +++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c @@ -418,7 +418,7 @@ AcpiUtDisplayInitPathname ( /* Get the full pathname to the node */ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; - Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, FALSE); if (ACPI_FAILURE (Status)) { return; diff --git a/sys/contrib/dev/acpica/components/utilities/utnonansi.c b/sys/contrib/dev/acpica/components/utilities/utnonansi.c new file mode 100644 index 000000000000..4ba96a1161ea --- /dev/null +++ b/sys/contrib/dev/acpica/components/utilities/utnonansi.c @@ -0,0 +1,455 @@ +/******************************************************************************* + * + * Module Name: utnonansi - Non-ansi C library functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utnonansi") + + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit + * version of strtoul. + */ + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlwr (strlwr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to lowercase + * + ******************************************************************************/ + +void +AcpiUtStrlwr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) tolower ((int) *String); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrupr (strupr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to uppercase + * + ******************************************************************************/ + +void +AcpiUtStrupr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) toupper ((int) *String); + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiUtStricmp (stricmp) + * + * PARAMETERS: String1 - first string to compare + * String2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Case-insensitive string compare. Implementation of the + * non-ANSI stricmp function. + * + ******************************************************************************/ + +int +AcpiUtStricmp ( + char *String1, + char *String2) +{ + int c1; + int c2; + + + do + { + c1 = tolower ((int) *String1); + c2 = tolower ((int) *String2); + + String1++; + String2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul64 + * + * PARAMETERS: String - Null terminated string + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of ToInteger' + * RetInteger - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger) +{ + UINT32 ThisDigit = 0; + UINT64 ReturnValue = 0; + UINT64 Quotient; + UINT64 Dividend; + UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE); + UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4); + UINT8 ValidDigits = 0; + UINT8 SignOf0x = 0; + UINT8 Term = 0; + + + ACPI_FUNCTION_TRACE_STR (UtStroul64, String); + + + switch (Base) + { + case ACPI_ANY_BASE: + case 16: + + break; + + default: + + /* Invalid Base */ + + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!String) + { + goto ErrorExit; + } + + /* Skip over any white space in the buffer */ + + while ((*String) && (isspace ((int) *String) || *String == '\t')) + { + String++; + } + + if (ToIntegerOp) + { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*String == '0') && (tolower ((int) *(String + 1)) == 'x')) + { + SignOf0x = 1; + Base = 16; + + /* Skip over the leading '0x' */ + String += 2; + } + else + { + Base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*String) || isspace ((int) *String) || *String == '\t') + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + goto AllDone; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*String) + { + if (isdigit ((int) *String)) + { + /* Convert ASCII 0-9 to Decimal value */ + + ThisDigit = ((UINT8) *String) - '0'; + } + else if (Base == 10) + { + /* Digit is out of range; possible in ToInteger case only */ + + Term = 1; + } + else + { + ThisDigit = (UINT8) toupper ((int) *String); + if (isxdigit ((int) ThisDigit)) + { + /* Convert ASCII Hex char to value */ + + ThisDigit = ThisDigit - 'A' + 10; + } + else + { + Term = 1; + } + } + + if (Term) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x) + { + /* Skip zeros */ + String++; + continue; + } + + ValidDigits++; + + if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32))) + { + /* + * This is ToInteger operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto ErrorExit; + } + + /* Divide the digit into the correct position */ + + (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit), + Base, &Quotient, NULL); + + if (ReturnValue > Quotient) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + + ReturnValue *= Base; + ReturnValue += ThisDigit; + String++; + } + + /* All done, normal exit */ + +AllDone: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ReturnValue))); + + *RetInteger = ReturnValue; + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + /* Base was set/validated above */ + + if (Base == 10) + { + return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); + } + else + { + return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); + } +} + + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +/******************************************************************************* + * + * FUNCTION: AcpiUtSafeStrcpy, AcpiUtSafeStrcat, AcpiUtSafeStrncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtSafeStrcpy ( + char *Dest, + ACPI_SIZE DestSize, + char *Source) +{ + + if (strlen (Source) >= DestSize) + { + return (TRUE); + } + + strcpy (Dest, Source); + return (FALSE); +} + +BOOLEAN +AcpiUtSafeStrcat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source) +{ + + if ((strlen (Dest) + strlen (Source)) >= DestSize) + { + return (TRUE); + } + + strcat (Dest, Source); + return (FALSE); +} + +#ifndef _KERNEL +BOOLEAN +AcpiUtSafeStrncat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source, + ACPI_SIZE MaxTransferLength) +{ + ACPI_SIZE ActualTransferLength; + + + ActualTransferLength = ACPI_MIN (MaxTransferLength, strlen (Source)); + + if ((strlen (Dest) + ActualTransferLength) >= DestSize) + { + return (TRUE); + } + + strncat (Dest, Source, MaxTransferLength); + return (FALSE); +} +#endif +#endif diff --git a/sys/contrib/dev/acpica/components/utilities/utstring.c b/sys/contrib/dev/acpica/components/utilities/utstring.c index 6d38a5b4ffee..07525cb9bfdf 100644 --- a/sys/contrib/dev/acpica/components/utilities/utstring.c +++ b/sys/contrib/dev/acpica/components/utilities/utstring.c @@ -50,343 +50,6 @@ ACPI_MODULE_NAME ("utstring") -/* - * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit - * version of strtoul. - */ - -#ifdef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: AcpiUtStrlwr (strlwr) - * - * PARAMETERS: SrcString - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to lowercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void -AcpiUtStrlwr ( - char *SrcString) -{ - char *String; - - - ACPI_FUNCTION_ENTRY (); - - - if (!SrcString) - { - return; - } - - /* Walk entire string, lowercasing the letters */ - - for (String = SrcString; *String; String++) - { - *String = (char) tolower ((int) *String); - } - - return; -} - - -/****************************************************************************** - * - * FUNCTION: AcpiUtStricmp (stricmp) - * - * PARAMETERS: String1 - first string to compare - * String2 - second string to compare - * - * RETURN: int that signifies string relationship. Zero means strings - * are equal. - * - * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare - * strings with no case sensitivity) - * - ******************************************************************************/ - -int -AcpiUtStricmp ( - char *String1, - char *String2) -{ - int c1; - int c2; - - - do - { - c1 = tolower ((int) *String1); - c2 = tolower ((int) *String2); - - String1++; - String2++; - } - while ((c1 == c2) && (c1)); - - return (c1 - c2); -} -#endif - - -/******************************************************************************* - * - * FUNCTION: AcpiUtStrupr (strupr) - * - * PARAMETERS: SrcString - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void -AcpiUtStrupr ( - char *SrcString) -{ - char *String; - - - ACPI_FUNCTION_ENTRY (); - - - if (!SrcString) - { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (String = SrcString; *String; String++) - { - *String = (char) toupper ((int) *String); - } - - return; -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtStrtoul64 - * - * PARAMETERS: String - Null terminated string - * Base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of ToInteger' - * RetInteger - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiUtStrtoul64 ( - char *String, - UINT32 Base, - UINT64 *RetInteger) -{ - UINT32 ThisDigit = 0; - UINT64 ReturnValue = 0; - UINT64 Quotient; - UINT64 Dividend; - UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE); - UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4); - UINT8 ValidDigits = 0; - UINT8 SignOf0x = 0; - UINT8 Term = 0; - - - ACPI_FUNCTION_TRACE_STR (UtStroul64, String); - - - switch (Base) - { - case ACPI_ANY_BASE: - case 16: - - break; - - default: - - /* Invalid Base */ - - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - if (!String) - { - goto ErrorExit; - } - - /* Skip over any white space in the buffer */ - - while ((*String) && (isspace ((int) *String) || *String == '\t')) - { - String++; - } - - if (ToIntegerOp) - { - /* - * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*String == '0') && (tolower ((int) *(String + 1)) == 'x')) - { - SignOf0x = 1; - Base = 16; - - /* Skip over the leading '0x' */ - String += 2; - } - else - { - Base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*String) || isspace ((int) *String) || *String == '\t') - { - if (ToIntegerOp) - { - goto ErrorExit; - } - else - { - goto AllDone; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*String) - { - if (isdigit ((int) *String)) - { - /* Convert ASCII 0-9 to Decimal value */ - - ThisDigit = ((UINT8) *String) - '0'; - } - else if (Base == 10) - { - /* Digit is out of range; possible in ToInteger case only */ - - Term = 1; - } - else - { - ThisDigit = (UINT8) toupper ((int) *String); - if (isxdigit ((int) ThisDigit)) - { - /* Convert ASCII Hex char to value */ - - ThisDigit = ThisDigit - 'A' + 10; - } - else - { - Term = 1; - } - } - - if (Term) - { - if (ToIntegerOp) - { - goto ErrorExit; - } - else - { - break; - } - } - else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x) - { - /* Skip zeros */ - String++; - continue; - } - - ValidDigits++; - - if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32))) - { - /* - * This is ToInteger operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto ErrorExit; - } - - /* Divide the digit into the correct position */ - - (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit), - Base, &Quotient, NULL); - - if (ReturnValue > Quotient) - { - if (ToIntegerOp) - { - goto ErrorExit; - } - else - { - break; - } - } - - ReturnValue *= Base; - ReturnValue += ThisDigit; - String++; - } - - /* All done, normal exit */ - -AllDone: - - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (ReturnValue))); - - *RetInteger = ReturnValue; - return_ACPI_STATUS (AE_OK); - - -ErrorExit: - /* Base was set/validated above */ - - if (Base == 10) - { - return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); - } - else - { - return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); - } -} - - /******************************************************************************* * * FUNCTION: AcpiUtPrintString @@ -682,81 +345,3 @@ UtConvertBackslashes ( } } #endif - -#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) -/******************************************************************************* - * - * FUNCTION: AcpiUtSafeStrcpy, AcpiUtSafeStrcat, AcpiUtSafeStrncat - * - * PARAMETERS: Adds a "DestSize" parameter to each of the standard string - * functions. This is the size of the Destination buffer. - * - * RETURN: TRUE if the operation would overflow the destination buffer. - * - * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that - * the result of the operation will not overflow the output string - * buffer. - * - * NOTE: These functions are typically only helpful for processing - * user input and command lines. For most ACPICA code, the - * required buffer length is precisely calculated before buffer - * allocation, so the use of these functions is unnecessary. - * - ******************************************************************************/ - -BOOLEAN -AcpiUtSafeStrcpy ( - char *Dest, - ACPI_SIZE DestSize, - char *Source) -{ - - if (strlen (Source) >= DestSize) - { - return (TRUE); - } - - strcpy (Dest, Source); - return (FALSE); -} - -BOOLEAN -AcpiUtSafeStrcat ( - char *Dest, - ACPI_SIZE DestSize, - char *Source) -{ - - if ((strlen (Dest) + strlen (Source)) >= DestSize) - { - return (TRUE); - } - - strcat (Dest, Source); - return (FALSE); -} - -#ifndef _KERNEL -BOOLEAN -AcpiUtSafeStrncat ( - char *Dest, - ACPI_SIZE DestSize, - char *Source, - ACPI_SIZE MaxTransferLength) -{ - ACPI_SIZE ActualTransferLength; - - - ActualTransferLength = ACPI_MIN (MaxTransferLength, strlen (Source)); - - if ((strlen (Dest) + ActualTransferLength) >= DestSize) - { - return (TRUE); - } - - strncat (Dest, Source, MaxTransferLength); - return (FALSE); -} -#endif - -#endif diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h index 11cf02ee6433..8b6ac8956ad4 100644 --- a/sys/contrib/dev/acpica/include/acdebug.h +++ b/sys/contrib/dev/acpica/include/acdebug.h @@ -136,6 +136,12 @@ ACPI_STATUS AcpiDbSleep ( char *ObjectArg); +void +AcpiDbTrace ( + char *EnableArg, + char *MethodArg, + char *OnceArg); + void AcpiDbDisplayLocks ( void); @@ -424,6 +430,32 @@ AcpiDbGetNextToken ( ACPI_OBJECT_TYPE *ReturnType); +/* + * dbobject + */ +void +AcpiDbDecodeInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +void +AcpiDbDisplayInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDecodeArguments ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDecodeLocals ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDumpMethodInfo ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState); + + /* * dbstats - Generation and display of ACPI table statistics */ diff --git a/sys/contrib/dev/acpica/include/acdisasm.h b/sys/contrib/dev/acpica/include/acdisasm.h index bbd21b7e4cd5..e7c2814e238f 100644 --- a/sys/contrib/dev/acpica/include/acdisasm.h +++ b/sys/contrib/dev/acpica/include/acdisasm.h @@ -399,7 +399,9 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat3[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoStao[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoStaoStr[]; -extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaClient[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaServer[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoVrtc[]; @@ -594,6 +596,10 @@ void AcpiDmDumpStao ( ACPI_TABLE_HEADER *Table); +void +AcpiDmDumpTcpa ( + ACPI_TABLE_HEADER *Table); + void AcpiDmDumpVrtc ( ACPI_TABLE_HEADER *Table); @@ -637,10 +643,6 @@ AcpiDmDisassembleOneOp ( ACPI_OP_WALK_INFO *Info, ACPI_PARSE_OBJECT *Op); -void -AcpiDmDecodeInternalObject ( - ACPI_OPERAND_OBJECT *ObjDesc); - UINT32 AcpiDmListType ( ACPI_PARSE_OBJECT *Op); @@ -699,29 +701,6 @@ AcpiDmNamestring ( char *Name); -/* - * dmobject - */ -void -AcpiDmDisplayInternalObject ( - ACPI_OPERAND_OBJECT *ObjDesc, - ACPI_WALK_STATE *WalkState); - -void -AcpiDmDisplayArguments ( - ACPI_WALK_STATE *WalkState); - -void -AcpiDmDisplayLocals ( - ACPI_WALK_STATE *WalkState); - -void -AcpiDmDumpMethodInfo ( - ACPI_STATUS Status, - ACPI_WALK_STATE *WalkState, - ACPI_PARSE_OBJECT *Op); - - /* * dmbuffer */ diff --git a/sys/contrib/dev/acpica/include/acdispat.h b/sys/contrib/dev/acpica/include/acdispat.h index 9364fe398444..0a1b1ac4f64c 100644 --- a/sys/contrib/dev/acpica/include/acdispat.h +++ b/sys/contrib/dev/acpica/include/acdispat.h @@ -461,4 +461,14 @@ AcpiDsResultPush ( ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState); + +/* + * dsdebug - parser debugging routines + */ +void +AcpiDsDumpMethodStack ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + #endif /* _ACDISPAT_H_ */ diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h index 9e7da94ccf3a..eaa364d4e45c 100644 --- a/sys/contrib/dev/acpica/include/acglobal.h +++ b/sys/contrib/dev/acpica/include/acglobal.h @@ -293,8 +293,6 @@ ACPI_GLOBAL (UINT32, AcpiFixedEventCount[ACPI_NUM_FIXED_EVENT ACPI_GLOBAL (UINT32, AcpiGbl_OriginalDbgLevel); ACPI_GLOBAL (UINT32, AcpiGbl_OriginalDbgLayer); -ACPI_GLOBAL (UINT32, AcpiGbl_TraceDbgLevel); -ACPI_GLOBAL (UINT32, AcpiGbl_TraceDbgLayer); /***************************************************************************** @@ -313,6 +311,7 @@ ACPI_INIT_GLOBAL (UINT8, AcpiGbl_NoResourceDisassembly, FALSE); ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_IgnoreNoopOperator, FALSE); ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_CstyleDisassembly, TRUE); ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_ForceAmlDisassembly, FALSE); +ACPI_INIT_GLOBAL (ACPI_PARSE_OBJECT *, AcpiGbl_PreviousOp, NULL); ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbOpt_Disasm); ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbOpt_Verbose); diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h index 00eb8f0d2545..f53e6c58f849 100644 --- a/sys/contrib/dev/acpica/include/acinterp.h +++ b/sys/contrib/dev/acpica/include/acinterp.h @@ -143,6 +143,35 @@ AcpiExDoDebugObject ( UINT32 Level, UINT32 Index); +void +AcpiExStartTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStopTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStartTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStopTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +void +AcpiExTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname); + /* * exfield - ACPI AML (p-code) execution - field manipulation diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h index dc1afffde35a..7f62cc8d1c09 100644 --- a/sys/contrib/dev/acpica/include/aclocal.h +++ b/sys/contrib/dev/acpica/include/aclocal.h @@ -193,8 +193,12 @@ typedef struct acpi_namespace_node */ #ifdef ACPI_LARGE_NAMESPACE_NODE union acpi_parse_object *Op; + void *MethodLocals; + void *MethodArgs; UINT32 Value; UINT32 Length; + UINT8 ArgCount; + #endif } ACPI_NAMESPACE_NODE; @@ -864,7 +868,7 @@ typedef union acpi_parse_value } ACPI_PARSE_VALUE; -#ifdef ACPI_DISASSEMBLER +#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT) #define ACPI_DISASM_ONLY_MEMBERS(a) a; #else #define ACPI_DISASM_ONLY_MEMBERS(a) @@ -875,7 +879,7 @@ typedef union acpi_parse_value UINT8 DescriptorType; /* To differentiate various internal objs */\ UINT8 Flags; /* Type of Op */\ UINT16 AmlOpcode; /* AML opcode */\ - UINT32 AmlOffset; /* Offset of declaration in AML */\ + UINT8 *Aml; /* Address of declaration in AML */\ union acpi_parse_object *Next; /* Next op */\ ACPI_NAMESPACE_NODE *Node; /* For use by interpreter */\ ACPI_PARSE_VALUE Value; /* Value or args associated with the opcode */\ @@ -1291,7 +1295,9 @@ typedef struct acpi_db_method_info * Index of current thread inside all them created. */ char InitArgs; +#ifdef ACPI_DEBUGGER ACPI_OBJECT_TYPE ArgTypes[4]; +#endif char *Arguments[4]; char NumThreadsStr[11]; char IdOfThreadStr[11]; diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h index 35d53f660780..48620fb470a6 100644 --- a/sys/contrib/dev/acpica/include/acmacros.h +++ b/sys/contrib/dev/acpica/include/acmacros.h @@ -223,6 +223,16 @@ #define ACPI_MUL_32(a) _ACPI_MUL(a, 5) #define ACPI_MOD_32(a) _ACPI_MOD(a, 32) +/* Test for ASCII character */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) + +/* Signed integers */ + +#define ACPI_SIGN_POSITIVE 0 +#define ACPI_SIGN_NEGATIVE 1 + + /* * Rounding macros (Power of two boundaries only) */ diff --git a/sys/contrib/dev/acpica/include/acnamesp.h b/sys/contrib/dev/acpica/include/acnamesp.h index 786fd293688f..bea4ebf0ad7c 100644 --- a/sys/contrib/dev/acpica/include/acnamesp.h +++ b/sys/contrib/dev/acpica/include/acnamesp.h @@ -350,16 +350,22 @@ UINT32 AcpiNsOpensScope ( ACPI_OBJECT_TYPE Type); -ACPI_STATUS -AcpiNsBuildExternalPath ( - ACPI_NAMESPACE_NODE *Node, - ACPI_SIZE Size, - char *NameBuffer); - char * AcpiNsGetExternalPathname ( ACPI_NAMESPACE_NODE *Node); +UINT32 +AcpiNsBuildNormalizedPath ( + ACPI_NAMESPACE_NODE *Node, + char *FullPath, + UINT32 PathSize, + BOOLEAN NoTrailing); + +char * +AcpiNsGetNormalizedPathname ( + ACPI_NAMESPACE_NODE *Node, + BOOLEAN NoTrailing); + char * AcpiNsNameOfCurrentScope ( ACPI_WALK_STATE *WalkState); @@ -367,7 +373,8 @@ AcpiNsNameOfCurrentScope ( ACPI_STATUS AcpiNsHandleToPathname ( ACPI_HANDLE TargetHandle, - ACPI_BUFFER *Buffer); + ACPI_BUFFER *Buffer, + BOOLEAN NoTrailing); BOOLEAN AcpiNsPatternMatch ( diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h index 481eb449bbd3..adeb41403412 100644 --- a/sys/contrib/dev/acpica/include/acobject.h +++ b/sys/contrib/dev/acpica/include/acobject.h @@ -213,6 +213,7 @@ typedef struct acpi_object_method UINT8 ParamCount; UINT8 SyncLevel; union acpi_operand_object *Mutex; + union acpi_operand_object *Node; UINT8 *AmlStart; union { diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h index 0ef98eb4494d..197f28b068d8 100644 --- a/sys/contrib/dev/acpica/include/acoutput.h +++ b/sys/contrib/dev/acpica/include/acoutput.h @@ -89,7 +89,8 @@ #define ACPI_LV_DEBUG_OBJECT 0x00000002 #define ACPI_LV_INFO 0x00000004 #define ACPI_LV_REPAIR 0x00000008 -#define ACPI_LV_ALL_EXCEPTIONS 0x0000000F +#define ACPI_LV_TRACE_POINT 0x00000010 +#define ACPI_LV_ALL_EXCEPTIONS 0x0000001F /* Trace verbosity level 1 [Standard Trace Level] */ @@ -149,6 +150,7 @@ #define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) #define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) #define ACPI_DB_REPAIR ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR) +#define ACPI_DB_TRACE_POINT ACPI_DEBUG_LEVEL (ACPI_LV_TRACE_POINT) #define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) /* Trace level -- also used in the global "DebugLevel" */ @@ -185,6 +187,21 @@ #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) +/* + * Global trace flags + */ +#define ACPI_TRACE_ENABLED ((UINT32) 4) +#define ACPI_TRACE_ONESHOT ((UINT32) 2) +#define ACPI_TRACE_OPCODE ((UINT32) 1) + +/* Defaults for trace debugging level/layer */ + +#define ACPI_TRACE_LEVEL_ALL ACPI_LV_ALL +#define ACPI_TRACE_LAYER_ALL 0x000001FF +#define ACPI_TRACE_LEVEL_DEFAULT ACPI_LV_TRACE_POINT +#define ACPI_TRACE_LAYER_DEFAULT ACPI_EXECUTER + + #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) /* * The module name is used primarily for error and debug messages. @@ -439,6 +456,8 @@ #define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d) #define ACPI_DUMP_BUFFER(a, b) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) +#define ACPI_TRACE_POINT(a, b, c, d) AcpiTracePoint (a, b, c, d) + #else /* ACPI_DEBUG_OUTPUT */ /* * This is the non-debug case -- make everything go away, @@ -460,6 +479,7 @@ #define ACPI_DUMP_PATHNAME(a, b, c, d) #define ACPI_DUMP_BUFFER(a, b) #define ACPI_IS_DEBUG_ENABLED(Level, Component) 0 +#define ACPI_TRACE_POINT(a, b, c, d) /* Return macros must have a return statement at the minimum */ diff --git a/sys/contrib/dev/acpica/include/acparser.h b/sys/contrib/dev/acpica/include/acparser.h index a3c766610415..a89c5c4c4635 100644 --- a/sys/contrib/dev/acpica/include/acparser.h +++ b/sys/contrib/dev/acpica/include/acparser.h @@ -306,7 +306,7 @@ AcpiPsDeleteParseTree ( */ ACPI_PARSE_OBJECT * AcpiPsCreateScopeOp ( - void); + UINT8 *Aml); void AcpiPsInitOp ( @@ -315,7 +315,8 @@ AcpiPsInitOp ( ACPI_PARSE_OBJECT * AcpiPsAllocOp ( - UINT16 opcode); + UINT16 Opcode, + UINT8 *Aml); void AcpiPsFreeOp ( diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h index 21cac7a35b7e..4028a02e3d98 100644 --- a/sys/contrib/dev/acpica/include/acpiosxf.h +++ b/sys/contrib/dev/acpica/include/acpiosxf.h @@ -599,5 +599,14 @@ AcpiOsSetFileOffset ( UINT8 From); #endif +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTracePoint +void +AcpiOsTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname); +#endif + #endif /* __ACPIOSXF_H__ */ diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h index 037ffef82d11..9796379c3b81 100644 --- a/sys/contrib/dev/acpica/include/acpixf.h +++ b/sys/contrib/dev/acpica/include/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20150619 +#define ACPI_CA_VERSION 0x20150717 #include #include @@ -253,7 +253,9 @@ ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_ReducedHardware, FALSE); * traced each time it is executed. */ ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceFlags, 0); -ACPI_INIT_GLOBAL (ACPI_NAME, AcpiGbl_TraceMethodName, 0); +ACPI_INIT_GLOBAL (const char *, AcpiGbl_TraceMethodName, NULL); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceDbgLevel, ACPI_TRACE_LEVEL_DEFAULT); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceDbgLayer, ACPI_TRACE_LAYER_DEFAULT); /* * Runtime configuration of debug output control masks. We want the debug @@ -610,7 +612,7 @@ AcpiGetData ( ACPI_EXTERNAL_RETURN_STATUS ( ACPI_STATUS AcpiDebugTrace ( - char *Name, + const char *Name, UINT32 DebugLevel, UINT32 DebugLayer, UINT32 Flags)) @@ -1191,6 +1193,14 @@ AcpiDebugPrintRaw ( const char *Format, ...)) +ACPI_DBG_DEPENDENT_RETURN_VOID ( +void +AcpiTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname)) + ACPI_APP_DEPENDENT_RETURN_VOID ( ACPI_PRINTF_LIKE(1) void ACPI_INTERNAL_VAR_XFACE diff --git a/sys/contrib/dev/acpica/include/acstruct.h b/sys/contrib/dev/acpica/include/acstruct.h index 3a6faa6bf06b..10dc371ed9ac 100644 --- a/sys/contrib/dev/acpica/include/acstruct.h +++ b/sys/contrib/dev/acpica/include/acstruct.h @@ -88,7 +88,7 @@ typedef struct acpi_walk_state BOOLEAN NamespaceOverride; /* Override existing objects */ UINT8 ResultSize; /* Total elements for the result stack */ UINT8 ResultCount; /* Current number of occupied elements of result stack */ - UINT32 AmlOffset; + UINT8 *Aml; UINT32 ArgTypes; UINT32 MethodBreakpoint; /* For single stepping */ UINT32 UserBreakpoint; /* User AML breakpoint */ diff --git a/sys/contrib/dev/acpica/include/actbl2.h b/sys/contrib/dev/acpica/include/actbl2.h index 6ee36a61a7e1..389932ac1151 100644 --- a/sys/contrib/dev/acpica/include/actbl2.h +++ b/sys/contrib/dev/acpica/include/actbl2.h @@ -1376,14 +1376,28 @@ enum AcpiSpmiInterfaceTypes * December 19, 2014 * * NOTE: There are two versions of the table with the same signature -- - * the client version and the server version. + * the client version and the server version. The common PlatformClass + * field is used to differentiate the two types of tables. * ******************************************************************************/ -typedef struct acpi_table_tcpa_client +typedef struct acpi_table_tcpa_hdr { ACPI_TABLE_HEADER Header; /* Common ACPI table header */ UINT16 PlatformClass; + +} ACPI_TABLE_TCPA_HDR; + +/* + * Values for PlatformClass above. + * This is how the client and server subtables are differentiated + */ +#define ACPI_TCPA_CLIENT_TABLE 0 +#define ACPI_TCPA_SERVER_TABLE 1 + + +typedef struct acpi_table_tcpa_client +{ UINT32 MinimumLogLength; /* Minimum length for the event log area */ UINT64 LogAddress; /* Address of the event log area */ @@ -1391,8 +1405,6 @@ typedef struct acpi_table_tcpa_client typedef struct acpi_table_tcpa_server { - ACPI_TABLE_HEADER Header; /* Common ACPI table header */ - UINT16 PlatformClass; UINT16 Reserved; UINT64 MinimumLogLength; /* Minimum length for the event log area */ UINT64 LogAddress; /* Address of the event log area */ diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h index 837c784d6da2..dbc8e3a7c95b 100644 --- a/sys/contrib/dev/acpica/include/actypes.h +++ b/sys/contrib/dev/acpica/include/actypes.h @@ -1022,7 +1022,8 @@ typedef struct acpi_buffer */ #define ACPI_FULL_PATHNAME 0 #define ACPI_SINGLE_NAME 1 -#define ACPI_NAME_TYPE_MAX 1 +#define ACPI_FULL_PATHNAME_NO_TRAILING 2 +#define ACPI_NAME_TYPE_MAX 2 /* @@ -1345,6 +1346,17 @@ typedef struct acpi_memory_list } ACPI_MEMORY_LIST; +/* Definitions of trace event types */ + +typedef enum +{ + ACPI_TRACE_AML_METHOD, + ACPI_TRACE_AML_OPCODE, + ACPI_TRACE_AML_REGION + +} ACPI_TRACE_EVENT_TYPE; + + /* Definitions of _OSI support */ #define ACPI_VENDOR_STRINGS 0x01 diff --git a/sys/contrib/dev/acpica/include/acutils.h b/sys/contrib/dev/acpica/include/acutils.h index b7c2a64a2c92..a2bcf2faf106 100644 --- a/sys/contrib/dev/acpica/include/acutils.h +++ b/sys/contrib/dev/acpica/include/acutils.h @@ -173,6 +173,30 @@ typedef struct acpi_pkg_info #define DB_DWORD_DISPLAY 4 #define DB_QWORD_DISPLAY 8 + +/* + * utnonansi - Non-ANSI C library functions + */ +void +AcpiUtStrupr ( + char *SrcString); + +void +AcpiUtStrlwr ( + char *SrcString); + +int +AcpiUtStricmp ( + char *String1, + char *String2); + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger); + + /* * utglobal - Global data structures and procedures */ @@ -246,8 +270,6 @@ AcpiUtSubsystemShutdown ( void); -#define ACPI_IS_ASCII(c) ((c) < 0x80) - /* * utcopy - Object construction and conversion interfaces */ @@ -407,6 +429,7 @@ AcpiUtReportWarning ( char *ModuleName, UINT32 LineNumber); + /* * utdelete - Object deletion and reference counts */ @@ -732,11 +755,11 @@ AcpiUtWalkPackageTree ( ACPI_PKG_CALLBACK WalkCallback, void *Context); - /* Values for Base above (16=Hex, 10=Decimal) */ #define ACPI_ANY_BASE 0 + UINT32 AcpiUtDwordByteSwap ( UINT32 Value); @@ -809,27 +832,6 @@ AcpiUtGetResourceEndTag ( * utstring - String and character utilities */ void -AcpiUtStrupr ( - char *SrcString); - -#ifdef ACPI_ASL_COMPILER -void -AcpiUtStrlwr ( - char *SrcString); - -int -AcpiUtStricmp ( - char *String1, - char *String2); -#endif - -ACPI_STATUS -AcpiUtStrtoul64 ( - char *String, - UINT32 Base, - UINT64 *RetInteger); - -void AcpiUtPrintString ( char *String, UINT16 MaxLength); @@ -956,6 +958,7 @@ AcpiUtCreateList ( #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + /* * utaddress - address range check */ @@ -982,6 +985,7 @@ void AcpiUtDeleteAddressLists ( void); + /* * utxferror - various error/warning output functions */ @@ -1028,6 +1032,7 @@ AcpiUtMethodError ( const char *Path, ACPI_STATUS LookupStatus); + /* * Utility functions for ACPI names and IDs */ @@ -1043,6 +1048,7 @@ const char * AcpiAhMatchUuid ( UINT8 *Data); + /* * utprint - printf/vprintf output functions */ @@ -1084,6 +1090,7 @@ AcpiUtFilePrintf ( ...); #endif + /* * utuuid -- UUID support functions */ diff --git a/sys/contrib/dev/acpica/include/platform/acenvex.h b/sys/contrib/dev/acpica/include/platform/acenvex.h index c799fd8adbbe..12fec1279bf4 100644 --- a/sys/contrib/dev/acpica/include/platform/acenvex.h +++ b/sys/contrib/dev/acpica/include/platform/acenvex.h @@ -56,6 +56,9 @@ #if defined(_LINUX) || defined(__linux__) #include "aclinuxex.h" +#elif defined(WIN32) +#include "acwinex.h" + #elif defined(_AED_EFI) #include "acefiex.h" diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index d5d15daa66ff..92f1292f0258 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -3664,7 +3664,7 @@ acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify) handle_buf.Pointer = NULL; handle_buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiNsHandleToPathname(h, &handle_buf); + status = AcpiNsHandleToPathname(h, &handle_buf, FALSE); if (ACPI_FAILURE(status)) return; snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", notify); diff --git a/sys/dev/cyapa/cyapa.c b/sys/dev/cyapa/cyapa.c new file mode 100644 index 000000000000..2cf10630f42c --- /dev/null +++ b/sys/dev/cyapa/cyapa.c @@ -0,0 +1,1707 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported, + * modified and enhanced for FreeBSD by Michael Gmelin . + * + * 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 DragonFly Project 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS 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$"); + +/* + * CYAPA - Cypress APA trackpad with I2C Interface driver + * + * Based on DragonFlyBSD's cyapa driver, which referenced the linux + * cyapa.c driver to figure out the bootstrapping and commands. + * + * Unable to locate any datasheet for the device. + * + * + * Trackpad layout: + * + * 2/3 1/3 + * +--------------------+------------+ + * | | Middle | + * | | Button | + * | Left | | + * | Button +------------+ + * | | Right | + * | | Button | + * +--------------------+............| + * | Thumb/Button Area | 15% + * +---------------------------------+ + * + * + * FEATURES + * + * IMPS/2 emulation - Emulates the IntelliMouse protocol. + * + * Jitter supression - Implements 2-pixel hysteresis with memory. + * + * Jump detecion - Detect jumps caused by touchpad. + * + * Two finger scrolling - Use two fingers for Z axis scrolling. + * + * Button down/2nd finger - While one finger clicks and holds down the + * touchpad, the second one can be used to move + * the mouse cursor. Useful for drawing or + * selecting text. + * + * Thumb/Button Area - The lower 15%* of the trackpad will not affect + * the mouse cursor position. This allows for high + * precision clicking, by controlling the cursor + * with the index finger and pushing/holding the + * pad down with the thumb. + * * can be changed using sysctl + * + * Track-pad button - Push physical button. Left 2/3rds of the pad + * will issue a LEFT button event, upper right + * corner will issue a MIDDLE button event, + * lower right corner will issue a RIGHT button + * event. Optional tap support can be enabled + * and configured using sysctl. + * + * WARNINGS + * + * These trackpads get confused when three or more fingers are down on the + * same horizontal axis and will start to glitch the finger detection. + * Removing your hand for a few seconds will allow the trackpad to + * recalibrate. Generally speaking, when using three or more fingers + * please try to place at least one finger off-axis (a little above or + * below) the other two. + */ + +#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 "smbus_if.h" +#include "bus_if.h" +#include "device_if.h" + +#define CYAPA_BUFSIZE 128 /* power of 2 */ +#define CYAPA_BUFMASK (CYAPA_BUFSIZE - 1) + +#define ZSCALE 15 + +#define TIME_TO_IDLE (hz * 10) +#define TIME_TO_RESET (hz * 3) + +static MALLOC_DEFINE(M_CYAPA, "cyapa", "CYAPA device data"); + +struct cyapa_fifo { + int rindex; + int windex; + char buf[CYAPA_BUFSIZE]; +}; + +struct cyapa_softc { + device_t dev; + int count; /* >0 if device opened */ + int unit; + int addr; + struct cdev *devnode; + struct selinfo selinfo; + struct mtx mutex; + + int cap_resx; + int cap_resy; + int cap_phyx; + int cap_phyy; + uint8_t cap_buttons; + + int detaching; /* driver is detaching */ + int poll_thread_running; /* poll thread is running */ + + /* PS/2 mouse emulation */ + int track_x; /* current tracking */ + int track_y; + int track_z; + int track_z_ticks; + uint16_t track_but; + char track_id; /* first finger id */ + int track_nfingers; + int delta_x; /* accumulation -> report */ + int delta_y; + int delta_z; + int fuzz_x; + int fuzz_y; + int fuzz_z; + int touch_x; /* touch down coordinates */ + int touch_y; + int touch_z; + int finger1_ticks; + int finger2_ticks; + int finger3_ticks; + uint16_t reported_but; + + struct cyapa_fifo rfifo; /* device->host */ + struct cyapa_fifo wfifo; /* host->device */ + uint8_t ps2_cmd; /* active p2_cmd waiting for data */ + uint8_t ps2_acked; + int active_tick; + int data_signal; + int blocked; + int isselect; + int reporting_mode; /* 0=disabled 1=enabled */ + int scaling_mode; /* 0=1:1 1=2:1 */ + int remote_mode; /* 0 for streaming mode */ + int zenabled; /* z-axis enabled (mode 1 or 2) */ + mousehw_t hw; /* hardware information */ + mousemode_t mode; /* mode */ + int poll_ticks; +}; + +struct cyapa_cdevpriv { + struct cyapa_softc *sc; +}; + +#define CYPOLL_SHUTDOWN 0x0001 + +static void cyapa_poll_thread(void *arg); +static int cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs, + int freq); +static void cyapa_set_power_mode(struct cyapa_softc *sc, int mode); + +static int fifo_empty(struct cyapa_softc *sc, struct cyapa_fifo *fifo); +static size_t fifo_ready(struct cyapa_softc *sc, struct cyapa_fifo *fifo); +static char *fifo_read(struct cyapa_softc *sc, struct cyapa_fifo *fifo, + size_t n); +static char *fifo_write(struct cyapa_softc *sc, struct cyapa_fifo *fifo, + size_t n); +static uint8_t fifo_read_char(struct cyapa_softc *sc, + struct cyapa_fifo *fifo); +static void fifo_write_char(struct cyapa_softc *sc, struct cyapa_fifo *fifo, + uint8_t c); +static size_t fifo_space(struct cyapa_softc *sc, struct cyapa_fifo *fifo); +static void fifo_reset(struct cyapa_softc *sc, struct cyapa_fifo *fifo); + +static int cyapa_fuzz(int delta, int *fuzz); + +static int cyapa_idle_freq = 1; +SYSCTL_INT(_debug, OID_AUTO, cyapa_idle_freq, CTLFLAG_RW, + &cyapa_idle_freq, 0, "Scan frequency in idle mode"); +static int cyapa_slow_freq = 20; +SYSCTL_INT(_debug, OID_AUTO, cyapa_slow_freq, CTLFLAG_RW, + &cyapa_slow_freq, 0, "Scan frequency in slow mode "); +static int cyapa_norm_freq = 100; +SYSCTL_INT(_debug, OID_AUTO, cyapa_norm_freq, CTLFLAG_RW, + &cyapa_norm_freq, 0, "Normal scan frequency"); +static int cyapa_minpressure = 12; +SYSCTL_INT(_debug, OID_AUTO, cyapa_minpressure, CTLFLAG_RW, + &cyapa_minpressure, 0, "Minimum pressure to detect finger"); +static int cyapa_enable_tapclick = 0; +SYSCTL_INT(_debug, OID_AUTO, cyapa_enable_tapclick, CTLFLAG_RW, + &cyapa_enable_tapclick, 0, "Enable tap to click"); +static int cyapa_tapclick_min_ticks = 1; +SYSCTL_INT(_debug, OID_AUTO, cyapa_tapclick_min_ticks, CTLFLAG_RW, + &cyapa_tapclick_min_ticks, 0, "Minimum tap duration for click"); +static int cyapa_tapclick_max_ticks = 8; +SYSCTL_INT(_debug, OID_AUTO, cyapa_tapclick_max_ticks, CTLFLAG_RW, + &cyapa_tapclick_max_ticks, 0, "Maximum tap duration for click"); +static int cyapa_move_min_ticks = 4; +SYSCTL_INT(_debug, OID_AUTO, cyapa_move_min_ticks, CTLFLAG_RW, + &cyapa_move_min_ticks, 0, + "Minimum ticks before cursor position is changed"); +static int cyapa_scroll_wait_ticks = 0; +SYSCTL_INT(_debug, OID_AUTO, cyapa_scroll_wait_ticks, CTLFLAG_RW, + &cyapa_scroll_wait_ticks, 0, + "Wait N ticks before starting to scroll"); +static int cyapa_scroll_stick_ticks = 15; +SYSCTL_INT(_debug, OID_AUTO, cyapa_scroll_stick_ticks, CTLFLAG_RW, + &cyapa_scroll_stick_ticks, 0, + "Prevent cursor move on single finger for N ticks after scroll"); +static int cyapa_thumbarea_percent = 15; +SYSCTL_INT(_debug, OID_AUTO, cyapa_thumbarea_percent, CTLFLAG_RW, + &cyapa_thumbarea_percent, 0, + "Size of bottom thumb area in percent"); + +static int cyapa_debug = 0; +SYSCTL_INT(_debug, OID_AUTO, cyapa_debug, CTLFLAG_RW, + &cyapa_debug, 0, "Enable debugging"); +static int cyapa_reset = 0; +SYSCTL_INT(_debug, OID_AUTO, cyapa_reset, CTLFLAG_RW, + &cyapa_reset, 0, "Reset track pad"); + +static void +cyapa_lock(struct cyapa_softc *sc) +{ + + mtx_lock(&sc->mutex); +} + +static void +cyapa_unlock(struct cyapa_softc *sc) +{ + + mtx_unlock(&sc->mutex); +} + +#define CYAPA_LOCK_ASSERT(sc) mtx_assert(&(sc)->mutex, MA_OWNED); + +/* + * Notify if possible receive data ready. Must be called + * with sc->mutex held (cyapa_lock(sc)). + */ +static void +cyapa_notify(struct cyapa_softc *sc) +{ + + CYAPA_LOCK_ASSERT(sc); + + if (sc->data_signal || !fifo_empty(sc, &sc->rfifo)) { + KNOTE_LOCKED(&sc->selinfo.si_note, 0); + if (sc->blocked || sc->isselect) { + if (sc->blocked) { + sc->blocked = 0; + wakeup(&sc->blocked); + } + if (sc->isselect) { + sc->isselect = 0; + selwakeup(&sc->selinfo); + } + } + } +} + +/* + * Initialize the device + */ +static int +init_device(device_t dev, struct cyapa_cap *cap, int addr, int probe) +{ + static char bl_exit[] = { + 0x00, 0xff, 0xa5, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + static char bl_deactivate[] = { + 0x00, 0xff, 0x3b, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + device_t bus; + struct cyapa_boot_regs boot; + int error; + int retries; + + bus = device_get_parent(dev); /* smbus */ + + /* Get status */ + error = smbus_trans(bus, addr, CMD_BOOT_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, (void *)&boot, sizeof(boot), NULL); + if (error) + goto done; + + /* + * Bootstrap the device if necessary. It can take up to 2 seconds + * for the device to fully initialize. + */ + retries = 20; + while ((boot.stat & CYAPA_STAT_RUNNING) == 0 && retries > 0) { + if (boot.boot & CYAPA_BOOT_BUSY) { + /* Busy, wait loop. */ + } else if (boot.error & CYAPA_ERROR_BOOTLOADER) { + /* Magic */ + error = smbus_trans(bus, addr, CMD_BOOT_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + bl_deactivate, sizeof(bl_deactivate), + NULL, 0, NULL); + if (error) + goto done; + } else { + /* Magic */ + error = smbus_trans(bus, addr, CMD_BOOT_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + bl_exit, sizeof(bl_exit), NULL, 0, NULL); + if (error) + goto done; + } + pause("cyapab1", (hz * 2) / 10); + --retries; + error = smbus_trans(bus, addr, CMD_BOOT_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, (void *)&boot, sizeof(boot), NULL); + if (error) + goto done; + } + + if (retries == 0) { + device_printf(dev, "Unable to bring device out of bootstrap\n"); + error = ENXIO; + goto done; + } + + /* Check identity */ + if (cap) { + error = smbus_trans(bus, addr, CMD_QUERY_CAPABILITIES, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, (void *)cap, sizeof(*cap), NULL); + + if (strncmp(cap->prod_ida, "CYTRA", 5) != 0) { + device_printf(dev, "Product ID \"%5.5s\" mismatch\n", + cap->prod_ida); + error = ENXIO; + } + } + error = smbus_trans(bus, addr, CMD_BOOT_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, (void *)&boot, sizeof(boot), NULL); + + if (probe == 0) /* official init */ + device_printf(dev, "cyapa init status %02x\n", boot.stat); + else if (probe == 2) + device_printf(dev, "cyapa reset status %02x\n", boot.stat); + +done: + if (error) + device_printf(dev, "Unable to initialize\n"); + return (error); +} + +static int cyapa_probe(device_t); +static int cyapa_attach(device_t); +static int cyapa_detach(device_t); +static void cyapa_cdevpriv_dtor(void*); + +static devclass_t cyapa_devclass; + +static device_method_t cyapa_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, cyapa_probe), + DEVMETHOD(device_attach, cyapa_attach), + DEVMETHOD(device_detach, cyapa_detach), + + DEVMETHOD_END +}; + +static driver_t cyapa_driver = { + "cyapa", + cyapa_methods, + sizeof(struct cyapa_softc), +}; + +static d_open_t cyapaopen; +static d_ioctl_t cyapaioctl; +static d_read_t cyaparead; +static d_write_t cyapawrite; +static d_kqfilter_t cyapakqfilter; +static d_poll_t cyapapoll; + +static struct cdevsw cyapa_cdevsw = { + .d_version = D_VERSION, + .d_open = cyapaopen, + .d_ioctl = cyapaioctl, + .d_read = cyaparead, + .d_write = cyapawrite, + .d_kqfilter = cyapakqfilter, + .d_poll = cyapapoll, +}; + +static int +cyapa_probe(device_t dev) +{ + struct cyapa_cap cap; + int unit; + int addr; + int error; + + addr = smbus_get_addr(dev); + + /* + * 0x67 - cypress trackpad on the acer c720 + * (other devices might use other ids). + */ + if (addr != 0x67) + return (ENXIO); + + unit = device_get_unit(dev); + + error = init_device(dev, &cap, addr, 1); + if (error != 0) + return (ENXIO); + + device_set_desc(dev, "Cypress APA I2C Trackpad"); + + return (BUS_PROBE_VENDOR); +} + +static int +cyapa_attach(device_t dev) +{ + struct cyapa_softc *sc; + struct cyapa_cap cap; + int unit; + int addr; + + sc = device_get_softc(dev); + sc->reporting_mode = 1; + + unit = device_get_unit(dev); + addr = *((unsigned char*) device_get_ivars(dev)); + + if (init_device(dev, &cap, addr, 0)) + return (ENXIO); + + mtx_init(&sc->mutex, "cyapa", NULL, MTX_DEF); + + sc->dev = dev; + sc->unit = unit; + sc->addr = addr; + + knlist_init_mtx(&sc->selinfo.si_note, &sc->mutex); + + sc->cap_resx = ((cap.max_abs_xy_high << 4) & 0x0F00) | + cap.max_abs_x_low; + sc->cap_resy = ((cap.max_abs_xy_high << 8) & 0x0F00) | + cap.max_abs_y_low; + sc->cap_phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) | + cap.phy_siz_x_low; + sc->cap_phyy = ((cap.phy_siz_xy_high << 8) & 0x0F00) | + cap.phy_siz_y_low; + sc->cap_buttons = cap.buttons; + + device_printf(dev, "%5.5s-%6.6s-%2.2s buttons=%c%c%c res=%dx%d\n", + cap.prod_ida, cap.prod_idb, cap.prod_idc, + ((cap.buttons & CYAPA_FNGR_LEFT) ? 'L' : '-'), + ((cap.buttons & CYAPA_FNGR_MIDDLE) ? 'M' : '-'), + ((cap.buttons & CYAPA_FNGR_RIGHT) ? 'R' : '-'), + sc->cap_resx, sc->cap_resy); + + sc->hw.buttons = 5; + sc->hw.iftype = MOUSE_IF_PS2; + sc->hw.type = MOUSE_MOUSE; + sc->hw.model = MOUSE_MODEL_INTELLI; + sc->hw.hwid = addr; + + sc->mode.protocol = MOUSE_PROTO_PS2; + sc->mode.rate = 100; + sc->mode.resolution = 4; + sc->mode.accelfactor = 1; + sc->mode.level = 0; + sc->mode.packetsize = MOUSE_PS2_PACKETSIZE; + + /* Setup input event tracking */ + cyapa_set_power_mode(sc, CMD_POWER_MODE_IDLE); + + /* Start the polling thread */ + kthread_add(cyapa_poll_thread, sc, NULL, NULL, + 0, 0, "cyapa-poll"); + + sc->devnode = make_dev(&cyapa_cdevsw, unit, + UID_ROOT, GID_WHEEL, 0600, "cyapa%d", unit); + + sc->devnode->si_drv1 = sc; + + return (0); +} + +static int +cyapa_detach(device_t dev) +{ + struct cyapa_softc *sc; + + sc = device_get_softc(dev); + + /* Cleanup poller thread */ + cyapa_lock(sc); + while (sc->poll_thread_running) { + sc->detaching = 1; + mtx_sleep(&sc->detaching, &sc->mutex, PCATCH, "cyapadet", hz); + } + cyapa_unlock(sc); + + destroy_dev(sc->devnode); + + knlist_clear(&sc->selinfo.si_note, 0); + seldrain(&sc->selinfo); + knlist_destroy(&sc->selinfo.si_note); + + mtx_destroy(&sc->mutex); + + return (0); +} + +/* + * USER DEVICE I/O FUNCTIONS + */ +static int +cyapaopen(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + struct cyapa_cdevpriv *priv; + int error; + + priv = malloc(sizeof(*priv), M_CYAPA, M_WAITOK | M_ZERO); + priv->sc = dev->si_drv1; + + error = devfs_set_cdevpriv(priv, cyapa_cdevpriv_dtor); + if (error == 0) { + cyapa_lock(priv->sc); + priv->sc->count++; + cyapa_unlock(priv->sc); + } + else + free(priv, M_CYAPA); + + return (error); +} + +static void +cyapa_cdevpriv_dtor(void *data) +{ + struct cyapa_cdevpriv *priv; + + priv = data; + KASSERT(priv != NULL, ("cyapa cdevpriv should not be NULL!")); + + cyapa_lock(priv->sc); + priv->sc->count--; + cyapa_unlock(priv->sc); + + free(priv, M_CYAPA); +} + +static int +cyaparead(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct cyapa_softc *sc; + int error; + int didread; + size_t n; + char* ptr; + + sc = dev->si_drv1; + /* If buffer is empty, load a new event if it is ready */ + cyapa_lock(sc); +again: + if (fifo_empty(sc, &sc->rfifo) && + (sc->data_signal || sc->delta_x || sc->delta_y || + sc->track_but != sc->reported_but)) { + uint8_t c0; + uint16_t but; + int delta_x; + int delta_y; + int delta_z; + + /* Accumulate delta_x, delta_y */ + sc->data_signal = 0; + delta_x = sc->delta_x; + delta_y = sc->delta_y; + delta_z = sc->delta_z; + if (delta_x > 255) { + delta_x = 255; + sc->data_signal = 1; + } + if (delta_x < -256) { + delta_x = -256; + sc->data_signal = 1; + } + if (delta_y > 255) { + delta_y = 255; + sc->data_signal = 1; + } + if (delta_y < -256) { + delta_y = -256; + sc->data_signal = 1; + } + if (delta_z > 255) { + delta_z = 255; + sc->data_signal = 1; + } + if (delta_z < -256) { + delta_z = -256; + sc->data_signal = 1; + } + but = sc->track_but; + + /* Adjust baseline for next calculation */ + sc->delta_x -= delta_x; + sc->delta_y -= delta_y; + sc->delta_z -= delta_z; + sc->reported_but = but; + + /* + * Fuzz reduces movement jitter by introducing some + * hysteresis. It operates without cumulative error so + * if you swish around quickly and return your finger to + * where it started, so to will the mouse. + */ + delta_x = cyapa_fuzz(delta_x, &sc->fuzz_x); + delta_y = cyapa_fuzz(delta_y, &sc->fuzz_y); + delta_z = cyapa_fuzz(delta_z, &sc->fuzz_z); + + /* + * Generate report + */ + c0 = 0; + if (delta_x < 0) + c0 |= 0x10; + if (delta_y < 0) + c0 |= 0x20; + c0 |= 0x08; + if (but & CYAPA_FNGR_LEFT) + c0 |= 0x01; + if (but & CYAPA_FNGR_MIDDLE) + c0 |= 0x04; + if (but & CYAPA_FNGR_RIGHT) + c0 |= 0x02; + + fifo_write_char(sc, &sc->rfifo, c0); + fifo_write_char(sc, &sc->rfifo, (uint8_t)delta_x); + fifo_write_char(sc, &sc->rfifo, (uint8_t)delta_y); + switch(sc->zenabled) { + case 1: + /* Z axis all 8 bits */ + fifo_write_char(sc, &sc->rfifo, (uint8_t)delta_z); + break; + case 2: + /* + * Z axis low 4 bits + 4th button and 5th button + * (high 2 bits must be left 0). Auto-scale + * delta_z to fit to avoid a wrong-direction + * overflow (don't try to retain the remainder). + */ + while (delta_z > 7 || delta_z < -8) + delta_z >>= 1; + c0 = (uint8_t)delta_z & 0x0F; + fifo_write_char(sc, &sc->rfifo, c0); + break; + default: + /* basic PS/2 */ + break; + } + cyapa_notify(sc); + } + + /* Blocking / Non-blocking */ + error = 0; + didread = (uio->uio_resid == 0); + + while ((ioflag & IO_NDELAY) == 0 && fifo_empty(sc, &sc->rfifo)) { + if (sc->data_signal) + goto again; + sc->blocked = 1; + error = mtx_sleep(&sc->blocked, &sc->mutex, PCATCH, "cyablk", 0); + if (error) + break; + } + + /* Return any buffered data */ + while (error == 0 && uio->uio_resid && + (n = fifo_ready(sc, &sc->rfifo)) > 0) { + if (n > uio->uio_resid) + n = uio->uio_resid; + ptr = fifo_read(sc, &sc->rfifo, 0); + cyapa_unlock(sc); + error = uiomove(ptr, n, uio); + cyapa_lock(sc); + if (error) + break; + fifo_read(sc, &sc->rfifo, n); + didread = 1; + } + cyapa_unlock(sc); + + if (error == 0 && didread == 0) { + error = EWOULDBLOCK; + } + return (didread ? 0 : error); +} + +static int +cyapawrite(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct cyapa_softc *sc; + int error; + int cmd_completed; + size_t n; + uint8_t c0; + char* ptr; + + sc = dev->si_drv1; +again: + /* + * Copy data from userland. This will also cross-over the end + * of the fifo and keep filling. + */ + cyapa_lock(sc); + while ((n = fifo_space(sc, &sc->wfifo)) > 0 && uio->uio_resid) { + if (n > uio->uio_resid) + n = uio->uio_resid; + ptr = fifo_write(sc, &sc->wfifo, 0); + cyapa_unlock(sc); + error = uiomove(ptr, n, uio); + cyapa_lock(sc); + if (error) + break; + fifo_write(sc, &sc->wfifo, n); + } + + /* Handle commands */ + cmd_completed = (fifo_ready(sc, &sc->wfifo) != 0); + while (fifo_ready(sc, &sc->wfifo) && cmd_completed && error == 0) { + if (sc->ps2_cmd == 0) + sc->ps2_cmd = fifo_read_char(sc, &sc->wfifo); + switch(sc->ps2_cmd) { + case 0xE6: + /* SET SCALING 1:1 */ + sc->scaling_mode = 0; + fifo_write_char(sc, &sc->rfifo, 0xFA); + break; + case 0xE7: + /* SET SCALING 2:1 */ + sc->scaling_mode = 1; + fifo_write_char(sc, &sc->rfifo, 0xFA); + break; + case 0xE8: + /* SET RESOLUTION +1 byte */ + if (sc->ps2_acked == 0) { + sc->ps2_acked = 1; + fifo_write_char(sc, &sc->rfifo, 0xFA); + } + if (fifo_ready(sc, &sc->wfifo) == 0) { + cmd_completed = 0; + break; + } + sc->mode.resolution = fifo_read_char(sc, &sc->wfifo); + fifo_write_char(sc, &sc->rfifo, 0xFA); + break; + case 0xE9: + /* + * STATUS REQUEST + * + * byte1: + * bit 7 0 + * bit 6 Mode (1=remote mode, 0=stream mode) + * bit 5 Enable (data reporting enabled) + * bit 4 Scaling (0=1:1 1=2:1) + * bit 3 0 + * bit 2 LEFT BUTTON (1 if pressed) + * bit 1 MIDDLE BUTTON (1 if pressed) + * bit 0 RIGHT BUTTON (1 if pressed) + * + * byte2: resolution counts/mm + * byte3: sample rate + */ + c0 = 0; + if (sc->remote_mode) + c0 |= 0x40; + if (sc->reporting_mode) + c0 |= 0x20; + if (sc->scaling_mode) + c0 |= 0x10; + if (sc->track_but & CYAPA_FNGR_LEFT) + c0 |= 0x04; + if (sc->track_but & CYAPA_FNGR_MIDDLE) + c0 |= 0x02; + if (sc->track_but & CYAPA_FNGR_RIGHT) + c0 |= 0x01; + fifo_write_char(sc, &sc->rfifo, 0xFA); + fifo_write_char(sc, &sc->rfifo, c0); + fifo_write_char(sc, &sc->rfifo, 0x00); + fifo_write_char(sc, &sc->rfifo, 100); + break; + case 0xEA: + /* Set stream mode and reset movement counters */ + sc->remote_mode = 0; + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->delta_x = 0; + sc->delta_y = 0; + sc->delta_z = 0; + break; + case 0xEB: + /* + * Read Data (if in remote mode). If not in remote + * mode force an event. + */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->data_signal = 1; + break; + case 0xEC: + /* Reset Wrap Mode (ignored) */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + break; + case 0xEE: + /* Set Wrap Mode (ignored) */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + break; + case 0xF0: + /* Set Remote Mode */ + sc->remote_mode = 1; + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->delta_x = 0; + sc->delta_y = 0; + sc->delta_z = 0; + break; + case 0xF2: + /* + * Get Device ID + * + * If we send 0x00 - normal PS/2 mouse, no Z-axis + * + * If we send 0x03 - Intellimouse, data packet has + * an additional Z movement byte (8 bits signed). + * (also reset movement counters) + * + * If we send 0x04 - Now includes z-axis and the + * 4th and 5th mouse buttons. + */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + switch(sc->zenabled) { + case 1: + fifo_write_char(sc, &sc->rfifo, 0x03); + break; + case 2: + fifo_write_char(sc, &sc->rfifo, 0x04); + break; + default: + fifo_write_char(sc, &sc->rfifo, 0x00); + break; + } + sc->delta_x = 0; + sc->delta_y = 0; + sc->delta_z = 0; + break; + case 0xF3: + /* + * Set Sample Rate + * + * byte1: the sample rate + */ + if (sc->ps2_acked == 0) { + sc->ps2_acked = 1; + fifo_write_char(sc, &sc->rfifo, 0xFA); + } + if (fifo_ready(sc, &sc->wfifo) == 0) { + cmd_completed = 0; + break; + } + sc->mode.rate = fifo_read_char(sc, &sc->wfifo); + fifo_write_char(sc, &sc->rfifo, 0xFA); + + /* + * zenabling sequence: 200,100,80 (device id 0x03) + * 200,200,80 (device id 0x04) + * + * We support id 0x03 (no 4th or 5th button). + * We support id 0x04 (w/ 4th and 5th button). + */ + if (sc->zenabled == 0 && sc->mode.rate == 200) + sc->zenabled = -1; + else if (sc->zenabled == -1 && sc->mode.rate == 100) + sc->zenabled = -2; + else if (sc->zenabled == -1 && sc->mode.rate == 200) + sc->zenabled = -3; + else if (sc->zenabled == -2 && sc->mode.rate == 80) + sc->zenabled = 1; /* z-axis mode */ + else if (sc->zenabled == -3 && sc->mode.rate == 80) + sc->zenabled = 2; /* z-axis+but4/5 */ + if (sc->mode.level) + sc->zenabled = 1; + break; + case 0xF4: + /* Enable data reporting. Only effects stream mode. */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->reporting_mode = 1; + break; + case 0xF5: + /* + * Disable data reporting. Only effects stream mode + * and is ignored right now. + */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->reporting_mode = 1; + break; + case 0xF6: + /* + * SET DEFAULTS + * + * (reset sampling rate, resolution, scaling and + * enter stream mode) + */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->mode.rate = 100; + sc->mode.resolution = 4; + sc->scaling_mode = 0; + sc->reporting_mode = 1; + sc->remote_mode = 0; + sc->delta_x = 0; + sc->delta_y = 0; + sc->delta_z = 0; + /* signal */ + break; + case 0xFE: + /* + * RESEND + * + * Force a resend by guaranteeing that reported_but + * differs from track_but. + */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->data_signal = 1; + break; + case 0xFF: + /* + * RESET + */ + fifo_reset(sc, &sc->rfifo); /* should we do this? */ + fifo_reset(sc, &sc->wfifo); /* should we do this? */ + fifo_write_char(sc, &sc->rfifo, 0xFA); + sc->delta_x = 0; + sc->delta_y = 0; + sc->delta_z = 0; + sc->zenabled = 0; + sc->mode.level = 0; + break; + default: + printf("unknown command %02x\n", sc->ps2_cmd); + break; + } + if (cmd_completed) { + sc->ps2_cmd = 0; + sc->ps2_acked = 0; + } + cyapa_notify(sc); + } + cyapa_unlock(sc); + if (error == 0 && (cmd_completed || uio->uio_resid)) + goto again; + return (error); +} + +static void cyapafiltdetach(struct knote *); +static int cyapafilt(struct knote *, long); + +static struct filterops cyapa_filtops = { + .f_isfd = 1, + .f_detach = cyapafiltdetach, + .f_event = cyapafilt +}; + +static int +cyapakqfilter(struct cdev *dev, struct knote *kn) +{ + struct cyapa_softc *sc; + struct knlist *knlist; + + sc = dev->si_drv1; + + switch(kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &cyapa_filtops; + kn->kn_hook = (void *)sc; + break; + default: + return (EOPNOTSUPP); + } + knlist = &sc->selinfo.si_note; + knlist_add(knlist, kn, 0); + + return (0); +} + +static int +cyapapoll(struct cdev *dev, int events, struct thread *td) +{ + struct cyapa_softc *sc; + int revents; + + sc = dev->si_drv1; + revents = 0; + + cyapa_lock(sc); + if (events & (POLLIN | POLLRDNORM)) { + if (sc->data_signal || !fifo_empty(sc, &sc->rfifo)) + revents = events & (POLLIN | POLLRDNORM); + else { + sc->isselect = 1; + selrecord(td, &sc->selinfo); + } + } + cyapa_unlock(sc); + + return (revents); +} + +static void +cyapafiltdetach(struct knote *kn) +{ + struct cyapa_softc *sc; + struct knlist *knlist; + + sc = (struct cyapa_softc *)kn->kn_hook; + + knlist = &sc->selinfo.si_note; + knlist_remove(knlist, kn, 0); +} + +static int +cyapafilt(struct knote *kn, long hint) +{ + struct cyapa_softc *sc; + int ready; + + sc = (struct cyapa_softc *)kn->kn_hook; + + cyapa_lock(sc); + ready = fifo_ready(sc, &sc->rfifo) || sc->data_signal; + cyapa_unlock(sc); + + return (ready); +} + +static int +cyapaioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) +{ + struct cyapa_softc *sc; + int error; + + sc = dev->si_drv1; + error = 0; + + cyapa_lock(sc); + switch (cmd) { + case MOUSE_GETHWINFO: + *(mousehw_t *)data = sc->hw; + if (sc->mode.level == 0) + ((mousehw_t *)data)->model = MOUSE_MODEL_GENERIC; + break; + + case MOUSE_GETMODE: + *(mousemode_t *)data = sc->mode; + ((mousemode_t *)data)->resolution = + MOUSE_RES_LOW - sc->mode.resolution; + switch (sc->mode.level) { + case 0: + ((mousemode_t *)data)->protocol = MOUSE_PROTO_PS2; + ((mousemode_t *)data)->packetsize = + MOUSE_PS2_PACKETSIZE; + break; + case 2: + ((mousemode_t *)data)->protocol = MOUSE_PROTO_PS2; + ((mousemode_t *)data)->packetsize = + MOUSE_PS2_PACKETSIZE + 1; + break; + } + break; + + case MOUSE_GETLEVEL: + *(int *)data = sc->mode.level; + break; + + case MOUSE_SETLEVEL: + if ((*(int *)data < 0) && + (*(int *)data > 2)) { + error = EINVAL; + break; + } + sc->mode.level = *(int *)data ? 2 : 0; + sc->zenabled = sc->mode.level ? 1 : 0; + break; + + default: + error = ENOTTY; + break; + } + cyapa_unlock(sc); + + return (error); +} + +/* + * MAJOR SUPPORT FUNCTIONS + */ +static void +cyapa_poll_thread(void *arg) +{ + struct cyapa_softc *sc; + struct cyapa_regs regs; + device_t bus; /* smbus */ + int error; + int freq; + int isidle; + int pstate; + int npstate; + int last_reset; + + sc = arg; + freq = cyapa_norm_freq; + isidle = 0; + pstate = CMD_POWER_MODE_IDLE; + last_reset = ticks; + + bus = device_get_parent(sc->dev); + + cyapa_lock(sc); + sc->poll_thread_running = 1; + + while (!sc->detaching) { + cyapa_unlock(sc); + error = smbus_request_bus(bus, sc->dev, SMB_WAIT); + if (error == 0) { + error = smbus_trans(bus, sc->addr, CMD_DEV_STATUS, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, + (void *)®s, sizeof(regs), NULL); + if (error == 0) { + isidle = cyapa_raw_input(sc, ®s, freq); + } + + /* + * For some reason the device can crap-out. If it + * drops back into bootstrap mode try to reinitialize + * it. + */ + if (cyapa_reset || + ((regs.stat & CYAPA_STAT_RUNNING) == 0 && + (unsigned)(ticks - last_reset) > TIME_TO_RESET)) { + cyapa_reset = 0; + last_reset = ticks; + init_device(sc->dev, NULL, sc->addr, 2); + } + smbus_release_bus(bus, sc->dev); + } + pause("cyapw", hz / freq); + ++sc->poll_ticks; + + if (sc->count == 0) { + freq = cyapa_idle_freq; + npstate = CMD_POWER_MODE_IDLE; + } else if (isidle) { + freq = cyapa_slow_freq; + npstate = CMD_POWER_MODE_IDLE; + } else { + freq = cyapa_norm_freq; + npstate = CMD_POWER_MODE_FULL; + } + if (pstate != npstate) { + pstate = npstate; + cyapa_set_power_mode(sc, pstate); + if (cyapa_debug) { + switch(pstate) { + case CMD_POWER_MODE_OFF: + printf("cyapa: power off\n"); + break; + case CMD_POWER_MODE_IDLE: + printf("cyapa: power idle\n"); + break; + case CMD_POWER_MODE_FULL: + printf("cyapa: power full\n"); + break; + } + } + } + + cyapa_lock(sc); + } + sc->poll_thread_running = 0; + cyapa_unlock(sc); + kthread_exit(); +} + +static int +cyapa_raw_input(struct cyapa_softc *sc, struct cyapa_regs *regs, int freq) +{ + int nfingers; + int afingers; /* actual fingers after culling */ + int i; + int j; + int k; + int isidle; + int thumbarea_begin; + int seen_thumb; + int x; + int y; + int z; + int newfinger; + int lessfingers; + int click_x; + int click_y; + uint16_t but; /* high bits used for simulated but4/but5 */ + + thumbarea_begin = sc->cap_resy - + ((sc->cap_resy * cyapa_thumbarea_percent) / 100); + click_x = click_y = 0; + + /* + * If the device is not running the rest of the status + * means something else, set fingers to 0. + */ + if ((regs->stat & CYAPA_STAT_RUNNING) == 0) { + regs->fngr = 0; + } + + /* Process fingers/movement */ + nfingers = CYAPA_FNGR_NUMFINGERS(regs->fngr); + afingers = nfingers; + + if (cyapa_debug) { + printf("stat %02x buttons %c%c%c nfngrs=%d ", + regs->stat, + ((regs->fngr & CYAPA_FNGR_LEFT) ? 'L' : '-'), + ((regs->fngr & CYAPA_FNGR_MIDDLE) ? 'M' : '-'), + ((regs->fngr & CYAPA_FNGR_RIGHT) ? 'R' : '-'), + nfingers); + } + + seen_thumb = 0; + for (i = 0; i < afingers; ) { + if (cyapa_debug) { + printf(" [x=%04d y=%04d p=%d i=%d]", + CYAPA_TOUCH_X(regs, i), + CYAPA_TOUCH_Y(regs, i), + CYAPA_TOUCH_P(regs, i), + regs->touch[i].id); + } + if ((CYAPA_TOUCH_Y(regs, i) > thumbarea_begin && seen_thumb) || + CYAPA_TOUCH_P(regs, i) < cyapa_minpressure) { + --afingers; + if (i < afingers) { + regs->touch[i] = regs->touch[i+1]; + continue; + } + } else { + if (CYAPA_TOUCH_Y(regs, i) > thumbarea_begin) + seen_thumb = 1; + } + ++i; + } + nfingers = afingers; + + /* Tracking for local solutions */ + cyapa_lock(sc); + + /* + * Track timing for finger-downs. Used to detect false-3-finger + * button-down. + */ + switch(afingers) { + case 0: + break; + case 1: + if (sc->track_nfingers == 0) + sc->finger1_ticks = sc->poll_ticks; + break; + case 2: + if (sc->track_nfingers <= 0) + sc->finger1_ticks = sc->poll_ticks; + if (sc->track_nfingers <= 1) + sc->finger2_ticks = sc->poll_ticks; + break; + case 3: + default: + if (sc->track_nfingers <= 0) + sc->finger1_ticks = sc->poll_ticks; + if (sc->track_nfingers <= 1) + sc->finger2_ticks = sc->poll_ticks; + if (sc->track_nfingers <= 2) + sc->finger3_ticks = sc->poll_ticks; + break; + } + newfinger = sc->track_nfingers < afingers; + lessfingers = sc->track_nfingers > afingers; + sc->track_nfingers = afingers; + + /* + * Lookup and track finger indexes in the touch[] array. + */ + if (afingers == 0) { + click_x = sc->track_x; + click_y = sc->track_y; + sc->track_x = -1; + sc->track_y = -1; + sc->track_z = -1; + sc->fuzz_x = 0; + sc->fuzz_y = 0; + sc->fuzz_z = 0; + sc->touch_x = -1; + sc->touch_y = -1; + sc->touch_z = -1; + sc->track_id = -1; + sc->track_but = 0; + i = 0; + j = 0; + k = 0; + } else { + /* + * The id assigned on touch can move around in the array, + * find it. If that finger is lifted up, assign some other + * finger for mouse tracking and reset track_x and track_y + * to avoid a mouse jump. + * + * If >= 2 fingers are down be sure not to assign i and + * j to the same index. + */ + for (i = 0; i < nfingers; ++i) { + if (sc->track_id == regs->touch[i].id) + break; + } + if (i == nfingers) { + i = 0; + sc->track_x = -1; + sc->track_y = -1; + sc->track_z = -1; + while (CYAPA_TOUCH_Y(regs, i) >= thumbarea_begin && + i < nfingers) ++i; + if (i == nfingers) { + i = 0; + } + sc->track_id = regs->touch[i].id; + } + else if ((sc->track_but || + CYAPA_TOUCH_Y(regs, i) >= thumbarea_begin) && + newfinger && afingers == 2) { + j = regs->touch[0].id == sc->track_id ? 1 : 0; + if (CYAPA_TOUCH_Y(regs, j) < thumbarea_begin) { + i = j; + sc->track_x = -1; + sc->track_y = -1; + sc->track_z = -1; + sc->track_id = regs->touch[i].id; + } + } + } + + /* Two finger scrolling - reset after timeout */ + if (sc->track_z != -1 && afingers != 2 && + (sc->poll_ticks - sc->track_z_ticks) > cyapa_scroll_stick_ticks) { + sc->track_z = -1; + sc->track_z_ticks = 0; + } + + /* Initiate two finger scrolling */ + if (!(regs->fngr & CYAPA_FNGR_LEFT) && + ((afingers && sc->track_z != -1) || + (afingers == 2 && CYAPA_TOUCH_Y(regs, 0) < thumbarea_begin && + CYAPA_TOUCH_Y(regs, 1) < thumbarea_begin))) { + if (afingers == 2 && (sc->poll_ticks - sc->finger2_ticks) + > cyapa_scroll_wait_ticks) { + z = (CYAPA_TOUCH_Y(regs, 0) + + CYAPA_TOUCH_Y(regs, 1)) >> 1; + sc->delta_z += z / ZSCALE - sc->track_z; + if (sc->track_z == -1) { + sc->delta_z = 0; + } + if (sc->touch_z == -1) + sc->touch_z = z; /* not used atm */ + sc->track_z = z / ZSCALE; + sc->track_z_ticks = sc->poll_ticks; + } + } else if (afingers) { + /* Normal pad position reporting */ + x = CYAPA_TOUCH_X(regs, i); + y = CYAPA_TOUCH_Y(regs, i); + click_x = x; + click_y = y; + if (sc->track_x != -1 && sc->track_y < thumbarea_begin && + (afingers > 1 || (sc->poll_ticks - sc->finger1_ticks) + >= cyapa_move_min_ticks || freq < cyapa_norm_freq)) { + sc->delta_x += x - sc->track_x; + sc->delta_y -= y - sc->track_y; + if (sc->delta_x > sc->cap_resx) + sc->delta_x = sc->cap_resx; + if (sc->delta_x < -sc->cap_resx) + sc->delta_x = -sc->cap_resx; + if (sc->delta_y > sc->cap_resx) + sc->delta_y = sc->cap_resy; + if (sc->delta_y < -sc->cap_resy) + sc->delta_y = -sc->cap_resy; + + if (abs(sc->delta_y) > sc->cap_resy / 2 || + abs(sc->delta_x) > sc->cap_resx / 2) { + if (cyapa_debug) + printf("Detected jump by %i %i\n", + sc->delta_x, sc->delta_y); + sc->delta_x = sc->delta_y = 0; + } + } + if (sc->touch_x == -1) { + sc->touch_x = x; + sc->touch_y = y; + } + sc->track_x = x; + sc->track_y = y; + } + + /* Select finger (L = 2/3x, M = 1/3u, R = 1/3d) */ + int is_tapclick = (cyapa_enable_tapclick && lessfingers && + afingers == 0 && sc->poll_ticks - sc->finger1_ticks + >= cyapa_tapclick_min_ticks && + sc->poll_ticks - sc->finger1_ticks < cyapa_tapclick_max_ticks); + + if (regs->fngr & CYAPA_FNGR_LEFT || is_tapclick) { + if (sc->track_but) { + but = sc->track_but; + } else if (afingers == 1) { + if (click_x < sc->cap_resx * 2 / 3) + but = CYAPA_FNGR_LEFT; + else if (click_y < sc->cap_resy / 2) + but = CYAPA_FNGR_MIDDLE; + else + but = CYAPA_FNGR_RIGHT; + } else if (is_tapclick) { + if (click_x < sc->cap_resx * 2 / 3 || + cyapa_enable_tapclick < 2) + but = CYAPA_FNGR_LEFT; + else if (click_y < sc->cap_resy / 2 && + cyapa_enable_tapclick > 2) + but = CYAPA_FNGR_MIDDLE; + else + but = CYAPA_FNGR_RIGHT; + } else { + but = CYAPA_FNGR_LEFT; + } + } else { + but = 0; + } + + /* + * Detect state change from last reported state and + * determine if we have gone idle. + */ + sc->track_but = but; + if (sc->delta_x || sc->delta_y || sc->delta_z || + sc->track_but != sc->reported_but) { + sc->active_tick = ticks; + if (sc->remote_mode == 0 && sc->reporting_mode) + sc->data_signal = 1; + isidle = 0; + } else if ((unsigned)(ticks - sc->active_tick) >= TIME_TO_IDLE) { + sc->active_tick = ticks - TIME_TO_IDLE; /* prevent overflow */ + isidle = 1; + } else { + isidle = 0; + } + cyapa_notify(sc); + cyapa_unlock(sc); + + if (cyapa_debug) + printf("%i >> %i << %i\n", isidle, sc->track_id, sc->delta_y); + return (isidle); +} + +static void +cyapa_set_power_mode(struct cyapa_softc *sc, int mode) +{ + uint8_t data; + device_t bus; + int error; + + bus = device_get_parent(sc->dev); + error = smbus_request_bus(bus, sc->dev, SMB_WAIT); + if (error == 0) { + error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, (void *)&data, 1, NULL); + data = (data & ~0xFC) | mode; + if (error == 0) { + error = smbus_trans(bus, sc->addr, CMD_POWER_MODE, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + (void *)&data, 1, NULL, 0, NULL); + } + smbus_release_bus(bus, sc->dev); + } +} + +/* + * FIFO FUNCTIONS + */ + +/* + * Returns non-zero if the fifo is empty + */ +static int +fifo_empty(struct cyapa_softc *sc, struct cyapa_fifo *fifo) +{ + + CYAPA_LOCK_ASSERT(sc); + + return (fifo->rindex == fifo->windex); +} + +/* + * Returns the number of characters available for reading from + * the fifo without wrapping the fifo buffer. + */ +static size_t +fifo_ready(struct cyapa_softc *sc, struct cyapa_fifo *fifo) +{ + size_t n; + + CYAPA_LOCK_ASSERT(sc); + + n = CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK); + if (n > (size_t)(fifo->windex - fifo->rindex)) + n = (size_t)(fifo->windex - fifo->rindex); + return (n); +} + +/* + * Returns a read pointer into the fifo and then bumps + * rindex. The FIFO must have at least 'n' characters in + * it. The value (n) can cause the index to wrap but users + * of the buffer should never supply a value for (n) that wraps + * the buffer. + */ +static char * +fifo_read(struct cyapa_softc *sc, struct cyapa_fifo *fifo, size_t n) +{ + char *ptr; + + CYAPA_LOCK_ASSERT(sc); + if (n > (CYAPA_BUFSIZE - (fifo->rindex & CYAPA_BUFMASK))) { + printf("fifo_read: overflow\n"); + return (fifo->buf); + } + ptr = fifo->buf + (fifo->rindex & CYAPA_BUFMASK); + fifo->rindex += n; + + return (ptr); +} + +static uint8_t +fifo_read_char(struct cyapa_softc *sc, struct cyapa_fifo *fifo) +{ + uint8_t c; + + CYAPA_LOCK_ASSERT(sc); + + if (fifo->rindex == fifo->windex) { + printf("fifo_read_char: overflow\n"); + c = 0; + } else { + c = fifo->buf[fifo->rindex & CYAPA_BUFMASK]; + ++fifo->rindex; + } + return (c); +} + + +/* + * Write a character to the FIFO. The character will be discarded + * if the FIFO is full. + */ +static void +fifo_write_char(struct cyapa_softc *sc, struct cyapa_fifo *fifo, uint8_t c) +{ + + CYAPA_LOCK_ASSERT(sc); + + if (fifo->windex - fifo->rindex < CYAPA_BUFSIZE) { + fifo->buf[fifo->windex & CYAPA_BUFMASK] = c; + ++fifo->windex; + } +} + +/* + * Return the amount of space available for writing without wrapping + * the fifo. + */ +static size_t +fifo_space(struct cyapa_softc *sc, struct cyapa_fifo *fifo) +{ + size_t n; + + CYAPA_LOCK_ASSERT(sc); + + n = CYAPA_BUFSIZE - (fifo->windex & CYAPA_BUFMASK); + if (n > (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex))) + n = (size_t)(CYAPA_BUFSIZE - (fifo->windex - fifo->rindex)); + return (n); +} + +static char * +fifo_write(struct cyapa_softc *sc, struct cyapa_fifo *fifo, size_t n) +{ + char *ptr; + + CYAPA_LOCK_ASSERT(sc); + + ptr = fifo->buf + (fifo->windex & CYAPA_BUFMASK); + fifo->windex += n; + + return (ptr); +} + +static void +fifo_reset(struct cyapa_softc *sc, struct cyapa_fifo *fifo) +{ + + CYAPA_LOCK_ASSERT(sc); + + fifo->rindex = 0; + fifo->windex = 0; +} + +/* + * Fuzz handling + */ +static int +cyapa_fuzz(int delta, int *fuzzp) +{ + int fuzz; + + fuzz = *fuzzp; + if (fuzz >= 0 && delta < 0) { + ++delta; + --fuzz; + } else if (fuzz <= 0 && delta > 0) { + --delta; + ++fuzz; + } + *fuzzp = fuzz; + + return (delta); +} + +DRIVER_MODULE(cyapa, smbus, cyapa_driver, cyapa_devclass, NULL, NULL); +MODULE_DEPEND(cyapa, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(cyapa, 1); diff --git a/sys/dev/cyapa/cyapa.h b/sys/dev/cyapa/cyapa.h new file mode 100644 index 000000000000..eeef994e4ee9 --- /dev/null +++ b/sys/dev/cyapa/cyapa.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon and was subsequently ported + * to FreeBSD by Michael Gmelin + * + * 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 DragonFly Project 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS 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 _SYS_DEV_SMBUS_CYAPA_CYAPA_H_ +#define _SYS_DEV_SMBUS_CYAPA_CYAPA_H_ + +#define CYAPA_MAX_MT 5 + +/* + * Boot-time registers. This is the device map + * if (stat & CYAPA_STAT_RUNNING) is 0. + */ +struct cyapa_boot_regs { + uint8_t stat; /* CYAPA_STAT_xxx */ + uint8_t boot; /* CYAPA_BOOT_xxx */ + uint8_t error; +} __packed; + +#define CYAPA_BOOT_BUSY 0x80 +#define CYAPA_BOOT_RUNNING 0x10 +#define CYAPA_BOOT_DATA_VALID 0x08 +#define CYAPA_BOOT_CSUM_VALID 0x01 + +#define CYAPA_ERROR_INVALID 0x80 +#define CYAPA_ERROR_INVALID_KEY 0x40 +#define CYAPA_ERROR_BOOTLOADER 0x20 +#define CYAPA_ERROR_CMD_CSUM 0x10 +#define CYAPA_ERROR_FLASH_PROT 0x08 +#define CYAPA_ERROR_FLASH_CSUM 0x04 + +struct cyapa_regs { + uint8_t stat; + uint8_t fngr; + + struct { + uint8_t xy_high; /* 7:4 high 4 bits of x */ + uint8_t x_low; /* 3:0 high 4 bits of y */ + uint8_t y_low; + uint8_t pressure; + uint8_t id; /* 1-15 incremented each touch */ + } touch[CYAPA_MAX_MT]; +} __packed; + +struct cyapa_cap { + uint8_t prod_ida[5]; /* 0x00 - 0x04 */ + uint8_t prod_idb[6]; /* 0x05 - 0x0A */ + uint8_t prod_idc[2]; /* 0x0B - 0x0C */ + uint8_t reserved[6]; /* 0x0D - 0x12 */ + uint8_t buttons; /* 0x13 */ + uint8_t gen; /* 0x14, low 4 bits */ + uint8_t max_abs_xy_high;/* 0x15 7:4 high x bits, 3:0 high y bits */ + uint8_t max_abs_x_low; /* 0x16 */ + uint8_t max_abs_y_low; /* 0x17 */ + uint8_t phy_siz_xy_high;/* 0x18 7:4 high x bits, 3:0 high y bits */ + uint8_t phy_siz_x_low; /* 0x19 */ + uint8_t phy_siz_y_low; /* 0x1A */ +} __packed; + +#define CYAPA_STAT_RUNNING 0x80 +#define CYAPA_STAT_PWR_MASK 0x0C +#define CYAPA_PWR_OFF 0x00 +#define CYAPA_PWR_IDLE 0x08 +#define CYAPA_PWR_ACTIVE 0x0C + +#define CYAPA_STAT_DEV_MASK 0x03 +#define CYAPA_DEV_NORMAL 0x03 +#define CYAPA_DEV_BUSY 0x01 + +#define CYAPA_FNGR_DATA_VALID 0x08 +#define CYAPA_FNGR_MIDDLE 0x04 +#define CYAPA_FNGR_RIGHT 0x02 +#define CYAPA_FNGR_LEFT 0x01 +#define CYAPA_FNGR_NUMFINGERS(c) (((c) >> 4) & 0x0F) + +#define CYAPA_TOUCH_X(regs, i) ((((regs)->touch[i].xy_high << 4) & 0x0F00) | \ + (regs)->touch[i].x_low) +#define CYAPA_TOUCH_Y(regs, i) ((((regs)->touch[i].xy_high << 8) & 0x0F00) | \ + (regs)->touch[i].y_low) +#define CYAPA_TOUCH_P(regs, i) ((regs)->touch[i].pressure) + +#define CMD_BOOT_STATUS 0x00 /* only if in boot state */ +#define CMD_DEV_STATUS 0x00 /* only if in operational state */ +#define CMD_SOFT_RESET 0x28 +#define CMD_POWER_MODE 0x29 +#define CMD_POWER_MODE_OFF 0x00 +#define CMD_POWER_MODE_IDLE 0x14 +#define CMD_POWER_MODE_FULL 0xFC +#define CMD_QUERY_CAPABILITIES 0x2A + +#endif diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index d080168dedbb..528ad149ae89 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1872,13 +1872,12 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) struct ether_header *eh; struct ip *ip = NULL; struct tcphdr *tp = NULL; - u32 txd_upper, txd_lower, txd_used, txd_saved; + u32 txd_upper = 0, txd_lower = 0, txd_used = 0; int ip_off, poff; int nsegs, i, j, first, last = 0; int error, do_tso, tso_desc = 0, remap = 1; m_head = *m_headp; - txd_upper = txd_lower = txd_used = txd_saved = 0; do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0); ip_off = poff = 0; diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index 3d6a6cfe4bdf..e741d288dbe9 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -564,6 +564,10 @@ gpiobus_acquire_bus(device_t busdev, device_t child, int how) GPIOBUS_ASSERT_UNLOCKED(sc); GPIOBUS_LOCK(sc); if (sc->sc_owner != NULL) { + if (sc->sc_owner == child) + panic("%s: %s still owns the bus.", + device_get_nameunit(busdev), + device_get_nameunit(child)); if (how == GPIOBUS_DONTWAIT) { GPIOBUS_UNLOCK(sc); return (EWOULDBLOCK); @@ -586,9 +590,14 @@ gpiobus_release_bus(device_t busdev, device_t child) GPIOBUS_ASSERT_UNLOCKED(sc); GPIOBUS_LOCK(sc); if (sc->sc_owner == NULL) - panic("gpiobus: releasing unowned bus."); + panic("%s: %s releasing unowned bus.", + device_get_nameunit(busdev), + device_get_nameunit(child)); if (sc->sc_owner != child) - panic("gpiobus: you don't own the bus. game over."); + panic("%s: %s trying to release bus owned by %s", + device_get_nameunit(busdev), + device_get_nameunit(child), + device_get_nameunit(sc->sc_owner)); sc->sc_owner = NULL; wakeup(sc); GPIOBUS_UNLOCK(sc); diff --git a/sys/dev/isl/isl.c b/sys/dev/isl/isl.c new file mode 100644 index 000000000000..8d940e916081 --- /dev/null +++ b/sys/dev/isl/isl.c @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 2015 Michael Gmelin + * 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$"); + +/* + * Driver for intersil I2C ISL29018 Digital Ambient Light Sensor and Proximity + * Sensor with Interrupt Function, only tested connected over SMBus (ig4iic). + * + * Datasheet: + * http://www.intersil.com/en/products/optoelectronics/ambient-light-and-proximity-sensors/light-to-digital-sensors/ISL29018.html + * http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29018.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "smbus_if.h" +#include "bus_if.h" +#include "device_if.h" + +#define ISL_METHOD_ALS 0x10 +#define ISL_METHOD_IR 0x11 +#define ISL_METHOD_PROX 0x12 +#define ISL_METHOD_RESOLUTION 0x13 +#define ISL_METHOD_RANGE 0x14 + +struct isl_softc { + device_t dev; + int unit; + int addr; + + struct sx isl_sx; + struct sysctl_ctx_list *sysctl_ctx; + struct sysctl_oid *sysctl_tree; +}; + +/* Returns < 0 on problem. */ +static int isl_read_sensor(device_t dev, int addr, uint8_t cmd_mask); + +/* + * Initialize the device + */ +static +int +init_device(device_t dev, int addr, int probe) +{ + static char bl_init[] = { 0x00 }; + + device_t bus; + int error; + + bus = device_get_parent(dev); /* smbus */ + + /* + * init procedure: send 0x00 to test ref and cmd reg 1 + */ + error = smbus_trans(bus, addr, REG_TEST, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + bl_init, sizeof(bl_init), NULL, 0, NULL); + if (error) + goto done; + + error = smbus_trans(bus, addr, REG_CMD1, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + bl_init, sizeof(bl_init), NULL, 0, NULL); + if (error) + goto done; + + pause("islinit", hz/100); + +done: + if (error) + device_printf(dev, "Unable to initialize\n"); + return (error); +} + +static int isl_probe(device_t); +static int isl_attach(device_t); +static int isl_detach(device_t); + +static int isl_sysctl(SYSCTL_HANDLER_ARGS); + +static devclass_t isl_devclass; + +static device_method_t isl_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, isl_probe), + DEVMETHOD(device_attach, isl_attach), + DEVMETHOD(device_detach, isl_detach), + + DEVMETHOD_END +}; + +static driver_t isl_driver = { + "isl", + isl_methods, + sizeof(struct isl_softc), +}; + +static int +isl_probe(device_t dev) +{ + int unit; + int addr; + int error; + + addr = smbus_get_addr(dev); + + /* + * 0x44 - isl ambient light sensor on the acer c720. + * (other devices might use other ids). + */ + if (addr != 0x44) + return (ENXIO); + + unit = device_get_unit(dev); + + error = init_device(dev, addr, 1); + if (error) + return (ENXIO); + + device_set_desc(dev, "ISL Digital Ambient Light Sensor"); + + return (BUS_PROBE_VENDOR); +} + +static int +isl_attach(device_t dev) +{ + struct isl_softc *sc; + int unit; + int addr; + int use_als; + int use_ir; + int use_prox; + + sc = device_get_softc(dev); + + if (!sc) + return (ENOMEM); + + unit = device_get_unit(dev); + addr = *((unsigned char*) device_get_ivars(dev)); + + if (init_device(dev, addr, 0)) + return (ENXIO); + + sx_init(&sc->isl_sx, "ISL read lock"); + + sc->dev = dev; + sc->unit = unit; + sc->addr = addr; + + sc->sysctl_ctx = device_get_sysctl_ctx(dev); + sc->sysctl_tree = device_get_sysctl_tree(dev); + + use_als = isl_read_sensor(dev, addr, CMD1_MASK_ALS_ONCE) >= 0; + use_ir = isl_read_sensor(dev, addr, CMD1_MASK_IR_ONCE) >= 0; + use_prox = isl_read_sensor(dev, addr, CMD1_MASK_PROX_ONCE) >= 0; + + if (use_als) { + SYSCTL_ADD_PROC(sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + "als", CTLTYPE_INT | CTLFLAG_RD, + sc, ISL_METHOD_ALS, isl_sysctl, "I", + "Current ALS sensor read-out"); + } + + if (use_ir) { + SYSCTL_ADD_PROC(sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + "ir", CTLTYPE_INT | CTLFLAG_RD, + sc, ISL_METHOD_IR, isl_sysctl, "I", + "Current IR sensor read-out"); + } + + if (use_prox) { + SYSCTL_ADD_PROC(sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + "prox", CTLTYPE_INT | CTLFLAG_RD, + sc, ISL_METHOD_PROX, isl_sysctl, "I", + "Current proximity sensor read-out"); + } + + SYSCTL_ADD_PROC(sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + "resolution", CTLTYPE_INT | CTLFLAG_RD, + sc, ISL_METHOD_RESOLUTION, isl_sysctl, "I", + "Current proximity sensor resolution"); + + SYSCTL_ADD_PROC(sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, + "range", CTLTYPE_INT | CTLFLAG_RD, + sc, ISL_METHOD_RANGE, isl_sysctl, "I", + "Current proximity sensor range"); + + return (0); +} + +static int +isl_detach(device_t dev) +{ + struct isl_softc *sc; + + sc = device_get_softc(dev); + sx_destroy(&sc->isl_sx); + + return (0); +} + +static int +isl_sysctl(SYSCTL_HANDLER_ARGS) +{ + static int resolutions[] = { 16, 12, 8, 4}; + static int ranges[] = { 1000, 4000, 16000, 64000}; + + struct isl_softc *sc; + device_t bus; + uint8_t rbyte; + int arg; + int resolution; + int range; + + sc = (struct isl_softc *)oidp->oid_arg1; + arg = -1; + + sx_xlock(&sc->isl_sx); + bus = device_get_parent(sc->dev); /* smbus */ + if (smbus_trans(bus, sc->addr, REG_CMD2, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, &rbyte, sizeof(rbyte), NULL)) { + sx_xunlock(&sc->isl_sx); + return (-1); + } + resolution = resolutions[(rbyte & CMD2_MASK_RESOLUTION) + >> CMD2_SHIFT_RESOLUTION]; + range = ranges[(rbyte & CMD2_MASK_RANGE) >> CMD2_SHIFT_RANGE]; + + switch (oidp->oid_arg2) { + case ISL_METHOD_ALS: + arg = (isl_read_sensor(sc->dev, sc->addr, + CMD1_MASK_ALS_ONCE) * range) >> resolution; + break; + case ISL_METHOD_IR: + arg = isl_read_sensor(sc->dev, sc->addr, + CMD1_MASK_IR_ONCE); + break; + case ISL_METHOD_PROX: + arg = isl_read_sensor(sc->dev, sc->addr, + CMD1_MASK_PROX_ONCE); + break; + case ISL_METHOD_RESOLUTION: + arg = (1 << resolution); + break; + case ISL_METHOD_RANGE: + arg = range; + break; + } + sx_xunlock(&sc->isl_sx); + + SYSCTL_OUT(req, &arg, sizeof(arg)); + return (0); +} + +static int isl_read_sensor(device_t dev, int addr, uint8_t cmd_mask) +{ + device_t bus; + uint8_t rbyte; + uint8_t cmd; + int ret; + + bus = device_get_parent(dev); /* smbus */ + + if (smbus_trans(bus, addr, REG_CMD1, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, &rbyte, sizeof(rbyte), NULL)) { + device_printf(dev, + "Couldn't read first byte before issuing command %d\n", + cmd_mask); + return (-1); + } + + cmd = (rbyte & 0x1f) | cmd_mask; + if (smbus_trans(bus, addr, REG_CMD1, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + &cmd, sizeof(cmd), NULL, 0, NULL)) { + device_printf(dev, "Couldn't write command %d\n", cmd_mask); + return (-1); + } + + pause("islconv", hz/10); + + if (smbus_trans(bus, addr, REG_DATA1, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, &rbyte, sizeof(rbyte), NULL)) { + device_printf(dev, + "Couldn't read first byte after command %d\n", cmd_mask); + return (-1); + } + + ret = rbyte; + if (smbus_trans(bus, addr, REG_DATA2, + SMB_TRANS_NOCNT | SMB_TRANS_7BIT, + NULL, 0, &rbyte, sizeof(rbyte), NULL)) { + device_printf(dev, "Couldn't read second byte after command %d\n", cmd_mask); + return (-1); + } + ret += rbyte << 8; + + return (ret); +} + +DRIVER_MODULE(isl, smbus, isl_driver, isl_devclass, NULL, NULL); +MODULE_DEPEND(isl, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(isl, 1); diff --git a/sys/dev/isl/isl.h b/sys/dev/isl/isl.h new file mode 100644 index 000000000000..23bde4ab4e49 --- /dev/null +++ b/sys/dev/isl/isl.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2015 Michael Gmelin + * 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 _ISL_H_ +#define _ISL_H_ + +/* Command register 1 (bits 7-5) */ +#define REG_CMD1 0x00 +#define CMD1_MASK_POWER_DOWN 0x00 /* 00000000 */ +#define CMD1_MASK_ALS_ONCE 0x01 << 5 /* 00100000 */ +#define CMD1_MASK_IR_ONCE 0x02 << 5 /* 01000000 */ +#define CMD1_MASK_PROX_ONCE 0x03 << 5 /* 01100000 */ +/* RESERVED */ /* 10000000 */ +#define CMD1_MASK_ALS_CONT 0x05 << 5 /* 10100000 */ +#define CMD1_MASK_IR_CONT 0x06 << 5 /* 11000000 */ +#define CMD1_MASK_PROX_CONT 0x07 << 5 /* 11100000 */ + +/* Command register 2 (bits) */ +#define REG_CMD2 0x01 + +/* data registers */ +#define REG_DATA1 0x02 +#define REG_DATA2 0x03 +#define CMD2_SHIFT_RANGE 0x00 +#define CMD2_MASK_RANGE (0x03 << CMD2_SHIFT_RANGE) +#define CMD2_SHIFT_RESOLUTION 0x02 +#define CMD2_MASK_RESOLUTION (0x03 << CMD2_SHIFT_RESOLUTION) + +/* Interrupt registers */ +#define REG_INT_LO_LSB 0x04 +#define REG_INT_LO_MSB 0x05 +#define REG_INT_HI_LSB 0x06 +#define REG_INT_HI_MSB 0x07 + +/* Test register (should hold 0x00 at all times */ +#define REG_TEST 0x08 + +#endif diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index d5b2a180d559..93179652f3b3 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -1423,7 +1423,7 @@ mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd) /* Send the command */ for (i = 0; i < len; i++) { - mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++)); + mpt_write_stream(mpt, MPT_OFFSET_DOORBELL, *data32++); if (mpt_wait_db_ack(mpt) != MPT_OK) { mpt_prt(mpt, "mpt_send_handshake_cmd: timeout @ index %d\n", i); @@ -1457,7 +1457,7 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) *data16++ = le16toh(data & MPT_DB_DATA_MASK); mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - /* Get Second Word */ + /* Get second word */ if (mpt_wait_db_int(mpt) != MPT_OK) { mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2\n"); return ETIMEDOUT; @@ -1481,18 +1481,13 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) left = (hdr->MsgLength << 1) - 2; reply_left = reply_len - 2; while (left--) { - u_int16_t datum; - if (mpt_wait_db_int(mpt) != MPT_OK) { mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3\n"); return ETIMEDOUT; } data = mpt_read(mpt, MPT_OFFSET_DOORBELL); - datum = le16toh(data & MPT_DB_DATA_MASK); - if (reply_left-- > 0) - *data16++ = datum; - + *data16++ = le16toh(data & MPT_DB_DATA_MASK); mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); } diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index 1dcd76f52480..57dbe7b36346 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -329,7 +329,6 @@ typedef struct mpt_config_params { } cfgparms_t; /**************************** MPI Target State Info ***************************/ - typedef struct { uint32_t reply_desc; /* current reply descriptor */ uint32_t resid; /* current data residual */ @@ -784,6 +783,7 @@ mpt_assign_serno(struct mpt_softc *mpt, request_t *req) /******************************* Register Access ******************************/ static __inline void mpt_write(struct mpt_softc *, size_t, uint32_t); +static __inline void mpt_write_stream(struct mpt_softc *, size_t, uint32_t); static __inline uint32_t mpt_read(struct mpt_softc *, int); static __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t); static __inline uint32_t mpt_pio_read(struct mpt_softc *, int); @@ -794,6 +794,12 @@ mpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val) bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val); } +static __inline void +mpt_write_stream(struct mpt_softc *mpt, size_t offset, uint32_t val) +{ + bus_space_write_stream_4(mpt->pci_st, mpt->pci_sh, offset, val); +} + static __inline uint32_t mpt_read(struct mpt_softc *mpt, int offset) { @@ -818,6 +824,7 @@ mpt_pio_read(struct mpt_softc *mpt, int offset) KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource")); return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset)); } + /*********************** Reply Frame/Request Management ***********************/ /* Max MPT Reply we are willing to accept (must be power of 2) */ #define MPT_REPLY_SIZE 256 @@ -958,6 +965,7 @@ mpt_cdblen(uint8_t cdb0, int maxlen) return (16); } } + #ifdef INVARIANTS static __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t); static __inline request_t * @@ -1136,6 +1144,7 @@ mpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress, PageAddress, hdr, len, sleep_ok, timeout_ms)); } + /* mpt_debug.c functions */ void mpt_print_reply(void *vmsg); void mpt_print_db(uint32_t mb); @@ -1145,4 +1154,5 @@ void mpt_req_state(mpt_req_state_t state); void mpt_print_config_request(void *vmsg); void mpt_print_request(void *vmsg); void mpt_dump_sgl(SGE_IO_UNION *se, int offset); + #endif /* _MPT_H_ */ diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 00dc92ab290b..ee4b901a9c75 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012-2014 Intel Corporation + * Copyright (C) 2012-2015 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -207,7 +207,7 @@ nvme_ctrlr_fail_req_task(void *arg, int pending) } static int -nvme_ctrlr_wait_for_ready(struct nvme_controller *ctrlr) +nvme_ctrlr_wait_for_ready(struct nvme_controller *ctrlr, int desired_val) { int ms_waited; union cc_register cc; @@ -216,18 +216,19 @@ nvme_ctrlr_wait_for_ready(struct nvme_controller *ctrlr) cc.raw = nvme_mmio_read_4(ctrlr, cc); csts.raw = nvme_mmio_read_4(ctrlr, csts); - if (!cc.bits.en) { - nvme_printf(ctrlr, "%s called with cc.en = 0\n", __func__); + if (cc.bits.en != desired_val) { + nvme_printf(ctrlr, "%s called with desired_val = %d " + "but cc.en = %d\n", __func__, desired_val, cc.bits.en); return (ENXIO); } ms_waited = 0; - while (!csts.bits.rdy) { + while (csts.bits.rdy != desired_val) { DELAY(1000); if (ms_waited++ > ctrlr->ready_timeout_in_ms) { - nvme_printf(ctrlr, "controller did not become ready " - "within %d ms\n", ctrlr->ready_timeout_in_ms); + nvme_printf(ctrlr, "controller ready did not become %d " + "within %d ms\n", desired_val, ctrlr->ready_timeout_in_ms); return (ENXIO); } csts.raw = nvme_mmio_read_4(ctrlr, csts); @@ -246,11 +247,12 @@ nvme_ctrlr_disable(struct nvme_controller *ctrlr) csts.raw = nvme_mmio_read_4(ctrlr, csts); if (cc.bits.en == 1 && csts.bits.rdy == 0) - nvme_ctrlr_wait_for_ready(ctrlr); + nvme_ctrlr_wait_for_ready(ctrlr, 1); cc.bits.en = 0; nvme_mmio_write_4(ctrlr, cc, cc.raw); DELAY(5000); + nvme_ctrlr_wait_for_ready(ctrlr, 0); } static int @@ -267,7 +269,7 @@ nvme_ctrlr_enable(struct nvme_controller *ctrlr) if (csts.bits.rdy == 1) return (0); else - return (nvme_ctrlr_wait_for_ready(ctrlr)); + return (nvme_ctrlr_wait_for_ready(ctrlr, 1)); } nvme_mmio_write_8(ctrlr, asq, ctrlr->adminq.cmd_bus_addr); @@ -295,7 +297,7 @@ nvme_ctrlr_enable(struct nvme_controller *ctrlr) nvme_mmio_write_4(ctrlr, cc, cc.raw); DELAY(5000); - return (nvme_ctrlr_wait_for_ready(ctrlr)); + return (nvme_ctrlr_wait_for_ready(ctrlr, 1)); } int @@ -838,7 +840,6 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, */ PHOLD(curproc); buf = getpbuf(NULL); - buf->b_saveaddr = buf->b_data; buf->b_data = pt->buf; buf->b_bufsize = pt->len; buf->b_iocmd = pt->is_read ? BIO_READ : BIO_WRITE; @@ -930,7 +931,8 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) { union cap_lo_register cap_lo; union cap_hi_register cap_hi; - int i, num_vectors, per_cpu_io_queues, rid; + int i, per_cpu_io_queues, rid; + int num_vectors_requested, num_vectors_allocated; int status, timeout_period; ctrlr->dev = dev; @@ -988,7 +990,7 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) } /* One vector per IO queue, plus one vector for admin queue. */ - num_vectors = ctrlr->num_io_queues + 1; + num_vectors_requested = ctrlr->num_io_queues + 1; /* * If we cannot even allocate 2 vectors (one for admin, one for @@ -997,15 +999,36 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) if (pci_msix_count(dev) < 2) { ctrlr->msix_enabled = 0; goto intx; - } else if (pci_msix_count(dev) < num_vectors) { + } else if (pci_msix_count(dev) < num_vectors_requested) { ctrlr->per_cpu_io_queues = FALSE; ctrlr->num_io_queues = 1; - num_vectors = 2; /* one for admin, one for I/O */ + num_vectors_requested = 2; /* one for admin, one for I/O */ } - if (pci_alloc_msix(dev, &num_vectors) != 0) { + num_vectors_allocated = num_vectors_requested; + if (pci_alloc_msix(dev, &num_vectors_allocated) != 0) { ctrlr->msix_enabled = 0; goto intx; + } else if (num_vectors_allocated < num_vectors_requested) { + if (num_vectors_allocated < 2) { + pci_release_msi(dev); + ctrlr->msix_enabled = 0; + goto intx; + } else { + ctrlr->per_cpu_io_queues = FALSE; + ctrlr->num_io_queues = 1; + /* + * Release whatever vectors were allocated, and just + * reallocate the two needed for the admin and single + * I/O qpair. + */ + num_vectors_allocated = 2; + pci_release_msi(dev); + if (pci_alloc_msix(dev, &num_vectors_allocated) != 0) + panic("could not reallocate any vectors\n"); + if (num_vectors_allocated != 2) + panic("could not reallocate 2 vectors\n"); + } } /* @@ -1022,7 +1045,7 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) * vendors wishing to import this driver into kernels based on * older versions of FreeBSD. */ - for (i = 0; i < num_vectors; i++) { + for (i = 0; i < num_vectors_allocated; i++) { rid = i + 1; ctrlr->msi_res[i] = bus_alloc_resource_any(ctrlr->dev, SYS_RES_IRQ, &rid, RF_ACTIVE); diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 47d6267b8d5d..5edc72089f74 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -395,7 +395,7 @@ ofw_bus_reg_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells, * This may be just redundant when having ofw_bus_devinfo * but makes this routine independent of it. */ - ret = OF_getencprop_alloc(node, "name", sizeof(*name), (void **)&name); + ret = OF_getprop_alloc(node, "name", sizeof(*name), (void **)&name); if (ret == -1) name = NULL; @@ -511,7 +511,7 @@ ofw_bus_find_child(phandle_t start, const char *child_name) phandle_t child; for (child = OF_child(start); child != 0; child = OF_peer(child)) { - ret = OF_getencprop_alloc(child, "name", sizeof(*name), (void **)&name); + ret = OF_getprop_alloc(child, "name", sizeof(*name), (void **)&name); if (ret == -1) continue; if (strcmp(name, child_name) == 0) { diff --git a/sys/dev/proto/proto_busdma.c b/sys/dev/proto/proto_busdma.c index 27fe45159d85..52f1146ffdd0 100644 --- a/sys/dev/proto/proto_busdma.c +++ b/sys/dev/proto/proto_busdma.c @@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_PROTO_BUSDMA, "proto_busdma", "DMA management data"); +#define BNDRY_MIN(a, b) \ + (((a) == 0) ? (b) : (((b) == 0) ? (a) : MIN((a), (b)))) + struct proto_callback_bundle { struct proto_busdma *busdma; struct proto_md *md; @@ -63,6 +66,11 @@ proto_busdma_tag_create(struct proto_busdma *busdma, struct proto_tag *parent, { struct proto_tag *tag; + /* Make sure that when a boundary is specified, it's a power of 2 */ + if (ioc->u.tag.bndry != 0 && + (ioc->u.tag.bndry & (ioc->u.tag.bndry - 1)) != 0) + return (EINVAL); + /* * If nsegs is 1, ignore maxsegsz. What this means is that if we have * just 1 segment, then maxsz should be equal to maxsegsz. To keep it @@ -71,16 +79,12 @@ proto_busdma_tag_create(struct proto_busdma *busdma, struct proto_tag *parent, if (ioc->u.tag.maxsegsz > ioc->u.tag.maxsz || ioc->u.tag.nsegs == 1) ioc->u.tag.maxsegsz = ioc->u.tag.maxsz; - /* A bndry of 0 really means ~0, or no boundary. */ - if (ioc->u.tag.bndry == 0) - ioc->u.tag.bndry = ~0U; - tag = malloc(sizeof(*tag), M_PROTO_BUSDMA, M_WAITOK | M_ZERO); if (parent != NULL) { tag->parent = parent; LIST_INSERT_HEAD(&parent->children, tag, peers); tag->align = MAX(ioc->u.tag.align, parent->align); - tag->bndry = MIN(ioc->u.tag.bndry, parent->bndry); + tag->bndry = BNDRY_MIN(ioc->u.tag.bndry, parent->bndry); tag->maxaddr = MIN(ioc->u.tag.maxaddr, parent->maxaddr); tag->maxsz = MIN(ioc->u.tag.maxsz, parent->maxsz); tag->maxsegsz = MIN(ioc->u.tag.maxsegsz, parent->maxsegsz); diff --git a/sys/dev/sfxge/common/hunt_impl.h b/sys/dev/sfxge/common/hunt_impl.h index d1a4c9401124..0aa4ae52c564 100644 --- a/sys/dev/sfxge/common/hunt_impl.h +++ b/sys/dev/sfxge/common/hunt_impl.h @@ -695,6 +695,21 @@ hunt_tx_qstats_update( #define HUNT_MIN_PIO_ALLOC_SIZE (HUNT_PIOBUF_SIZE / 32) +#define HUNT_LEGACY_PF_PRIVILEGE_MASK \ + (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \ + MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS) + +#define HUNT_LEGACY_VF_PRIVILEGE_MASK 0 + typedef uint32_t efx_piobuf_handle_t; #define EFX_PIOBUF_HANDLE_INVALID ((efx_piobuf_handle_t) -1) diff --git a/sys/dev/sfxge/common/hunt_mac.c b/sys/dev/sfxge/common/hunt_mac.c index b9f7ca4a2073..be9eb37e9bf0 100644 --- a/sys/dev/sfxge/common/hunt_mac.c +++ b/sys/dev/sfxge/common/hunt_mac.c @@ -150,8 +150,19 @@ hunt_mac_addr_set( { int rc; - if ((rc = efx_mcdi_vadapter_set_mac(enp)) != 0) - goto fail1; + if ((rc = efx_mcdi_vadapter_set_mac(enp)) != 0) { + if (rc != ENOTSUP) + goto fail1; + + /* Fallback for older firmware without Vadapter support */ + if ((rc = hunt_mac_reconfigure(enp)) != 0) + goto fail2; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, int, rc); diff --git a/sys/dev/sfxge/common/hunt_nic.c b/sys/dev/sfxge/common/hunt_nic.c index a4babc39eab6..3a7204e7078f 100644 --- a/sys/dev/sfxge/common/hunt_nic.c +++ b/sys/dev/sfxge/common/hunt_nic.c @@ -1239,8 +1239,19 @@ hunt_board_cfg( * the privilege mask to check for sufficient privileges, as that * can result in time-of-check/time-of-use bugs. */ - if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) - goto fail13; + if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) { + if (rc != ENOTSUP) + goto fail13; + + /* Fallback for old firmware without privilege mask support */ + if (EFX_PCI_FUNCTION_IS_PF(encp)) { + /* Assume PF has admin privilege */ + mask = HUNT_LEGACY_PF_PRIVILEGE_MASK; + } else { + /* VF is always unprivileged by default */ + mask = HUNT_LEGACY_VF_PRIVILEGE_MASK; + } + } encp->enc_privilege_mask = mask; diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index 7394651e841a..e78d7697979a 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -99,6 +99,7 @@ struct uart_softc { int sc_polled:1; /* This UART has no interrupts. */ int sc_txbusy:1; /* This UART is transmitting. */ int sc_isquelch:1; /* This UART has input squelched. */ + int sc_testintr:1; /* This UART is under int. testing. */ struct uart_devinfo *sc_sysdev; /* System device (or NULL). */ @@ -135,7 +136,7 @@ struct uart_softc { }; extern devclass_t uart_devclass; -extern char uart_driver_name[]; +extern const char uart_driver_name[]; int uart_bus_attach(device_t dev); int uart_bus_detach(device_t dev); @@ -157,14 +158,16 @@ void uart_tty_intr(void *arg); static __inline int uart_rx_empty(struct uart_softc *sc) { + return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0); } static __inline int uart_rx_full(struct uart_softc *sc) { - return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) - ? (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0)); + + return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ? + (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0)); } static __inline int diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index 4114f375986e..191244a2ae02 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); #include "uart_if.h" devclass_t uart_devclass; -char uart_driver_name[] = "uart"; +const char uart_driver_name[] = "uart"; SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs = SLIST_HEAD_INITIALIZER(uart_sysdevs); @@ -260,13 +260,14 @@ static int uart_intr(void *arg) { struct uart_softc *sc = arg; - int cnt, ipend; + int cnt, ipend, testintr; if (sc->sc_leaving) return (FILTER_STRAY); cnt = 0; - while (cnt < 20 && (ipend = UART_IPEND(sc)) != 0) { + testintr = sc->sc_testintr; + while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) { cnt++; if (ipend & SER_INT_OVERRUN) uart_intr_overrun(sc); @@ -277,7 +278,7 @@ uart_intr(void *arg) if (ipend & SER_INT_SIGCHG) uart_intr_sigchg(sc); if (ipend & SER_INT_TXIDLE) - uart_intr_txidle(sc); + uart_intr_txidle(sc); } if (sc->sc_polled) { @@ -286,7 +287,8 @@ uart_intr(void *arg) } return ((cnt == 0) ? FILTER_STRAY : - ((cnt == 20) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED)); + ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD : + FILTER_HANDLED)); } serdev_intr_t * @@ -433,7 +435,7 @@ uart_bus_attach(device_t dev) /* * Protect ourselves against interrupts while we're not completely * finished attaching and initializing. We don't expect interrupts - * until after UART_ATTACH() though. + * until after UART_ATTACH(), though. */ sc->sc_leaving = 1; @@ -513,7 +515,9 @@ uart_bus_attach(device_t dev) pps_init(&sc->sc_pps); sc->sc_leaving = 0; + sc->sc_testintr = 1; filt = uart_intr(sc); + sc->sc_testintr = 0; /* * Don't use interrupts if we couldn't clear any pending interrupt diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 412c27ae3b02..1c1d2b0ee3d7 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -375,54 +375,12 @@ xhci_start_controller(struct xhci_softc *sc) return (USB_ERR_IOERROR); } - if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) { - device_printf(sc->sc_bus.parent, "Controller does " - "not support 4K page size.\n"); - return (USB_ERR_IOERROR); - } - - temp = XREAD4(sc, capa, XHCI_HCSPARAMS1); - - i = XHCI_HCS1_N_PORTS(temp); - - if (i == 0) { - device_printf(sc->sc_bus.parent, "Invalid number " - "of ports: %u\n", i); - return (USB_ERR_IOERROR); - } - - sc->sc_noport = i; - sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp); - - if (sc->sc_noslot > XHCI_MAX_DEVICES) - sc->sc_noslot = XHCI_MAX_DEVICES; - /* set up number of device slots */ - DPRINTF("CONFIG=0x%08x -> 0x%08x\n", XREAD4(sc, oper, XHCI_CONFIG), sc->sc_noslot); XWRITE4(sc, oper, XHCI_CONFIG, sc->sc_noslot); - DPRINTF("Max slots: %u\n", sc->sc_noslot); - - temp = XREAD4(sc, capa, XHCI_HCSPARAMS2); - - sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp); - - if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) { - device_printf(sc->sc_bus.parent, "XHCI request " - "too many scratchpads\n"); - return (USB_ERR_NOMEM); - } - - DPRINTF("Max scratch: %u\n", sc->sc_noscratch); - - temp = XREAD4(sc, capa, XHCI_HCSPARAMS3); - - sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) + - XHCI_HCS3_U2_DEL(temp) + 250 /* us */; - temp = XREAD4(sc, oper, XHCI_USBSTS); /* clear interrupts */ @@ -454,29 +412,13 @@ xhci_start_controller(struct xhci_softc *sc) XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr); XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32)); - /* Setup event table size */ - - temp = XREAD4(sc, capa, XHCI_HCSPARAMS2); - - DPRINTF("HCS2=0x%08x\n", temp); - - temp = XHCI_HCS2_ERST_MAX(temp); - temp = 1U << temp; - if (temp > XHCI_MAX_RSEG) - temp = XHCI_MAX_RSEG; - - sc->sc_erst_max = temp; - + /* set up event table size */ DPRINTF("ERSTSZ=0x%08x -> 0x%08x\n", - XREAD4(sc, runt, XHCI_ERSTSZ(0)), temp); + XREAD4(sc, runt, XHCI_ERSTSZ(0)), sc->sc_erst_max); - XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(temp)); + XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(sc->sc_erst_max)); - /* Check if we should use the default IMOD value */ - if (sc->sc_imod_default == 0) - sc->sc_imod_default = XHCI_IMOD_DEFAULT; - - /* Setup interrupt rate */ + /* set up interrupt rate */ XWRITE4(sc, runt, XHCI_IMOD(0), sc->sc_imod_default); usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res); @@ -503,8 +445,7 @@ xhci_start_controller(struct xhci_softc *sc) XWRITE4(sc, runt, XHCI_ERSTBA_LO(0), (uint32_t)addr); XWRITE4(sc, runt, XHCI_ERSTBA_HI(0), (uint32_t)(addr >> 32)); - /* Setup interrupter registers */ - + /* set up interrupter registers */ temp = XREAD4(sc, runt, XHCI_IMAN(0)); temp |= XHCI_IMAN_INTR_ENA; XWRITE4(sc, runt, XHCI_IMAN(0), temp); @@ -615,6 +556,12 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION)); + if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) { + device_printf(sc->sc_bus.parent, "Controller does " + "not support 4K page size.\n"); + return (ENXIO); + } + temp = XREAD4(sc, capa, XHCI_HCSPARAMS0); DPRINTF("HCS0 = 0x%08x\n", temp); @@ -633,6 +580,55 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) device_printf(self, "%d bytes context size, %d-bit DMA\n", sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits); + temp = XREAD4(sc, capa, XHCI_HCSPARAMS1); + + /* get number of device slots */ + sc->sc_noport = XHCI_HCS1_N_PORTS(temp); + + if (sc->sc_noport == 0) { + device_printf(sc->sc_bus.parent, "Invalid number " + "of ports: %u\n", sc->sc_noport); + return (ENXIO); + } + + sc->sc_noport = sc->sc_noport; + sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp); + + DPRINTF("Max slots: %u\n", sc->sc_noslot); + + if (sc->sc_noslot > XHCI_MAX_DEVICES) + sc->sc_noslot = XHCI_MAX_DEVICES; + + temp = XREAD4(sc, capa, XHCI_HCSPARAMS2); + + DPRINTF("HCS2=0x%08x\n", temp); + + /* get number of scratchpads */ + sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp); + + if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) { + device_printf(sc->sc_bus.parent, "XHCI request " + "too many scratchpads\n"); + return (ENOMEM); + } + + DPRINTF("Max scratch: %u\n", sc->sc_noscratch); + + /* get event table size */ + sc->sc_erst_max = 1U << XHCI_HCS2_ERST_MAX(temp); + if (sc->sc_erst_max > XHCI_MAX_RSEG) + sc->sc_erst_max = XHCI_MAX_RSEG; + + temp = XREAD4(sc, capa, XHCI_HCSPARAMS3); + + /* get maximum exit latency */ + sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) + + XHCI_HCS3_U2_DEL(temp) + 250 /* us */; + + /* Check if we should use the default IMOD value. */ + if (sc->sc_imod_default == 0) + sc->sc_imod_default = XHCI_IMOD_DEFAULT; + /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) { diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index 0e2c63201cb5..0ad7357caf7e 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -86,10 +86,9 @@ static driver_t xhci_driver = { static devclass_t xhci_devclass; -DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, 0, 0); +DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, NULL, NULL); MODULE_DEPEND(xhci, usb, 1, 1, 1); - static const char * xhci_pci_match(device_t self) { @@ -101,6 +100,8 @@ xhci_pci_match(device_t self) case 0x10421b21: return ("ASMedia ASM1042 USB 3.0 controller"); + case 0x11421b21: + return ("ASMedia ASM1042A USB 3.0 controller"); case 0x0f358086: return ("Intel Intel BayTrail USB 3.0 controller"); @@ -193,16 +194,28 @@ xhci_pci_attach(device_t self) sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = rman_get_size(sc->sc_io_res); - /* check for USB 3.0 controllers which don't support 64-bit DMA */ switch (pci_get_devid(self)) { case 0x01941033: /* NEC uPD720200 USB 3.0 controller */ + /* Don't use 64-bit DMA on these controllers. */ usedma32 = 1; break; + case 0x0f358086: /* BayTrail */ + case 0x9c318086: /* Panther Point */ + case 0x1e318086: /* Panther Point */ + case 0x8c318086: /* Lynx Point */ + case 0x8cb18086: /* Wildcat Point */ + /* + * On Intel chipsets, reroute ports from EHCI to XHCI + * controller and use a different IMOD value. + */ + sc->sc_port_route = &xhci_pci_port_route; + sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP; + /* FALLTHROUGH */ default: usedma32 = 0; break; } - + if (xhci_init(sc, self, usedma32)) { device_printf(self, "Could not initialize softc\n"); bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM, @@ -261,20 +274,6 @@ xhci_pci_attach(device_t self) goto error; } - /* On Intel chipsets reroute ports from EHCI to XHCI controller. */ - switch (pci_get_devid(self)) { - case 0x0f358086: /* BayTrail */ - case 0x9c318086: /* Panther Point */ - case 0x1e318086: /* Panther Point */ - case 0x8c318086: /* Lynx Point */ - case 0x8cb18086: /* Wildcat Point */ - sc->sc_port_route = &xhci_pci_port_route; - sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP; - break; - default: - break; - } - xhci_pci_take_controller(self); err = xhci_halt_controller(sc); diff --git a/sys/dev/usb/net/if_urndis.c b/sys/dev/usb/net/if_urndis.c index ef6e18840833..3c24dcf1d4d7 100644 --- a/sys/dev/usb/net/if_urndis.c +++ b/sys/dev/usb/net/if_urndis.c @@ -78,12 +78,20 @@ static uether_fn_t urndis_start; static uether_fn_t urndis_setmulti; static uether_fn_t urndis_setpromisc; -static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, const void **, uint16_t *); -static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, struct urndis_set_req *, uint16_t); -static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, const struct urndis_comp_hdr *); -static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, const struct urndis_comp_hdr *, const void **, uint16_t *); -static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, const struct urndis_comp_hdr *); -static uint32_t urndis_ctrl_init(struct urndis_softc *); +static uint32_t urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, + struct urndis_query_req *msg, uint16_t len, + const void **rbuf, uint16_t *rbufsz); +static uint32_t urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, + struct urndis_set_req *msg, uint16_t len); +static uint32_t urndis_ctrl_handle_init(struct urndis_softc *sc, + const struct urndis_comp_hdr *hdr); +static uint32_t urndis_ctrl_handle_query(struct urndis_softc *sc, + const struct urndis_comp_hdr *hdr, const void **buf, + uint16_t *bufsz); +static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *sc, + const struct urndis_comp_hdr *hdr); +static uint32_t urndis_ctrl_init(struct urndis_softc *sc); +static uint32_t urndis_ctrl_halt(struct urndis_softc *sc); #ifdef USB_DEBUG static int urndis_debug = 0; @@ -93,7 +101,6 @@ SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RWTUN, &urndis_debug, 0, #endif static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = { - [URNDIS_BULK_RX] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, @@ -154,7 +161,7 @@ static driver_t urndis_driver = { static devclass_t urndis_devclass; -DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, 0); +DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL); MODULE_VERSION(urndis, 1); MODULE_DEPEND(urndis, uether, 1, 1, 1); MODULE_DEPEND(urndis, usb, 1, 1, 1); @@ -171,6 +178,9 @@ static const struct usb_ether_methods urndis_ue_methods = { static const STRUCT_USB_HOST_ID urndis_host_devs[] = { /* Generic RNDIS class match */ + {USB_IFACE_CLASS(UICLASS_CDC), + USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), + USB_IFACE_PROTOCOL(0xff)}, {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF), USB_IFACE_PROTOCOL(UIPROTO_RNDIS)}, {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC), @@ -192,21 +202,27 @@ urndis_probe(device_t dev) static void urndis_attach_post(struct usb_ether *ue) { + /* no-op */ - return; } static int urndis_attach(device_t dev) { + static struct { + union { + struct urndis_query_req query; + struct urndis_set_req set; + } hdr; + union { + uint8_t eaddr[ETHER_ADDR_LEN]; + uint32_t filter; + } ibuf; + } msg; struct urndis_softc *sc = device_get_softc(dev); struct usb_ether *ue = &sc->sc_ue; struct usb_attach_arg *uaa = device_get_ivars(dev); struct usb_cdc_cm_descriptor *cmd; - struct { - struct urndis_set_req hdr; - uint32_t filter; - } msg_filter; const void *buf; uint16_t bufsz; uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex }; @@ -228,9 +244,7 @@ urndis_attach(device_t dev) mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); /* scan the alternate settings looking for a valid one */ - for (i = 0; i != 32; i++) { - error = usbd_set_alt_interface_index(uaa->device, iface_index[0], i); @@ -244,16 +258,27 @@ urndis_attach(device_t dev) if (error == 0) break; } - if ((error != 0) || (i == 32)) { - device_printf(dev, "No valid alternate " - "setting found\n"); + device_printf(dev, "No valid alternate setting found\n"); goto detach; } - URNDIS_LOCK(sc); - error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, &buf, &bufsz); - URNDIS_UNLOCK(sc); + /* Initialize device - must be done before even querying it */ + URNDIS_LOCK(sc); + error = urndis_ctrl_init(sc); + URNDIS_UNLOCK(sc); + if (error != (int)RNDIS_STATUS_SUCCESS) { + device_printf(dev, "Unable to initialize hardware\n"); + goto detach; + } + + /* Determine MAC address */ + memset(msg.ibuf.eaddr, 0, sizeof(msg.ibuf.eaddr)); + URNDIS_LOCK(sc); + error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, + &msg.hdr.query, sizeof(msg.hdr.query) + sizeof(msg.ibuf.eaddr), + &buf, &bufsz); + URNDIS_UNLOCK(sc); if (error != (int)RNDIS_STATUS_SUCCESS) { device_printf(dev, "Unable to get hardware address\n"); goto detach; @@ -267,17 +292,16 @@ urndis_attach(device_t dev) /* Initialize packet filter */ sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST | RNDIS_PACKET_TYPE_ALL_MULTICAST; - msg_filter.filter = htole32(sc->sc_filter); - + msg.ibuf.filter = htole32(sc->sc_filter); URNDIS_LOCK(sc); error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, - &msg_filter.hdr, sizeof(msg_filter)); + &msg.hdr.set, sizeof(msg.hdr.set) + sizeof(msg.ibuf.filter)); URNDIS_UNLOCK(sc); - if (error != (int)RNDIS_STATUS_SUCCESS) { device_printf(dev, "Unable to set data filters\n"); goto detach; } + ue->ue_sc = sc; ue->ue_dev = dev; ue->ue_udev = uaa->device; @@ -298,7 +322,7 @@ urndis_attach(device_t dev) return (0); /* success */ detach: - urndis_detach(dev); + (void)urndis_detach(dev); return (ENXIO); /* failure */ } @@ -313,6 +337,10 @@ urndis_detach(device_t dev) uether_ifdetach(ue); + URNDIS_LOCK(sc); + (void)urndis_ctrl_halt(sc); + URNDIS_UNLOCK(sc); + mtx_destroy(&sc->sc_mtx); return (0); @@ -340,8 +368,6 @@ urndis_init(struct usb_ether *ue) ifp->if_drv_flags |= IFF_DRV_RUNNING; - urndis_ctrl_init(sc); - /* stall data write direction, which depends on USB mode */ usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]); @@ -369,20 +395,21 @@ urndis_stop(struct usb_ether *ue) static void urndis_setmulti(struct usb_ether *ue) { + /* no-op */ - return; } static void urndis_setpromisc(struct usb_ether *ue) { + /* no-op */ - return; } static int urndis_suspend(device_t dev) { + device_printf(dev, "Suspending\n"); return (0); } @@ -390,6 +417,7 @@ urndis_suspend(device_t dev) static int urndis_resume(device_t dev) { + device_printf(dev, "Resuming\n"); return (0); } @@ -416,8 +444,8 @@ urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len) { usb_error_t err; - err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS, - sc->sc_ifaceno_ctl, 0, buf, len); + err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, + UCDC_SEND_ENCAPSULATED_COMMAND, sc->sc_ifaceno_ctl, 0, buf, len); DPRINTF("%s\n", usbd_errstr(err)); @@ -430,8 +458,9 @@ urndis_ctrl_recv(struct urndis_softc *sc) struct urndis_comp_hdr *hdr; usb_error_t err; - err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE, - sc->sc_ifaceno_ctl, 0, sc->sc_response_buf, RNDIS_RESPONSE_LEN); + err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, + UCDC_GET_ENCAPSULATED_RESPONSE, sc->sc_ifaceno_ctl, 0, + sc->sc_response_buf, RNDIS_RESPONSE_LEN); if (err != USB_ERR_NORMAL_COMPLETION) return (NULL); @@ -480,7 +509,8 @@ urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr, break; default: - DPRINTF("ctrl message error: unknown event 0x%x\n", + device_printf(sc->sc_ue.ue_dev, + "ctrl message error: unknown event 0x%x\n", le32toh(hdr->rm_type)); rval = RNDIS_STATUS_FAILURE; break; @@ -548,10 +578,8 @@ urndis_ctrl_handle_query(struct urndis_softc *sc, le32toh(msg->rm_infobuflen), le32toh(msg->rm_infobufoffset)); - if (buf != NULL && bufsz != NULL) { - *buf = NULL; - *bufsz = 0; - } + *buf = NULL; + *bufsz = 0; if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status)); return (le32toh(msg->rm_status)); @@ -571,10 +599,10 @@ urndis_ctrl_handle_query(struct urndis_softc *sc, le32toh(msg->rm_len)); return (RNDIS_STATUS_FAILURE); } - if (buf != NULL && bufsz != NULL) { - *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + le32toh(msg->rm_infobufoffset); - *bufsz = le32toh(msg->rm_infobuflen); - } + *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + + le32toh(msg->rm_infobufoffset); + *bufsz = le32toh(msg->rm_infobuflen); + return (le32toh(msg->rm_status)); } @@ -627,7 +655,7 @@ urndis_ctrl_init(struct urndis_softc *sc) msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG); msg.rm_len = htole32(sizeof(msg)); - msg.rm_rid = htole32(0); + msg.rm_rid = 0; msg.rm_ver_major = htole32(1); msg.rm_ver_minor = htole32(1); msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN); @@ -656,7 +684,6 @@ urndis_ctrl_init(struct urndis_softc *sc) return (rval); } -#if 0 static uint32_t urndis_ctrl_halt(struct urndis_softc *sc) { @@ -675,39 +702,48 @@ urndis_ctrl_halt(struct urndis_softc *sc) rval = urndis_ctrl_send(sc, &msg, sizeof(msg)); if (rval != RNDIS_STATUS_SUCCESS) - printf("halt failed\n"); + DPRINTF("halt failed\n"); return (rval); } -#endif - +/* + * NB: Querying a device has the requirment of using an input buffer the size + * of the expected reply or larger, except for variably sized replies. + */ static uint32_t -urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint16_t *rbufsz) +urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, + struct urndis_query_req *msg, uint16_t len, const void **rbuf, + uint16_t *rbufsz) { - struct urndis_query_req msg; - uint32_t rval; struct urndis_comp_hdr *hdr; + uint32_t datalen, rval; - msg.rm_type = htole32(REMOTE_NDIS_QUERY_MSG); - msg.rm_len = htole32(sizeof(msg)); - msg.rm_rid = 0; /* XXX */ - msg.rm_oid = htole32(oid); - msg.rm_infobuflen = htole32(0); - msg.rm_infobufoffset = 0; - msg.rm_devicevchdl = 0; + msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG); + msg->rm_len = htole32(len); + msg->rm_rid = 0; /* XXX */ + msg->rm_oid = htole32(oid); + datalen = len - sizeof(*msg); + msg->rm_infobuflen = htole32(datalen); + if (datalen != 0) { + msg->rm_infobufoffset = htole32(sizeof(*msg) - + RNDIS_HEADER_OFFSET); + } else { + msg->rm_infobufoffset = 0; + } + msg->rm_devicevchdl = 0; DPRINTF("type %u len %u rid %u oid 0x%x " "infobuflen %u infobufoffset %u devicevchdl %u\n", - le32toh(msg.rm_type), - le32toh(msg.rm_len), - le32toh(msg.rm_rid), - le32toh(msg.rm_oid), - le32toh(msg.rm_infobuflen), - le32toh(msg.rm_infobufoffset), - le32toh(msg.rm_devicevchdl)); + le32toh(msg->rm_type), + le32toh(msg->rm_len), + le32toh(msg->rm_rid), + le32toh(msg->rm_oid), + le32toh(msg->rm_infobuflen), + le32toh(msg->rm_infobufoffset), + le32toh(msg->rm_devicevchdl)); - rval = urndis_ctrl_send(sc, &msg, sizeof(msg)); + rval = urndis_ctrl_send(sc, msg, len); if (rval != RNDIS_STATUS_SUCCESS) { DPRINTF("query failed\n"); @@ -723,19 +759,21 @@ urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint } static uint32_t -urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, struct urndis_set_req *msg, uint16_t len) +urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, + struct urndis_set_req *msg, uint16_t len) { struct urndis_comp_hdr *hdr; - uint32_t rval; - uint32_t datalen = len - sizeof(*msg); + uint32_t datalen, rval; msg->rm_type = htole32(REMOTE_NDIS_SET_MSG); msg->rm_len = htole32(len); msg->rm_rid = 0; /* XXX */ msg->rm_oid = htole32(oid); + datalen = len - sizeof(*msg); msg->rm_infobuflen = htole32(datalen); if (datalen != 0) { - msg->rm_infobufoffset = htole32(sizeof(*msg) - RNDIS_HEADER_OFFSET); + msg->rm_infobufoffset = htole32(sizeof(*msg) - + RNDIS_HEADER_OFFSET); } else { msg->rm_infobufoffset = 0; } @@ -782,13 +820,11 @@ urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: - usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes); for (offset = 0; actlen >= (uint32_t)sizeof(msg);) { - /* copy out header */ usbd_copy_out(pc, offset, &msg, sizeof(msg)); @@ -929,7 +965,7 @@ urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x); - next_pkt: +next_pkt: IFQ_DRV_DEQUEUE(&ifp->if_snd, m); if (m == NULL) diff --git a/sys/dev/vt/colors/vt_termcolors.c b/sys/dev/vt/colors/vt_termcolors.c index d8a59091d39a..507561945dbd 100644 --- a/sys/dev/vt/colors/vt_termcolors.c +++ b/sys/dev/vt/colors/vt_termcolors.c @@ -25,15 +25,16 @@ * 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 +__FBSDID("$FreeBSD$"); + #include #include -static struct { +static const struct { unsigned char r; /* Red percentage value. */ unsigned char g; /* Green percentage value. */ unsigned char b; /* Blue percentage value. */ @@ -68,8 +69,8 @@ static const int cons_to_vga_colors[16] = { }; int -vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax, int roffset, - uint32_t gmax, int goffset, uint32_t bmax, int boffset) +vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax, + int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset) { int i; diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c index 05b2d795228a..74da47938385 100644 --- a/sys/dev/vt/hw/efifb/efifb.c +++ b/sys/dev/vt/hw/efifb/efifb.c @@ -25,8 +25,6 @@ * 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 @@ -178,4 +176,3 @@ vt_efifb_remap(void *xinfo) info->fb_vbase = (intptr_t)pmap_mapdev_attr(info->fb_pbase, info->fb_size, VM_MEMATTR_WRITE_COMBINING); } - diff --git a/sys/dev/vt/hw/fb/vt_early_fb.c b/sys/dev/vt/hw/fb/vt_early_fb.c index 187f7f72dd93..3eddfba48021 100644 --- a/sys/dev/vt/hw/fb/vt_early_fb.c +++ b/sys/dev/vt/hw/fb/vt_early_fb.c @@ -25,8 +25,6 @@ * 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 @@ -127,7 +125,7 @@ vt_efb_initialize(struct fb_info *info) default: panic("Unknown color space fb_depth %d", info->fb_depth); break; - } + } } static phandle_t @@ -213,9 +211,9 @@ vt_efb_init(struct vt_device *vd) if (len == -1) { len = OF_getprop(OF_parent(node), "assigned-addresses", pciaddrs, sizeof(pciaddrs)); - } - if (len == -1) - len = 0; + } + if (len == -1) + len = 0; n_pciaddrs = len / sizeof(struct ofw_pci_register); /* @@ -283,7 +281,7 @@ vt_efb_init(struct vt_device *vd) BUS_SPACE_MAP_PREFETCHABLE, (bus_space_handle_t *)&info->fb_vbase); #endif - } + } /* blank full size */ len = info->fb_size / 4; diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c index b2babd1a7f7b..c8b221f7b37c 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -25,8 +25,6 @@ * 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 @@ -188,7 +186,6 @@ vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color) /* panic? */ return; } - } void diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 1b633fdd3e28..99da8923d1b8 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -110,8 +110,8 @@ const struct terminal_class vt_termclass = { #define VT_TIMERFREQ 25 /* Bell pitch/duration. */ -#define VT_BELLDURATION ((5 * hz + 99) / 100) -#define VT_BELLPITCH 800 +#define VT_BELLDURATION ((5 * hz + 99) / 100) +#define VT_BELLPITCH 800 #define VT_UNIT(vw) ((vw)->vw_device->vd_unit * VT_MAXWINDOWS + \ (vw)->vw_number) @@ -137,11 +137,11 @@ static VT_SYSCTL_INT(kbd_panic, 0, "Enable request to panic. " /* Used internally, not a tunable. */ int vt_draw_logo_cpus; -VT_SYSCTL_INT(splash_cpu, 1, "Show logo CPUs during boot"); +VT_SYSCTL_INT(splash_cpu, 0, "Show logo CPUs during boot"); VT_SYSCTL_INT(splash_ncpu, 0, "Override number of logos displayed " "(0 = do not override)"); -VT_SYSCTL_INT(splash_cpu_style, 1, "Draw logo style " - "(0=Beastie, 1=Alternate beastie, 2=Orb)"); +VT_SYSCTL_INT(splash_cpu_style, 2, "Draw logo style " + "(0 = Alternate beastie, 1 = Beastie, 2 = Orb)"); VT_SYSCTL_INT(splash_cpu_duration, 10, "Hide logos after (seconds)"); static struct vt_device vt_consdev; @@ -154,6 +154,10 @@ extern unsigned int vt_logo_width; extern unsigned int vt_logo_height; extern unsigned int vt_logo_depth; extern unsigned char vt_logo_image[]; +#ifndef DEV_SPLASH +#define vtterm_draw_cpu_logos(...) do {} while (0) +const unsigned int vt_logo_sprite_height; +#endif /* Font. */ extern struct vt_font vt_font_default; @@ -178,8 +182,8 @@ static void vt_resume_handler(void *priv); SET_DECLARE(vt_drv_set, struct vt_driver); -#define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)) -#define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)) +#define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)) +#define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)) struct terminal vt_consterm; static struct vt_window vt_conswindow; diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 9a8aa8ace46b..fa489b2f3842 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1709,20 +1709,18 @@ tmpfs_chtimes(struct vnode *vp, struct vattr *vap, if (error != 0) return (error); - if (vap->va_atime.tv_sec != VNOVAL && vap->va_atime.tv_nsec != VNOVAL) + if (vap->va_atime.tv_sec != VNOVAL) node->tn_status |= TMPFS_NODE_ACCESSED; - if (vap->va_mtime.tv_sec != VNOVAL && vap->va_mtime.tv_nsec != VNOVAL) + if (vap->va_mtime.tv_sec != VNOVAL) node->tn_status |= TMPFS_NODE_MODIFIED; - if (vap->va_birthtime.tv_nsec != VNOVAL && - vap->va_birthtime.tv_nsec != VNOVAL) + if (vap->va_birthtime.tv_sec != VNOVAL) node->tn_status |= TMPFS_NODE_MODIFIED; tmpfs_itimes(vp, &vap->va_atime, &vap->va_mtime); - if (vap->va_birthtime.tv_nsec != VNOVAL && - vap->va_birthtime.tv_nsec != VNOVAL) + if (vap->va_birthtime.tv_sec != VNOVAL) node->tn_birthtime = vap->va_birthtime; MPASS(VOP_ISLOCKED(vp)); diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 680aabd3ac26..52a554d125ce 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -322,8 +322,10 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp) if (e1->gpe_offset > offset) offset = e1->gpe_offset; if ((offset + pp->stripeoffset) % pp->stripesize) { - DPRINTF("partition %d is not aligned on %u " - "bytes\n", e1->gpe_index, pp->stripesize); + DPRINTF("partition %d on (%s, %s) is not " + "aligned on %u bytes\n", e1->gpe_index, + pp->name, table->gpt_scheme->name, + pp->stripesize); /* Don't treat this as a critical failure */ } } diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c index b5ea2aff05ce..945608da2834 100644 --- a/sys/kern/kern_rmlock.c +++ b/sys/kern/kern_rmlock.c @@ -586,7 +586,7 @@ _rm_wunlock(struct rmlock *rm) mtx_unlock(&rm->rm_lock_mtx); } -#ifdef LOCK_DEBUG +#if LOCK_DEBUG > 0 void _rm_wlock_debug(struct rmlock *rm, const char *file, int line) diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index ab494cebb65c..70e2ca96a140 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -661,6 +661,9 @@ static struct witness_order_list_entry order_lists[] = { */ { "intrcnt", &lock_class_mtx_spin }, { "icu", &lock_class_mtx_spin }, +#if defined(SMP) && defined(__sparc64__) + { "ipi", &lock_class_mtx_spin }, +#endif #ifdef __i386__ { "allpmaps", &lock_class_mtx_spin }, { "descriptor tables", &lock_class_mtx_spin }, diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index dbfa28a7f4c3..1b2c7615d44b 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -651,12 +651,13 @@ struct ksem_close_args { int sys_ksem_close(struct thread *td, struct ksem_close_args *uap) { + cap_rights_t rights; struct ksem *ks; struct file *fp; int error; /* No capability rights required to close a semaphore. */ - error = ksem_get(td, uap->id, 0, &fp); + error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp); if (error) return (error); ks = fp->f_data; @@ -872,12 +873,13 @@ struct ksem_destroy_args { int sys_ksem_destroy(struct thread *td, struct ksem_destroy_args *uap) { + cap_rights_t rights; struct file *fp; struct ksem *ks; int error; /* No capability rights required to close a semaphore. */ - error = ksem_get(td, uap->id, 0, &fp); + error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp); if (error) return (error); ks = fp->f_data; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index c9d817954b97..350ca3cdd0b0 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -440,7 +440,7 @@ sodealloc(struct socket *so) if (so->so_snd.sb_hiwat) (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, 0, RLIM_INFINITY); - /* remove acccept filter if one is present. */ + /* remove accept filter if one is present. */ if (so->so_accf != NULL) do_setopt_accept_filter(so, NULL); #ifdef MAC @@ -2334,6 +2334,9 @@ soshutdown(struct socket *so, int how) if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) return (EINVAL); + if ((so->so_state & + (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) + return (ENOTCONN); CURVNET_SET(so->so_vnet); if (pr->pr_usrreqs->pru_flush != NULL) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index e3557ba72604..54c13024c611 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1383,6 +1383,15 @@ sys_shutdown(td, uap) if (error == 0) { so = fp->f_data; error = soshutdown(so, uap->how); + /* + * Previous versions did not return ENOTCONN, but 0 in + * case the socket was not connected. Some important + * programs like syslogd up to r279016, 2015-02-19, + * still depend on this behavior. + */ + if (error == ENOTCONN && + td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN) + error = 0; fdrop(fp, td); } return (error); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 19ec6ddc1b9a..d29c308d825b 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -137,12 +137,11 @@ SYSCTL_PROC(_vfs, OID_AUTO, bufspace, CTLTYPE_LONG|CTLFLAG_MPSAFE|CTLFLAG_RD, &bufspace, 0, sysctl_bufspace, "L", "Virtual memory used for buffers"); #else SYSCTL_LONG(_vfs, OID_AUTO, bufspace, CTLFLAG_RD, &bufspace, 0, - "Virtual memory used for buffers"); + "Physical memory used for buffers"); #endif -static long unmapped_bufspace; -SYSCTL_LONG(_vfs, OID_AUTO, unmapped_bufspace, CTLFLAG_RD, - &unmapped_bufspace, 0, - "Amount of unmapped buffers, inclusive in the bufspace"); +static long bufkvaspace; +SYSCTL_LONG(_vfs, OID_AUTO, bufkvaspace, CTLFLAG_RD, &bufkvaspace, 0, + "Kernel virtual memory used for buffers"); static long maxbufspace; SYSCTL_LONG(_vfs, OID_AUTO, maxbufspace, CTLFLAG_RD, &maxbufspace, 0, "Maximum allowed value of bufspace (including buf_daemon)"); @@ -454,15 +453,14 @@ bdirtyadd(void) * sufficient buffer space. Buffer space becomes recoverable when * bp's get placed back in the queues. */ - static __inline void bufspacewakeup(void) { int need_wakeup, on; /* - * If someone is waiting for BUF space, wake them up. Even - * though we haven't freed the kva space yet, the waiting + * If someone is waiting for bufspace, wake them up. Even + * though we may not have freed the kva space yet, the waiting * process will be able to now. */ rw_rlock(&nblock); @@ -481,6 +479,50 @@ bufspacewakeup(void) rw_runlock(&nblock); } +/* + * bufspaceadjust: + * + * Adjust the reported bufspace for a KVA managed buffer, possibly + * waking any waiters. + */ +static void +bufspaceadjust(struct buf *bp, int bufsize) +{ + int diff; + + KASSERT((bp->b_flags & B_MALLOC) == 0, + ("bufspaceadjust: malloc buf %p", bp)); + diff = bufsize - bp->b_bufsize; + if (diff < 0) { + atomic_subtract_long(&bufspace, -diff); + bufspacewakeup(); + } else + atomic_add_long(&bufspace, diff); + bp->b_bufsize = bufsize; +} + +/* + * bufmallocadjust: + * + * Adjust the reported bufspace for a malloc managed buffer, possibly + * waking any waiters. + */ +static void +bufmallocadjust(struct buf *bp, int bufsize) +{ + int diff; + + KASSERT((bp->b_flags & B_MALLOC) != 0, + ("bufmallocadjust: non-malloc buf %p", bp)); + diff = bufsize - bp->b_bufsize; + if (diff < 0) { + atomic_subtract_long(&bufmallocspace, -diff); + bufspacewakeup(); + } else + atomic_add_long(&bufmallocspace, diff); + bp->b_bufsize = bufsize; +} + /* * runningwakeup: * @@ -817,6 +859,8 @@ bufinit(void) for (i = 0; i < BUFFER_QUEUES; i++) TAILQ_INIT(&bufqueues[i]); + unmapped_buf = (caddr_t)kva_alloc(MAXPHYS); + /* finally, initialize each buffer header and stick on empty q */ for (i = 0; i < nbuf; i++) { bp = &buf[i]; @@ -826,6 +870,7 @@ bufinit(void) bp->b_wcred = NOCRED; bp->b_qindex = QUEUE_EMPTY; bp->b_xflags = 0; + bp->b_data = bp->b_kvabase = unmapped_buf; LIST_INIT(&bp->b_dep); BUF_LOCKINIT(bp); TAILQ_INSERT_TAIL(&bufqueues[QUEUE_EMPTY], bp, b_freelist); @@ -900,7 +945,6 @@ bufinit(void) bogus_page = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | VM_ALLOC_WIRED); - unmapped_buf = (caddr_t)kva_alloc(MAXPHYS); } #ifdef INVARIANTS @@ -908,22 +952,18 @@ static inline void vfs_buf_check_mapped(struct buf *bp) { - KASSERT((bp->b_flags & B_UNMAPPED) == 0, - ("mapped buf %p %x", bp, bp->b_flags)); KASSERT(bp->b_kvabase != unmapped_buf, ("mapped buf: b_kvabase was not updated %p", bp)); KASSERT(bp->b_data != unmapped_buf, ("mapped buf: b_data was not updated %p", bp)); + KASSERT(bp->b_data < unmapped_buf || bp->b_data > unmapped_buf + + MAXPHYS, ("b_data + b_offset unmapped %p", bp)); } static inline void vfs_buf_check_unmapped(struct buf *bp) { - KASSERT((bp->b_flags & B_UNMAPPED) == B_UNMAPPED, - ("unmapped buf %p %x", bp, bp->b_flags)); - KASSERT(bp->b_kvabase == unmapped_buf, - ("unmapped buf: corrupted b_kvabase %p", bp)); KASSERT(bp->b_data == unmapped_buf, ("unmapped buf: corrupted b_data %p", bp)); } @@ -951,37 +991,6 @@ bpmap_qenter(struct buf *bp) (vm_offset_t)(bp->b_offset & PAGE_MASK)); } -/* - * bfreekva() - free the kva allocation for a buffer. - * - * Since this call frees up buffer space, we call bufspacewakeup(). - */ -static void -bfreekva(struct buf *bp) -{ - - if (bp->b_kvasize == 0) - return; - - atomic_add_int(&buffreekvacnt, 1); - atomic_subtract_long(&bufspace, bp->b_kvasize); - if ((bp->b_flags & B_UNMAPPED) == 0) { - BUF_CHECK_MAPPED(bp); - vmem_free(buffer_arena, (vm_offset_t)bp->b_kvabase, - bp->b_kvasize); - } else { - BUF_CHECK_UNMAPPED(bp); - if ((bp->b_flags & B_KVAALLOC) != 0) { - vmem_free(buffer_arena, (vm_offset_t)bp->b_kvaalloc, - bp->b_kvasize); - } - atomic_subtract_long(&unmapped_bufspace, bp->b_kvasize); - bp->b_flags &= ~(B_UNMAPPED | B_KVAALLOC); - } - bp->b_kvasize = 0; - bufspacewakeup(); -} - /* * binsfree: * @@ -1103,6 +1112,75 @@ bremfreel(struct buf *bp) bufcountsub(bp); } +/* + * bufkvafree: + * + * Free the kva allocation for a buffer. + * + */ +static void +bufkvafree(struct buf *bp) +{ + +#ifdef INVARIANTS + if (bp->b_kvasize == 0) { + KASSERT(bp->b_kvabase == unmapped_buf && + bp->b_data == unmapped_buf, + ("Leaked KVA space on %p", bp)); + } else if (buf_mapped(bp)) + BUF_CHECK_MAPPED(bp); + else + BUF_CHECK_UNMAPPED(bp); +#endif + if (bp->b_kvasize == 0) + return; + + vmem_free(buffer_arena, (vm_offset_t)bp->b_kvabase, bp->b_kvasize); + atomic_subtract_long(&bufkvaspace, bp->b_kvasize); + atomic_add_int(&buffreekvacnt, 1); + bp->b_data = bp->b_kvabase = unmapped_buf; + bp->b_kvasize = 0; +} + +/* + * bufkvaalloc: + * + * Allocate the buffer KVA and set b_kvasize and b_kvabase. + */ +static int +bufkvaalloc(struct buf *bp, int maxsize, int gbflags) +{ + vm_offset_t addr; + int error; + + KASSERT((gbflags & GB_UNMAPPED) == 0 || (gbflags & GB_KVAALLOC) != 0, + ("Invalid gbflags 0x%x in %s", gbflags, __func__)); + + bufkvafree(bp); + + addr = 0; + error = vmem_alloc(buffer_arena, maxsize, M_BESTFIT | M_NOWAIT, &addr); + if (error != 0) { + /* + * Buffer map is too fragmented. Request the caller + * to defragment the map. + */ + atomic_add_int(&bufdefragcnt, 1); + return (error); + } + bp->b_kvabase = (caddr_t)addr; + bp->b_kvasize = maxsize; + atomic_add_long(&bufkvaspace, bp->b_kvasize); + if ((gbflags & GB_UNMAPPED) != 0) { + bp->b_data = unmapped_buf; + BUF_CHECK_UNMAPPED(bp); + } else { + bp->b_data = bp->b_kvabase; + BUF_CHECK_MAPPED(bp); + } + return (0); +} + /* * Attempt to initiate asynchronous I/O on read-ahead blocks. We must * clear BIO_ERROR and B_INVAL prior to initiating I/O . If B_CACHE is set, @@ -1563,15 +1641,6 @@ buf_dirty_count_severe(void) return(numdirtybuffers >= hidirtybuffers); } -static __noinline int -buf_vm_page_count_severe(void) -{ - - KFAIL_POINT_CODE(DEBUG_FP, buf_pressure, return 1); - - return vm_page_count_severe(); -} - /* * brelse: * @@ -1647,20 +1716,9 @@ brelse(struct buf *bp) * * We still allow the B_INVAL case to call vfs_vmio_release(), even * if B_DELWRI is set. - * - * If B_DELWRI is not set we may have to set B_RELBUF if we are low - * on pages to return pages to the VM page queues. */ if (bp->b_flags & B_DELWRI) bp->b_flags &= ~B_RELBUF; - else if (buf_vm_page_count_severe()) { - /* - * BKGRDINPROG can only be set with the buf and bufobj - * locks both held. We tolerate a race to clear it here. - */ - if (!(bp->b_vflags & BV_BKGRDINPROG)) - bp->b_flags |= B_RELBUF; - } /* * VMIO buffer rundown. It is not very necessary to keep a VMIO buffer @@ -1735,7 +1793,8 @@ brelse(struct buf *bp) } VM_OBJECT_RUNLOCK(obj); - if ((bp->b_flags & (B_INVAL | B_UNMAPPED)) == 0) { + if ((bp->b_flags & B_INVAL) == 0 && + buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qenter( trunc_page((vm_offset_t)bp->b_data), @@ -1875,20 +1934,6 @@ bqrelse(struct buf *bp) if ((bp->b_flags & B_DELWRI) == 0 && (bp->b_xflags & BX_VNDIRTY)) panic("bqrelse: not dirty"); - /* - * BKGRDINPROG can only be set with the buf and bufobj - * locks both held. We tolerate a race to clear it here. - */ - if (buf_vm_page_count_severe() && - (bp->b_vflags & BV_BKGRDINPROG) == 0) { - /* - * We are too low on memory, we have to try to free - * the buffer (most importantly: the wired pages - * making up its backing store) *now*. - */ - brelse(bp); - return; - } qindex = QUEUE_CLEAN; } binsfree(bp, qindex); @@ -1906,7 +1951,7 @@ vfs_vmio_release(struct buf *bp) vm_page_t m; int i; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qremove(trunc_page((vm_offset_t)bp->b_data), bp->b_npages); } else @@ -1934,17 +1979,13 @@ vfs_vmio_release(struct buf *bp) vm_page_free(m); } else if (bp->b_flags & B_DIRECT) vm_page_try_to_free(m); - else if (buf_vm_page_count_severe()) - vm_page_try_to_cache(m); vm_page_unlock(m); } if (obj != NULL) VM_OBJECT_WUNLOCK(obj); - if (bp->b_bufsize) { - bufspacewakeup(); - bp->b_bufsize = 0; - } + if (bp->b_bufsize) + bufspaceadjust(bp, 0); bp->b_npages = 0; bp->b_flags &= ~B_VMIO; if (bp->b_vp) @@ -2013,7 +2054,7 @@ vfs_bio_awrite(struct buf *bp) int gbflags; bo = &vp->v_bufobj; - gbflags = (bp->b_flags & B_UNMAPPED) != 0 ? GB_UNMAPPED : 0; + gbflags = (bp->b_data == unmapped_buf) ? GB_UNMAPPED : 0; /* * right now we support clustered writing only to regular files. If * we find a clusterable block we could be in the middle of a cluster @@ -2062,49 +2103,6 @@ vfs_bio_awrite(struct buf *bp) return (nwritten); } -static void -setbufkva(struct buf *bp, vm_offset_t addr, int maxsize, int gbflags) -{ - - KASSERT((bp->b_flags & (B_UNMAPPED | B_KVAALLOC)) == 0 && - bp->b_kvasize == 0, ("call bfreekva(%p)", bp)); - if ((gbflags & GB_UNMAPPED) == 0) { - bp->b_kvabase = (caddr_t)addr; - } else if ((gbflags & GB_KVAALLOC) != 0) { - KASSERT((gbflags & GB_UNMAPPED) != 0, - ("GB_KVAALLOC without GB_UNMAPPED")); - bp->b_kvaalloc = (caddr_t)addr; - bp->b_flags |= B_UNMAPPED | B_KVAALLOC; - atomic_add_long(&unmapped_bufspace, bp->b_kvasize); - } - bp->b_kvasize = maxsize; -} - -/* - * Allocate the buffer KVA and set b_kvasize. Also set b_kvabase if - * needed. - */ -static int -allocbufkva(struct buf *bp, int maxsize, int gbflags) -{ - vm_offset_t addr; - - bfreekva(bp); - addr = 0; - - if (vmem_alloc(buffer_arena, maxsize, M_BESTFIT | M_NOWAIT, &addr)) { - /* - * Buffer map is too fragmented. Request the caller - * to defragment the map. - */ - atomic_add_int(&bufdefragcnt, 1); - return (1); - } - setbufkva(bp, addr, maxsize, gbflags); - atomic_add_long(&bufspace, bp->b_kvasize); - return (0); -} - /* * Ask the bufdaemon for help, or act as bufdaemon itself, when a * locked vnode is supplied. @@ -2228,7 +2226,7 @@ getnewbuf_reuse_bp(struct buf *bp, int qindex) if (bp->b_bufsize) allocbuf(bp, 0); - bp->b_flags &= B_UNMAPPED | B_KVAALLOC; + bp->b_flags = 0; bp->b_ioflags = 0; bp->b_xflags = 0; KASSERT((bp->b_flags & B_INFREECNT) == 0, @@ -2245,6 +2243,7 @@ getnewbuf_reuse_bp(struct buf *bp, int qindex) bp->b_dirtyoff = bp->b_dirtyend = 0; bp->b_bufobj = NULL; bp->b_pin_count = 0; + bp->b_data = bp->b_kvabase; bp->b_fsprivate1 = NULL; bp->b_fsprivate2 = NULL; bp->b_fsprivate3 = NULL; @@ -2364,14 +2363,11 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) } /* * If we are defragging then we need a buffer with - * b_kvasize != 0. XXX this situation should no longer - * occur, if defrag is non-zero the buffer's b_kvasize - * should also be non-zero at this point. XXX + * b_kvasize != 0. This situation occurs when we + * have many unmapped bufs. */ - if (defrag && bp->b_kvasize == 0) { - printf("Warning: defrag empty buffer %p\n", bp); + if (defrag && bp->b_kvasize == 0) continue; - } /* * Start freeing the bp. This is somewhat involved. nbp @@ -2416,7 +2412,7 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) */ if (defrag) { bp->b_flags |= B_INVAL; - bfreekva(bp); + bufkvafree(bp); brelse(bp); defrag = 0; goto restart; @@ -2428,7 +2424,7 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) */ if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp)) { bp->b_flags |= B_INVAL; - bfreekva(bp); + bufkvafree(bp); brelse(bp); goto restart; } @@ -2445,7 +2441,7 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) flushingbufs = 1; if (flushingbufs && bp->b_kvasize != 0) { bp->b_flags |= B_INVAL; - bfreekva(bp); + bufkvafree(bp); brelse(bp); goto restart; } @@ -2516,65 +2512,31 @@ getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int size, int maxsize, } else if ((gbflags & (GB_UNMAPPED | GB_KVAALLOC)) == GB_UNMAPPED) { mtx_assert(&bqclean, MA_NOTOWNED); - bfreekva(bp); - bp->b_flags |= B_UNMAPPED; - bp->b_kvabase = bp->b_data = unmapped_buf; - bp->b_kvasize = maxsize; - atomic_add_long(&bufspace, bp->b_kvasize); - atomic_add_long(&unmapped_bufspace, bp->b_kvasize); + bufkvafree(bp); atomic_add_int(&bufreusecnt, 1); } else { mtx_assert(&bqclean, MA_NOTOWNED); /* * We finally have a valid bp. We aren't quite out of the - * woods, we still have to reserve kva space. In order - * to keep fragmentation sane we only allocate kva in - * BKVASIZE chunks. + * woods, we still have to reserve kva space. In order to + * keep fragmentation sane we only allocate kva in BKVASIZE + * chunks. */ maxsize = (maxsize + BKVAMASK) & ~BKVAMASK; - if (maxsize != bp->b_kvasize || (bp->b_flags & (B_UNMAPPED | - B_KVAALLOC)) == B_UNMAPPED) { - if (allocbufkva(bp, maxsize, gbflags)) { - defrag = 1; - bp->b_flags |= B_INVAL; - brelse(bp); - goto restart; - } - atomic_add_int(&bufreusecnt, 1); - } else if ((bp->b_flags & B_KVAALLOC) != 0 && - (gbflags & (GB_UNMAPPED | GB_KVAALLOC)) == 0) { - /* - * If the reused buffer has KVA allocated, - * reassign b_kvaalloc to b_kvabase. - */ - bp->b_kvabase = bp->b_kvaalloc; - bp->b_flags &= ~B_KVAALLOC; - atomic_subtract_long(&unmapped_bufspace, - bp->b_kvasize); - atomic_add_int(&bufreusecnt, 1); - } else if ((bp->b_flags & (B_UNMAPPED | B_KVAALLOC)) == 0 && - (gbflags & (GB_UNMAPPED | GB_KVAALLOC)) == (GB_UNMAPPED | - GB_KVAALLOC)) { - /* - * The case of reused buffer already have KVA - * mapped, but the request is for unmapped - * buffer with KVA allocated. - */ - bp->b_kvaalloc = bp->b_kvabase; - bp->b_data = bp->b_kvabase = unmapped_buf; - bp->b_flags |= B_UNMAPPED | B_KVAALLOC; - atomic_add_long(&unmapped_bufspace, - bp->b_kvasize); - atomic_add_int(&bufreusecnt, 1); - } - if ((gbflags & GB_UNMAPPED) == 0) { - bp->b_saveaddr = bp->b_kvabase; - bp->b_data = bp->b_saveaddr; - bp->b_flags &= ~B_UNMAPPED; - BUF_CHECK_MAPPED(bp); + if (maxsize != bp->b_kvasize && + bufkvaalloc(bp, maxsize, gbflags)) { + defrag = 1; + bp->b_flags |= B_INVAL; + brelse(bp); + goto restart; + } else if ((gbflags & (GB_UNMAPPED | GB_KVAALLOC)) == + (GB_UNMAPPED | GB_KVAALLOC)) { + bp->b_data = unmapped_buf; + BUF_CHECK_UNMAPPED(bp); } + atomic_add_int(&bufreusecnt, 1); } return (bp); } @@ -3004,9 +2966,9 @@ vfs_setdirty_locked_object(struct buf *bp) } /* - * Allocate the KVA mapping for an existing buffer. It handles the - * cases of both B_UNMAPPED buffer, and buffer with the preallocated - * KVA which is not mapped (B_KVAALLOC). + * Allocate the KVA mapping for an existing buffer. + * If an unmapped buffer is provided but a mapped buffer is requested, take + * also care to properly setup mappings between pages and KVA. */ static void bp_unmapped_get_kva(struct buf *bp, daddr_t blkno, int size, int gbflags) @@ -3015,25 +2977,22 @@ bp_unmapped_get_kva(struct buf *bp, daddr_t blkno, int size, int gbflags) int bsize, maxsize, need_mapping, need_kva; off_t offset; - need_mapping = (bp->b_flags & B_UNMAPPED) != 0 && + need_mapping = bp->b_data == unmapped_buf && (gbflags & GB_UNMAPPED) == 0; - need_kva = (bp->b_flags & (B_KVAALLOC | B_UNMAPPED)) == B_UNMAPPED && + need_kva = bp->b_kvabase == unmapped_buf && + bp->b_data == unmapped_buf && (gbflags & GB_KVAALLOC) != 0; if (!need_mapping && !need_kva) return; BUF_CHECK_UNMAPPED(bp); - if (need_mapping && (bp->b_flags & B_KVAALLOC) != 0) { + if (need_mapping && bp->b_kvabase != unmapped_buf) { /* * Buffer is not mapped, but the KVA was already * reserved at the time of the instantiation. Use the * allocated space. */ - bp->b_flags &= ~B_KVAALLOC; - KASSERT(bp->b_kvaalloc != 0, ("kvaalloc == 0")); - bp->b_kvabase = bp->b_kvaalloc; - atomic_subtract_long(&unmapped_bufspace, bp->b_kvasize); goto has_addr; } @@ -3048,7 +3007,7 @@ bp_unmapped_get_kva(struct buf *bp, daddr_t blkno, int size, int gbflags) maxsize = imax(maxsize, bsize); mapping_loop: - if (allocbufkva(bp, maxsize, gbflags)) { + if (bufkvaalloc(bp, maxsize, gbflags)) { /* * Request defragmentation. getnewbuf() returns us the * allocated space by the scratch buffer KVA. @@ -3061,31 +3020,31 @@ bp_unmapped_get_kva(struct buf *bp, daddr_t blkno, int size, int gbflags) * XXXKIB: defragmentation cannot * succeed, not sure what else to do. */ - panic("GB_NOWAIT_BD and B_UNMAPPED %p", bp); + panic("GB_NOWAIT_BD and GB_UNMAPPED %p", bp); } atomic_add_int(&mappingrestarts, 1); goto mapping_loop; } - KASSERT((scratch_bp->b_flags & B_KVAALLOC) != 0, - ("scratch bp !B_KVAALLOC %p", scratch_bp)); - setbufkva(bp, (vm_offset_t)scratch_bp->b_kvaalloc, - scratch_bp->b_kvasize, gbflags); + KASSERT(scratch_bp->b_kvabase != unmapped_buf, + ("scratch bp has no KVA %p", scratch_bp)); + /* Grab pointers. */ + bp->b_kvabase = scratch_bp->b_kvabase; + bp->b_kvasize = scratch_bp->b_kvasize; + bp->b_data = scratch_bp->b_data; /* Get rid of the scratch buffer. */ scratch_bp->b_kvasize = 0; scratch_bp->b_flags |= B_INVAL; - scratch_bp->b_flags &= ~(B_UNMAPPED | B_KVAALLOC); + scratch_bp->b_data = scratch_bp->b_kvabase = unmapped_buf; brelse(scratch_bp); } - if (!need_mapping) - return; - has_addr: - bp->b_saveaddr = bp->b_kvabase; - bp->b_data = bp->b_saveaddr; /* b_offset is handled by bpmap_qenter */ - bp->b_flags &= ~B_UNMAPPED; - BUF_CHECK_MAPPED(bp); - bpmap_qenter(bp); + if (need_mapping) { + /* b_offset is handled by bpmap_qenter. */ + bp->b_data = bp->b_kvabase; + BUF_CHECK_MAPPED(bp); + bpmap_qenter(bp); + } } /* @@ -3301,7 +3260,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo, } else { maxsize = size; /* Do not allow non-VMIO notmapped buffers. */ - flags &= ~GB_UNMAPPED; + flags &= ~(GB_UNMAPPED | GB_KVAALLOC); } maxsize = imax(maxsize, bsize); @@ -3394,7 +3353,6 @@ geteblk(int size, int flags) return (bp); } - /* * This code constitutes the buffer memory from either anonymous system * memory (in the case of non-VMIO operations) or from an associated @@ -3418,7 +3376,7 @@ allocbuf(struct buf *bp, int size) BUF_ASSERT_HELD(bp); - if (bp->b_kvasize < size) + if (bp->b_kvasize != 0 && bp->b_kvasize < size) panic("allocbuf: buffer too small"); if ((bp->b_flags & B_VMIO) == 0) { @@ -3443,15 +3401,8 @@ allocbuf(struct buf *bp, int size) bp->b_bcount = size; } else { free(bp->b_data, M_BIOBUF); - if (bp->b_bufsize) { - atomic_subtract_long( - &bufmallocspace, - bp->b_bufsize); - bufspacewakeup(); - bp->b_bufsize = 0; - } - bp->b_saveaddr = bp->b_kvabase; - bp->b_data = bp->b_saveaddr; + bufmallocadjust(bp, 0); + bp->b_data = bp->b_kvabase; bp->b_bcount = 0; bp->b_flags &= ~B_MALLOC; } @@ -3470,33 +3421,28 @@ allocbuf(struct buf *bp, int size) * is probably extremely rare and not worth worrying * over. */ - if ( (bufmallocspace < maxbufmallocspace) && + if ((bufmallocspace < maxbufmallocspace) && (bp->b_bufsize == 0) && (mbsize <= PAGE_SIZE/2)) { bp->b_data = malloc(mbsize, M_BIOBUF, M_WAITOK); - bp->b_bufsize = mbsize; bp->b_bcount = size; bp->b_flags |= B_MALLOC; - atomic_add_long(&bufmallocspace, mbsize); + bufmallocadjust(bp, mbsize); return 1; } origbuf = NULL; origbufsize = 0; /* - * If the buffer is growing on its other-than-first allocation, - * then we revert to the page-allocation scheme. + * If the buffer is growing on its other-than-first + * allocation then we revert to the page-allocation + * scheme. */ if (bp->b_flags & B_MALLOC) { origbuf = bp->b_data; origbufsize = bp->b_bufsize; bp->b_data = bp->b_kvabase; - if (bp->b_bufsize) { - atomic_subtract_long(&bufmallocspace, - bp->b_bufsize); - bufspacewakeup(); - bp->b_bufsize = 0; - } + bufmallocadjust(bp, 0); bp->b_flags &= ~B_MALLOC; newbsize = round_page(newbsize); } @@ -3534,7 +3480,7 @@ allocbuf(struct buf *bp, int size) if (desiredpages < bp->b_npages) { vm_page_t m; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qremove((vm_offset_t)trunc_page( (vm_offset_t)bp->b_data) + @@ -3647,18 +3593,18 @@ allocbuf(struct buf *bp, int size) VM_OBJECT_WUNLOCK(obj); /* - * Step 3, fixup the KVM pmap. + * Step 3, fixup the KVA pmap. */ - if ((bp->b_flags & B_UNMAPPED) == 0) + if (buf_mapped(bp)) bpmap_qenter(bp); else BUF_CHECK_UNMAPPED(bp); } } - if (newbsize < bp->b_bufsize) - bufspacewakeup(); - bp->b_bufsize = newbsize; /* actual buffer allocation */ - bp->b_bcount = size; /* requested buffer size */ + /* Record changes in allocation size. */ + if (bp->b_bufsize != newbsize) + bufspaceadjust(bp, newbsize); + bp->b_bcount = size; /* requested buffer size. */ return 1; } @@ -3955,7 +3901,7 @@ bufdone_finish(struct buf *bp) } vm_object_pip_wakeupn(obj, 0); VM_OBJECT_WUNLOCK(obj); - if (bogus && (bp->b_flags & B_UNMAPPED) == 0) { + if (bogus && buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qenter(trunc_page((vm_offset_t)bp->b_data), bp->b_pages, bp->b_npages); @@ -4002,7 +3948,7 @@ vfs_unbusy_pages(struct buf *bp) if (!m) panic("vfs_unbusy_pages: page missing\n"); bp->b_pages[i] = m; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qenter(trunc_page((vm_offset_t)bp->b_data), bp->b_pages, bp->b_npages); @@ -4176,7 +4122,7 @@ vfs_busy_pages(struct buf *bp, int clear_modify) foff = (foff + PAGE_SIZE) & ~(off_t)PAGE_MASK; } VM_OBJECT_WUNLOCK(obj); - if (bogus && (bp->b_flags & B_UNMAPPED) == 0) { + if (bogus && buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); pmap_qenter(trunc_page((vm_offset_t)bp->b_data), bp->b_pages, bp->b_npages); @@ -4296,7 +4242,7 @@ vfs_bio_bzero_buf(struct buf *bp, int base, int size) vm_page_t m; int i, n; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { BUF_CHECK_MAPPED(bp); bzero(bp->b_data + base, size); } else { @@ -4389,11 +4335,12 @@ vm_hold_free_pages(struct buf *bp, int newbsize) * be valid, a race or a smaller-file mapped into a larger space may * actually cause vmapbuf() to fail, so all callers of vmapbuf() MUST * check the return value. + * + * This function only works with pager buffers. */ int vmapbuf(struct buf *bp, int mapbuf) { - caddr_t kva; vm_prot_t prot; int pidx; @@ -4407,24 +4354,20 @@ vmapbuf(struct buf *bp, int mapbuf) btoc(MAXPHYS))) < 0) return (-1); bp->b_npages = pidx; + bp->b_offset = ((vm_offset_t)bp->b_data) & PAGE_MASK; if (mapbuf || !unmapped_buf_allowed) { - pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx); - kva = bp->b_saveaddr; - bp->b_saveaddr = bp->b_data; - bp->b_data = kva + (((vm_offset_t)bp->b_data) & PAGE_MASK); - bp->b_flags &= ~B_UNMAPPED; - } else { - bp->b_flags |= B_UNMAPPED; - bp->b_offset = ((vm_offset_t)bp->b_data) & PAGE_MASK; - bp->b_saveaddr = bp->b_data; + pmap_qenter((vm_offset_t)bp->b_kvabase, bp->b_pages, pidx); + bp->b_data = bp->b_kvabase + bp->b_offset; + } else bp->b_data = unmapped_buf; - } return(0); } /* * Free the io map PTEs associated with this IO operation. * We also invalidate the TLB entries and restore the original b_addr. + * + * This function only works with pager buffers. */ void vunmapbuf(struct buf *bp) @@ -4432,13 +4375,11 @@ vunmapbuf(struct buf *bp) int npages; npages = bp->b_npages; - if (bp->b_flags & B_UNMAPPED) - bp->b_flags &= ~B_UNMAPPED; - else + if (buf_mapped(bp)) pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages); vm_page_unhold_pages(bp->b_pages, npages); - - bp->b_data = bp->b_saveaddr; + + bp->b_data = unmapped_buf; } void @@ -4579,7 +4520,7 @@ void bdata2bio(struct buf *bp, struct bio *bip) { - if ((bp->b_flags & B_UNMAPPED) != 0) { + if (!buf_mapped(bp)) { KASSERT(unmapped_buf_allowed, ("unmapped")); bip->bio_ma = bp->b_pages; bip->bio_ma_n = bp->b_npages; @@ -4622,6 +4563,8 @@ DB_SHOW_COMMAND(buffer, db_show_buffer) bp->b_error, bp->b_bufsize, bp->b_bcount, bp->b_resid, bp->b_bufobj, bp->b_data, (intmax_t)bp->b_blkno, (intmax_t)bp->b_lblkno, bp->b_dep.lh_first); + db_printf("b_kvabase = %p, b_kvasize = %d\n", + bp->b_kvabase, bp->b_kvasize); if (bp->b_npages) { int i; db_printf("b_npages = %d, pages(OBJ, IDX, PA): ", bp->b_npages); diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 362ebb7ba671..476b28a01533 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -354,7 +354,6 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn, */ bp->b_flags = B_ASYNC | B_CLUSTER | B_VMIO; if ((gbflags & GB_UNMAPPED) != 0) { - bp->b_flags |= B_UNMAPPED; bp->b_data = unmapped_buf; } else { bp->b_data = (char *)((vm_offset_t)bp->b_data | @@ -517,9 +516,8 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn, if (bp->b_bufsize > bp->b_kvasize) panic("cluster_rbuild: b_bufsize(%ld) > b_kvasize(%d)\n", bp->b_bufsize, bp->b_kvasize); - bp->b_kvasize = bp->b_bufsize; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { pmap_qenter(trunc_page((vm_offset_t) bp->b_data), (vm_page_t *)bp->b_pages, bp->b_npages); } @@ -545,7 +543,7 @@ cluster_callback(bp) if (bp->b_ioflags & BIO_ERROR) error = bp->b_error; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages); } @@ -871,7 +869,6 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len, bp->b_data = (char *)((vm_offset_t)bp->b_data | ((vm_offset_t)tbp->b_data & PAGE_MASK)); } else { - bp->b_flags |= B_UNMAPPED; bp->b_data = unmapped_buf; } bp->b_flags |= B_CLUSTER | (tbp->b_flags & (B_VMIO | @@ -1004,7 +1001,7 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len, tbp, b_cluster.cluster_entry); } finishcluster: - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { pmap_qenter(trunc_page((vm_offset_t) bp->b_data), (vm_page_t *)bp->b_pages, bp->b_npages); } @@ -1012,7 +1009,6 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len, panic( "cluster_wbuild: b_bufsize(%ld) > b_kvasize(%d)\n", bp->b_bufsize, bp->b_kvasize); - bp->b_kvasize = bp->b_bufsize; totalwritten += bp->b_bufsize; bp->b_dirtyoff = 0; bp->b_dirtyend = bp->b_bufsize; diff --git a/sys/modules/i2c/Makefile b/sys/modules/i2c/Makefile index 7ba1f436f495..a2199f561051 100644 --- a/sys/modules/i2c/Makefile +++ b/sys/modules/i2c/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ SUBDIR = -SUBDIR += controllers if_ic smbus iicbus iicbb iicsmb iic smb +SUBDIR += controllers if_ic smbus iicbus iicbb iicsmb iic cyapa smb isl .include diff --git a/sys/modules/i2c/cyapa/Makefile b/sys/modules/i2c/cyapa/Makefile new file mode 100644 index 000000000000..80f5fbac2372 --- /dev/null +++ b/sys/modules/i2c/cyapa/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/cyapa +KMOD = cyapa +SRCS = cyapa.c device_if.h bus_if.h smbus_if.h vnode_if.h + +.include diff --git a/sys/modules/i2c/isl/Makefile b/sys/modules/i2c/isl/Makefile new file mode 100644 index 000000000000..a9fac280216d --- /dev/null +++ b/sys/modules/i2c/isl/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/isl +KMOD = isl +SRCS = isl.c device_if.h bus_if.h smbus_if.h vnode_if.h + +.include diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 9bfdddc13c80..f8bf05ff7d24 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -578,10 +578,10 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD); } SCTPDBG(SCTP_DEBUG_INDATA1, - "queue to stream called for ssn:%u lastdel:%u nxt:%u\n", - (uint32_t) control->sinfo_stream, - (uint32_t) strm->last_sequence_delivered, - (uint32_t) nxt_todel); + "queue to stream called for sid:%u ssn:%u tsn:%u lastdel:%u nxt:%u\n", + (uint32_t) control->sinfo_stream, (uint32_t) control->sinfo_ssn, + (uint32_t) control->sinfo_tsn, + (uint32_t) strm->last_sequence_delivered, (uint32_t) nxt_todel); if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) { /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", @@ -602,6 +602,20 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, return; } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + struct socket *so; + + so = SCTP_INP_SO(stcb->sctp_ep); + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_SOCKET_LOCK(so, 1); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { + SCTP_SOCKET_UNLOCK(so, 1); + return; + } +#endif if (nxt_todel == control->sinfo_ssn) { /* can be delivered right away? */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { @@ -617,7 +631,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, - SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); + SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED); TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) { /* all delivered */ nxt_todel = strm->last_sequence_delivered + 1; @@ -641,7 +655,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, - SCTP_SO_NOT_LOCKED); + SCTP_SO_LOCKED); continue; } break; @@ -653,6 +667,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, * to put it on the queue. */ if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif goto protocol_error; } if (TAILQ_EMPTY(&strm->inqueue)) { @@ -699,6 +716,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif return; } else { if (TAILQ_NEXT(at, next) == NULL) { @@ -718,6 +738,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, } } } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif } /* diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 341982124786..aa7c30c6bf51 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -3764,7 +3764,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, } } if (asoc->stream_reset_outstanding == 0) { - sctp_send_stream_reset_out_if_possible(stcb); + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); } return (0); } @@ -3832,7 +3832,7 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, } else { sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } - sctp_send_stream_reset_out_if_possible(stcb); + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); } static int diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index bae67f0edc6b..0d99f5472e4b 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -95,7 +95,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 59f0e49360a2..1beab07adbda 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -10104,7 +10104,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, sctp_fix_ecn_echo(asoc); if (stcb->asoc.trigger_reset) { - if (sctp_send_stream_reset_out_if_possible(stcb) == 0) { + if (sctp_send_stream_reset_out_if_possible(stcb, so_locked) == 0) { goto do_it_again; } } @@ -11839,7 +11839,7 @@ sctp_add_an_in_stream(struct sctp_tmit_chunk *chk, } int -sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb) +sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb, int so_locked) { struct sctp_association *asoc; struct sctp_tmit_chunk *chk; @@ -11865,7 +11865,7 @@ sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb) chk->book_size_scale = 0; chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); if (chk->data == NULL) { - sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED); + sctp_free_a_chunk(stcb, chk, so_locked); SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); return (ENOMEM); } @@ -11892,7 +11892,7 @@ sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb) } else { m_freem(chk->data); chk->data = NULL; - sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED); + sctp_free_a_chunk(stcb, chk, so_locked); return (ENOENT); } asoc->str_reset = chk; @@ -11901,6 +11901,10 @@ sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb) chk, sctp_next); asoc->ctrl_queue_cnt++; + + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, so_locked); + } sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); return (0); } @@ -12101,6 +12105,9 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, chk, sctp_next); asoc->ctrl_queue_cnt++; + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, SCTP_SO_LOCKED); + } sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); return (0); } diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index 8fd5659c5c8a..d7222c44bf51 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -181,7 +181,7 @@ void sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *, uint32_t, uint32_t, uint32_t, uint32_t); int - sctp_send_stream_reset_out_if_possible(struct sctp_tcb *); + sctp_send_stream_reset_out_if_possible(struct sctp_tcb *, int); int sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 53a0a0adc5f7..76a285773a29 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -4689,8 +4689,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, strrst->srs_stream_list, send_in, 0, 0, 0, 0, 0); } else - error = sctp_send_stream_reset_out_if_possible(stcb); - + error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED); if (!error) sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 9413721624cb..342990e22b70 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1212,7 +1212,6 @@ tcp_output(struct tcpcb *tp) /* * Enable TSO and specify the size of the segments. * The TCP pseudo header checksum is always provided. - * XXX: Fixme: This is currently not the case for IPv6. */ if (tso) { KASSERT(len > tp->t_maxopd - optlen, diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 009c47fd23cf..4f0d83d26e65 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -39,9 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef INET6 #include -#endif #include #include #include @@ -54,13 +52,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #ifdef IPSEC #include -#ifdef INET6 #include -#endif /* INET6 */ #endif /* IPSEC */ extern struct protosw inetsw[]; diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h index 2e1110b95c8e..c46c4f8ad14e 100644 --- a/sys/sparc64/include/smp.h +++ b/sys/sparc64/include/smp.h @@ -39,13 +39,15 @@ #ifndef LOCORE +#include #include +#include +#include #include #include #include #include -#include #include #define IDR_BUSY 0x0000000000000001ULL @@ -96,6 +98,7 @@ struct ipi_tlb_args { }; #define ita_va ita_start +struct pcb; struct pcpu; extern struct pcb stoppcbs[]; @@ -108,8 +111,9 @@ extern cpu_ipi_selected_t *cpu_ipi_selected; typedef void cpu_ipi_single_t(u_int, u_long, u_long, u_long); extern cpu_ipi_single_t *cpu_ipi_single; -void mp_init(u_int cpu_impl); +void mp_init(void); +extern struct mtx ipi_mtx; extern struct ipi_cache_args ipi_cache_args; extern struct ipi_rd_args ipi_rd_args; extern struct ipi_tlb_args ipi_tlb_args; @@ -139,23 +143,37 @@ ipi_all_but_self(u_int ipi) { cpuset_t cpus; + if (__predict_false(smp_started == 0)) + return; cpus = all_cpus; + sched_pin(); CPU_CLR(PCPU_GET(cpuid), &cpus); + mtx_lock_spin(&ipi_mtx); cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi); + mtx_unlock_spin(&ipi_mtx); + sched_unpin(); } static __inline void ipi_selected(cpuset_t cpus, u_int ipi) { + if (__predict_false(smp_started == 0 || CPU_EMPTY(&cpus))) + return; + mtx_lock_spin(&ipi_mtx); cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi); + mtx_unlock_spin(&ipi_mtx); } static __inline void ipi_cpu(int cpu, u_int ipi) { + if (__predict_false(smp_started == 0)) + return; + mtx_lock_spin(&ipi_mtx); cpu_ipi_single(cpu, 0, (u_long)tl_ipi_level, ipi); + mtx_unlock_spin(&ipi_mtx); } #if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_) @@ -165,11 +183,11 @@ ipi_dcache_page_inval(void *func, vm_paddr_t pa) { struct ipi_cache_args *ica; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); ica = &ipi_cache_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); ica->ica_mask = all_cpus; CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask); ica->ica_pa = pa; @@ -182,11 +200,11 @@ ipi_icache_page_inval(void *func, vm_paddr_t pa) { struct ipi_cache_args *ica; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); ica = &ipi_cache_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); ica->ica_mask = all_cpus; CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask); ica->ica_pa = pa; @@ -199,11 +217,11 @@ ipi_rd(u_int cpu, void *func, u_long *val) { struct ipi_rd_args *ira; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); ira = &ipi_rd_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); CPU_SETOF(cpu, &ira->ira_mask); ira->ira_val = val; cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira); @@ -216,7 +234,7 @@ ipi_tlb_context_demap(struct pmap *pm) struct ipi_tlb_args *ita; cpuset_t cpus; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; @@ -227,7 +245,7 @@ ipi_tlb_context_demap(struct pmap *pm) return (NULL); } ita = &ipi_tlb_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap, @@ -241,7 +259,7 @@ ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va) struct ipi_tlb_args *ita; cpuset_t cpus; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; @@ -252,7 +270,7 @@ ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va) return (NULL); } ita = &ipi_tlb_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; ita->ita_va = va; @@ -266,7 +284,7 @@ ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end) struct ipi_tlb_args *ita; cpuset_t cpus; - if (smp_cpus == 1) + if (__predict_false(smp_started == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; @@ -277,7 +295,7 @@ ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end) return (NULL); } ita = &ipi_tlb_args; - mtx_lock_spin(&smp_ipi_mtx); + mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; ita->ita_start = start; @@ -292,10 +310,10 @@ ipi_wait(void *cookie) { volatile cpuset_t *mask; - if ((mask = cookie) != NULL) { + if (__predict_false((mask = cookie) != NULL)) { while (!CPU_EMPTY(mask)) ; - mtx_unlock_spin(&smp_ipi_mtx); + mtx_unlock_spin(&ipi_mtx); sched_unpin(); } } diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index a95bc637761f..f0e54a5e3939 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -499,7 +499,7 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) } #ifdef SMP - mp_init(cpu_impl); + mp_init(); #endif /* diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index 0f977b3e3921..c2c4e3e298e8 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -113,12 +114,13 @@ struct ipi_rd_args ipi_rd_args; struct ipi_tlb_args ipi_tlb_args; struct pcb stoppcbs[MAXCPU]; +struct mtx ipi_mtx; + cpu_ipi_selected_t *cpu_ipi_selected; cpu_ipi_single_t *cpu_ipi_single; static vm_offset_t mp_tramp; static u_int cpuid_to_mid[MAXCPU]; -static int isjbus; static volatile cpuset_t shutdown_cpus; static void ap_count(phandle_t node, u_int mid, u_int cpu_impl); @@ -138,7 +140,7 @@ static cpu_ipi_single_t spitfire_ipi_single; SYSINIT(cpu_mp_unleash, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL); void -mp_init(u_int cpu_impl) +mp_init(void) { struct tte *tp; int i; @@ -157,24 +159,6 @@ mp_init(u_int cpu_impl) } for (i = 0; i < PAGE_SIZE; i += sizeof(vm_offset_t)) flush(mp_tramp + i); - - /* - * On UP systems cpu_ipi_selected() can be called while - * cpu_mp_start() wasn't so initialize these here. - */ - if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi || - cpu_impl == CPU_IMPL_ULTRASPARCIIIip) { - isjbus = 1; - cpu_ipi_selected = jalapeno_ipi_selected; - cpu_ipi_single = jalapeno_ipi_single; - } else if (cpu_impl == CPU_IMPL_SPARC64V || - cpu_impl >= CPU_IMPL_ULTRASPARCIII) { - cpu_ipi_selected = cheetah_ipi_selected; - cpu_ipi_single = cheetah_ipi_single; - } else { - cpu_ipi_selected = spitfire_ipi_selected; - cpu_ipi_single = spitfire_ipi_single; - } } static void @@ -219,7 +203,7 @@ foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid, * Probe for other CPUs. */ void -cpu_mp_setmaxid() +cpu_mp_setmaxid(void) { CPU_SETOF(curcpu, &all_cpus); @@ -277,6 +261,25 @@ sun4u_startcpu(phandle_t cpu, void *func, u_long arg) void cpu_mp_start(void) { + u_int cpu_impl, isjbus; + + mtx_init(&ipi_mtx, "ipi", NULL, MTX_SPIN); + + isjbus = 0; + cpu_impl = PCPU_GET(impl); + if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi || + cpu_impl == CPU_IMPL_ULTRASPARCIIIip) { + isjbus = 1; + cpu_ipi_selected = jalapeno_ipi_selected; + cpu_ipi_single = jalapeno_ipi_single; + } else if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) { + cpu_ipi_selected = cheetah_ipi_selected; + cpu_ipi_single = cheetah_ipi_single; + } else { + cpu_ipi_selected = spitfire_ipi_selected; + cpu_ipi_single = spitfire_ipi_single; + } intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL); intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action, @@ -360,7 +363,7 @@ cpu_mp_announce(void) } static void -cpu_mp_unleash(void *v) +cpu_mp_unleash(void *v __unused) { volatile struct cpu_start_args *csa; struct pcpu *pc; @@ -407,7 +410,6 @@ cpu_mp_unleash(void *v) membar(StoreLoad); csa->csa_count = 0; - smp_started = 1; } void @@ -464,6 +466,9 @@ cpu_mp_bootstrap(struct pcpu *pc) while (csa->csa_count != 0) ; + if (smp_cpus == mp_ncpus) + atomic_store_rel_int(&smp_started, 1); + /* Start per-CPU event timers. */ cpu_initclocks_ap(); @@ -530,7 +535,7 @@ cpu_ipi_stop(struct trapframe *tf __unused) } static void -cpu_ipi_preempt(struct trapframe *tf) +cpu_ipi_preempt(struct trapframe *tf __unused) { sched_preempt(curthread); @@ -573,9 +578,11 @@ spitfire_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) u_int mid; int i; + mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY) == 0, ("%s: outstanding dispatch", __func__)); + mid = cpuid_to_mid[cpu]; for (i = 0; i < IPI_RETRIES; i++) { s = intr_disable(); @@ -601,12 +608,6 @@ spitfire_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) intr_restore(s); if ((ids & (IDR_BUSY | IDR_NACK)) == 0) return; - /* - * Leave interrupts enabled for a bit before retrying - * in order to avoid deadlocks if the other CPU is also - * trying to send an IPI. - */ - DELAY(2); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", @@ -624,10 +625,12 @@ cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) u_int mid; int i; + mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); + mid = cpuid_to_mid[cpu]; for (i = 0; i < IPI_RETRIES; i++) { s = intr_disable(); @@ -644,12 +647,6 @@ cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) intr_restore(s); if ((ids & (IDR_BUSY | IDR_NACK)) == 0) return; - /* - * Leave interrupts enabled for a bit before retrying - * in order to avoid deadlocks if the other CPU is also - * trying to send an IPI. - */ - DELAY(2); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", @@ -669,13 +666,14 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) u_int cpu; int i; + mtx_assert(&ipi_mtx, MA_OWNED); + KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__)); KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); - if (CPU_EMPTY(&cpus)) - return; + ids = 0; for (i = 0; i < IPI_RETRIES * mp_ncpus; i++) { s = intr_disable(); @@ -709,12 +707,6 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) } if (CPU_EMPTY(&cpus)) return; - /* - * Leave interrupts enabled for a bit before retrying - * in order to avoid deadlocks if the other CPUs are - * also trying to send IPIs. - */ - DELAY(2 * mp_ncpus); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n", @@ -732,10 +724,12 @@ jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) u_int busy, busynack, mid; int i; + mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); + mid = cpuid_to_mid[cpu]; busy = IDR_BUSY << (2 * mid); busynack = (IDR_BUSY | IDR_NACK) << (2 * mid); @@ -754,12 +748,6 @@ jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) intr_restore(s); if ((ids & busynack) == 0) return; - /* - * Leave interrupts enabled for a bit before retrying - * in order to avoid deadlocks if the other CPU is also - * trying to send an IPI. - */ - DELAY(2); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", @@ -778,13 +766,14 @@ jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) u_int cpu; int i; + mtx_assert(&ipi_mtx, MA_OWNED); + KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__)); KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); - if (CPU_EMPTY(&cpus)) - return; + ids = 0; for (i = 0; i < IPI_RETRIES * mp_ncpus; i++) { s = intr_disable(); @@ -811,12 +800,6 @@ jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) if ((ids & (IDR_NACK << (2 * cpuid_to_mid[cpu]))) == 0) CPU_CLR(cpu, &cpus); - /* - * Leave interrupts enabled for a bit before retrying - * in order to avoid deadlocks if the other CPUs are - * also trying to send IPIs. - */ - DELAY(2 * mp_ncpus); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n", diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c index 130efa691dce..2072b18fa83f 100644 --- a/sys/sparc64/sparc64/tick.c +++ b/sys/sparc64/sparc64/tick.c @@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include #include @@ -46,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -326,7 +323,7 @@ tick_get_timecount_up(struct timecounter *tc) static u_int stick_get_timecount_mp(struct timecounter *tc) { - u_long stick; + static u_long stick; sched_pin(); if (curcpu == 0) @@ -340,7 +337,7 @@ stick_get_timecount_mp(struct timecounter *tc) static u_int tick_get_timecount_mp(struct timecounter *tc) { - u_long tick; + static u_long tick; sched_pin(); if (curcpu == 0) diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 49ec4d526693..2ffa4f5b27fb 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -112,17 +112,15 @@ struct buf { b_xflags_t b_xflags; /* extra flags */ struct lock b_lock; /* Buffer lock */ long b_bufsize; /* Allocated buffer size. */ - long b_runningbufspace; /* when I/O is running, pipelining */ - caddr_t b_kvabase; /* base kva for buffer */ - caddr_t b_kvaalloc; /* allocated kva for B_KVAALLOC */ + int b_runningbufspace; /* when I/O is running, pipelining */ int b_kvasize; /* size of kva for buffer */ - daddr_t b_lblkno; /* Logical block number. */ - struct vnode *b_vp; /* Device vnode. */ int b_dirtyoff; /* Offset in buffer of dirty region. */ int b_dirtyend; /* Offset of end of dirty region. */ + caddr_t b_kvabase; /* base kva for buffer */ + daddr_t b_lblkno; /* Logical block number. */ + struct vnode *b_vp; /* Device vnode. */ struct ucred *b_rcred; /* Read credentials reference. */ struct ucred *b_wcred; /* Write credentials reference. */ - void *b_saveaddr; /* Original b_addr for physio. */ union { TAILQ_ENTRY(buf) bu_freelist; /* (Q) */ struct { @@ -206,8 +204,8 @@ struct buf { #define B_PERSISTENT 0x00000100 /* Perm. ref'ed while EXT2FS mounted. */ #define B_DONE 0x00000200 /* I/O completed. */ #define B_EINTR 0x00000400 /* I/O was interrupted */ -#define B_UNMAPPED 0x00000800 /* KVA is not mapped. */ -#define B_KVAALLOC 0x00001000 /* But allocated. */ +#define B_00000800 0x00000800 /* Available flag. */ +#define B_00001000 0x00001000 /* Available flag. */ #define B_INVAL 0x00002000 /* Does not contain valid info. */ #define B_BARRIER 0x00004000 /* Write this and all preceeding first. */ #define B_NOCACHE 0x00008000 /* Do not cache block after use. */ @@ -231,7 +229,7 @@ struct buf { #define PRINT_BUF_FLAGS "\20\40remfree\37cluster\36vmio\35ram\34managed" \ "\33paging\32infreecnt\31nocopy\30b23\27relbuf\26dirty\25b20" \ "\24b19\23b18\22clusterok\21malloc\20nocache\17b14\16inval" \ - "\15kvaalloc\14unmapped\13eintr\12done\11persist\10delwri" \ + "\15b12\14b11\13eintr\12done\11persist\10delwri" \ "\7validsuspwrt\6cache\5deferred\4direct\3async\2needcommit\1age" /* @@ -374,15 +372,11 @@ struct buf_queue_head { }; /* - * This structure describes a clustered I/O. It is stored in the b_saveaddr - * field of the buffer on which I/O is done. At I/O completion, cluster - * callback uses the structure to parcel I/O's to individual buffers, and - * then free's this structure. + * This structure describes a clustered I/O. */ struct cluster_save { long bs_bcount; /* Saved b_bcount. */ long bs_bufsize; /* Saved b_bufsize. */ - void *bs_saveaddr; /* Saved b_addr. */ int bs_nchildren; /* Number of associated buffers. */ struct buf **bs_children; /* List of associated buffers. */ }; @@ -478,7 +472,14 @@ extern int cluster_pbuf_freecnt; /* Number of pbufs for clusters */ extern int vnode_pbuf_freecnt; /* Number of pbufs for vnode pager */ extern int vnode_async_pbuf_freecnt; /* Number of pbufs for vnode pager, asynchronous reads */ -extern caddr_t unmapped_buf; +extern caddr_t unmapped_buf; /* Data address for unmapped buffers. */ + +static inline int +buf_mapped(struct buf *bp) +{ + + return (bp->b_data != unmapped_buf); +} void runningbufwakeup(struct buf *); void waitrunningbufspace(void); diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h index fe4910e0c65c..09105bd5e9c8 100644 --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -315,16 +315,16 @@ __BEGIN_DECLS __cap_rights_init(CAP_RIGHTS_VERSION, __VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_init(int version, cap_rights_t *rights, ...); -#define cap_rights_set(rights, ...) \ - __cap_rights_set((rights), __VA_ARGS__, 0ULL) +#define cap_rights_set(...) \ + __cap_rights_set(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_set(cap_rights_t *rights, ...); -#define cap_rights_clear(rights, ...) \ - __cap_rights_clear((rights), __VA_ARGS__, 0ULL) +#define cap_rights_clear(...) \ + __cap_rights_clear(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_clear(cap_rights_t *rights, ...); -#define cap_rights_is_set(rights, ...) \ - __cap_rights_is_set((rights), __VA_ARGS__, 0ULL) +#define cap_rights_is_set(...) \ + __cap_rights_is_set(__VA_ARGS__, 0ULL) bool __cap_rights_is_set(const cap_rights_t *rights, ...); bool cap_rights_is_valid(const cap_rights_t *rights); diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index d429e86676a1..2e784d67a769 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -297,6 +297,7 @@ typedef struct { #define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */ #define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ +#define EM_RISCV 243 /* RISC-V */ /* Non-standard or deprecated. */ #define EM_486 6 /* Intel i486. */ diff --git a/sys/sys/param.h b/sys/sys/param.h index a146da86a42f..5f6665668145 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -77,12 +77,13 @@ #define __FreeBSD_kernel__ #ifdef _KERNEL -#define P_OSREL_SIGWAIT 700000 -#define P_OSREL_SIGSEGV 700004 -#define P_OSREL_MAP_ANON 800104 -#define P_OSREL_MAP_FSTRICT 1100036 +#define P_OSREL_SIGWAIT 700000 +#define P_OSREL_SIGSEGV 700004 +#define P_OSREL_MAP_ANON 800104 +#define P_OSREL_MAP_FSTRICT 1100036 +#define P_OSREL_SHUTDOWN_ENOTCONN 1100077 -#define P_OSREL_MAJOR(x) ((x) / 100000) +#define P_OSREL_MAJOR(x) ((x) / 100000) #endif #ifndef LOCORE diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c index aaa052e9ecb9..84fa0db9c6b0 100644 --- a/sys/ufs/ffs/ffs_rawread.c +++ b/sys/ufs/ffs/ffs_rawread.c @@ -62,8 +62,7 @@ static int ffs_rawread_readahead(struct vnode *vp, off_t offset, size_t len, struct thread *td, - struct buf *bp, - caddr_t sa); + struct buf *bp); static int ffs_rawread_main(struct vnode *vp, struct uio *uio); @@ -190,8 +189,7 @@ ffs_rawread_readahead(struct vnode *vp, off_t offset, size_t len, struct thread *td, - struct buf *bp, - caddr_t sa) + struct buf *bp) { int error; u_int iolen; @@ -219,7 +217,6 @@ ffs_rawread_readahead(struct vnode *vp, bp->b_iocmd = BIO_READ; bp->b_iodone = bdone; bp->b_data = udata; - bp->b_saveaddr = sa; blockno = offset / bsize; blockoff = (offset % bsize) / DEV_BSIZE; if ((daddr_t) blockno != blockno) { @@ -272,7 +269,6 @@ ffs_rawread_main(struct vnode *vp, { int error, nerror; struct buf *bp, *nbp, *tbp; - caddr_t sa, nsa, tsa; u_int iolen; int spl; caddr_t udata; @@ -295,18 +291,15 @@ ffs_rawread_main(struct vnode *vp, bp = NULL; nbp = NULL; - sa = NULL; - nsa = NULL; while (resid > 0) { if (bp == NULL) { /* Setup first read */ /* XXX: Leave some bufs for swap */ bp = getpbuf(&ffsrawbufcnt); - sa = bp->b_data; pbgetvp(vp, bp); error = ffs_rawread_readahead(vp, udata, offset, - resid, td, bp, sa); + resid, td, bp); if (error != 0) break; @@ -317,7 +310,6 @@ ffs_rawread_main(struct vnode *vp, else nbp = NULL; if (nbp != NULL) { - nsa = nbp->b_data; pbgetvp(vp, nbp); nerror = ffs_rawread_readahead(vp, @@ -328,8 +320,7 @@ ffs_rawread_main(struct vnode *vp, resid - bp->b_bufsize, td, - nbp, - nsa); + nbp); if (nerror) { pbrelvp(nbp); relpbuf(nbp, &ffsrawbufcnt); @@ -365,8 +356,7 @@ ffs_rawread_main(struct vnode *vp, offset, bp->b_bufsize - iolen, td, - bp, - sa); + bp); if (error != 0) break; } else if (nbp != NULL) { /* Complete read with readahead */ @@ -375,10 +365,6 @@ ffs_rawread_main(struct vnode *vp, bp = nbp; nbp = tbp; - tsa = sa; - sa = nsa; - nsa = tsa; - if (resid <= bp->b_bufsize) { /* No more readaheads */ pbrelvp(nbp); relpbuf(nbp, &ffsrawbufcnt); @@ -392,8 +378,7 @@ ffs_rawread_main(struct vnode *vp, resid - bp->b_bufsize, td, - nbp, - nsa); + nbp); if (nerror != 0) { pbrelvp(nbp); relpbuf(nbp, &ffsrawbufcnt); @@ -404,7 +389,7 @@ ffs_rawread_main(struct vnode *vp, break; } else if (resid > 0) { /* More to read, no readahead */ error = ffs_rawread_readahead(vp, udata, offset, - resid, td, bp, sa); + resid, td, bp); if (error != 0) break; } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 1f59a86c4a87..ebd8520d87ad 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -2094,7 +2094,7 @@ ffs_bufwrite(struct buf *bp) if (newbp == NULL) goto normal_write; - KASSERT((bp->b_flags & B_UNMAPPED) == 0, ("Unmapped cg")); + KASSERT(buf_mapped(bp), ("Unmapped cg")); memcpy(newbp->b_data, bp->b_data, bp->b_bufsize); BO_LOCK(bp->b_bufobj); bp->b_vflags |= BV_BKGRDINPROG; diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 618ed8e77d42..5a70e5c1da15 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -581,7 +581,7 @@ ffs_read(ap) xfersize = size; } - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { error = vn_io_fault_uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); } else { @@ -758,7 +758,7 @@ ffs_write(ap) if (size < xfersize) xfersize = size; - if ((bp->b_flags & B_UNMAPPED) == 0) { + if (buf_mapped(bp)) { error = vn_io_fault_uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); } else { diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index b3ad70ed9484..b8e1014aa878 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -772,11 +772,8 @@ swp_pager_strategy(struct buf *bp) mtx_unlock(&sw_dev_mtx); if ((sp->sw_flags & SW_UNMAPPED) != 0 && unmapped_buf_allowed) { - bp->b_kvaalloc = bp->b_data; bp->b_data = unmapped_buf; - bp->b_kvabase = unmapped_buf; bp->b_offset = 0; - bp->b_flags |= B_UNMAPPED; } else { pmap_qenter((vm_offset_t)bp->b_data, &bp->b_pages[0], bp->b_bcount / PAGE_SIZE); @@ -1496,12 +1493,10 @@ swp_pager_async_iodone(struct buf *bp) /* * remove the mapping for kernel virtual */ - if ((bp->b_flags & B_UNMAPPED) != 0) { - bp->b_data = bp->b_kvaalloc; - bp->b_kvabase = bp->b_kvaalloc; - bp->b_flags &= ~B_UNMAPPED; - } else + if (buf_mapped(bp)) pmap_qremove((vm_offset_t)bp->b_data, bp->b_npages); + else + bp->b_data = bp->b_kvabase; if (bp->b_npages) { object = bp->b_pages[0]->object; @@ -2597,7 +2592,7 @@ swapgeom_strategy(struct buf *bp, struct swdevt *sp) bio->bio_offset = (bp->b_blkno - sp->sw_first) * PAGE_SIZE; bio->bio_length = bp->b_bcount; bio->bio_done = swapgeom_done; - if ((bp->b_flags & B_UNMAPPED) != 0) { + if (!buf_mapped(bp)) { bio->bio_ma = bp->b_pages; bio->bio_data = unmapped_buf; bio->bio_ma_offset = (vm_offset_t)bp->b_offset & PAGE_MASK; diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index c7f31539a6ba..a4aac95c7adb 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1063,9 +1063,9 @@ vm_object_sync(vm_object_t object, vm_ooffset_t offset, vm_size_t size, */ flags = OBJPR_NOTMAPPED; else if (old_msync) - flags = OBJPR_NOTWIRED; + flags = 0; else - flags = OBJPR_CLEANONLY | OBJPR_NOTWIRED; + flags = OBJPR_CLEANONLY; vm_object_page_remove(object, OFF_TO_IDX(offset), OFF_TO_IDX(offset + size + PAGE_MASK), flags); } @@ -1894,7 +1894,6 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int options) { vm_page_t p, next; - int wirings; VM_OBJECT_ASSERT_WLOCKED(object); KASSERT((object->flags & OBJ_UNMANAGED) == 0 || @@ -1928,15 +1927,9 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, VM_OBJECT_WLOCK(object); goto again; } - if ((wirings = p->wire_count) != 0 && - (wirings = pmap_page_wired_mappings(p)) != p->wire_count) { - if ((options & (OBJPR_NOTWIRED | OBJPR_NOTMAPPED)) == - 0) { + if (p->wire_count != 0) { + if ((options & OBJPR_NOTMAPPED) == 0) pmap_remove_all(p); - /* Account for removal of wired mappings. */ - if (wirings != 0) - p->wire_count -= wirings; - } if ((options & OBJPR_CLEANONLY) == 0) { p->valid = 0; vm_page_undirty(p); @@ -1957,19 +1950,8 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, if (p->dirty) goto next; } - if ((options & OBJPR_NOTMAPPED) == 0) { - if ((options & OBJPR_NOTWIRED) != 0 && wirings != 0) - goto next; + if ((options & OBJPR_NOTMAPPED) == 0) pmap_remove_all(p); - /* Account for removal of wired mappings. */ - if (wirings != 0) { - KASSERT(p->wire_count == wirings, - ("inconsistent wire count %d %d %p", - p->wire_count, wirings, p)); - p->wire_count = 0; - atomic_subtract_int(&vm_cnt.v_wire_count, 1); - } - } vm_page_free(p); next: vm_page_unlock(p); diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 1f591568137c..7e433aee0228 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -207,7 +207,6 @@ struct vm_object { */ #define OBJPR_CLEANONLY 0x1 /* Don't remove dirty pages. */ #define OBJPR_NOTMAPPED 0x2 /* Don't unmap pages. */ -#define OBJPR_NOTWIRED 0x4 /* Don't remove wired pages. */ TAILQ_HEAD(object_q, vm_object); diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index b4fe8d0b6ecc..a42061c0417b 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -400,12 +400,11 @@ initpbuf(struct buf *bp) bp->b_rcred = NOCRED; bp->b_wcred = NOCRED; bp->b_qindex = 0; /* On no queue (QUEUE_NONE) */ - bp->b_saveaddr = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; - bp->b_data = bp->b_saveaddr; - bp->b_kvabase = bp->b_saveaddr; + bp->b_kvabase = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; + bp->b_data = bp->b_kvabase; bp->b_kvasize = MAXPHYS; - bp->b_xflags = 0; bp->b_flags = 0; + bp->b_xflags = 0; bp->b_ioflags = 0; bp->b_iodone = NULL; bp->b_error = 0; diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index b65a2a374caf..7a0dcfc4a6b9 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -965,8 +965,6 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, size = (size + secmask) & ~secmask; } - bp->b_kvaalloc = bp->b_data; - /* * and map the pages to be read into the kva, if the filesystem * requires mapped buffers. @@ -974,11 +972,11 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, if ((vp->v_mount->mnt_kern_flag & MNTK_UNMAPPED_BUFS) != 0 && unmapped_buf_allowed) { bp->b_data = unmapped_buf; - bp->b_kvabase = unmapped_buf; bp->b_offset = 0; - bp->b_flags |= B_UNMAPPED; - } else - pmap_qenter((vm_offset_t)bp->b_kvaalloc, m, count); + } else { + bp->b_data = bp->b_kvabase; + pmap_qenter((vm_offset_t)bp->b_data, m, count); + } /* build a minimal buffer header */ bp->b_iocmd = BIO_READ; @@ -1053,20 +1051,17 @@ vnode_pager_generic_getpages_done(struct buf *bp) object = bp->b_vp->v_object; if (error == 0 && bp->b_bcount != bp->b_npages * PAGE_SIZE) { - if ((bp->b_flags & B_UNMAPPED) != 0) { - bp->b_flags &= ~B_UNMAPPED; - pmap_qenter((vm_offset_t)bp->b_kvaalloc, bp->b_pages, + if (!buf_mapped(bp)) { + bp->b_data = bp->b_kvabase; + pmap_qenter((vm_offset_t)bp->b_data, bp->b_pages, bp->b_npages); } - bzero(bp->b_kvaalloc + bp->b_bcount, + bzero(bp->b_data + bp->b_bcount, PAGE_SIZE * bp->b_npages - bp->b_bcount); } - if ((bp->b_flags & B_UNMAPPED) == 0) - pmap_qremove((vm_offset_t)bp->b_kvaalloc, bp->b_npages); - if ((bp->b_vp->v_mount->mnt_kern_flag & MNTK_UNMAPPED_BUFS) != 0) { - bp->b_data = bp->b_kvaalloc; - bp->b_kvabase = bp->b_kvaalloc; - bp->b_flags &= ~B_UNMAPPED; + if (buf_mapped(bp)) { + pmap_qremove((vm_offset_t)bp->b_data, bp->b_npages); + bp->b_data = unmapped_buf; } VM_OBJECT_WLOCK(object); diff --git a/tests/sys/fifo/fifo_misc.c b/tests/sys/fifo/fifo_misc.c index 888547e32fcd..2c834b127e63 100644 --- a/tests/sys/fifo/fifo_misc.c +++ b/tests/sys/fifo/fifo_misc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -149,7 +150,7 @@ test_truncate(void) } static int -test_ioctl_setclearflag(int fd, int flag, const char *testname, +test_ioctl_setclearflag(int fd, unsigned long flag, const char *testname, const char *fdname, const char *flagname) { int i; diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 4bec221e0f1f..dbbe28329c45 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -6332,7 +6332,6 @@ OLD_FILES+=usr/share/man/man8/rwhod.8.gz .if ${MK_RCS} == no OLD_FILES+=usr/bin/ci OLD_FILES+=usr/bin/co -OLD_FILES+=usr/bin/ident OLD_FILES+=usr/bin/merge OLD_FILES+=usr/bin/rcs OLD_FILES+=usr/bin/rcsclean @@ -6343,7 +6342,6 @@ OLD_FILES+=usr/bin/rlog OLD_FILES+=usr/sbin/etcupdate OLD_FILES+=usr/share/man/man1/ci.1.gz OLD_FILES+=usr/share/man/man1/co.1.gz -OLD_FILES+=usr/share/man/man1/ident.1.gz OLD_FILES+=usr/share/man/man1/merge.1.gz OLD_FILES+=usr/share/man/man1/rcs.1.gz OLD_FILES+=usr/share/man/man1/rcsclean.1.gz diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c index d9c3f52cde18..f9b404b1b26c 100644 --- a/tools/bus_space/C/lang.c +++ b/tools/bus_space/C/lang.c @@ -80,10 +80,10 @@ bus_write_4(int rid, long ofs, uint32_t val) } int -bus_map(const char *dev) +bus_map(const char *dev, const char *resource) { - return (bs_map(dev)); + return (bs_map(dev, resource)); } int diff --git a/tools/bus_space/C/libbus.h b/tools/bus_space/C/libbus.h index 50efd3808cc8..0fae9879d2ce 100644 --- a/tools/bus_space/C/libbus.h +++ b/tools/bus_space/C/libbus.h @@ -29,7 +29,7 @@ #ifndef _LIBBUS_SPACE_H_ #define _LIBBUS_SPACE_H_ -int bus_map(const char *dev); +int bus_map(const char *dev, const char *resource); int16_t bus_read_1(int rid, long ofs); int32_t bus_read_2(int rid, long ofs); int64_t bus_read_4(int rid, long ofs); diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c index 0b96db3fcfd5..48a112ba0c30 100644 --- a/tools/bus_space/Python/lang.c +++ b/tools/bus_space/Python/lang.c @@ -131,12 +131,12 @@ bus_write_4(PyObject *self, PyObject *args) static PyObject * bus_map(PyObject *self, PyObject *args) { - char *dev; + char *dev, *resource; int rid; - if (!PyArg_ParseTuple(args, "s", &dev)) + if (!PyArg_ParseTuple(args, "ss", &dev, &resource)) return (NULL); - rid = bs_map(dev); + rid = bs_map(dev, resource); if (rid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); diff --git a/tools/bus_space/bus.c b/tools/bus_space/bus.c index 01b7693c3bf8..1b0d2ca59c3d 100644 --- a/tools/bus_space/bus.c +++ b/tools/bus_space/bus.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -92,19 +93,25 @@ rid_lookup(int rid) } int -bs_map(const char *dev) +bs_map(const char *dev, const char *res) { + char path[PATH_MAX]; struct proto_ioc_region region; struct resource *r; - int rid; + int len, rid; + len = snprintf(path, PATH_MAX, "/dev/proto/%s/%s", dev, res); + if (len >= PATH_MAX) { + errno = EINVAL; + return (-1); + } rid = rid_alloc(); if (rid == -1) return (-1); r = rid_lookup(rid); if (r == NULL) return (-1); - r->fd = open(dev, O_RDWR); + r->fd = open(path, O_RDWR); if (r->fd == -1) return (-1); r->rid = -1; diff --git a/tools/bus_space/bus.h b/tools/bus_space/bus.h index d34710641c66..a1835d74e2b5 100644 --- a/tools/bus_space/bus.h +++ b/tools/bus_space/bus.h @@ -29,7 +29,7 @@ #ifndef _TOOLS_BUS_SPACE_H_ #define _TOOLS_BUS_SPACE_H_ -int bs_map(const char *dev); +int bs_map(const char *dev, const char *res); int bs_read(int rid, off_t ofs, void *buf, ssize_t bufsz); int bs_subregion(int rid0, long ofs, long sz); int bs_unmap(int rid); diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c index 44c7b68ca5b7..3f948b72f983 100644 --- a/tools/bus_space/busdma.c +++ b/tools/bus_space/busdma.c @@ -184,10 +184,16 @@ int bd_tag_create(const char *dev, u_long align, u_long bndry, u_long maxaddr, u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags) { + char path[PATH_MAX]; struct obj *tag; - int fd; + int fd, len; - fd = open(dev, O_RDWR); + len = snprintf(path, PATH_MAX, "/dev/proto/%s/busdma", dev); + if (len >= PATH_MAX) { + errno = EINVAL; + return (-1); + } + fd = open(path, O_RDWR); if (fd == -1) return (-1); @@ -348,10 +354,6 @@ bd_md_load(int mdid, void *buf, u_long len, u_int flags) if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); - printf("XXX: %s: phys(%d, %#lx), bus(%d, %#lx)\n", __func__, - ioc.u.md.phys_nsegs, ioc.u.md.phys_addr, - ioc.u.md.bus_nsegs, ioc.u.md.bus_addr); - error = bd_md_add_seg(md, BUSDMA_MD_VIRT, ioc.u.md.virt_addr, len); error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, len); error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, len); @@ -412,10 +414,6 @@ bd_mem_alloc(int tid, u_int flags) tag->refcnt++; md->key = ioc.result; - printf("XXX: %s: phys(%d, %#lx), bus(%d, %#lx)\n", __func__, - ioc.u.md.phys_nsegs, ioc.u.md.phys_addr, - ioc.u.md.bus_nsegs, ioc.u.md.bus_addr); - /* XXX we need to support multiple segments */ assert(ioc.u.md.phys_nsegs == 1); assert(ioc.u.md.bus_nsegs == 1); diff --git a/usr.bin/Makefile b/usr.bin/Makefile index fd786025fa78..cf5604c79a06 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -64,6 +64,7 @@ SUBDIR= ${_addr2line} \ hexdump \ ${_iconv} \ id \ + ident \ ipcrm \ ipcs \ join \ diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1 index 1ef8c89fd7ed..02e99f1a92c9 100644 --- a/usr.bin/ar/ar.1 +++ b/usr.bin/ar/ar.1 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 22, 2011 +.Dd July 24, 2015 .Dt AR 1 .Os .Sh NAME @@ -66,6 +66,7 @@ .Op Fl D .Op Fl f .Op Fl s | Fl S +.Op Fl U .Op Fl v .Op Fl z .Ar archive @@ -82,6 +83,7 @@ .Op Fl j .Op Fl s | Fl S .Op Fl u +.Op Fl U .Op Fl v .Op Fl z .Ar archive @@ -112,6 +114,7 @@ .Fl M .Nm ranlib .Op Fl D +.Op Fl U .Ar archive ... .Sh DESCRIPTION The @@ -207,6 +210,11 @@ and 0644 instead of file mode from the members named by arguments .Ar . This ensures that checksums on the resulting archives are reproducible when member contents are identical. +If multiple +.Fl D +and +.Fl U +options are specified on the command line, the final one takes precedence. .It Fl f Synonymous with option .Fl T . @@ -316,6 +324,19 @@ option, the members specified by arguments .Ar will be extracted only if they are newer than the corresponding files in the file system. +.It Fl U +When used in combination with the +.Fl r +or +.Fl q +option, insert the real mtime, uid and gid, and file mode values +from the members named by arguments +.Ar . +If multiple +.Fl D +and +.Fl U +options are specified on the command line, the final one takes precedence. .It Fl v Provide verbose output. When used with the diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c index 7c76290207ea..3d5e2b87667b 100644 --- a/usr.bin/ar/ar.c +++ b/usr.bin/ar/ar.c @@ -113,7 +113,7 @@ main(int argc, char **argv) len = strlen(bsdar->progname); if (len >= strlen("ranlib") && strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) { - while ((opt = getopt_long(argc, argv, "tDV", longopts, + while ((opt = getopt_long(argc, argv, "tDUV", longopts, NULL)) != -1) { switch(opt) { case 't': @@ -122,6 +122,9 @@ main(int argc, char **argv) case 'D': bsdar->options |= AR_D; break; + case 'U': + bsdar->options &= ~AR_D; + break; case 'V': ranlib_version(); break; @@ -157,7 +160,7 @@ main(int argc, char **argv) } } - while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtuVvxz", + while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz", longopts, NULL)) != -1) { switch(opt) { case 'a': @@ -216,6 +219,9 @@ main(int argc, char **argv) case 't': set_mode(bsdar, opt); break; + case 'U': + bsdar->options &= ~AR_D; + break; case 'u': bsdar->options |= AR_U; break; @@ -364,9 +370,9 @@ bsdar_usage(void) (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n"); (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n"); (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); - (void)fprintf(stderr, "\tar -q [-TcDjsvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -r [-TcDjsuvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -r [-TabcDijsuvz] position archive file ...\n"); + (void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n"); + (void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n"); + (void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n"); (void)fprintf(stderr, "\tar -s [-jz] archive\n"); (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); (void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n"); @@ -378,7 +384,7 @@ static void ranlib_usage(void) { - (void)fprintf(stderr, "usage: ranlib [-t] archive ...\n"); + (void)fprintf(stderr, "usage: ranlib [-DtU] archive ...\n"); (void)fprintf(stderr, "\tranlib -V\n"); exit(EX_USAGE); } diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c index cd10ce3141d3..2147fcb3179b 100644 --- a/usr.bin/elfdump/elfdump.c +++ b/usr.bin/elfdump/elfdump.c @@ -272,6 +272,7 @@ e_machines(u_int mach) case EM_IA_64: return "EM_IA_64"; case EM_X86_64: return "EM_X86_64"; case EM_AARCH64:return "EM_AARCH64"; + case EM_RISCV: return "EM_RISCV"; } snprintf(machdesc, sizeof(machdesc), "(unknown machine) -- type 0x%x", mach); diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile index af2147180031..1c0e8ccd362d 100644 --- a/usr.bin/grep/Makefile +++ b/usr.bin/grep/Makefile @@ -20,6 +20,8 @@ SRCS= file.c grep.c queue.c util.c SRCS+= fastmatch.c hashtable.c tre-compile.c tre-fastmatch.c xmalloc.c CFLAGS+=-I${.CURDIR}/regex +CFLAGS.gcc+= --param max-inline-insns-single=500 + .if ${MK_BSD_GREP} == "yes" LINKS= ${BINDIR}/grep ${BINDIR}/egrep \ ${BINDIR}/grep ${BINDIR}/fgrep \ diff --git a/usr.bin/ident/Makefile b/usr.bin/ident/Makefile new file mode 100644 index 000000000000..49798e8251fe --- /dev/null +++ b/usr.bin/ident/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +.include + +PROG= ident + +LIBADD= sbuf + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + +.include diff --git a/usr.bin/ident/ident.1 b/usr.bin/ident/ident.1 new file mode 100644 index 000000000000..183a578e3309 --- /dev/null +++ b/usr.bin/ident/ident.1 @@ -0,0 +1,68 @@ +.\" Copyright (c) 2015 Baptiste Daroussin +.\" 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$ +.\" +.Dd Jul 25, 2015 +.Dt IDENT 1 +.Os +.Sh NAME +.Nm ident +.Nd identify RCS keyword string in files +.Sh SYNOPSIS +.Nm +.Op Fl q +.Op Fl V +.Op Ar File Ns s +.Sh DESCRIPTION +The +.Nm +utility searches for all instances of the pattern +.Sq $keyword: text$ +in +.Ar files . +.Pp +If no arguments are passed, then +.Nm +parses the standard input. +.Pp +.Em keyword +must only be composed of alphanumeric values in the C locale, followed by +.Sq \&: +and a space. +.Pp +These options are supported: +.Bl -tag -width "XXX" +.It Fl q +Quiet mode: suppress warnings if no pattern found. +.It Fl V +Do nothing, added for compatibility with GNU ident. +.El +.Sh EXIT STATUS +.Ex -std ident +.Sh AUTHORS +This version of the +.Nm +utility was written by +.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org . diff --git a/usr.bin/ident/ident.c b/usr.bin/ident/ident.c new file mode 100644 index 000000000000..36e56a0cefda --- /dev/null +++ b/usr.bin/ident/ident.c @@ -0,0 +1,242 @@ +/*- + * Copyright (c) 2015 Baptiste Daroussin + * Copyright (c) 2015 Xin LI + * 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 + * in this position and unchanged. + * 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(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 AUTHOR(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 +#include +#include +#include + +typedef enum { + /* state condition to transit to next state */ + INIT, /* '$' */ + DELIM_SEEN, /* letter */ + KEYWORD, /* punctuation mark */ + PUNC_SEEN, /* ':' -> _SVN; space -> TEXT */ + PUNC_SEEN_SVN, /* space */ + TEXT +} analyzer_states; + +static int +scan(FILE *fp, const char *name, bool quiet) +{ + int c; + bool hasid = false; + bool subversion = false; + analyzer_states state = INIT; + struct sbuf *id = sbuf_new_auto(); + locale_t l; + + l = newlocale(LC_ALL_MASK, "C", NULL); + + if (name != NULL) + printf("%s:\n", name); + + while ((c = fgetc(fp)) != EOF) { + switch (state) { + case INIT: + if (c == '$') { + /* Transit to DELIM_SEEN if we see $ */ + state = DELIM_SEEN; + } else { + /* Otherwise, stay in INIT state */ + continue; + } + break; + case DELIM_SEEN: + if (isalpha_l(c, l)) { + /* Transit to KEYWORD if we see letter */ + sbuf_clear(id); + sbuf_putc(id, '$'); + sbuf_putc(id, c); + state = KEYWORD; + + continue; + } else if (c == '$') { + /* Or, stay in DELIM_SEEN if more $ */ + continue; + } else { + /* Otherwise, transit back to INIT */ + state = INIT; + } + break; + case KEYWORD: + sbuf_putc(id, c); + + if (isalpha_l(c, l)) { + /* + * Stay in KEYWORD if additional letter is seen + */ + continue; + } else if (c == ':') { + /* + * See ':' for the first time, transit to + * PUNC_SEEN. + */ + state = PUNC_SEEN; + subversion = false; + } else if (c == '$') { + /* + * Incomplete ident. Go back to DELIM_SEEN + * state because we see a '$' which could be + * the beginning of a keyword. + */ + state = DELIM_SEEN; + } else { + /* + * Go back to INIT state otherwise. + */ + state = INIT; + } + break; + case PUNC_SEEN: + case PUNC_SEEN_SVN: + sbuf_putc(id, c); + + switch (c) { + case ':': + /* + * If we see '::' (seen : in PUNC_SEEN), + * activate subversion treatment and transit + * to PUNC_SEEN_SVN state. + * + * If more than two :'s were seen, the ident + * is invalid and we would therefore go back + * to INIT state. + */ + if (state == PUNC_SEEN) { + state = PUNC_SEEN_SVN; + subversion = true; + } else { + state = INIT; + } + break; + case ' ': + /* + * A space after ':' or '::' indicates we are at the + * last component of potential ident. + */ + state = TEXT; + break; + default: + /* All other characters are invalid */ + state = INIT; + break; + } + break; + case TEXT: + sbuf_putc(id, c); + + if (iscntrl_l(c, l)) { + /* Control characters are not allowed in this state */ + state = INIT; + } else if (c == '$') { + sbuf_finish(id); + /* + * valid ident should end with a space. + * + * subversion extension uses '#' to indicate that + * the keyword expansion have exceeded the fixed + * width, so it is also permitted if we are in + * subversion mode. No length check is enforced + * because GNU RCS ident(1) does not do it either. + */ + c = sbuf_data(id)[sbuf_len(id) - 2]; + if (c == ' ' || (subversion && c == '#')) { + printf(" %s\n", sbuf_data(id)); + hasid = true; + } + state = INIT; + } + /* Other characters: stay in the state */ + break; + } + } + sbuf_delete(id); + freelocale(l); + + if (!hasid) { + if (!quiet) + fprintf(stderr, "%s warning: no id keywords in %s\n", + getprogname(), name ? name : "standard input"); + + return (EXIT_FAILURE); + } + + return (EXIT_SUCCESS); +} + +int +main(int argc, char **argv) +{ + bool quiet = false; + int ch, i; + int ret = EXIT_SUCCESS; + FILE *fp; + + while ((ch = getopt(argc, argv, "qV")) != -1) { + switch (ch) { + case 'q': + quiet = true; + break; + case 'V': + /* Do nothing, compat with GNU rcs's ident */ + return (EXIT_SUCCESS); + default: + errx(EXIT_FAILURE, "usage: %s [-q] [-V] [file...]", + getprogname()); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return (scan(stdin, NULL, quiet)); + + for (i = 0; i < argc; i++) { + fp = fopen(argv[i], "r"); + if (fp == NULL) { + warn("%s", argv[i]); + ret = EXIT_FAILURE; + continue; + } + if (scan(fp, argv[i], quiet) != EXIT_SUCCESS) + ret = EXIT_FAILURE; + fclose(fp); + } + + return (ret); +} diff --git a/usr.bin/ident/tests/Makefile b/usr.bin/ident/tests/Makefile new file mode 100644 index 000000000000..cc29bb8c6f8e --- /dev/null +++ b/usr.bin/ident/tests/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/usr.bin/ident + +ATF_TESTS_SH= ident +FILES= test.in \ + test.out \ + testnoid +FILESDIR= ${TESTSDIR} + +.include diff --git a/usr.bin/ident/tests/ident.sh b/usr.bin/ident/tests/ident.sh new file mode 100755 index 000000000000..5a3118254bfa --- /dev/null +++ b/usr.bin/ident/tests/ident.sh @@ -0,0 +1,16 @@ +# $FreeBSD$ + +atf_test_case ident +ident_body() { + atf_check -o file:$(atf_get_srcdir)/test.out \ + ident < $(atf_get_srcdir)/test.in + atf_check -o match:'Foo.*' -s exit:1 \ + -e inline:"ident warning: no id keywords in $(atf_get_srcdir)/testnoid\n" \ + ident $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid + atf_check -o match:'Foo.*' -s exit:1 \ + ident -q $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid +} +atf_init_test_cases() +{ + atf_add_test_case ident +} diff --git a/usr.bin/ident/tests/test.in b/usr.bin/ident/tests/test.in new file mode 100644 index 000000000000..634943833ce5 --- /dev/null +++ b/usr.bin/ident/tests/test.in @@ -0,0 +1,15 @@ +# tranditional + $Foo: bar $ (OK traditional) + $$Foo: bar $ + $$Fo$o: bar $ + $Fo$o: bar $ + $ Foo : bar $ (WRONG -- NON ALPHANUM BEFORE :) + $ Foo : bar $ (WRONG -- NON ALPHANUM BEFORE :) + $Foo: bar $ (WRONG -- NO SPACE AFTER :) + $Foo:bar $ (WRONG -- NO SPACE AFTER :) + $Foo: bar$ (WRONG -- NO SPACE BEFORE $)) +# Subversion like + $Bar:: baz$ (WRONG -- NO SPACE BEFORE $) + $Bar:: baz $ (OK -- SPACE BEFORE $) + $Qux:: frobby zow#$ (OK -- HASH BEFORE $)' ' + diff --git a/usr.bin/ident/tests/test.out b/usr.bin/ident/tests/test.out new file mode 100644 index 000000000000..36cccc9b2098 --- /dev/null +++ b/usr.bin/ident/tests/test.out @@ -0,0 +1,6 @@ + $Foo: bar $ + $Foo: bar $ + $o: bar $ + $o: bar $ + $Bar:: baz $ + $Qux:: frobby zow#$ diff --git a/usr.bin/ident/tests/testnoid b/usr.bin/ident/tests/testnoid new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/usr.bin/man/man.sh b/usr.bin/man/man.sh index 5e4d767a3064..e125e5be3f85 100755 --- a/usr.bin/man/man.sh +++ b/usr.bin/man/man.sh @@ -925,6 +925,8 @@ whatis_usage() { # Supported commands do_apropos() { + [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ + exec apropos "$@" search_whatis apropos "$@" } @@ -960,6 +962,8 @@ do_manpath() { } do_whatis() { + [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ + exec whatis "$@" search_whatis whatis "$@" } diff --git a/usr.bin/truss/amd64-fbsd.c b/usr.bin/truss/amd64-fbsd.c index 516c4d280caf..d0be3e6b141a 100644 --- a/usr.bin/truss/amd64-fbsd.c +++ b/usr.bin/truss/amd64-fbsd.c @@ -158,6 +158,7 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/amd64-fbsd32.c b/usr.bin/truss/amd64-fbsd32.c index 72f42958183e..74d45a2189d5 100644 --- a/usr.bin/truss/amd64-fbsd32.c +++ b/usr.bin/truss/amd64-fbsd32.c @@ -165,6 +165,7 @@ amd64_fbsd32_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/arm-fbsd.c b/usr.bin/truss/arm-fbsd.c index 3bac40095c7c..dd1ae0896483 100644 --- a/usr.bin/truss/arm-fbsd.c +++ b/usr.bin/truss/arm-fbsd.c @@ -172,6 +172,7 @@ arm_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/i386-fbsd.c b/usr.bin/truss/i386-fbsd.c index d146ecd528bd..89879d2ff543 100644 --- a/usr.bin/truss/i386-fbsd.c +++ b/usr.bin/truss/i386-fbsd.c @@ -162,6 +162,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/mips-fbsd.c b/usr.bin/truss/mips-fbsd.c index 6f5be66188a7..71e9efabdf31 100644 --- a/usr.bin/truss/mips-fbsd.c +++ b/usr.bin/truss/mips-fbsd.c @@ -155,6 +155,7 @@ mips_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/powerpc-fbsd.c b/usr.bin/truss/powerpc-fbsd.c index 8cfb9ef75010..990da29c143e 100644 --- a/usr.bin/truss/powerpc-fbsd.c +++ b/usr.bin/truss/powerpc-fbsd.c @@ -169,6 +169,7 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/powerpc64-fbsd.c b/usr.bin/truss/powerpc64-fbsd.c index 7147f8117a8d..9d5cbd9199b9 100644 --- a/usr.bin/truss/powerpc64-fbsd.c +++ b/usr.bin/truss/powerpc64-fbsd.c @@ -157,6 +157,7 @@ powerpc64_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.bin/truss/sparc64-fbsd.c b/usr.bin/truss/sparc64-fbsd.c index 429fa2421d14..3c6de5fe2fa1 100644 --- a/usr.bin/truss/sparc64-fbsd.c +++ b/usr.bin/truss/sparc64-fbsd.c @@ -161,6 +161,7 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) if (fsc->name && (trussinfo->flags & FOLLOWFORKS) && (strcmp(fsc->name, "fork") == 0 || + strcmp(fsc->name, "pdfork") == 0 || strcmp(fsc->name, "rfork") == 0 || strcmp(fsc->name, "vfork") == 0)) trussinfo->curthread->in_fork = 1; diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile index d470a9bc8dfa..8d13e77bd9d2 100644 --- a/usr.sbin/acpi/acpidb/Makefile +++ b/usr.sbin/acpi/acpidb/Makefile @@ -8,18 +8,18 @@ SRCS+= acgetline.c ahids.c ahuuids.c cmfsize.c # components/debugger SRCS+= dbcmds.c dbconvert.c dbdisply.c dbexec.c dbfileio.c \ - dbhistry.c dbinput.c dbmethod.c dbnames.c dbstats.c \ - dbtest.c dbutils.c dbxface.c + dbhistry.c dbinput.c dbmethod.c dbnames.c dbobject.c \ + dbstats.c dbtest.c dbutils.c dbxface.c # components/disassembler -SRCS+= dmbuffer.c dmcstyle.c dmdeferred.c dmnames.c dmobject.c \ - dmopcode.c dmresrc.c dmresrcl.c dmresrcl2.c dmresrcs.c \ - dmutils.c dmwalk.c +SRCS+= dmbuffer.c dmcstyle.c dmdeferred.c dmnames.c dmopcode.c \ + dmresrc.c dmresrcl.c dmresrcl2.c dmresrcs.c dmutils.c \ + dmwalk.c # components/dispatcher -SRCS+= dsargs.c dscontrol.c dsfield.c dsinit.c dsmethod.c \ - dsmthdat.c dsobject.c dsopcode.c dsutils.c dswexec.c \ - dswload.c dswload2.c dswscope.c dswstate.c +SRCS+= dsargs.c dscontrol.c dsdebug.c dsfield.c dsinit.c \ + dsmethod.c dsmthdat.c dsobject.c dsopcode.c dsutils.c \ + dswexec.c dswload.c dswload2.c dswscope.c dswstate.c # components/events SRCS+= evevent.c evglock.c evgpe.c evgpeblk.c evgpeinit.c \ @@ -63,9 +63,9 @@ SRCS+= utaddress.c utalloc.c utbuffer.c utcache.c utcopy.c \ utdebug.c utdecode.c utdelete.c uterror.c uteval.c \ utexcep.c utfileio.c utglobal.c uthex.c utids.c \ utinit.c utlock.c utmath.c utmisc.c utmutex.c \ - utobject.c utosi.c utownerid.c utpredef.c utprint.c \ - utresrc.c utstate.c utstring.c uttrack.c utuuid.c \ - utxface.c utxferror.c utxfinit.c + utnonansi.c utobject.c utosi.c utownerid.c utpredef.c \ + utprint.c utresrc.c utstate.c utstring.c uttrack.c \ + utuuid.c utxface.c utxferror.c utxfinit.c # os_specific/service_layers SRCS+= oslibcfs.c osunixxf.c diff --git a/usr.sbin/acpi/iasl/Makefile b/usr.sbin/acpi/iasl/Makefile index e9faad2b28fd..210b31aa0428 100644 --- a/usr.sbin/acpi/iasl/Makefile +++ b/usr.sbin/acpi/iasl/Makefile @@ -62,9 +62,9 @@ SRCS+= tbdata.c tbfadt.c tbinstal.c tbprint.c tbutils.c \ SRCS+= utaddress.c utalloc.c utbuffer.c utcache.c utcopy.c \ utdebug.c utdecode.c utdelete.c uterror.c utexcep.c \ utfileio.c utglobal.c uthex.c utinit.c utlock.c \ - utmath.c utmisc.c utmutex.c utobject.c utownerid.c \ - utpredef.c utprint.c utresrc.c utstate.c utstring.c \ - utuuid.c utxface.c utxferror.c + utmath.c utmisc.c utmutex.c utnonansi.c utobject.c \ + utownerid.c utpredef.c utprint.c utresrc.c utstate.c \ + utstring.c utuuid.c utxface.c utxferror.c # os_specific/service_layers SRCS+= oslibcfs.c osunixxf.c diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 index 5122e0f22eea..c9b79c4df16f 100644 --- a/usr.sbin/jail/jail.8 +++ b/usr.sbin/jail/jail.8 @@ -620,7 +620,7 @@ The command parameters are .Xr sh 1 command lines that are run in either the system or jail environment. -They may be given multiple values, which run would the specified +They may be given multiple values, which would run the specified commands in sequence. All commands must succeed (return a zero exit status), or the jail will not be created or removed, as appropriate.