diff --git a/Makefile.inc1 b/Makefile.inc1 index 14b553a9058b..1d858d2cf5bc 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1581,10 +1581,6 @@ _groff= gnu/usr.bin/groff \ _vtfontcvt= usr.bin/vtfontcvt .endif -.if ${BOOTSTRAPPING} < 900002 -_sed= usr.bin/sed -.endif - .if ${BOOTSTRAPPING} < 1000033 _libopenbsd= lib/libopenbsd _m4= usr.bin/m4 @@ -1623,10 +1619,6 @@ _crunchide= usr.sbin/crunch/crunchide _crunchgen= usr.sbin/crunch/crunchgen .endif -.if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 -_awk= usr.bin/awk -.endif - # r296926 -P keymap search path, MFC to stable/10 in r298297 .if ${BOOTSTRAPPING} < 1003501 || \ (${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103) @@ -1694,7 +1686,6 @@ bootstrap-tools: .PHONY ${_gperf} \ ${_groff} \ ${_dtc} \ - ${_awk} \ ${_cat} \ ${_dd} \ ${_kbdcontrol} \ @@ -1702,7 +1693,6 @@ bootstrap-tools: .PHONY ${_libopenbsd} \ ${_makewhatis} \ usr.bin/rpcgen \ - ${_sed} \ ${_yacc} \ ${_m4} \ ${_lex} \ diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index d5e71e9c6e6b..02a55b608cb1 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20160815: Remove mcd(4) +OLD_FILES+=usr/share/man/man4/mcd.4.gz # 20160703: POSIXify locales with variants OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_COLLATE OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_CTYPE diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dstyle.pl b/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dstyle.pl index 3c3e180a0e75..30b54d850733 100755 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dstyle.pl +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dstyle.pl @@ -25,6 +25,10 @@ # Use is subject to license terms. # +# +# Copyright (c) 2014, 2016 by Delphix. All rights reserved. +# + require 5.8.4; $PNAME = $0; @@ -131,7 +135,8 @@ sub dstyle } if (!/^enum/ && !/^\t*struct/ && !/^\t*union/ && !/^typedef/ && - !/^translator/ && !/^provider/) { + !/^translator/ && !/^provider/ && !/\tif / && + !/ else /) { if (/[\w\s]+{/) { err "left brace not on its own line"; } @@ -141,7 +146,7 @@ sub dstyle } } - if (!/;$/) { + if (!/;$/ && !/\t*}$/ && !/ else /) { if (/[\w\s]+}/) { err "right brace not on its own line"; } diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16kglobal.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16kglobal.d new file mode 100644 index 000000000000..8a5d1cd3a01e --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16kglobal.d @@ -0,0 +1,32 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2016, Joyent, Inc. All rights reserved. + */ + +#pragma D option strsize=16k + +char *k; + +BEGIN +{ + j = probeprov; + k = j; + k[0] = 'D'; + k[1] = 'T'; +} + +BEGIN +{ + trace(stringof(k)); + exit(k == "DTrace" ? 0 : 1); +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16klocal.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16klocal.d new file mode 100644 index 000000000000..930520c235c5 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/scalars/tst.16klocal.d @@ -0,0 +1,29 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2016, Joyent, Inc. All rights reserved. + */ + +#pragma D option strsize=16k + +BEGIN +{ + this->j = probeprov; + this->j[0] = 'D'; + this->j[1] = 'T'; +} + +BEGIN +{ + trace(this->j); + exit(this->j == "DTrace" ? 0 : 1); +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.else.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.else.d new file mode 100644 index 000000000000..88da007436fb --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.else.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "else" statement is executed + */ + +BEGIN +{ + if (0) { + n = 1; + } else { + n = 0; + } + exit(n) +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if.d new file mode 100644 index 000000000000..3da5d2daf695 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" statement executes the correct body. + */ + +BEGIN +{ + if (1) { + n = 0; + } else { + n = 1; + } + exit(n) +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if2.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if2.d new file mode 100644 index 000000000000..b56e39929d67 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if2.d @@ -0,0 +1,33 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" statement executes the correct body. + * parses single-statement, braceless bodies correctly. + */ + +BEGIN +{ + if (1) + n = 0; + else + n = 1; + exit(n) +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d new file mode 100644 index 000000000000..00837eb65c2c --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_before_after.d @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * statements before and after an if statement are executed. + */ + +BEGIN +{ + i = 1; + if (1) { + i++; + } else { + i++; + } + i++; +} + +BEGIN +/i == 3/ +{ + exit(0); +} + +BEGIN +/i != 3/ +{ + exit(1); +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d new file mode 100644 index 000000000000..e8ad443a04bd --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_nested.d @@ -0,0 +1,38 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * nested "if" statement executes the correct body. + */ + +BEGIN +{ + if (0) { + exit(1); + } else { + if (0) { + exit(1); + } else { + exit(0); + } + exit(1); + } + exit(1); +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d new file mode 100644 index 000000000000..81196c0ca47c --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon.d @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" body without trailing semicolon parses correctly + */ + +BEGIN +{ + if (1) { + exit(0) + } +} diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d new file mode 100644 index 000000000000..e1bd3895f9f0 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/sugar/tst.if_trailing_semicolon2.d @@ -0,0 +1,31 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. + */ + +/* + * ASSERTION: + * "if" body without trailing semicolon parses correctly + */ + +BEGIN +{ + if (1) { + i = 1; + exit(0) + } +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c index 84f8661e3fb4..ef10e0bc7e94 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c @@ -21,8 +21,9 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2015 Gary Mills */ /* @@ -119,7 +120,6 @@ static const dtrace_diftype_t dt_int_rtype = { static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *, uint_t, int, char *const[], FILE *, const char *); - /*ARGSUSED*/ static int dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored) @@ -2435,7 +2435,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, dt_node_t *dnp; dt_decl_t *ddp; dt_pcb_t pcb; - void *rv; + void *volatile rv; int err; if ((fp == NULL && s == NULL) || (cflags & ~DTRACE_C_MASK) != 0) { @@ -2517,6 +2517,28 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1); } + /* + * Perform sugar transformations (for "if" / "else") and replace the + * existing clause chain with the new one. + */ + if (context == DT_CTX_DPROG) { + dt_node_t *dnp, *next_dnp; + dt_node_t *new_list = NULL; + + for (dnp = yypcb->pcb_root->dn_list; + dnp != NULL; dnp = next_dnp) { + /* remove this node from the list */ + next_dnp = dnp->dn_list; + dnp->dn_list = NULL; + + if (dnp->dn_kind == DT_NODE_CLAUSE) + dnp = dt_compile_sugar(dtp, dnp); + /* append node to the new list */ + new_list = dt_node_link(new_list, dnp); + } + yypcb->pcb_root->dn_list = new_list; + } + /* * If we have successfully created a parse tree for a D program, loop * over the clauses and actions and instantiate the corresponding @@ -2537,6 +2559,8 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, for (; dnp != NULL; dnp = dnp->dn_list) { switch (dnp->dn_kind) { case DT_NODE_CLAUSE: + if (DT_TREEDUMP_PASS(dtp, 4)) + dt_printd(dnp, stderr, 0); dt_compile_clause(dtp, dnp); break; case DT_NODE_XLATOR: diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y index 6321b65808d3..0cb6fa6b5253 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y @@ -23,8 +23,9 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -155,6 +156,8 @@ %type probe_specifier_list %type probe_specifier %type statement_list +%type statement_list_impl +%type statement_or_block %type statement %type declaration %type init_declarator_list @@ -319,9 +322,11 @@ probe_definition: "or actions following probe description\n"); } $$ = dt_node_clause($1, NULL, NULL); + yybegin(YYS_CLAUSE); } | probe_specifiers '{' statement_list '}' { $$ = dt_node_clause($1, NULL, $3); + yybegin(YYS_CLAUSE); } | probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED { dnerror($3, D_SYNTAX, "expected actions { } following " @@ -330,6 +335,7 @@ probe_definition: | probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED '{' statement_list '}' { $$ = dt_node_clause($1, $3, $6); + yybegin(YYS_CLAUSE); } ; @@ -349,12 +355,30 @@ probe_specifier: | DT_TOK_INT { $$ = dt_node_pdesc_by_id($1); } ; -statement_list: statement { $$ = $1; } - | statement_list ';' statement { $$ = LINK($1, $3); } +statement_list_impl: /* empty */ { $$ = NULL; } + | statement_list_impl statement { $$ = LINK($1, $2); } ; -statement: /* empty */ { $$ = NULL; } - | expression { $$ = dt_node_statement($1); } +statement_list: + statement_list_impl { $$ = $1; } + | statement_list_impl expression { + $$ = LINK($1, dt_node_statement($2)); + } + ; + +statement_or_block: + statement + | '{' statement_list '}' { $$ = $2; } + +statement: ';' { $$ = NULL; } + | expression ';' { $$ = dt_node_statement($1); } + | DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR statement_or_block { + $$ = dt_node_if($3, $5, NULL); + } + | DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR + statement_or_block DT_KEY_ELSE statement_or_block { + $$ = dt_node_if($3, $5, $7); + } ; argument_expression_list: diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h index 36cc5396e214..e71e9d71aeff 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h @@ -26,7 +26,7 @@ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2011, 2016 by Delphix. All rights reserved. */ #ifndef _DT_IMPL_H @@ -362,6 +362,7 @@ struct dtrace_hdl { int dt_indent; /* recommended flow indent */ dtrace_epid_t dt_last_epid; /* most recently consumed EPID */ uint64_t dt_last_timestamp; /* most recently consumed timestamp */ + boolean_t dt_has_sugar; /* syntactic sugar used? */ }; /* diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c index ac0524b07050..a56b98681d3b 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #include @@ -130,8 +130,9 @@ #define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0) #define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0) #define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1) -#define DT_VERS_LATEST DT_VERS_1_12_1 -#define DT_VERS_STRING "Sun D 1.12.1" +#define DT_VERS_1_13 DT_VERSION_NUMBER(1, 13, 0) +#define DT_VERS_LATEST DT_VERS_1_13 +#define DT_VERS_STRING "Sun D 1.13" const dt_version_t _dtrace_versions[] = { DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */ @@ -157,6 +158,7 @@ const dt_version_t _dtrace_versions[] = { DT_VERS_1_11, /* D API 1.11 */ DT_VERS_1_12, /* D API 1.12 */ DT_VERS_1_12_1, /* D API 1.12.1 */ + DT_VERS_1_13, /* D API 1.13 */ 0 }; diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c index ee31cef5f28c..5af7a00a80fe 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c @@ -23,7 +23,7 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2013, Joyent Inc. All rights reserved. - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -2142,6 +2142,17 @@ dt_node_statement(dt_node_t *expr) return (dnp); } +dt_node_t * +dt_node_if(dt_node_t *pred, dt_node_t *acts, dt_node_t *else_acts) +{ + dt_node_t *dnp = dt_node_alloc(DT_NODE_IF); + dnp->dn_conditional = pred; + dnp->dn_body = acts; + dnp->dn_alternate_body = else_acts; + + return (dnp); +} + dt_node_t * dt_node_pdesc_by_name(char *spec) { @@ -2211,7 +2222,6 @@ dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts) dnp->dn_pred = pred; dnp->dn_acts = acts; - yybegin(YYS_CLAUSE); return (dnp); } @@ -3203,8 +3213,9 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags) dt_xcook_ident(lp, dhp, idkind, B_TRUE); else dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE); - } else + } else { lp = dnp->dn_left = dt_node_cook(lp, 0); + } /* * Switch op to '+' for *(E1 + E2) array mode in these cases: @@ -3218,10 +3229,12 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags) if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) { if (lp->dn_args != NULL) op = DT_TOK_ADD; - } else if (!dt_ident_unref(lp->dn_ident)) + } else if (!dt_ident_unref(lp->dn_ident)) { op = DT_TOK_ADD; - } else if (lp->dn_kind != DT_NODE_AGG) + } + } else if (lp->dn_kind != DT_NODE_AGG) { op = DT_TOK_ADD; + } } switch (op) { @@ -3645,45 +3658,34 @@ asgn_common: case DT_TOK_PTR: /* - * If the left-hand side of operator -> is the name "self", - * then we permit a TLS variable to be created or referenced. + * If the left-hand side of operator -> is one of the scoping + * keywords, permit a local or thread variable to be created or + * referenced. */ - if (lp->dn_kind == DT_NODE_IDENT && - strcmp(lp->dn_string, "self") == 0) { - if (rp->dn_kind != DT_NODE_VAR) { - dt_xcook_ident(rp, dtp->dt_tls, - DT_IDENT_SCALAR, B_TRUE); + if (lp->dn_kind == DT_NODE_IDENT) { + dt_idhash_t *dhp = NULL; + + if (strcmp(lp->dn_string, "self") == 0) { + dhp = dtp->dt_tls; + } else if (strcmp(lp->dn_string, "this") == 0) { + dhp = yypcb->pcb_locals; } + if (dhp != NULL) { + if (rp->dn_kind != DT_NODE_VAR) { + dt_xcook_ident(rp, dhp, + DT_IDENT_SCALAR, B_TRUE); + } - if (idflags != 0) - rp = dt_node_cook(rp, idflags); + if (idflags != 0) + rp = dt_node_cook(rp, idflags); - dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ - dt_node_free(dnp); - return (rp); - } - - /* - * If the left-hand side of operator -> is the name "this", - * then we permit a local variable to be created or referenced. - */ - if (lp->dn_kind == DT_NODE_IDENT && - strcmp(lp->dn_string, "this") == 0) { - if (rp->dn_kind != DT_NODE_VAR) { - dt_xcook_ident(rp, yypcb->pcb_locals, - DT_IDENT_SCALAR, B_TRUE); + /* avoid freeing rp */ + dnp->dn_right = dnp->dn_left; + dt_node_free(dnp); + return (rp); } - - if (idflags != 0) - rp = dt_node_cook(rp, idflags); - - dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ - dt_node_free(dnp); - return (rp); } - /*FALLTHRU*/ - case DT_TOK_DOT: lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); @@ -4502,7 +4504,8 @@ static dt_node_t *(*dt_cook_funcs[])(dt_node_t *, uint_t) = { dt_cook_xlator, /* DT_NODE_XLATOR */ dt_cook_none, /* DT_NODE_PROBE */ dt_cook_provider, /* DT_NODE_PROVIDER */ - dt_cook_none /* DT_NODE_PROG */ + dt_cook_none, /* DT_NODE_PROG */ + dt_cook_none, /* DT_NODE_IF */ }; /* @@ -4517,6 +4520,8 @@ dt_node_cook(dt_node_t *dnp, uint_t idflags) yylineno = dnp->dn_line; + assert(dnp->dn_kind < + sizeof (dt_cook_funcs) / sizeof (dt_cook_funcs[0])); dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags); dnp->dn_flags |= DT_NF_COOKED; @@ -4619,6 +4624,181 @@ dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp) tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type); } +/* + * Output the parse tree as D. The "-xtree=8" argument will call this + * function to print out the program after any syntactic sugar + * transformations have been applied (e.g. to implement "if"). The + * resulting output can be used to understand the transformations + * applied by these features, or to run such a script on a system that + * does not support these features + * + * Note that the output does not express precisely the same program as + * the input. In particular: + * - Only the clauses are output. #pragma options, variable + * declarations, etc. are excluded. + * - Command argument substitution has already been done, so the output + * will not contain e.g. $$1, but rather the substituted string. + */ +void +dt_printd(dt_node_t *dnp, FILE *fp, int depth) +{ + dt_node_t *arg; + + switch (dnp->dn_kind) { + case DT_NODE_INT: + (void) fprintf(fp, "0x%llx", (u_longlong_t)dnp->dn_value); + if (!(dnp->dn_flags & DT_NF_SIGNED)) + (void) fprintf(fp, "u"); + break; + + case DT_NODE_STRING: { + char *escd = strchr2esc(dnp->dn_string, strlen(dnp->dn_string)); + (void) fprintf(fp, "\"%s\"", escd); + free(escd); + break; + } + + case DT_NODE_IDENT: + (void) fprintf(fp, "%s", dnp->dn_string); + break; + + case DT_NODE_VAR: + (void) fprintf(fp, "%s%s", + (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" : + (dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "", + dnp->dn_ident->di_name); + + if (dnp->dn_args != NULL) { + (void) fprintf(fp, "["); + + for (arg = dnp->dn_args; arg != NULL; + arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ", "); + } + + (void) fprintf(fp, "]"); + } + break; + + case DT_NODE_SYM: { + const dtrace_syminfo_t *dts = dnp->dn_ident->di_data; + (void) fprintf(fp, "%s`%s", dts->dts_object, dts->dts_name); + break; + } + case DT_NODE_FUNC: + (void) fprintf(fp, "%s(", dnp->dn_ident->di_name); + + for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ", "); + } + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP1: + (void) fprintf(fp, "%s(", opstr(dnp->dn_op)); + dt_printd(dnp->dn_child, fp, 0); + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP2: + (void) fprintf(fp, "("); + dt_printd(dnp->dn_left, fp, 0); + if (dnp->dn_op == DT_TOK_LPAR) { + (void) fprintf(fp, ")"); + dt_printd(dnp->dn_right, fp, 0); + break; + } + if (dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT || + dnp->dn_op == DT_TOK_LBRAC) + (void) fprintf(fp, "%s", opstr(dnp->dn_op)); + else + (void) fprintf(fp, " %s ", opstr(dnp->dn_op)); + dt_printd(dnp->dn_right, fp, 0); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + (void) fprintf(fp, ", "); + dt_printd(ln->dn_list, fp, depth); + ln = ln->dn_list; + } + (void) fprintf(fp, "]"); + } + (void) fprintf(fp, ")"); + break; + + case DT_NODE_OP3: + (void) fprintf(fp, "("); + dt_printd(dnp->dn_expr, fp, 0); + (void) fprintf(fp, " ? "); + dt_printd(dnp->dn_left, fp, 0); + (void) fprintf(fp, " : "); + dt_printd(dnp->dn_right, fp, 0); + (void) fprintf(fp, ")"); + break; + + case DT_NODE_DEXPR: + case DT_NODE_DFUNC: + (void) fprintf(fp, "%*s", depth * 8, ""); + dt_printd(dnp->dn_expr, fp, depth + 1); + (void) fprintf(fp, ";\n"); + break; + + case DT_NODE_PDESC: + (void) fprintf(fp, "%s:%s:%s:%s", + dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod, + dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name); + break; + + case DT_NODE_CLAUSE: + for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) { + dt_printd(arg, fp, 0); + if (arg->dn_list != NULL) + (void) fprintf(fp, ","); + (void) fprintf(fp, "\n"); + } + + if (dnp->dn_pred != NULL) { + (void) fprintf(fp, "/"); + dt_printd(dnp->dn_pred, fp, 0); + (void) fprintf(fp, "/\n"); + } + (void) fprintf(fp, "{\n"); + + for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + (void) fprintf(fp, "}\n"); + (void) fprintf(fp, "\n"); + break; + + case DT_NODE_IF: + (void) fprintf(fp, "%*sif (", depth * 8, ""); + dt_printd(dnp->dn_conditional, fp, 0); + (void) fprintf(fp, ") {\n"); + + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + if (dnp->dn_alternate_body == NULL) { + (void) fprintf(fp, "%*s}\n", depth * 8, ""); + } else { + (void) fprintf(fp, "%*s} else {\n", depth * 8, ""); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_printd(arg, fp, depth + 1); + (void) fprintf(fp, "%*s}\n", depth * 8, ""); + } + + break; + + default: + (void) fprintf(fp, "/* bad node %p, kind %d */\n", + (void *)dnp, dnp->dn_kind); + } +} + void dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) { @@ -4729,6 +4909,13 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) (void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf); dt_node_printr(dnp->dn_left, fp, depth + 1); dt_node_printr(dnp->dn_right, fp, depth + 1); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + dt_node_printr(ln->dn_list, fp, depth + 1); + ln = ln->dn_list; + } + } break; case DT_NODE_OP3: @@ -4790,6 +4977,7 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) dt_node_printr(arg, fp, depth + 1); + (void) fprintf(fp, "\n"); break; case DT_NODE_INLINE: @@ -4840,6 +5028,24 @@ dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) dt_node_printr(arg, fp, depth + 1); break; + case DT_NODE_IF: + (void) fprintf(fp, "IF attr=%s CONDITION:\n", a); + + dt_node_printr(dnp->dn_conditional, fp, depth + 1); + + (void) fprintf(fp, "%*sIF BODY: \n", depth * 2, ""); + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_node_printr(arg, fp, depth + 1); + + if (dnp->dn_alternate_body != NULL) { + (void) fprintf(fp, "%*sIF ELSE: \n", depth * 2, ""); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_node_printr(arg, fp, depth + 1); + } + + break; + default: (void) fprintf(fp, "\n", (void *)dnp, dnp->dn_kind); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h index 38f21c9f2e9e..3a146c5d2592 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h @@ -23,7 +23,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, 2016 by Delphix. All rights reserved. * Copyright (c) 2013 Joyent, Inc. All rights reserved. */ @@ -105,6 +105,12 @@ typedef struct dt_node { struct dt_node *_probes; /* list of probe nodes */ int _redecl; /* provider redeclared */ } _provider; + + struct { + struct dt_node *_conditional; + struct dt_node *_body; + struct dt_node *_alternate_body; + } _conditional; } dn_u; struct dt_node *dn_list; /* parse tree list link */ @@ -140,6 +146,11 @@ typedef struct dt_node { #define dn_provred dn_u._provider._redecl /* DT_NODE_PROVIDER */ #define dn_probes dn_u._provider._probes /* DT_NODE_PROVIDER */ +/* DT_NODE_IF: */ +#define dn_conditional dn_u._conditional._conditional +#define dn_body dn_u._conditional._body +#define dn_alternate_body dn_u._conditional._alternate_body + #define DT_NODE_FREE 0 /* unused node (waiting to be freed) */ #define DT_NODE_INT 1 /* integer value */ #define DT_NODE_STRING 2 /* string value */ @@ -162,6 +173,7 @@ typedef struct dt_node { #define DT_NODE_PROBE 19 /* probe definition */ #define DT_NODE_PROVIDER 20 /* provider definition */ #define DT_NODE_PROG 21 /* program translation unit */ +#define DT_NODE_IF 22 /* if statement */ #define DT_NF_SIGNED 0x01 /* data is a signed quantity (else unsigned) */ #define DT_NF_COOKED 0x02 /* data is a known type (else still cooking) */ @@ -213,6 +225,7 @@ extern dt_node_t *dt_node_xlator(dt_decl_t *, dt_decl_t *, char *, dt_node_t *); extern dt_node_t *dt_node_probe(char *, int, dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_provider(char *, dt_node_t *); extern dt_node_t *dt_node_program(dt_node_t *); +extern dt_node_t *dt_node_if(dt_node_t *, dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_link(dt_node_t *, dt_node_t *); extern dt_node_t *dt_node_cook(dt_node_t *, uint_t); @@ -237,6 +250,7 @@ extern void dt_node_promote(dt_node_t *, dt_node_t *, dt_node_t *); extern void dt_node_diftype(dtrace_hdl_t *, const dt_node_t *, dtrace_diftype_t *); extern void dt_node_printr(dt_node_t *, FILE *, int); +extern void dt_printd(dt_node_t *, FILE *, int); extern const char *dt_node_name(const dt_node_t *, char *, size_t); extern int dt_node_root(dt_node_t *); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_sugar.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_sugar.c new file mode 100644 index 000000000000..8bd052384d68 --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_sugar.c @@ -0,0 +1,516 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. + */ + +/* + * Syntactic sugar features are implemented by transforming the D parse tree + * such that it only uses the subset of D that is supported by the rest of the + * compiler / the kernel. A clause containing these language features is + * referred to as a "super-clause", and its transformation typically entails + * creating several "sub-clauses" to implement it. For diagnosability, the + * sub-clauses will be printed if the "-xtree=8" flag is specified. + * + * Currently, the only syntactic sugar feature is "if/else" statements. Each + * basic block (e.g. the body of the "if" and "else" statements, and the + * statements before and after) is turned into its own sub-clause, with a + * predicate that causes it to be executed only if the code flows to this point. + * Nested if/else statements are supported. + * + * This infrastructure is designed to accommodate other syntactic sugar features + * in the future. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct dt_sugar_parse { + dtrace_hdl_t *dtsp_dtp; /* dtrace handle */ + dt_node_t *dtsp_pdescs; /* probe descriptions */ + int dtsp_num_conditions; /* number of condition variables */ + int dtsp_num_ifs; /* number of "if" statements */ + dt_node_t *dtsp_clause_list; /* list of clauses */ +} dt_sugar_parse_t; + +static void dt_sugar_visit_stmts(dt_sugar_parse_t *, dt_node_t *, int); + +/* + * Return a node for "self->%error". + * + * Note that the "%" is part of the variable name, and is included so that + * this variable name can not collide with any user-specified variable. + * + * This error variable is used to keep track of if there has been an error + * in any of the sub-clauses, and is used to prevent execution of subsequent + * sub-clauses following an error. + */ +static dt_node_t * +dt_sugar_new_error_var(void) +{ + return (dt_node_op2(DT_TOK_PTR, dt_node_ident(strdup("self")), + dt_node_ident(strdup("%error")))); +} + +/* + * Append this clause to the clause list. + */ +static void +dt_sugar_append_clause(dt_sugar_parse_t *dp, dt_node_t *clause) +{ + dp->dtsp_clause_list = dt_node_link(dp->dtsp_clause_list, clause); +} + +/* + * Prepend this clause to the clause list. + */ +static void +dt_sugar_prepend_clause(dt_sugar_parse_t *dp, dt_node_t *clause) +{ + dp->dtsp_clause_list = dt_node_link(clause, dp->dtsp_clause_list); +} + +/* + * Return a node for "this->%condition_", or NULL if condid==0. + * + * Note that the "%" is part of the variable name, and is included so that + * this variable name can not collide with any user-specified variable. + */ +static dt_node_t * +dt_sugar_new_condition_var(int condid) +{ + char *str; + + if (condid == 0) + return (NULL); + assert(condid > 0); + + (void) asprintf(&str, "%%condition_%d", ABS(condid)); + return (dt_node_op2(DT_TOK_PTR, dt_node_ident(strdup("this")), + dt_node_ident(str))); +} + +/* + * Return new clause to evaluate predicate and set newcond. condid is + * the condition that we are already under, or 0 if none. + * The new clause will be of the form: + * + * dp_pdescs + * /!self->%error/ + * { + * this->%condition_ = + * (this->%condition_ && pred); + * } + * + * Note: if condid==0, we will instead do "... = (1 && pred)", to effectively + * convert the pred to a boolean. + * + * Note: Unless an error has been encountered, we always set the condition + * variable (either to 0 or 1). This lets us avoid resetting the condition + * variables back to 0 when the super-clause completes. + */ +static dt_node_t * +dt_sugar_new_condition_impl(dt_sugar_parse_t *dp, + dt_node_t *pred, int condid, int newcond) +{ + dt_node_t *value, *body, *newpred; + + /* predicate is !self->%error */ + newpred = dt_node_op1(DT_TOK_LNEG, dt_sugar_new_error_var()); + + if (condid == 0) { + /* + * value is (1 && pred) + * + * Note, D doesn't allow a probe-local "this" variable to + * be reused as a different type, even from a different probe. + * Therefore, value can't simply be , because then + * its type could be different when we reuse this condid + * in a different meta-clause. + */ + value = dt_node_op2(DT_TOK_LAND, dt_node_int(1), pred); + } else { + /* value is (this->%condition_ && pred) */ + value = dt_node_op2(DT_TOK_LAND, + dt_sugar_new_condition_var(condid), pred); + } + + /* body is "this->%condition_ = ;" */ + body = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_condition_var(newcond), value)); + + return (dt_node_clause(dp->dtsp_pdescs, newpred, body)); +} + +/* + * Generate a new clause to evaluate predicate and set a new condition variable, + * whose ID will be returned. The new clause will be appended to + * dp_first_new_clause. + */ +static int +dt_sugar_new_condition(dt_sugar_parse_t *dp, dt_node_t *pred, int condid) +{ + dp->dtsp_num_conditions++; + dt_sugar_append_clause(dp, dt_sugar_new_condition_impl(dp, + pred, condid, dp->dtsp_num_conditions)); + return (dp->dtsp_num_conditions); +} + +/* + * Visit the specified node and all of its descendants. Currently this is only + * used to count the number of "if" statements (dtsp_num_ifs). + */ +static void +dt_sugar_visit_all(dt_sugar_parse_t *dp, dt_node_t *dnp) +{ + dt_node_t *arg; + + switch (dnp->dn_kind) { + case DT_NODE_FREE: + case DT_NODE_INT: + case DT_NODE_STRING: + case DT_NODE_SYM: + case DT_NODE_TYPE: + case DT_NODE_PROBE: + case DT_NODE_PDESC: + case DT_NODE_IDENT: + break; + + case DT_NODE_FUNC: + for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_OP1: + dt_sugar_visit_all(dp, dnp->dn_child); + break; + + case DT_NODE_OP2: + dt_sugar_visit_all(dp, dnp->dn_left); + dt_sugar_visit_all(dp, dnp->dn_right); + if (dnp->dn_op == DT_TOK_LBRAC) { + dt_node_t *ln = dnp->dn_right; + while (ln->dn_list != NULL) { + dt_sugar_visit_all(dp, ln->dn_list); + ln = ln->dn_list; + } + } + break; + + case DT_NODE_OP3: + dt_sugar_visit_all(dp, dnp->dn_expr); + dt_sugar_visit_all(dp, dnp->dn_left); + dt_sugar_visit_all(dp, dnp->dn_right); + break; + + case DT_NODE_DEXPR: + case DT_NODE_DFUNC: + dt_sugar_visit_all(dp, dnp->dn_expr); + break; + + case DT_NODE_AGG: + for (arg = dnp->dn_aggtup; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + if (dnp->dn_aggfun) + dt_sugar_visit_all(dp, dnp->dn_aggfun); + break; + + case DT_NODE_CLAUSE: + for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + if (dnp->dn_pred != NULL) + dt_sugar_visit_all(dp, dnp->dn_pred); + + for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_INLINE: { + const dt_idnode_t *inp = dnp->dn_ident->di_iarg; + + dt_sugar_visit_all(dp, inp->din_root); + break; + } + case DT_NODE_MEMBER: + if (dnp->dn_membexpr) + dt_sugar_visit_all(dp, dnp->dn_membexpr); + break; + + case DT_NODE_XLATOR: + for (arg = dnp->dn_members; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_PROVIDER: + for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_PROG: + for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + break; + + case DT_NODE_IF: + dp->dtsp_num_ifs++; + dt_sugar_visit_all(dp, dnp->dn_conditional); + + for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + for (arg = dnp->dn_alternate_body; arg != NULL; + arg = arg->dn_list) + dt_sugar_visit_all(dp, arg); + + break; + + default: + (void) dnerror(dnp, D_UNKNOWN, "bad node %p, kind %d\n", + (void *)dnp, dnp->dn_kind); + } +} + +/* + * Return a new clause which resets the error variable to zero: + * + * dp_pdescs{ self->%error = 0; } + * + * This clause will be executed at the beginning of each meta-clause, to + * ensure the error variable is unset (in case the previous meta-clause + * failed). + */ +static dt_node_t * +dt_sugar_new_clearerror_clause(dt_sugar_parse_t *dp) +{ + dt_node_t *stmt = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_error_var(), dt_node_int(0))); + return (dt_node_clause(dp->dtsp_pdescs, NULL, stmt)); +} + +/* + * Evaluate the conditional, and recursively visit the body of the "if" + * statement (and the "else", if present). + */ +static void +dt_sugar_do_if(dt_sugar_parse_t *dp, dt_node_t *if_stmt, int precondition) +{ + int newid; + + assert(if_stmt->dn_kind == DT_NODE_IF); + + /* condition */ + newid = dt_sugar_new_condition(dp, + if_stmt->dn_conditional, precondition); + + /* body of if */ + dt_sugar_visit_stmts(dp, if_stmt->dn_body, newid); + + /* + * Visit the body of the "else" statement, if present. Note that we + * generate a new condition which is the inverse of the previous + * condition. + */ + if (if_stmt->dn_alternate_body != NULL) { + dt_node_t *pred = + dt_node_op1(DT_TOK_LNEG, dt_sugar_new_condition_var(newid)); + dt_sugar_visit_stmts(dp, if_stmt->dn_alternate_body, + dt_sugar_new_condition(dp, pred, precondition)); + } +} + +/* + * Generate a new clause to evaluate the statements based on the condition. + * The new clause will be appended to dp_first_new_clause. + * + * dp_pdescs + * /!self->%error && this->%condition_/ + * { + * stmts + * } + */ +static void +dt_sugar_new_basic_block(dt_sugar_parse_t *dp, int condid, dt_node_t *stmts) +{ + dt_node_t *pred = NULL; + + if (condid == 0) { + /* + * Don't bother with !error on the first clause, because if + * there is only one clause, we don't add the prelude to + * zero out %error. + */ + if (dp->dtsp_num_conditions != 0) { + pred = dt_node_op1(DT_TOK_LNEG, + dt_sugar_new_error_var()); + } + } else { + pred = dt_node_op2(DT_TOK_LAND, + dt_node_op1(DT_TOK_LNEG, dt_sugar_new_error_var()), + dt_sugar_new_condition_var(condid)); + } + dt_sugar_append_clause(dp, + dt_node_clause(dp->dtsp_pdescs, pred, stmts)); +} + +/* + * Visit all the statements in this list, and break them into basic blocks, + * generating new clauses for "if" and "else" statements. + */ +static void +dt_sugar_visit_stmts(dt_sugar_parse_t *dp, dt_node_t *stmts, int precondition) +{ + dt_node_t *stmt; + dt_node_t *prev_stmt = NULL; + dt_node_t *next_stmt; + dt_node_t *first_stmt_in_basic_block = NULL; + + for (stmt = stmts; stmt != NULL; stmt = next_stmt) { + next_stmt = stmt->dn_list; + + if (stmt->dn_kind != DT_NODE_IF) { + if (first_stmt_in_basic_block == NULL) + first_stmt_in_basic_block = stmt; + prev_stmt = stmt; + continue; + } + + /* + * Remove this and following statements from the previous + * clause. + */ + if (prev_stmt != NULL) + prev_stmt->dn_list = NULL; + + /* + * Generate clause for statements preceding the "if" + */ + if (first_stmt_in_basic_block != NULL) { + dt_sugar_new_basic_block(dp, precondition, + first_stmt_in_basic_block); + } + + dt_sugar_do_if(dp, stmt, precondition); + + first_stmt_in_basic_block = NULL; + + prev_stmt = stmt; + } + + /* generate clause for statements after last "if". */ + if (first_stmt_in_basic_block != NULL) { + dt_sugar_new_basic_block(dp, precondition, + first_stmt_in_basic_block); + } +} + +/* + * Generate a new clause which will set the error variable when an error occurs. + * Only one of these clauses is created per program (e.g. script file). + * The clause is: + * + * dtrace:::ERROR{ self->%error = 1; } + */ +static dt_node_t * +dt_sugar_makeerrorclause(void) +{ + dt_node_t *acts, *pdesc; + + pdesc = dt_node_pdesc_by_name(strdup("dtrace:::ERROR")); + + acts = dt_node_statement(dt_node_op2(DT_TOK_ASGN, + dt_sugar_new_error_var(), dt_node_int(1))); + + return (dt_node_clause(pdesc, NULL, acts)); +} + +/* + * Transform the super-clause into straight-D, returning the new list of + * sub-clauses. + */ +dt_node_t * +dt_compile_sugar(dtrace_hdl_t *dtp, dt_node_t *clause) +{ + dt_sugar_parse_t dp = { 0 }; + int condid = 0; + + dp.dtsp_dtp = dtp; + dp.dtsp_pdescs = clause->dn_pdescs; + + /* make dt_node_int() generate an "int"-typed integer */ + yyintdecimal = B_TRUE; + yyintsuffix[0] = '\0'; + yyintprefix = 0; + + dt_sugar_visit_all(&dp, clause); + + if (dp.dtsp_num_ifs == 0 && dp.dtsp_num_conditions == 0) { + /* + * There is nothing that modifies the number of clauses. Use + * the existing clause as-is, with its predicate intact. This + * ensures that in the absence of D sugar, the body of the + * clause can create a variable that is referenced in the + * predicate. + */ + dt_sugar_append_clause(&dp, dt_node_clause(clause->dn_pdescs, + clause->dn_pred, clause->dn_acts)); + } else { + if (clause->dn_pred != NULL) { + condid = dt_sugar_new_condition(&dp, + clause->dn_pred, condid); + } + + if (clause->dn_acts == NULL) { + /* + * dt_sugar_visit_stmts() does not emit a clause with + * an empty body (e.g. if there's an empty "if" body), + * but we need the empty body here so that we + * continue to get the default tracing action. + */ + dt_sugar_new_basic_block(&dp, condid, NULL); + } else { + dt_sugar_visit_stmts(&dp, clause->dn_acts, condid); + } + } + + if (dp.dtsp_num_conditions != 0) { + dt_sugar_prepend_clause(&dp, + dt_sugar_new_clearerror_clause(&dp)); + } + + if (dp.dtsp_clause_list != NULL && + dp.dtsp_clause_list->dn_list != NULL && !dtp->dt_has_sugar) { + dtp->dt_has_sugar = B_TRUE; + dt_sugar_prepend_clause(&dp, dt_sugar_makeerrorclause()); + } + return (dp.dtsp_clause_list); +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h index f0088a939cb0..f0bc83a7fc7b 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2014, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -59,6 +59,7 @@ extern "C" { #define DTRACE_VERSION 3 /* library ABI interface version */ struct ps_prochandle; +struct dt_node; typedef struct dtrace_hdl dtrace_hdl_t; typedef struct dtrace_prog dtrace_prog_t; typedef struct dtrace_vector dtrace_vector_t; @@ -115,7 +116,7 @@ typedef struct dtrace_proginfo { #define DTRACE_C_CPP 0x0010 /* Preprocess input file with cpp(1) utility */ #define DTRACE_C_KNODEF 0x0020 /* Permit unresolved kernel symbols in DIFO */ #define DTRACE_C_UNODEF 0x0040 /* Permit unresolved user symbols in DIFO */ -#define DTRACE_C_PSPEC 0x0080 /* Intepret ambiguous specifiers as probes */ +#define DTRACE_C_PSPEC 0x0080 /* Interpret ambiguous specifiers as probes */ #define DTRACE_C_ETAGS 0x0100 /* Prefix error messages with error tags */ #define DTRACE_C_ARGREF 0x0200 /* Do not require all macro args to be used */ #define DTRACE_C_DEFARG 0x0800 /* Use 0/"" as value for unspecified args */ @@ -523,6 +524,10 @@ extern int dtrace_type_strcompile(dtrace_hdl_t *, extern int dtrace_type_fcompile(dtrace_hdl_t *, FILE *, dtrace_typeinfo_t *); +extern struct dt_node *dt_compile_sugar(dtrace_hdl_t *, + struct dt_node *); + + /* * DTrace Probe Interface * diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index 080865c44bab..83a93cf0cb50 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -42,6 +42,7 @@ SRCS= dt_aggregate.c \ dt_string.c \ dt_strtab.c \ dt_subr.c \ + dt_sugar.c \ dt_work.c \ dt_xlator.c \ gmatch.c diff --git a/cddl/usr.sbin/dtrace/tests/common/Makefile b/cddl/usr.sbin/dtrace/tests/common/Makefile index 7c7bb1718d05..4c0ad4b50bdb 100644 --- a/cddl/usr.sbin/dtrace/tests/common/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/Makefile @@ -69,6 +69,7 @@ TESTS_SUBDIRS+= aggs \ strlen \ strtoll \ struct \ + sugar \ syscall \ tick-n \ trace \ diff --git a/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile b/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile index 8a08eac05375..9f019068da35 100644 --- a/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/scalars/Makefile @@ -18,6 +18,8 @@ ${PACKAGE}FILES= \ err.D_SYNTAX.declare.d \ err.bigglobal.d \ err.biglocal.d \ + tst.16kglobal.d \ + tst.16klocal.d \ tst.basicvar.d \ tst.basicvar.d.out \ tst.localvar.d \ diff --git a/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile b/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile new file mode 100644 index 000000000000..40fc86a45ce0 --- /dev/null +++ b/cddl/usr.sbin/dtrace/tests/common/sugar/Makefile @@ -0,0 +1,25 @@ +# $FreeBSD$ + +# +# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh. +# + +PACKAGE= tests + +${PACKAGE}FILES= \ + tst.else.d \ + tst.if.d \ + tst.if2.d \ + tst.if_before_after.d \ + tst.if_nested.d \ + tst.if_trailing_semicolon.d \ + tst.if_trailing_semicolon2.d \ + +TESTEXES= \ + + +CFILES= \ + + + +.include "../../dtrace.test.mk" diff --git a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh index 33c9efca0f45..38180da97c69 100755 --- a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh +++ b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh @@ -27,7 +27,6 @@ exclude() } exclude EXFAIL common/aggs/tst.subr.d -exclude EXFAIL common/dtraceUtil/tst.DataModel32.d.ksh exclude EXFAIL common/dtraceUtil/tst.ELFGenerationOut.d.ksh exclude EXFAIL common/dtraceUtil/tst.ELFGenerationWithO.d.ksh exclude EXFAIL common/funcs/tst.copyin.d diff --git a/contrib/elftoolchain/elfcopy/ascii.c b/contrib/elftoolchain/elfcopy/ascii.c index fb1edb3cce46..6adecf8d347a 100644 --- a/contrib/elftoolchain/elfcopy/ascii.c +++ b/contrib/elftoolchain/elfcopy/ascii.c @@ -251,6 +251,7 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd) sec_index = 1; sec_addr = entry = 0; while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { + sz = 0; /* Silence GCC 5.3 uninitialized variable warning */ if (line[0] == '\r' || line[0] == '\n') continue; if (line[0] == '$' && line[1] == '$') { diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 index 20dea3cb97d9..c340c0c5b68d 100644 --- a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 +++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 @@ -89,6 +89,7 @@ Known descriptor names and their properties include: .It Li elf64-ia64-big Ta ELF Ta MSB Ta 64 .It Li elf64-ia64-little Ta ELF Ta LSB Ta 64 .It Li elf64-little Ta ELF Ta LSB Ta 64 +.It Li elf64-littleaarch64 Ta ELF Ta LSB Ta 64 .It Li elf64-littlemips Ta ELF Ta LSB Ta 64 .It Li elf64-powerpc Ta ELF Ta MSB Ta 64 .It Li elf64-powerpcle Ta ELF Ta LSB Ta 64 diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c index 88f3220df0b0..d6a031e73090 100644 --- a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c +++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c @@ -249,6 +249,14 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = { .bt_elfclass = ELFCLASS64, }, + { + .bt_name = "elf64-littleaarch64", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_AARCH64, + }, + { .bt_name = "elf64-littlemips", .bt_type = ETF_ELF, diff --git a/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c b/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c index 6c82cb471c27..184e660cc017 100644 --- a/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c +++ b/contrib/netbsd-tests/lib/libc/gen/t_basedirname.c @@ -111,6 +111,7 @@ ATF_TC_BODY(basename_posix, tc) } else base = basename(NULL); +#ifdef __NetBSD__ /* * basename(3) is allowed to modify the input buffer. * However, that is considered hostile by some programs, @@ -127,6 +128,7 @@ ATF_TC_BODY(basename_posix, tc) test_basename_table[i].input); atf_tc_fail("Input buffer was modified."); } +#endif /* Make sure the result is correct. */ if (strcmp(test_basename_table[i].output, base) != 0) { @@ -162,6 +164,7 @@ ATF_TC_BODY(dirname_posix, tc) } else base = dirname(NULL); +#ifdef __NetBSD__ /* * dirname(3) is allowed to modify the input buffer. * However, that is considered hostile by some programs, @@ -178,6 +181,7 @@ ATF_TC_BODY(dirname_posix, tc) test_dirname_table[i].input); atf_tc_fail("Input buffer was modified."); } +#endif /* Make sure the result is correct. */ if (strcmp(test_dirname_table[i].output, base) != 0) { diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 1f45fcd3c76a..27d52ca85568 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -183,6 +183,8 @@ .. struct .. + sugar + .. syscall .. sysevent diff --git a/etc/periodic/daily/480.leapfile-ntpd b/etc/periodic/daily/480.leapfile-ntpd index 5a3ccceadf07..8a3836427b4e 100755 --- a/etc/periodic/daily/480.leapfile-ntpd +++ b/etc/periodic/daily/480.leapfile-ntpd @@ -16,7 +16,7 @@ case "$daily_ntpd_leapfile_enable" in case "$daily_ntpd_avoid_congestion" in [Yy][Ee][Ss]) # Avoid dogpiling - (sleep $(jot -r 1 0 86400); service ntpd onefetch) & + (sleep $(jot -r 1 0 3600); service ntpd onefetch) & ;; *) service ntpd onefetch diff --git a/include/string.h b/include/string.h index af8b0d46c86c..9fe1f826d9cd 100644 --- a/include/string.h +++ b/include/string.h @@ -134,6 +134,8 @@ typedef __ssize_t ssize_t; void swab(const void * __restrict, void * __restrict, ssize_t); #endif /* _SWAB_DECLARED */ +int timingsafe_bcmp(const void *, const void *, size_t); +int timingsafe_memcmp(const void *, const void *, size_t); #endif /* __BSD_VISIBLE */ #if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) diff --git a/include/unistd.h b/include/unistd.h index 0fb36e50e050..eab79f20eb7d 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -384,6 +384,7 @@ extern int optind, opterr, optopt; /* ISO/IEC 9945-1: 1996 */ #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE int fsync(int); +int fdatasync(int); /* * ftruncate() was in the POSIX Realtime Extension (it's used for shared diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 8c4d72d14093..cf346f1367f0 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -228,6 +228,7 @@ enum { INTERPOS_wait6, INTERPOS_ppoll, INTERPOS_map_stacks_exec, + INTERPOS_fdatasync, INTERPOS_MAX }; @@ -318,6 +319,7 @@ int __sys_clock_gettime(__clockid_t, struct timespec *ts); int __sys_close(int); int __sys_connect(int, const struct sockaddr *, __socklen_t); int __sys_fcntl(int, int, ...); +int __sys_fdatasync(int); int __sys_fsync(int); __pid_t __sys_fork(void); int __sys_ftruncate(int, __off_t); diff --git a/lib/libc/net/nss_compat.c b/lib/libc/net/nss_compat.c index ba1e95198ced..be2f75762bc2 100644 --- a/lib/libc/net/nss_compat.c +++ b/lib/libc/net/nss_compat.c @@ -97,9 +97,9 @@ __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) const char *name; struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; name = va_arg(ap, const char *); @@ -107,11 +107,11 @@ __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(name, grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(name, grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - return (status); + return (ns_status); } @@ -122,9 +122,9 @@ __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) gid_t gid; struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; gid = va_arg(ap, gid_t); @@ -132,11 +132,11 @@ __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(gid, grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(gid, grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - return (status); + return (ns_status); } @@ -146,9 +146,9 @@ __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) int (*fn)(struct group *, char *, size_t, int *); struct group *grp; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; if (CHECK_TERMINATOR(group)) return (NS_NOTFOUND); @@ -157,13 +157,13 @@ __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(grp, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(grp, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct group **)retval = grp; - else if (status != NS_RETURN) + else if (ns_status != NS_RETURN) SET_TERMINATOR(group, &terminator); - return (status); + return (ns_status); } @@ -198,9 +198,9 @@ __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) const char *name; struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; name = va_arg(ap, const char *); @@ -208,11 +208,11 @@ __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(name, pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(name, pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - return (status); + return (ns_status); } @@ -223,9 +223,9 @@ __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) uid_t uid; struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; fn = mdata; uid = va_arg(ap, uid_t); @@ -233,11 +233,11 @@ __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(uid, pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(uid, pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - return (status); + return (ns_status); } @@ -247,9 +247,9 @@ __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) int (*fn)(struct passwd *, char *, size_t, int *); struct passwd *pwd; char *buffer; - int *errnop; + int *errnop, ns_status; size_t bufsize; - enum nss_status status; + enum nss_status nss_status; if (CHECK_TERMINATOR(passwd)) return (NS_NOTFOUND); @@ -258,13 +258,13 @@ __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); - status = fn(pwd, buffer, bufsize, errnop); - status = __nss_compat_result(status, *errnop); - if (status == NS_SUCCESS) + nss_status = fn(pwd, buffer, bufsize, errnop); + ns_status = __nss_compat_result(nss_status, *errnop); + if (ns_status == NS_SUCCESS) *(struct passwd **)retval = pwd; - else if (status != NS_RETURN) + else if (ns_status != NS_RETURN) SET_TERMINATOR(passwd, &terminator); - return (status); + return (ns_status); } diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc index 1217b7bc82d2..7b2b9b734808 100644 --- a/lib/libc/string/Makefile.inc +++ b/lib/libc/string/Makefile.inc @@ -16,7 +16,10 @@ MISRCS+=bcmp.c bcopy.c bzero.c explicit_bzero.c \ strcspn.c strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c \ strncat.c strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \ strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \ - strxfrm.c swab.c wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \ + strxfrm.c swab.c \ + timingsafe_bcmp.c \ + timingsafe_memcmp.c \ + wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \ wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \ wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.c wcsncat.c wcsncmp.c \ wcsncpy.c wcsnlen.c wcspbrk.c \ @@ -34,7 +37,9 @@ MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \ memcmp.3 memcpy.3 memmem.3 memmove.3 memset.3 strcasecmp.3 strcat.3 \ strchr.3 strcmp.3 strcoll.3 strcpy.3 strdup.3 strerror.3 \ string.3 strlcpy.3 strlen.3 strmode.3 strpbrk.3 strsep.3 \ - strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \ + strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 \ + timingsafe_bcmp.3 \ + wcscoll.3 wcstok.3 \ wcswidth.3 wcsxfrm.3 wmemchr.3 MLINKS+=bzero.3 explicit_bzero.3 @@ -69,6 +74,7 @@ MLINKS+=strstr.3 strcasestr.3 \ strstr.3 strcasestr_l.3 MLINKS+=strtok.3 strtok_r.3 MLINKS+=strxfrm.3 strxfrm_l.3 +MLINKS+=timingsafe_bcmp.3 timingsafe_memcmp.3 MLINKS+=wmemchr.3 wcpcpy.3 \ wmemchr.3 wcpncpy.3 \ wmemchr.3 wcscasecmp.3 \ diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map index 59610925fe33..cbf80cf9751c 100644 --- a/lib/libc/string/Symbol.map +++ b/lib/libc/string/Symbol.map @@ -104,6 +104,11 @@ FBSD_1.4 { explicit_bzero; }; +FBSD_1.5 { + timingsafe_bcmp; + timingsafe_memcmp; +}; + FBSDprivate_1.0 { __strtok_r; }; diff --git a/lib/libc/string/bcmp.3 b/lib/libc/string/bcmp.3 index fa5666c57ea0..e2d4063a1654 100644 --- a/lib/libc/string/bcmp.3 +++ b/lib/libc/string/bcmp.3 @@ -30,7 +30,7 @@ .\" @(#)bcmp.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd August 15, 2016 .Dt BCMP 3 .Os .Sh NAME @@ -62,7 +62,8 @@ The strings may overlap. .Xr strcasecmp 3 , .Xr strcmp 3 , .Xr strcoll 3 , -.Xr strxfrm 3 +.Xr strxfrm 3 , +.Xr timingsafe_bcmp 3 .Sh HISTORY A .Fn bcmp diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3 index 00e8e1a1d759..245e2abe1d71 100644 --- a/lib/libc/string/memcmp.3 +++ b/lib/libc/string/memcmp.3 @@ -32,7 +32,7 @@ .\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd August 15, 2016 .Dt MEMCMP 3 .Os .Sh NAME @@ -75,6 +75,7 @@ Zero-length strings are always identical. .Xr strcmp 3 , .Xr strcoll 3 , .Xr strxfrm 3 , +.Xr timingsafe_memcmp 3 , .Xr wmemcmp 3 .Sh STANDARDS The diff --git a/lib/libc/string/timingsafe_bcmp.3 b/lib/libc/string/timingsafe_bcmp.3 new file mode 100644 index 000000000000..502e57176806 --- /dev/null +++ b/lib/libc/string/timingsafe_bcmp.3 @@ -0,0 +1,92 @@ +.\" $OpenBSD: timingsafe_bcmp.3,v 1.2 2014/06/21 20:22:15 tedu Exp $ +.\" +.\" Copyright (c) 2014 Google Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $FreeBSD$ +.Dd August 15, 2016 +.Dt TIMINGSAFE_BCMP 3 +.Os +.Sh NAME +.Nm timingsafe_bcmp , +.Nm timingsafe_memcmp +.Nd timing-safe byte sequence comparisons +.Sh SYNOPSIS +.In string.h +.Ft int +.Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len" +.Ft int +.Fn timingsafe_memcmp "const void *b1" "const void *b2" "size_t len" +.Sh DESCRIPTION +The +.Fn timingsafe_bcmp +and +.Fn timingsafe_memcmp +functions lexicographically compare the first +.Fa len +bytes (each interpreted as an +.Vt unsigned char ) +pointed to by +.Fa b1 +and +.Fa b2 . +.Pp +Additionally, their running times are independent of the byte sequences compared, +making them safe to use for comparing secret values such as cryptographic MACs. +In contrast, +.Xr bcmp 3 +and +.Xr memcmp 3 +may short-circuit after finding the first differing byte. +.Sh RETURN VALUES +The +.Fn timingsafe_bcmp +function returns 0 or not zero if the byte sequence pointed to by +.Fa b1 +compares equal to or not equal to (respectively) +the byte sequence pointed to by +.Fa b2 . +.Pp +The +.Fn timingsafe_memcmp +function returns a negative value, 0, or positive value if the byte sequence +pointed to by +.Fa b1 +compares less than, equal to, or greater than (respectively) +the byte sequence pointed to by +.Fa b2 . +.Sh SEE ALSO +.Xr bcmp 3 , +.Xr memcmp 3 +.Sh STANDARDS +The +.Fn timingsafe_bcmp +and +.Fn timingsafe_memcmp +functions are +.Fx +extensions. +.Sh HISTORY +The +.Fn timingsafe_bcmp +function first appeared in +.Ox 4.9 . +.Pp +The +.Fn timingsafe_memcmp +function first appeared in +.Ox 5.6 . +.Pp +Both functions first appeared in +.Fx 12.0 . diff --git a/lib/libc/string/timingsafe_bcmp.c b/lib/libc/string/timingsafe_bcmp.c new file mode 100644 index 000000000000..d098158059f3 --- /dev/null +++ b/lib/libc/string/timingsafe_bcmp.c @@ -0,0 +1,36 @@ +/* $OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $ */ +/* + * Copyright (c) 2010 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +int __timingsafe_bcmp(const void *, const void *, size_t); + +int +__timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ + const unsigned char *p1 = b1, *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +} + +__weak_reference(__timingsafe_bcmp, timingsafe_bcmp); diff --git a/lib/libc/string/timingsafe_memcmp.c b/lib/libc/string/timingsafe_memcmp.c new file mode 100644 index 000000000000..7abfb48045f8 --- /dev/null +++ b/lib/libc/string/timingsafe_memcmp.c @@ -0,0 +1,53 @@ +/* $OpenBSD: timingsafe_memcmp.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +int __timingsafe_memcmp(const void *, const void *, size_t); + +int +__timingsafe_memcmp(const void *b1, const void *b2, size_t len) +{ + const unsigned char *p1 = b1, *p2 = b2; + size_t i; + int res = 0, done = 0; + + for (i = 0; i < len; i++) { + /* lt is -1 if p1[i] < p2[i]; else 0. */ + int lt = (p1[i] - p2[i]) >> CHAR_BIT; + + /* gt is -1 if p1[i] > p2[i]; else 0. */ + int gt = (p2[i] - p1[i]) >> CHAR_BIT; + + /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ + int cmp = lt - gt; + + /* set res = cmp if !done. */ + res |= cmp & ~done; + + /* set done if p1[i] != p2[i]. */ + done |= lt | gt; + } + + return (res); +} + +__weak_reference(__timingsafe_memcmp, timingsafe_memcmp); diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index a2be249e7e62..a37c5661c720 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -37,6 +37,7 @@ INTERPOSED = \ close \ connect \ fcntl \ + fdatasync \ fsync \ fork \ kevent \ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index c1532ac94bc4..312b3660cfdc 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -400,6 +400,10 @@ FBSD_1.4 { recvmmsg; }; +FBSD_1.5 { + fdatasync; +}; + FBSDprivate_1.0 { ___acl_aclcheck_fd; __sys___acl_aclcheck_fd; @@ -594,6 +598,8 @@ FBSDprivate_1.0 { __sys_fstatfs; _fsync; __sys_fsync; + _fdatasync; + __sys_fdatasync; _futimes; __sys_futimes; _getaudit; diff --git a/lib/libc/sys/fdatasync.c b/lib/libc/sys/fdatasync.c new file mode 100644 index 000000000000..fed97913d31e --- /dev/null +++ b/lib/libc/sys/fdatasync.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 The FreeBSD Foundation. + * All rights reserved. + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "libc_private.h" + +int +fdatasync(int fd) +{ + + return (((int (*)(int))__libc_interposing[INTERPOS_fdatasync])(fd)); +} diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c index 75bb2804b759..1447e42ef238 100644 --- a/lib/libc/sys/interposing_table.c +++ b/lib/libc/sys/interposing_table.c @@ -79,6 +79,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = { SLOT(wait6, __sys_wait6), SLOT(ppoll, __sys_ppoll), SLOT(map_stacks_exec, __libc_map_stacks_exec), + SLOT(fdatasync, __sys_fdatasync), }; #undef SLOT diff --git a/lib/libthr/arch/mips/include/pthread_md.h b/lib/libthr/arch/mips/include/pthread_md.h index 47c178b02a40..d27ecf073056 100644 --- a/lib/libthr/arch/mips/include/pthread_md.h +++ b/lib/libthr/arch/mips/include/pthread_md.h @@ -84,7 +84,7 @@ _tcb_get(void) ".set\tmips64r2\n\t" "rdhwr\t%0, $29\n\t" ".set\tpop" - : "=v" (_rv)); + : "=r" (_rv)); /* * XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' @@ -106,7 +106,7 @@ _tcb_get(void) ".set\tmips32r2\n\t" "rdhwr\t%0, $29\n\t" ".set\tpop" - : "=v" (_rv)); + : "=r" (_rv)); /* * XXXSS See 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 712249b1e573..362826ca2f91 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -227,6 +227,20 @@ __thr_fsync(int fd) return (ret); } +static int +__thr_fdatasync(int fd) +{ + struct pthread *curthread; + int ret; + + curthread = _get_curthread(); + _thr_cancel_enter2(curthread, 0); + ret = __sys_fdatasync(fd); + _thr_cancel_leave(curthread, 1); + + return (ret); +} + /* * Cancellation behavior: * Thread may be canceled after system call. @@ -653,6 +667,7 @@ __thr_interpose_libc(void) SLOT(wait6); SLOT(ppoll); SLOT(map_stacks_exec); + SLOT(fdatasync); #undef SLOT *(__libc_interposing_slot( INTERPOS__pthread_mutex_init_calloc_cb)) = diff --git a/share/man/man3/pthread_testcancel.3 b/share/man/man3/pthread_testcancel.3 index fc412de5b1ae..1dfc96483445 100644 --- a/share/man/man3/pthread_testcancel.3 +++ b/share/man/man3/pthread_testcancel.3 @@ -1,5 +1,5 @@ .\" $FreeBSD$ -.Dd April 16, 2015 +.Dd August 16, 2016 .Dt PTHREAD_TESTCANCEL 3 .Os .Sh NAME @@ -114,6 +114,7 @@ function is a cancellation point if .Fa cmd is .Dv F_SETLKW . +.It Fn fdatasync .It Fn fsync .It Fn kevent The diff --git a/share/man/man3/queue.3 b/share/man/man3/queue.3 index 87cfc8bd6ea9..1023c65a5640 100644 --- a/share/man/man3/queue.3 +++ b/share/man/man3/queue.3 @@ -28,12 +28,13 @@ .\" @(#)queue.3 8.2 (Berkeley) 1/24/94 .\" $FreeBSD$ .\" -.Dd June 24, 2015 +.Dd August 15, 2016 .Dt QUEUE 3 .Os .Sh NAME .Nm SLIST_CLASS_ENTRY , .Nm SLIST_CLASS_HEAD , +.Nm SLIST_CONCAT , .Nm SLIST_EMPTY , .Nm SLIST_ENTRY , .Nm SLIST_FIRST , @@ -75,6 +76,7 @@ .Nm STAILQ_SWAP , .Nm LIST_CLASS_ENTRY , .Nm LIST_CLASS_HEAD , +.Nm LIST_CONCAT , .Nm LIST_EMPTY , .Nm LIST_ENTRY , .Nm LIST_FIRST , @@ -125,6 +127,7 @@ lists and tail queues .\" .Fn SLIST_CLASS_ENTRY "CLASSTYPE" .Fn SLIST_CLASS_HEAD "HEADNAME" "CLASSTYPE" +.Fn SLIST_CONCAT "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE" "SLIST_ENTRY NAME" .Fn SLIST_EMPTY "SLIST_HEAD *head" .Fn SLIST_ENTRY "TYPE" .Fn SLIST_FIRST "SLIST_HEAD *head" @@ -168,6 +171,7 @@ lists and tail queues .\" .Fn LIST_CLASS_ENTRY "CLASSTYPE" .Fn LIST_CLASS_HEAD "HEADNAME" "CLASSTYPE" +.Fn LIST_CONCAT "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME" .Fn LIST_EMPTY "LIST_HEAD *head" .Fn LIST_ENTRY "TYPE" .Fn LIST_FIRST "LIST_HEAD *head" @@ -249,6 +253,8 @@ Singly-linked lists add the following functionality: .Bl -enum -compact -offset indent .It O(n) removal of any entry in the list. +.It +O(n) concatenation of two lists. .El .Pp Singly-linked tail queues add the following functionality: @@ -296,6 +302,8 @@ Linked lists are the simplest of the doubly linked data structures. They add the following functionality over the above: .Bl -enum -compact -offset indent .It +O(n) concatenation of two lists. +.It They may be traversed backwards. .El However: @@ -401,6 +409,19 @@ evaluates to an initializer for the list .Fa head . .Pp The macro +.Nm SLIST_CONCAT +concatenates the list headed by +.Fa head2 +onto the end of the one headed by +.Fa head1 +removing all entries from the former. +Use of this macro should be avoided as it traverses the entirety of the +.Fa head1 +list. +A singly-linked tail queue should be used if this macro is needed in +high-usage code paths or to operate on long lists. +.Pp +The macro .Nm SLIST_EMPTY evaluates to true if there are no elements in the list. .Pp @@ -508,6 +529,9 @@ The macro removes the element .Fa elm from the list. +Use of this macro should be avoided as it traverses the entire list. +A doubly-linked list should be used if this macro is needed in +high-usage code paths or to operate on long lists. .Pp The macro .Nm SLIST_SWAP @@ -724,6 +748,9 @@ The macro removes the element .Fa elm from the tail queue. +Use of this macro should be avoided as it traverses the entire list. +A doubly-linked tail queue should be used if this macro is needed in +high-usage code paths or to operate on long tail queues. .Pp The macro .Nm STAILQ_SWAP @@ -823,6 +850,19 @@ evaluates to an initializer for the list .Fa head . .Pp The macro +.Nm LIST_CONCAT +concatenates the list headed by +.Fa head2 +onto the end of the one headed by +.Fa head1 +removing all entries from the former. +Use of this macro should be avoided as it traverses the entirety of the +.Fa head1 +list. +A tail queue should be used if this macro is needed in +high-usage code paths or to operate on long lists. +.Pp +The macro .Nm LIST_EMPTY evaluates to true if there are no elements in the list. .Pp diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 1cd099b0b5a4..e85e531aa802 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -269,7 +269,6 @@ MAN= aac.4 \ mac_stub.4 \ mac_test.4 \ malo.4 \ - mcd.4 \ md.4 \ mdio.4 \ me.4 \ diff --git a/share/man/man4/mcd.4 b/share/man/man4/mcd.4 deleted file mode 100644 index 3a79eee41799..000000000000 --- a/share/man/man4/mcd.4 +++ /dev/null @@ -1,165 +0,0 @@ -.\" -.\" Copyright (c) 1994 Keith E. Walker -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd December 8, 1994 -.Dt MCD 4 -.Os -.Sh NAME -.Nm mcd -.Nd Mitsumi CD-ROM driver -.Sh SYNOPSIS -.Cd "device mcd" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.mcd.0.at="isa" -.Cd hint.mcd.0.port="0x300" -.Cd hint.mcd.0.irq="10" -.Sh DESCRIPTION -The -.Nm -driver provides a data and audio interface to the Mitsumi-brand CD-ROM -player. -The CD-ROM player must be interfaced to the ISA bus through -one of the Mitsumi proprietary controller boards. -The controller -boards supported are the LU002S, LU005S, the FX001 and the quite -common FX001D. -.Pp -The -.Nm -driver responds to disk-specific -.Fn ioctl -commands, namely the -.Dv DIOCGPART -command. -Other disk-specific -.Fn ioctl -commands will return an error. -.Pp -The -.Nm -driver also responds to special CD-ROM -.Fn ioctl -commands. -These commands -control the CD-ROM player's audio features. -The commands are: -.Pp -.Bl -tag -width CDIOCREADSUBCHANNEL -compact -offset indent -.It CDIOCREADSUBCHANNEL -get sub-channel information on current status of disc playing -.It CDIOCREADTOCHEADER -get table of contents header -.It CDIOCREADTOCENTRYS -gets all of the table of contents -.It CDIOCPLAYTRACKS -begins audio playing at location specified -.It CDIOCPLAYBLOCKS -fails with error -.Er EINVAL -.It CDIOCPLAYMSF -begins audio playing at location specified -.It CDIOCRESUME -resumes playing a previously paused disc -.It CDIOCPAUSE -pauses a playing disc -.It CDIOCSTART -begins playing a disc -.It CDIOCSTOP -stops a previously playing disc -.It CDIOCEJECT -opens the disc tray (there is no support for a corresponding un-eject -command). -.It CDIOCRESET -stops any play and resets the Mitsumi controller board -.It CDIOCSETDEBUG -cause the kernel to print debug messages to the console about the -.Nm -driver -.It CDIOCCLRDEBUG -cause the kernel to quit printing debug messages about the -.Nm -driver -.El -.Pp -The -.Fn ioctl -commands defined above are the only ones that the -.Nm -driver supports. -There are other CD-ROM related -.Fn ioctl -commands (such as -.Dv CDIOCSETVOL -and -.Dv CDIOCSETSTERIO ) -which are available -and may be supported by future versions of the driver. -.Sh FILES -.Bl -tag -width /dev/(r)mcd0a -compact -.It Pa /dev/(r)mcd0a -accesses -.Bx -partition on the disc. -Normally, there is only -one file system on a CD-ROM disc. -.It Pa /dev/(r)mcd0c -accesses raw device. -.El -.Sh NOTES -The character-mode devices for the -.Nm -driver should only be used for accessing the audio features of the -CD-ROM player as the performance on data is abysmal. -.Pp -The current version of the driver uses neither the DMA or IRQ -features of the interface board, although it has an interrupt handler -for any IRQ requests that are generated. -Until the DMA features are -supported, the only interrupts that the board generates are those that -are not supported by the driver anyway. -.Sh SEE ALSO -.In sys/cdio.h -.Sh HISTORY -An -.Nm -driver appeared in -.Fx 1.0 . -.Sh AUTHORS -.An -nosplit -The driver was written by -.An Holger Veit -(data part) and -.An Brian Moore -(audio part). -Changes were provided by -.An Gary Clark II , -.An Andrew A. Chernov , -and -.An Jordan K. Hubbard . diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index f275a4da45f9..54f503f5c2c8 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -633,7 +633,8 @@ when trying to use a TCP function block that is not available; .Xr mod_cc 4 , .Xr siftr 4 , .Xr syncache 4 , -.Xr setkey 8 +.Xr setkey 8 , +.Xr tcp_functions 9 .Rs .%A "V. Jacobson" .%A "R. Braden" diff --git a/share/man/man9/tcp_functions.9 b/share/man/man9/tcp_functions.9 index 06c42ff0fa60..b998dd0dd7df 100644 --- a/share/man/man9/tcp_functions.9 +++ b/share/man/man9/tcp_functions.9 @@ -114,14 +114,17 @@ struct tcp_function_block { struct inpcb *inp, struct tcpcb *tp); /* Optional memory allocation/free routine */ void (*tfb_tcp_fb_init)(struct tcpcb *); - void (*tfb_tcp_fb_fini)(struct tcpcb *); + void (*tfb_tcp_fb_fini)(struct tcpcb *, int); /* Optional timers, must define all if you define one */ int (*tfb_tcp_timer_stop_all)(struct tcpcb *); void (*tfb_tcp_timer_activate)(struct tcpcb *, uint32_t, u_int); int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); + /* Optional functions */ void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); + void (*tfb_tcp_handoff_ok)(struct tcpcb *); + /* System use */ volatile uint32_t tfb_refcnt; uint32_t tfb_flags; }; @@ -157,6 +160,16 @@ in the .Va tfb_tcp_fb_fini field. .Pp +If the +.Va tfb_tcp_fb_fini +argument is non-NULL, the function to which it points is called when the +kernel is destroying the TCP control block or when the socket is transitioning +to use a different TCP stack. +The function is called with arguments of the TCP control block and an integer +flag. +The flag will be zero if the socket is transitioning to use another TCP stack +or one if the TCP control block is being destroyed. +.Pp If the TCP stack implements additional timers, the TCP stack should set a non-NULL pointer in the .Va tfb_tcp_timer_stop_all , @@ -193,6 +206,37 @@ However, care must be taken to ensure the retransmit timer leaves the TCP control block in a valid state for the remainder of the retransmit timer logic. .Pp +A user may select a new TCP stack before calling +.Xr connect 2 +or +.Xr listen 2 . +Optionally, a TCP stack may also allow a user to begin using the TCP stack for +a connection that is in a later state by setting a non-NULL function pointer in +the +.Va tfb_tcp_handoff_ok +field. +If this field is non-NULL and a user attempts to select that TCP stack after +calling +.Xr connect 2 +or +.Xr listen 2 +for that socket, the kernel will call the function pointed to by the +.Va tfb_tcp_handoff_ok +field. +The function should return 0 if the user is allowed to switch the socket to use +the TCP stack. Otherwise, the function should return an error code, which will +be returned to the user. +If the +.Va tfb_tcp_handoff_ok +field is +.Dv NULL +and a user attempts to select the TCP stack after calling +.Xr connect 2 +or +.Xr listen 2 +for that socket, the operation will fail and the kernel will return +.Er EINVAL . +.Pp The .Va tfb_refcnt and @@ -269,8 +313,10 @@ The .Fa blk argument references a function block that is not currently registered. .Sh SEE ALSO -.Xr malloc 9 , -.Xr tcp 4 +.Xr connect 2 , +.Xr listen 2 , +.Xr tcp 4 , +.Xr malloc 9 .Sh HISTORY This framework first appeared in .Fx 11.0 . diff --git a/share/timedef/ko_KR.UTF-8.src b/share/timedef/ko_KR.UTF-8.src index 6623233d6e74..98e512a7761e 100644 --- a/share/timedef/ko_KR.UTF-8.src +++ b/share/timedef/ko_KR.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1ì›” - 2ì›” - 3ì›” - 4ì›” - 5ì›” - 6ì›” - 7ì›” - 8ì›” - 9ì›” -10ì›” -11ì›” -12ì›” + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1ì›” diff --git a/share/timedef/ko_KR.eucKR.src b/share/timedef/ko_KR.eucKR.src index 096e484b07f6..b85195371a95 100644 --- a/share/timedef/ko_KR.eucKR.src +++ b/share/timedef/ko_KR.eucKR.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1¿ù - 2¿ù - 3¿ù - 4¿ù - 5¿ù - 6¿ù - 7¿ù - 8¿ù - 9¿ù -10¿ù -11¿ù -12¿ù + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1¿ù diff --git a/share/timedef/zh_CN.GB2312.src b/share/timedef/zh_CN.GB2312.src index bcc7b3793c64..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.GB2312.src +++ b/share/timedef/zh_CN.GB2312.src @@ -4,53 +4,53 @@ # ----------------------------------------------------------------------------- # # Short month names -!!#1TB -!!#2TB -!!#3TB -!!#4TB -!!#5TB -!!#6TB -!!#7TB -!!#8TB -!!#9TB -#1#0TB -#1#1TB -#1#2TB + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) -R;TB -6~TB -H}TB -KDTB -NeTB -AyTB -F_TB -0KTB ->ETB -J.TB -J.R;TB -J.6~TB +Ò»Ô +¶þÔ +ÈýÔ +ËÄÔ +ÎåÔ +ÁùÔ +ÆßÔ +°ËÔ +¾ÅÔ +ʮԠ+ʮһÔ +Ê®¶þÔ # # Short weekday names -V\HU -V\R; -V\6~ -V\H} -V\KD -V\Ne -V\Ay +ÖÜÈÕ +ÖÜÒ» +Öܶþ +ÖÜÈý +ÖÜËÄ +ÖÜÎå +ÖÜÁù # # Long weekday names -PGFZHU -PGFZR; -PGFZ6~ -PGFZH} -PGFZKD -PGFZNe -PGFZAy +ÐÇÆÚÈÕ +ÐÇÆÚÒ» +ÐÇÆÚ¶þ +ÐÇÆÚÈý +ÐÇÆÚËÄ +ÐÇÆÚÎå +ÐÇÆÚÁù # # X_fmt -%Hʱ%M·Ö%SÃë +%Hʱ%M·Ö%SÃë # # x_fmt %Y/%m/%d @@ -59,25 +59,25 @@ PGFZAy %a %b/%e %T %Y # # AM/PM -IONg -OBNg +ÉÏÎç +ÏÂÎç # # date_fmt -%YÄê%bÔÂ%eÈÕ %A %X %Z +%YÄê%bÔÂ%eÈÕ %A %X %Z # # Long month names (without case ending) -R;TB -6~TB -H}TB -KDTB -NeTB -AyTB -F_TB -0KTB ->ETB -J.TB -J.R;TB -J.6~TB +Ò»Ô +¶þÔ +ÈýÔ +ËÄÔ +ÎåÔ +ÁùÔ +ÆßÔ +°ËÔ +¾ÅÔ +ʮԠ+ʮһÔ +Ê®¶þÔ # # md_order md diff --git a/share/timedef/zh_CN.GBK.src b/share/timedef/zh_CN.GBK.src index 9130d83797f3..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.GBK.src +++ b/share/timedef/zh_CN.GBK.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1Ô - 2Ô - 3Ô - 4Ô - 5Ô - 6Ô - 7Ô - 8Ô - 9Ô -10Ô -11Ô -12Ô + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) Ò»Ô diff --git a/share/timedef/zh_CN.UTF-8.src b/share/timedef/zh_CN.UTF-8.src index e87f300b0692..2460706f3bf3 100644 --- a/share/timedef/zh_CN.UTF-8.src +++ b/share/timedef/zh_CN.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 一月 diff --git a/share/timedef/zh_CN.eucCN.src b/share/timedef/zh_CN.eucCN.src index a654ee23643a..e98dc5fc28fa 100644 --- a/share/timedef/zh_CN.eucCN.src +++ b/share/timedef/zh_CN.eucCN.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names -¡¡£±Ô -¡¡£²Ô -¡¡£³Ô -¡¡£´Ô -¡¡£µÔ -¡¡£¶Ô -¡¡£·Ô -¡¡£¸Ô -¡¡£¹Ô -£±£°Ô -£±£±Ô -£±£²Ô + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) Ò»Ô diff --git a/share/timedef/zh_HK.UTF-8.src b/share/timedef/zh_HK.UTF-8.src index 390c9bdddaec..9800bcf231eb 100644 --- a/share/timedef/zh_HK.UTF-8.src +++ b/share/timedef/zh_HK.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1月 diff --git a/share/timedef/zh_TW.Big5.src b/share/timedef/zh_TW.Big5.src index e22bd18f0584..4ed7cdeeda12 100644 --- a/share/timedef/zh_TW.Big5.src +++ b/share/timedef/zh_TW.Big5.src @@ -4,32 +4,32 @@ # ----------------------------------------------------------------------------- # # Short month names -¡@¢°¤ë -¡@¢±¤ë -¡@¢²¤ë -¡@¢³¤ë -¡@¢´¤ë -¡@¢µ¤ë -¡@¢¶¤ë -¡@¢·¤ë -¡@¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) -¢°¤ë -¢±¤ë -¢²¤ë -¢³¤ë -¢´¤ë -¢µ¤ë -¢¶¤ë -¢·¤ë -¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë # # Short weekday names ¶g¤é @@ -62,21 +62,22 @@ ¤W¤È ¤U¤È # +# date_fmt %Y¦~%b¤ë%e¤é %A %X %Z # # Long month names (without case ending) -¢°¤ë -¢±¤ë -¢²¤ë -¢³¤ë -¢´¤ë -¢µ¤ë -¢¶¤ë -¢·¤ë -¢¸¤ë -¢°¢¯¤ë -¢°¢°¤ë -¢°¢±¤ë +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë # # md_order md diff --git a/share/timedef/zh_TW.UTF-8.src b/share/timedef/zh_TW.UTF-8.src index 8eb552159b0e..3121d4a4f4fc 100644 --- a/share/timedef/zh_TW.UTF-8.src +++ b/share/timedef/zh_TW.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1月 - 2月 - 3月 - 4月 - 5月 - 6月 - 7月 - 8月 - 9月 -10月 -11月 -12月 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 # # Long month names (as in a date) 1月 diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index 72e2021e6dc1..70a2d84183f2 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -188,6 +188,27 @@ print_cpu_features(u_int cpu) if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) { printed = 0; printf(" Instruction Set Attributes 0 = <"); + + switch (ID_AA64ISAR0_RDM(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_RDM_NONE: + break; + case ID_AA64ISAR0_RDM_IMPL: + printf("%sRDM", SEP_STR); + break; + default: + printf("%sUnknown RDM", SEP_STR); + } + + switch (ID_AA64ISAR0_ATOMIC(cpu_desc[cpu].id_aa64isar0)) { + case ID_AA64ISAR0_ATOMIC_NONE: + break; + case ID_AA64ISAR0_ATOMIC_IMPL: + printf("%sAtomic", SEP_STR); + break; + default: + printf("%sUnknown Atomic", SEP_STR); + } + switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) { case ID_AA64ISAR0_AES_NONE: break; @@ -466,8 +487,82 @@ print_cpu_features(u_int cpu) /* AArch64 Memory Model Feature Register 1 */ if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) { - printf(" Memory Model Features 1 = <%#lx>\n", - cpu_desc[cpu].id_aa64mmfr1); + printed = 0; + printf(" Memory Model Features 1 = <"); + + switch (ID_AA64MMFR1_PAN(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_PAN_NONE: + break; + case ID_AA64MMFR1_PAN_IMPL: + printf("%sPAN", SEP_STR); + break; + default: + printf("%sUnknown PAN", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_LO(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_LO_NONE: + break; + case ID_AA64MMFR1_LO_IMPL: + printf("%sLO", SEP_STR); + break; + default: + printf("%sUnknown LO", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_HPDS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_HPDS_NONE: + break; + case ID_AA64MMFR1_HPDS_IMPL: + printf("%sHPDS", SEP_STR); + break; + default: + printf("%sUnknown HPDS", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_VH(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_VH_NONE: + break; + case ID_AA64MMFR1_VH_IMPL: + printf("%sVHE", SEP_STR); + break; + default: + printf("%sUnknown VHE", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_VMIDBITS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_VMIDBITS_8: + break; + case ID_AA64MMFR1_VMIDBITS_16: + printf("%s16 VMID bits", SEP_STR); + break; + default: + printf("%sUnknown VMID bits", SEP_STR); + break; + } + + switch (ID_AA64MMFR1_HAFDBS(cpu_desc[cpu].id_aa64mmfr1)) { + case ID_AA64MMFR1_HAFDBS_NONE: + break; + case ID_AA64MMFR1_HAFDBS_AF: + printf("%sAF", SEP_STR); + break; + case ID_AA64MMFR1_HAFDBS_AF_DBS: + printf("%sAF+DBS", SEP_STR); + break; + default: + printf("%sUnknown Hardware update AF/DBS", SEP_STR); + break; + } + + if ((cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK) != 0) + printf("%s%#lx", SEP_STR, + cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK); + printf(">\n"); } /* AArch64 Debug Feature Register 0 */ @@ -489,6 +584,9 @@ print_cpu_features(u_int cpu) case ID_AA64DFR0_PMU_VER_3: printf("%sPMUv3", SEP_STR); break; + case ID_AA64DFR0_PMU_VER_3_1: + printf("%sPMUv3+16 bit evtCount", SEP_STR); + break; case ID_AA64DFR0_PMU_VER_IMPL: printf("%sImplementation defined PMU", SEP_STR); break; @@ -512,6 +610,9 @@ print_cpu_features(u_int cpu) case ID_AA64DFR0_DEBUG_VER_8: printf("%sDebug v8", SEP_STR); break; + case ID_AA64DFR0_DEBUG_VER_8_VHE: + printf("%sDebug v8+VHE", SEP_STR); + break; default: printf("%sUnknown Debug", SEP_STR); break; diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 392a2b3721e3..d812124f869d 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -172,6 +172,7 @@ #define ID_AA64DFR0_DEBUG_VER_MASK (0xf << ID_AA64DFR0_DEBUG_VER_SHIFT) #define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK) #define ID_AA64DFR0_DEBUG_VER_8 (0x6 << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER_8_VHE (0x7 << ID_AA64DFR0_DEBUG_VER_SHIFT) #define ID_AA64DFR0_TRACE_VER_SHIFT 4 #define ID_AA64DFR0_TRACE_VER_MASK (0xf << ID_AA64DFR0_TRACE_VER_SHIFT) #define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK) @@ -182,6 +183,7 @@ #define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK) #define ID_AA64DFR0_PMU_VER_NONE (0x0 << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_PMU_VER_3 (0x1 << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3_1 (0x4 << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_PMU_VER_IMPL (0xf << ID_AA64DFR0_PMU_VER_SHIFT) #define ID_AA64DFR0_BRPS_SHIFT 12 #define ID_AA64DFR0_BRPS_MASK (0xf << ID_AA64DFR0_BRPS_SHIFT) @@ -197,7 +199,7 @@ ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1) /* ID_AA64ISAR0_EL1 */ -#define ID_AA64ISAR0_MASK 0x000ffff0 +#define ID_AA64ISAR0_MASK 0xf0fffff0 #define ID_AA64ISAR0_AES_SHIFT 4 #define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK) @@ -219,6 +221,16 @@ #define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK) #define ID_AA64ISAR0_CRC32_NONE (0x0 << ID_AA64ISAR0_CRC32_SHIFT) #define ID_AA64ISAR0_CRC32_BASE (0x1 << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_ATOMIC_SHIFT 20 +#define ID_AA64ISAR0_ATOMIC_MASK (0xf << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC(x) ((x) & ID_AA64ISAR0_ATOMIC_MASK) +#define ID_AA64ISAR0_ATOMIC_NONE (0x0 << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC_IMPL (0x2 << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_RDM_SHIFT 28 +#define ID_AA64ISAR0_RDM_MASK (0xf << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM(x) ((x) & ID_AA64ISAR0_RDM_MASK) +#define ID_AA64ISAR0_RDM_NONE (0x0 << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM_IMPL (0x1 << ID_AA64ISAR0_RDM_SHIFT) /* ID_AA64MMFR0_EL1 */ #define ID_AA64MMFR0_MASK 0xffffffff @@ -267,6 +279,40 @@ #define ID_AA64MMFR0_TGRAN4_IMPL (0x0 << ID_AA64MMFR0_TGRAN4_SHIFT) #define ID_AA64MMFR0_TGRAN4_NONE (0xf << ID_AA64MMFR0_TGRAN4_SHIFT) +/* ID_AA64MMFR1_EL1 */ +#define ID_AA64MMFR1_MASK 0x00ffffff +#define ID_AA64MMFR1_HAFDBS_SHIFT 0 +#define ID_AA64MMFR1_HAFDBS_MASK (0xf << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK) +#define ID_AA64MMFR1_HAFDBS_NONE (0x0 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF (0x1 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF_DBS (0x2 << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_SHIFT 4 +#define ID_AA64MMFR1_VMIDBITS_MASK (0xf << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS(x) ((x) & ID_AA64MMFR1_VMIDBITS_MASK) +#define ID_AA64MMFR1_VMIDBITS_8 (0x0 << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_16 (0x2 << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VH_SHIFT 8 +#define ID_AA64MMFR1_VH_MASK (0xf << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH(x) ((x) & ID_AA64MMFR1_VH_MASK) +#define ID_AA64MMFR1_VH_NONE (0x0 << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH_IMPL (0x1 << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_HPDS_SHIFT 12 +#define ID_AA64MMFR1_HPDS_MASK (0xf << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS(x) ((x) & ID_AA64MMFR1_HPDS_MASK) +#define ID_AA64MMFR1_HPDS_NONE (0x0 << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS_IMPL (0x1 << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_LO_SHIFT 16 +#define ID_AA64MMFR1_LO_MASK (0xf << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO(x) ((x) & ID_AA64MMFR1_LO_MASK) +#define ID_AA64MMFR1_LO_NONE (0x0 << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO_IMPL (0x1 << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_PAN_SHIFT 20 +#define ID_AA64MMFR1_PAN_MASK (0xf << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN(x) ((x) & ID_AA64MMFR1_PAN_MASK) +#define ID_AA64MMFR1_PAN_NONE (0x0 << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_IMPL (0x1 << ID_AA64MMFR1_PAN_SHIFT) + /* ID_AA64PFR0_EL1 */ #define ID_AA64PFR0_MASK 0x0fffffff #define ID_AA64PFR0_EL0_SHIFT 0 diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c index ae3e9ac4b6f6..2efdfc7e69e5 100644 --- a/sys/boot/efi/boot1/ufs_module.c +++ b/sys/boot/efi/boot1/ufs_module.c @@ -56,7 +56,7 @@ dskread(void *buf, u_int64_t lba, int nblk) devinfo->dev->Media->MediaId, lba, size, buf); if (status != EFI_SUCCESS) { - DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, " + DPRINTF("dskread: failed dev: %p, id: %u, lba: %zu, size: %d, " "status: %lu\n", devinfo->dev, devinfo->dev->Media->MediaId, lba, size, EFI_ERROR_CODE(status)); diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c index 07d66bbd8ca1..60ad7c0eac0c 100644 --- a/sys/boot/efi/boot1/zfs_module.c +++ b/sys/boot/efi/boot1/zfs_module.c @@ -53,7 +53,7 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) status = devinfo->dev->ReadBlocks(devinfo->dev, devinfo->dev->Media->MediaId, lba, bytes, buf); if (status != EFI_SUCCESS) { - DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %zu, size: %zu," + DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %jd, size: %zu," " status: %lu\n", devinfo->dev, devinfo->dev->Media->MediaId, lba, bytes, EFI_ERROR_CODE(status)); diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c index 838becc5d2a6..6ad5d3c1e142 100644 --- a/sys/boot/efi/libefi/efi_console.c +++ b/sys/boot/efi/libefi/efi_console.c @@ -438,8 +438,10 @@ efi_cons_getchar() /* Try to read a key stroke. We wait for one if none is pending. */ status = conin->ReadKeyStroke(conin, &key); - if (status == EFI_NOT_READY) { - BS->WaitForEvent(1, &conin->WaitForKey, &junk); + while (status == EFI_NOT_READY) { + /* Some EFI implementation (u-boot for example) do not support WaitForKey */ + if (conin->WaitForKey != NULL) + BS->WaitForEvent(1, &conin->WaitForKey, &junk); status = conin->ReadKeyStroke(conin, &key); } switch (key.ScanCode) { @@ -454,6 +456,9 @@ efi_cons_getchar() int efi_cons_poll() { + + if (conin->WaitForKey == NULL) + return (1); /* This can clear the signaled state. */ return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index e14af78f4873..8ef31211fe1f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -480,6 +480,14 @@ static kmutex_t dtrace_errlock; (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \ (testaddr) + (testsz) >= (testaddr)) +#define DTRACE_RANGE_REMAIN(remp, addr, baseaddr, basesz) \ +do { \ + if ((remp) != NULL) { \ + *(remp) = (uintptr_t)(baseaddr) + (basesz) - (addr); \ + } \ +_NOTE(CONSTCOND) } while (0) + + /* * Test whether alloc_sz bytes will fit in the scratch region. We isolate * alloc_sz on the righthand side of the comparison in order to avoid overflow @@ -588,6 +596,10 @@ dtrace_dynvar_t *dtrace_dynvar(dtrace_dstate_t *, uint_t, dtrace_key_t *, uintptr_t dtrace_dif_varstr(uintptr_t, dtrace_state_t *, dtrace_mstate_t *); static int dtrace_priv_proc(dtrace_state_t *); static void dtrace_getf_barrier(void); +static int dtrace_canload_remains(uint64_t, size_t, size_t *, + dtrace_mstate_t *, dtrace_vstate_t *); +static int dtrace_canstore_remains(uint64_t, size_t, size_t *, + dtrace_mstate_t *, dtrace_vstate_t *); /* * DTrace Probe Context Functions @@ -698,7 +710,7 @@ dtrace_inscratch(uintptr_t dest, size_t size, dtrace_mstate_t *mstate) } static int -dtrace_canstore_statvar(uint64_t addr, size_t sz, +dtrace_canstore_statvar(uint64_t addr, size_t sz, size_t *remain, dtrace_statvar_t **svars, int nsvars) { int i; @@ -707,8 +719,8 @@ dtrace_canstore_statvar(uint64_t addr, size_t sz, if (nsvars == 0) return (0); - maxglobalsize = dtrace_statvar_maxsize; - maxlocalsize = (maxglobalsize + sizeof (uint64_t)) * NCPU; + maxglobalsize = dtrace_statvar_maxsize + sizeof (uint64_t); + maxlocalsize = maxglobalsize * NCPU; for (i = 0; i < nsvars; i++) { dtrace_statvar_t *svar = svars[i]; @@ -726,11 +738,15 @@ dtrace_canstore_statvar(uint64_t addr, size_t sz, * DTrace to escalate an orthogonal kernel heap corruption bug * into the ability to store to arbitrary locations in memory. */ - VERIFY((scope == DIFV_SCOPE_GLOBAL && size < maxglobalsize) || - (scope == DIFV_SCOPE_LOCAL && size < maxlocalsize)); + VERIFY((scope == DIFV_SCOPE_GLOBAL && size <= maxglobalsize) || + (scope == DIFV_SCOPE_LOCAL && size <= maxlocalsize)); - if (DTRACE_INRANGE(addr, sz, svar->dtsv_data, svar->dtsv_size)) + if (DTRACE_INRANGE(addr, sz, svar->dtsv_data, + svar->dtsv_size)) { + DTRACE_RANGE_REMAIN(remain, addr, svar->dtsv_data, + svar->dtsv_size); return (1); + } } return (0); @@ -745,13 +761,27 @@ dtrace_canstore_statvar(uint64_t addr, size_t sz, static int dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) +{ + return (dtrace_canstore_remains(addr, sz, NULL, mstate, vstate)); +} + +/* + * Implementation of dtrace_canstore which communicates the upper bound of the + * allowed memory region. + */ +static int +dtrace_canstore_remains(uint64_t addr, size_t sz, size_t *remain, + dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) { /* * First, check to see if the address is in scratch space... */ if (DTRACE_INRANGE(addr, sz, mstate->dtms_scratch_base, - mstate->dtms_scratch_size)) + mstate->dtms_scratch_size)) { + DTRACE_RANGE_REMAIN(remain, addr, mstate->dtms_scratch_base, + mstate->dtms_scratch_size); return (1); + } /* * Now check to see if it's a dynamic variable. This check will pick @@ -804,6 +834,7 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, ((dvar->dtdv_tuple.dtt_nkeys - 1) * sizeof (dtrace_key_t))) return (0); + DTRACE_RANGE_REMAIN(remain, addr, dvar, dstate->dtds_chunksize); return (1); } @@ -811,11 +842,11 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * Finally, check the static local and global variables. These checks * take the longest, so we perform them last. */ - if (dtrace_canstore_statvar(addr, sz, + if (dtrace_canstore_statvar(addr, sz, remain, vstate->dtvs_locals, vstate->dtvs_nlocals)) return (1); - if (dtrace_canstore_statvar(addr, sz, + if (dtrace_canstore_statvar(addr, sz, remain, vstate->dtvs_globals, vstate->dtvs_nglobals)) return (1); @@ -835,6 +866,17 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, static int dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) +{ + return (dtrace_canload_remains(addr, sz, NULL, mstate, vstate)); +} + +/* + * Implementation of dtrace_canload which communicates the uppoer bound of the + * allowed memory region. + */ +static int +dtrace_canload_remains(uint64_t addr, size_t sz, size_t *remain, + dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) { volatile uintptr_t *illval = &cpu_core[curcpu].cpuc_dtrace_illval; file_t *fp; @@ -843,21 +885,27 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * If we hold the privilege to read from kernel memory, then * everything is readable. */ - if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) + if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) { + DTRACE_RANGE_REMAIN(remain, addr, addr, sz); return (1); + } /* * You can obviously read that which you can store. */ - if (dtrace_canstore(addr, sz, mstate, vstate)) + if (dtrace_canstore_remains(addr, sz, remain, mstate, vstate)) return (1); /* * We're allowed to read from our own string table. */ if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab, - mstate->dtms_difo->dtdo_strlen)) + mstate->dtms_difo->dtdo_strlen)) { + DTRACE_RANGE_REMAIN(remain, addr, + mstate->dtms_difo->dtdo_strtab, + mstate->dtms_difo->dtdo_strlen); return (1); + } if (vstate->dtvs_state != NULL && dtrace_priv_proc(vstate->dtvs_state)) { @@ -879,27 +927,38 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * deallocated and reallocated as something else while it's * being operated upon. */ - if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t))) + if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t))) { + DTRACE_RANGE_REMAIN(remain, addr, curthread, + sizeof (kthread_t)); return (1); + } if ((p = curthread->t_procp) != NULL && DTRACE_INRANGE(addr, sz, curthread->t_procp, sizeof (proc_t))) { + DTRACE_RANGE_REMAIN(remain, addr, curthread->t_procp, + sizeof (proc_t)); return (1); } if (curthread->t_cred != NULL && DTRACE_INRANGE(addr, sz, curthread->t_cred, sizeof (cred_t))) { + DTRACE_RANGE_REMAIN(remain, addr, curthread->t_cred, + sizeof (cred_t)); return (1); } #ifdef illumos if (p != NULL && p->p_pidp != NULL && DTRACE_INRANGE(addr, sz, &(p->p_pidp->pid_id), sizeof (pid_t))) { + DTRACE_RANGE_REMAIN(remain, addr, &(p->p_pidp->pid_id), + sizeof (pid_t)); return (1); } if (curthread->t_cpu != NULL && DTRACE_INRANGE(addr, sz, curthread->t_cpu, offsetof(cpu_t, cpu_pause_thread))) { + DTRACE_RANGE_REMAIN(remain, addr, curthread->t_cpu, + offsetof(cpu_t, cpu_pause_thread)); return (1); } #endif @@ -922,31 +981,46 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * either dtms_getf itself or its f_vnode member to reference * freed memory). */ - if (DTRACE_INRANGE(addr, sz, fp, sizeof (file_t))) + if (DTRACE_INRANGE(addr, sz, fp, sizeof (file_t))) { + DTRACE_RANGE_REMAIN(remain, addr, fp, sizeof (file_t)); return (1); + } if ((vp = fp->f_vnode) != NULL) { + size_t slen; #ifdef illumos - if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz)) + if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz)) { + DTRACE_RANGE_REMAIN(remain, addr, &vp->v_path, + psz); return (1); - if (vp->v_path != NULL && DTRACE_INRANGE(addr, sz, - vp->v_path, strlen(vp->v_path) + 1)) { + } + slen = strlen(vp->v_path) + 1; + if (DTRACE_INRANGE(addr, sz, vp->v_path, slen)) { + DTRACE_RANGE_REMAIN(remain, addr, vp->v_path, + slen); return (1); } #endif - if (DTRACE_INRANGE(addr, sz, &vp->v_op, psz)) + if (DTRACE_INRANGE(addr, sz, &vp->v_op, psz)) { + DTRACE_RANGE_REMAIN(remain, addr, &vp->v_op, + psz); return (1); + } #ifdef illumos if ((op = vp->v_op) != NULL && DTRACE_INRANGE(addr, sz, &op->vnop_name, psz)) { + DTRACE_RANGE_REMAIN(remain, addr, + &op->vnop_name, psz); return (1); } if (op != NULL && op->vnop_name != NULL && DTRACE_INRANGE(addr, sz, op->vnop_name, - strlen(op->vnop_name) + 1)) { + (slen = strlen(op->vnop_name) + 1))) { + DTRACE_RANGE_REMAIN(remain, addr, + op->vnop_name, slen); return (1); } #endif @@ -965,21 +1039,41 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * calls in the event that the user has all privileges. */ static int -dtrace_strcanload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, - dtrace_vstate_t *vstate) +dtrace_strcanload(uint64_t addr, size_t sz, size_t *remain, + dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) { - size_t strsz; + size_t rsize; /* * If we hold the privilege to read from kernel memory, then * everything is readable. */ - if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) + if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) { + DTRACE_RANGE_REMAIN(remain, addr, addr, sz); return (1); + } - strsz = 1 + dtrace_strlen((char *)(uintptr_t)addr, sz); - if (dtrace_canload(addr, strsz, mstate, vstate)) - return (1); + /* + * Even if the caller is uninterested in querying the remaining valid + * range, it is required to ensure that the access is allowed. + */ + if (remain == NULL) { + remain = &rsize; + } + if (dtrace_canload_remains(addr, 0, remain, mstate, vstate)) { + size_t strsz; + /* + * Perform the strlen after determining the length of the + * memory region which is accessible. This prevents timing + * information from being used to find NULs in memory which is + * not accessible to the caller. + */ + strsz = 1 + dtrace_strlen((char *)(uintptr_t)addr, + MIN(sz, *remain)); + if (strsz <= *remain) { + return (1); + } + } return (0); } @@ -989,26 +1083,49 @@ dtrace_strcanload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate, * region in which a load may be issued given the user's privilege level. */ static int -dtrace_vcanload(void *src, dtrace_diftype_t *type, dtrace_mstate_t *mstate, - dtrace_vstate_t *vstate) +dtrace_vcanload(void *src, dtrace_diftype_t *type, size_t *remain, + dtrace_mstate_t *mstate, dtrace_vstate_t *vstate) { size_t sz; ASSERT(type->dtdt_flags & DIF_TF_BYREF); + /* + * Calculate the max size before performing any checks since even + * DTRACE_ACCESS_KERNEL-credentialed callers expect that this function + * return the max length via 'remain'. + */ + if (type->dtdt_kind == DIF_TYPE_STRING) { + dtrace_state_t *state = vstate->dtvs_state; + + if (state != NULL) { + sz = state->dts_options[DTRACEOPT_STRSIZE]; + } else { + /* + * In helper context, we have a NULL state; fall back + * to using the system-wide default for the string size + * in this case. + */ + sz = dtrace_strsize_default; + } + } else { + sz = type->dtdt_size; + } + /* * If we hold the privilege to read from kernel memory, then * everything is readable. */ - if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) + if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0) { + DTRACE_RANGE_REMAIN(remain, (uintptr_t)src, src, sz); return (1); + } - if (type->dtdt_kind == DIF_TYPE_STRING) - sz = dtrace_strlen(src, - vstate->dtvs_state->dts_options[DTRACEOPT_STRSIZE]) + 1; - else - sz = type->dtdt_size; - - return (dtrace_canload((uintptr_t)src, sz, mstate, vstate)); + if (type->dtdt_kind == DIF_TYPE_STRING) { + return (dtrace_strcanload((uintptr_t)src, sz, remain, mstate, + vstate)); + } + return (dtrace_canload_remains((uintptr_t)src, sz, remain, mstate, + vstate)); } /* @@ -1198,14 +1315,14 @@ dtrace_strcpy(const void *src, void *dst, size_t len) * specified type; we assume that we can store to directly. */ static void -dtrace_vcopy(void *src, void *dst, dtrace_diftype_t *type) +dtrace_vcopy(void *src, void *dst, dtrace_diftype_t *type, size_t limit) { ASSERT(type->dtdt_flags & DIF_TF_BYREF); if (type->dtdt_kind == DIF_TYPE_STRING) { - dtrace_strcpy(src, dst, type->dtdt_size); + dtrace_strcpy(src, dst, MIN(type->dtdt_size, limit)); } else { - dtrace_bcopy(src, dst, type->dtdt_size); + dtrace_bcopy(src, dst, MIN(type->dtdt_size, limit)); } } @@ -4503,31 +4620,30 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, uintptr_t kaddr = tupregs[0].dttk_value; uintptr_t uaddr = tupregs[1].dttk_value; uint64_t size = tupregs[2].dttk_value; + size_t lim; if (!dtrace_destructive_disallow && dtrace_priv_proc_control(state) && !dtrace_istoxic(kaddr, size) && - dtrace_strcanload(kaddr, size, mstate, vstate)) { + dtrace_strcanload(kaddr, size, &lim, mstate, vstate)) { DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); - dtrace_copyoutstr(kaddr, uaddr, size, flags); + dtrace_copyoutstr(kaddr, uaddr, lim, flags); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); } break; } case DIF_SUBR_STRLEN: { - size_t sz; + size_t size = state->dts_options[DTRACEOPT_STRSIZE]; uintptr_t addr = (uintptr_t)tupregs[0].dttk_value; - sz = dtrace_strlen((char *)addr, - state->dts_options[DTRACEOPT_STRSIZE]); + size_t lim; - if (!dtrace_canload(addr, sz + 1, mstate, vstate)) { + if (!dtrace_strcanload(addr, size, &lim, mstate, vstate)) { regs[rd] = 0; break; } - regs[rd] = sz; - + regs[rd] = dtrace_strlen((char *)addr, lim); break; } @@ -4540,12 +4656,19 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * is DIF_SUBR_STRRCHR, we will look for the last occurrence * of the specified character instead of the first. */ - uintptr_t saddr = tupregs[0].dttk_value; uintptr_t addr = tupregs[0].dttk_value; - uintptr_t limit = addr + state->dts_options[DTRACEOPT_STRSIZE]; + uintptr_t addr_limit; + uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; + size_t lim; char c, target = (char)tupregs[1].dttk_value; - for (regs[rd] = 0; addr < limit; addr++) { + if (!dtrace_strcanload(addr, size, &lim, mstate, vstate)) { + regs[rd] = 0; + break; + } + addr_limit = addr + lim; + + for (regs[rd] = 0; addr < addr_limit; addr++) { if ((c = dtrace_load8(addr)) == target) { regs[rd] = addr; @@ -4556,12 +4679,6 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, if (c == '\0') break; } - - if (!dtrace_canload(saddr, addr - saddr, mstate, vstate)) { - regs[rd] = 0; - break; - } - break; } @@ -4719,7 +4836,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, uintptr_t addr = tupregs[0].dttk_value; uintptr_t tokaddr = tupregs[1].dttk_value; uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; - uintptr_t limit, toklimit = tokaddr + size; + uintptr_t limit, toklimit; + size_t clim; uint8_t c = 0, tokmap[32]; /* 256 / 8 */ char *dest = (char *)mstate->dtms_scratch_ptr; int i; @@ -4728,10 +4846,11 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * Check both the token buffer and (later) the input buffer, * since both could be non-scratch addresses. */ - if (!dtrace_strcanload(tokaddr, size, mstate, vstate)) { + if (!dtrace_strcanload(tokaddr, size, &clim, mstate, vstate)) { regs[rd] = 0; break; } + toklimit = tokaddr + clim; if (!DTRACE_INSCRATCH(mstate, size)) { DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH); @@ -4748,6 +4867,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * it behaves like an implicit clause-local variable. */ addr = mstate->dtms_strtok; + limit = mstate->dtms_strtok_limit; } else { /* * If the user-specified address is non-NULL we must @@ -4757,10 +4877,12 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * (when we fetch addr from mstate->dtms_strtok) * would fail this access check. */ - if (!dtrace_strcanload(addr, size, mstate, vstate)) { + if (!dtrace_strcanload(addr, size, &clim, mstate, + vstate)) { regs[rd] = 0; break; } + limit = addr + clim; } /* @@ -4779,10 +4901,10 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, tokmap[c >> 3] |= (1 << (c & 0x7)); } - for (limit = addr + size; addr < limit; addr++) { + for (; addr < limit; addr++) { /* - * We're looking for a character that is _not_ contained - * in the token string. + * We're looking for a character that is _not_ + * contained in the token string. */ if ((c = dtrace_load8(addr)) == '\0') break; @@ -4800,6 +4922,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, */ regs[rd] = 0; mstate->dtms_strtok = 0; + mstate->dtms_strtok_limit = 0; break; } @@ -4822,6 +4945,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, regs[rd] = (uintptr_t)dest; mstate->dtms_scratch_ptr += size; mstate->dtms_strtok = addr; + mstate->dtms_strtok_limit = limit; break; } @@ -5199,10 +5323,12 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; uintptr_t s1 = tupregs[0].dttk_value; uintptr_t s2 = tupregs[1].dttk_value; - int i = 0; + int i = 0, j = 0; + size_t lim1, lim2; + char c; - if (!dtrace_strcanload(s1, size, mstate, vstate) || - !dtrace_strcanload(s2, size, mstate, vstate)) { + if (!dtrace_strcanload(s1, size, &lim1, mstate, vstate) || + !dtrace_strcanload(s2, size, &lim2, mstate, vstate)) { regs[rd] = 0; break; } @@ -5219,8 +5345,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, regs[rd] = 0; break; } - - if ((d[i++] = dtrace_load8(s1++)) == '\0') { + c = (i >= lim1) ? '\0' : dtrace_load8(s1++); + if ((d[i++] = c) == '\0') { i--; break; } @@ -5233,7 +5359,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, break; } - if ((d[i++] = dtrace_load8(s2++)) == '\0') + c = (j++ >= lim2) ? '\0' : dtrace_load8(s2++); + if ((d[i++] = c) == '\0') break; } @@ -5248,6 +5375,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, case DIF_SUBR_STRTOLL: { uintptr_t s = tupregs[0].dttk_value; uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; + size_t lim; int base = 10; if (nargs > 1) { @@ -5258,12 +5386,12 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, } } - if (!dtrace_strcanload(s, size, mstate, vstate)) { + if (!dtrace_strcanload(s, size, &lim, mstate, vstate)) { regs[rd] = INT64_MIN; break; } - regs[rd] = dtrace_strtoll((char *)s, base, size); + regs[rd] = dtrace_strtoll((char *)s, base, lim); break; } @@ -5498,12 +5626,13 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, char *dest = (char *)mstate->dtms_scratch_ptr, c; uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; uintptr_t src = tupregs[0].dttk_value; + size_t lim; int i = 0, j = 0; #ifdef illumos zone_t *z; #endif - if (!dtrace_strcanload(src, size, mstate, vstate)) { + if (!dtrace_strcanload(src, size, &lim, mstate, vstate)) { regs[rd] = 0; break; } @@ -5518,7 +5647,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * Move forward, loading each character. */ do { - c = dtrace_load8(src + i++); + c = (i >= lim) ? '\0' : dtrace_load8(src + i++); next: if (j + 5 >= size) /* 5 = strlen("/..c\0") */ break; @@ -5528,7 +5657,7 @@ next: continue; } - c = dtrace_load8(src + i++); + c = (i >= lim) ? '\0' : dtrace_load8(src + i++); if (c == '/') { /* @@ -5549,7 +5678,7 @@ next: continue; } - c = dtrace_load8(src + i++); + c = (i >= lim) ? '\0' : dtrace_load8(src + i++); if (c == '/') { /* @@ -5572,7 +5701,7 @@ next: continue; } - c = dtrace_load8(src + i++); + c = (i >= lim) ? '\0' : dtrace_load8(src + i++); if (c != '/' && c != '\0') { /* @@ -6211,15 +6340,17 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, size_t sz = state->dts_options[DTRACEOPT_STRSIZE]; uintptr_t s1 = regs[r1]; uintptr_t s2 = regs[r2]; + size_t lim1, lim2; if (s1 != 0 && - !dtrace_strcanload(s1, sz, mstate, vstate)) + !dtrace_strcanload(s1, sz, &lim1, mstate, vstate)) break; if (s2 != 0 && - !dtrace_strcanload(s2, sz, mstate, vstate)) + !dtrace_strcanload(s2, sz, &lim2, mstate, vstate)) break; - cc_r = dtrace_strncmp((char *)s1, (char *)s2, sz); + cc_r = dtrace_strncmp((char *)s1, (char *)s2, + MIN(lim1, lim2)); cc_n = cc_r < 0; cc_z = cc_r == 0; @@ -6278,6 +6409,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) { uintptr_t a = (uintptr_t)svar->dtsv_data; + size_t lim; ASSERT(a != 0); ASSERT(svar->dtsv_size != 0); @@ -6291,11 +6423,11 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, } if (!dtrace_vcanload( (void *)(uintptr_t)regs[rd], &v->dtdv_type, - mstate, vstate)) + &lim, mstate, vstate)) break; dtrace_vcopy((void *)(uintptr_t)regs[rd], - (void *)a, &v->dtdv_type); + (void *)a, &v->dtdv_type, lim); break; } @@ -6334,6 +6466,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) { uintptr_t a = (uintptr_t)svar->dtsv_data; size_t sz = v->dtdv_type.dtdt_size; + size_t lim; sz += sizeof (uint64_t); ASSERT(svar->dtsv_size == NCPU * sz); @@ -6373,6 +6506,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) { uintptr_t a = (uintptr_t)svar->dtsv_data; size_t sz = v->dtdv_type.dtdt_size; + size_t lim; sz += sizeof (uint64_t); ASSERT(svar->dtsv_size == NCPU * sz); @@ -6388,11 +6522,11 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, if (!dtrace_vcanload( (void *)(uintptr_t)regs[rd], &v->dtdv_type, - mstate, vstate)) + &lim, mstate, vstate)) break; dtrace_vcopy((void *)(uintptr_t)regs[rd], - (void *)a, &v->dtdv_type); + (void *)a, &v->dtdv_type, lim); break; } @@ -6466,13 +6600,15 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, break; if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) { + size_t lim; + if (!dtrace_vcanload( (void *)(uintptr_t)regs[rd], - &v->dtdv_type, mstate, vstate)) + &v->dtdv_type, &lim, mstate, vstate)) break; dtrace_vcopy((void *)(uintptr_t)regs[rd], - dvar->dtdv_data, &v->dtdv_type); + dvar->dtdv_data, &v->dtdv_type, lim); } else { *((uint64_t *)dvar->dtdv_data) = regs[rd]; } @@ -6614,13 +6750,15 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, break; if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) { + size_t lim; + if (!dtrace_vcanload( (void *)(uintptr_t)regs[rd], &v->dtdv_type, - mstate, vstate)) + &lim, mstate, vstate)) break; dtrace_vcopy((void *)(uintptr_t)regs[rd], - dvar->dtdv_data, &v->dtdv_type); + dvar->dtdv_data, &v->dtdv_type, lim); } else { *((uint64_t *)dvar->dtdv_data) = regs[rd]; } @@ -6929,6 +7067,7 @@ dtrace_action_ustack(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t *pcs = &buf[1], *fps; char *str = (char *)&pcs[nframes]; int size, offs = 0, i, j; + size_t rem; uintptr_t old = mstate->dtms_scratch_ptr, saved; uint16_t *flags = &cpu_core[curcpu].cpuc_dtrace_flags; char *sym; @@ -7000,12 +7139,18 @@ dtrace_action_ustack(dtrace_mstate_t *mstate, dtrace_state_t *state, continue; } + if (!dtrace_strcanload((uintptr_t)sym, strsize, &rem, mstate, + &(state->dts_vstate))) { + str[offs++] = '\0'; + continue; + } + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); /* * Now copy in the string that the helper returned to us. */ - for (j = 0; offs + j < strsize; j++) { + for (j = 0; offs + j < strsize && j < rem; j++) { if ((str[offs + j] = sym[j]) == '\0') break; } @@ -7740,7 +7885,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF && !dtrace_vcanload((void *)(uintptr_t)val, - &dp->dtdo_rtype, &mstate, vstate)) + &dp->dtdo_rtype, NULL, &mstate, vstate)) continue; dtrace_store_by_ref(dp, tomax, size, &valoffs, @@ -11017,7 +11162,7 @@ dtrace_ecb_enable(dtrace_ecb_t *ecb) } } -static void +static int dtrace_ecb_resize(dtrace_ecb_t *ecb) { dtrace_action_t *act; @@ -11051,6 +11196,8 @@ dtrace_ecb_resize(dtrace_ecb_t *ecb) curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment); rec->dtrd_offset = curneeded; + if (curneeded + rec->dtrd_size < curneeded) + return (EINVAL); curneeded += rec->dtrd_size; ecb->dte_needed = MAX(ecb->dte_needed, curneeded); @@ -11075,6 +11222,8 @@ dtrace_ecb_resize(dtrace_ecb_t *ecb) } curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment); rec->dtrd_offset = curneeded; + if (curneeded + rec->dtrd_size < curneeded) + return (EINVAL); curneeded += rec->dtrd_size; } else { /* tuples must be followed by an aggregation */ @@ -11084,6 +11233,8 @@ dtrace_ecb_resize(dtrace_ecb_t *ecb) ecb->dte_size = P2ROUNDUP(ecb->dte_size, rec->dtrd_alignment); rec->dtrd_offset = ecb->dte_size; + if (ecb->dte_size + rec->dtrd_size < ecb->dte_size) + return (EINVAL); ecb->dte_size += rec->dtrd_size; ecb->dte_needed = MAX(ecb->dte_needed, ecb->dte_size); } @@ -11103,6 +11254,7 @@ dtrace_ecb_resize(dtrace_ecb_t *ecb) ecb->dte_needed = P2ROUNDUP(ecb->dte_needed, (sizeof (dtrace_epid_t))); ecb->dte_state->dts_needed = MAX(ecb->dte_state->dts_needed, ecb->dte_needed); + return (0); } static dtrace_action_t * @@ -11788,7 +11940,10 @@ dtrace_ecb_create(dtrace_state_t *state, dtrace_probe_t *probe, } } - dtrace_ecb_resize(ecb); + if ((enab->dten_error = dtrace_ecb_resize(ecb)) != 0) { + dtrace_ecb_destroy(ecb); + return (NULL); + } return (dtrace_ecb_create_cache = ecb); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h index 1ec90914d5be..130511de0377 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h @@ -23,12 +23,12 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. * Use is subject to license terms. */ /* - * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright 2016 Joyent, Inc. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_DTRACE_IMPL_H @@ -932,6 +932,7 @@ typedef struct dtrace_mstate { int dtms_ipl; /* cached interrupt pri lev */ int dtms_fltoffs; /* faulting DIFO offset */ uintptr_t dtms_strtok; /* saved strtok() pointer */ + uintptr_t dtms_strtok_limit; /* upper bound of strtok ptr */ uint32_t dtms_access; /* memory access rights */ dtrace_difo_t *dtms_difo; /* current dif object */ file_t *dtms_getf; /* cached rval of getf() */ diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c index c044adcdf1d8..5500e3920e17 100644 --- a/sys/compat/cloudabi/cloudabi_fd.c +++ b/sys/compat/cloudabi/cloudabi_fd.c @@ -172,12 +172,8 @@ int cloudabi_sys_fd_datasync(struct thread *td, struct cloudabi_sys_fd_datasync_args *uap) { - struct fsync_args fsync_args = { - .fd = uap->fd - }; - /* Call into fsync(), as FreeBSD lacks fdatasync(). */ - return (sys_fsync(td, &fsync_args)); + return (kern_fsync(td, uap->fd, false)); } int @@ -557,9 +553,6 @@ cloudabi_sys_fd_stat_put(struct thread *td, int cloudabi_sys_fd_sync(struct thread *td, struct cloudabi_sys_fd_sync_args *uap) { - struct fsync_args fsync_args = { - .fd = uap->fd - }; - return (sys_fsync(td, &fsync_args)); + return (kern_fsync(td, uap->fd, true)); } diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 894d2ac67c73..538892efc44f 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #ifndef _FREEBSD32_SYSPROTO_H_ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 6493561c7bc8..54292f7a4b4e 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #define FREEBSD32_SYS_syscall 0 @@ -457,4 +457,5 @@ #define FREEBSD32_SYS_freebsd32_utimensat 547 #define FREEBSD32_SYS_numa_getaffinity 548 #define FREEBSD32_SYS_numa_setaffinity 549 -#define FREEBSD32_SYS_MAXSYSCALL 550 +#define FREEBSD32_SYS_fdatasync 550 +#define FREEBSD32_SYS_MAXSYSCALL 551 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 239ec7405210..27f361c65107 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ const char *freebsd32_syscallnames[] = { @@ -583,4 +583,5 @@ const char *freebsd32_syscallnames[] = { "freebsd32_utimensat", /* 547 = freebsd32_utimensat */ "numa_getaffinity", /* 548 = numa_getaffinity */ "numa_setaffinity", /* 549 = numa_setaffinity */ + "fdatasync", /* 550 = fdatasync */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 0b0195149639..5a98f2a6385b 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 303699 2016-08-03 06:33:04Z ed + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #include "opt_compat.h" @@ -626,4 +626,5 @@ struct sysent freebsd32_sysent[] = { { AS(freebsd32_utimensat_args), (sy_call_t *)freebsd32_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 547 = freebsd32_utimensat */ { AS(numa_getaffinity_args), (sy_call_t *)sys_numa_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 548 = numa_getaffinity */ { AS(numa_setaffinity_args), (sy_call_t *)sys_numa_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 549 = numa_setaffinity */ + { AS(fdatasync_args), (sy_call_t *)sys_fdatasync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 550 = fdatasync */ }; diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index 72d3a78fa310..0bc7f515a6ad 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3316,6 +3316,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 3; break; } + /* fdatasync */ + case 550: { + struct fdatasync_args *p = params; + iarg[0] = p->fd; /* int */ + *n_args = 1; + break; + } default: *n_args = 0; break; @@ -8902,6 +8909,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* fdatasync */ + case 550: + switch(ndx) { + case 0: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10783,6 +10800,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* fdatasync */ + case 550: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 4b4ff2713382..3172db49d93d 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1081,3 +1081,4 @@ 549 AUE_NULL NOPROTO { int numa_setaffinity(cpuwhich_t which, \ id_t id, \ const struct vm_domain_policy *policy); } +550 AUE_FSYNC NOPROTO { int fdatasync(int fd); } diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index d3af86093db7..b5126f4b6cbc 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1013,10 +1013,8 @@ linux_fdatasync(td, uap) struct thread *td; struct linux_fdatasync_args *uap; { - struct fsync_args bsd; - bsd.fd = uap->fd; - return (sys_fsync(td, &bsd)); + return (kern_fsync(td, uap->fd, false)); } int diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 9b7d8cd95482..dda8211d44a3 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2412,15 +2412,10 @@ options SND_OLDSTEREO # Miscellaneous hardware: # # scd: Sony CD-ROM using proprietary (non-ATAPI) interface -# mcd: Mitsumi CD-ROM using proprietary (non-ATAPI) interface # bktr: Brooktree bt848/848a/849a/878/879 video capture and TV Tuner board # joy: joystick (including IO DATA PCJOY PC Card joystick) # cmx: OmniKey CardMan 4040 pccard smartcard reader -# Mitsumi CD-ROM -device mcd -hint.mcd.0.at="isa" -hint.mcd.0.port="0x300" # for the Sony CDU31/33A CDROM device scd hint.scd.0.at="isa" diff --git a/sys/conf/files b/sys/conf/files index 5da337273bcd..40c5281b3baf 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2018,8 +2018,6 @@ dev/malo/if_malohal.c optional malo dev/malo/if_malo_pci.c optional malo pci dev/mc146818/mc146818.c optional mc146818 dev/mca/mca_bus.c optional mca -dev/mcd/mcd.c optional mcd isa nowerror -dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mdio/mdio_if.m optional miiproxy | mdio dev/mdio/mdio.c optional miiproxy | mdio diff --git a/sys/conf/options b/sys/conf/options index 89ce7902f413..f115e7e14212 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -418,6 +418,7 @@ IPFILTER_LOOKUP opt_ipfilter.h IPFIREWALL opt_ipfw.h IPFIREWALL_DEFAULT_TO_ACCEPT opt_ipfw.h IPFIREWALL_NAT opt_ipfw.h +IPFIREWALL_NAT64 opt_ipfw.h IPFIREWALL_NAT64_DIRECT_OUTPUT opt_ipfw.h IPFIREWALL_NPTV6 opt_ipfw.h IPFIREWALL_VERBOSE opt_ipfw.h diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index cc6edf32a3c7..1cbdf8ee059a 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -215,6 +215,8 @@ struct sge_params { int pad_boundary; int pack_boundary; int fl_pktshift; + u32 sge_control; + u32 sge_fl_buffer_size[SGE_FLBUF_SIZES]; }; struct tp_params { diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 7ecdb81a44b8..ca6d2069a5f0 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -289,6 +289,14 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, if ((size & 15) || size > MBOX_LEN) return -EINVAL; + if (adap->flags & IS_VF) { + if (is_t6(adap)) + data_reg = FW_T6VF_MBDATA_BASE_ADDR; + else + data_reg = FW_T4VF_MBDATA_BASE_ADDR; + ctl_reg = VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL); + } + /* * If we have a negative timeout, that implies that we can't sleep. */ @@ -343,6 +351,22 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, for (i = 0; i < size; i += 8, p++) t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p)); + if (adap->flags & IS_VF) { + /* + * For the VFs, the Mailbox Data "registers" are + * actually backed by T4's "MA" interface rather than + * PL Registers (as is the case for the PFs). Because + * these are in different coherency domains, the write + * to the VF's PL-register-backed Mailbox Control can + * race in front of the writes to the MA-backed VF + * Mailbox Data "registers". So we need to do a + * read-back on at least one byte of the VF Mailbox + * Data registers before doing the write to the VF + * Mailbox Control register. + */ + t4_read_reg(adap, data_reg); + } + CH_DUMP_MBOX(adap, mbox, data_reg); t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW)); @@ -355,10 +379,13 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, * Loop waiting for the reply; bail out if we time out or the firmware * reports an error. */ - for (i = 0; - !((pcie_fw = t4_read_reg(adap, A_PCIE_FW)) & F_PCIE_FW_ERR) && - i < timeout; - i += ms) { + pcie_fw = 0; + for (i = 0; i < timeout; i += ms) { + if (!(adap->flags & IS_VF)) { + pcie_fw = t4_read_reg(adap, A_PCIE_FW); + if (pcie_fw & F_PCIE_FW_ERR) + break; + } if (sleep_ok) { ms = delay[delay_idx]; /* last element may repeat */ if (delay_idx < ARRAY_SIZE(delay) - 1) @@ -698,10 +725,14 @@ unsigned int t4_get_regs_len(struct adapter *adapter) switch (chip_version) { case CHELSIO_T4: + if (adapter->flags & IS_VF) + return FW_T4VF_REGMAP_SIZE; return T4_REGMAP_SIZE; case CHELSIO_T5: case CHELSIO_T6: + if (adapter->flags & IS_VF) + return FW_T4VF_REGMAP_SIZE; return T5_REGMAP_SIZE; } @@ -1180,6 +1211,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x27e00, 0x27e04, }; + static const unsigned int t4vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_WHOAMI), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T4VF_MBDATA_BASE_ADDR, + FW_T4VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + static const unsigned int t5_reg_ranges[] = { 0x1008, 0x10c0, 0x10cc, 0x10f8, @@ -1955,6 +1998,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x51300, 0x51308, }; + static const unsigned int t5vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T4VF_MBDATA_BASE_ADDR, + FW_T4VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + static const unsigned int t6_reg_ranges[] = { 0x1008, 0x101c, 0x1024, 0x10a8, @@ -2532,6 +2587,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x51300, 0x51324, }; + static const unsigned int t6vf_reg_ranges[] = { + VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS), + VF_MPS_REG(A_MPS_VF_CTL), + VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H), + VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL), + VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS), + FW_T6VF_MBDATA_BASE_ADDR, + FW_T6VF_MBDATA_BASE_ADDR + + ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4), + }; + u32 *buf_end = (u32 *)(buf + buf_size); const unsigned int *reg_ranges; int reg_ranges_size, range; @@ -2543,18 +2610,33 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) */ switch (chip_version) { case CHELSIO_T4: - reg_ranges = t4_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t4_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t4vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t4vf_reg_ranges); + } else { + reg_ranges = t4_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t4_reg_ranges); + } break; case CHELSIO_T5: - reg_ranges = t5_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t5_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t5vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t5vf_reg_ranges); + } else { + reg_ranges = t5_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t5_reg_ranges); + } break; case CHELSIO_T6: - reg_ranges = t6_reg_ranges; - reg_ranges_size = ARRAY_SIZE(t6_reg_ranges); + if (adap->flags & IS_VF) { + reg_ranges = t6vf_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t6vf_reg_ranges); + } else { + reg_ranges = t6_reg_ranges; + reg_ranges_size = ARRAY_SIZE(t6_reg_ranges); + } break; default: @@ -7644,6 +7726,7 @@ int t4_init_sge_params(struct adapter *adapter) { u32 r; struct sge_params *sp = &adapter->params.sge; + unsigned i; r = t4_read_reg(adapter, A_SGE_INGRESS_RX_THRESHOLD); sp->counter_val[0] = G_THRESHOLD_0(r); @@ -7686,6 +7769,7 @@ int t4_init_sge_params(struct adapter *adapter) sp->page_shift = (r & M_HOSTPAGESIZEPF0) + 10; r = t4_read_reg(adapter, A_SGE_CONTROL); + sp->sge_control = r; sp->spg_len = r & F_EGRSTATUSPAGESIZE ? 128 : 64; sp->fl_pktshift = G_PKTSHIFT(r); sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) + 5); @@ -7698,6 +7782,9 @@ int t4_init_sge_params(struct adapter *adapter) else sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(r) + 5); } + for (i = 0; i < SGE_FLBUF_SIZES; i++) + sp->sge_fl_buffer_size[i] = t4_read_reg(adapter, + A_SGE_FL_BUFFER_SIZE0 + (4 * i)); return 0; } diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 31c5796587d6..6b7edaf215d2 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -3332,6 +3332,8 @@ get_params__post_init(struct adapter *sc) sc->vres.iscsi.size = val[1] - val[0] + 1; } + t4_init_sge_params(sc); + /* * We've got the params we wanted to query via the firmware. Now grab * some others directly from the chip. @@ -8763,7 +8765,7 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, } case CHELSIO_T4_REGDUMP: { struct t4_regdump *regs = (struct t4_regdump *)data; - int reglen = is_t4(sc) ? T4_REGDUMP_SIZE : T5_REGDUMP_SIZE; + int reglen = t4_get_regs_len(sc); uint8_t *buf; if (regs->len < reglen) { diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 51185f7e9d64..bd949b097fa0 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -625,11 +625,9 @@ t4_read_chip_settings(struct adapter *sc) struct sw_zone_info *swz, *safe_swz; struct hw_buf_info *hwb; - t4_init_sge_params(sc); - m = F_RXPKTCPLMODE; v = F_RXPKTCPLMODE; - r = t4_read_reg(sc, A_SGE_CONTROL); + r = sc->params.sge.sge_control; if ((r & m) != v) { device_printf(sc->dev, "invalid SGE_CONTROL(0x%x)\n", r); rc = EINVAL; @@ -647,7 +645,7 @@ t4_read_chip_settings(struct adapter *sc) /* Filter out unusable hw buffer sizes entirely (mark with -2). */ hwb = &s->hw_buf_info[0]; for (i = 0; i < nitems(s->hw_buf_info); i++, hwb++) { - r = t4_read_reg(sc, A_SGE_FL_BUFFER_SIZE0 + (4 * i)); + r = sc->params.sge.sge_fl_buffer_size[i]; hwb->size = r; hwb->zidx = hwsz_ok(sc, r) ? -1 : -2; hwb->next = -1; diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 28379cc572d3..52e260950d24 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -304,6 +304,10 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_SPT_I219_LM2: case E1000_DEV_ID_PCH_SPT_I219_V2: case E1000_DEV_ID_PCH_LBG_I219_LM3: + case E1000_DEV_ID_PCH_SPT_I219_LM4: + case E1000_DEV_ID_PCH_SPT_I219_V4: + case E1000_DEV_ID_PCH_SPT_I219_LM5: + case E1000_DEV_ID_PCH_SPT_I219_V5: mac->type = e1000_pch_spt; break; case E1000_DEV_ID_82575EB_COPPER: diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 1792e14ef38a..e1464a7b655a 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -142,6 +142,10 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */ #define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */ #define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM4 0x15D7 +#define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8 +#define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3 +#define E1000_DEV_ID_PCH_SPT_I219_V5 0x15D6 #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -957,9 +961,13 @@ struct e1000_dev_spec_ich8lan { E1000_MUTEX nvm_mutex; E1000_MUTEX swflag_mutex; bool nvm_k1_enabled; + bool disable_k1_off; bool eee_disable; u16 eee_lp_ability; enum e1000_ulp_state ulp_state; + bool ulp_capability_disabled; + bool during_suspend_flow; + bool during_dpg_exit; }; struct e1000_dev_spec_82575 { diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index ae97a8c0d389..4c50ce296385 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -288,7 +288,7 @@ static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); - usec_delay(10); + msec_delay(1); mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); @@ -1625,7 +1625,17 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) hw->phy.ops.write_reg_locked(hw, I217_PLL_CLOCK_GATE_REG, phy_reg); - } + + if (speed == SPEED_1000) { + hw->phy.ops.read_reg_locked(hw, HV_PM_CTRL, + &phy_reg); + + phy_reg |= HV_PM_CTRL_K1_CLK_REQ; + + hw->phy.ops.write_reg_locked(hw, HV_PM_CTRL, + phy_reg); + } + } hw->phy.ops.release(hw); if (ret_val) @@ -1718,7 +1728,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG); u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); - if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) + if ((pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) && + (hw->dev_spec.ich8lan.disable_k1_off == FALSE)) fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; else fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index edc1dd14ccc9..6d812911e8b8 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -239,7 +239,7 @@ /* PHY Power Management Control */ #define HV_PM_CTRL PHY_REG(770, 17) -#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 +#define HV_PM_CTRL_K1_CLK_REQ 0x200 #define HV_PM_CTRL_K1_ENABLE 0x4000 #define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index 847d3155e2af..9684b43f5503 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -4146,12 +4146,13 @@ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) *data = E1000_READ_REG(hw, E1000_MPHY_DATA); /* Disable access to mPHY if it was originally disabled */ - if (locked) { + if (locked) ready = e1000_is_mphy_ready(hw); - if (!ready) - return -E1000_ERR_PHY; - } - E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); + if (!ready) + return -E1000_ERR_PHY; + E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, + E1000_MPHY_DIS_ACCESS); + return E1000_SUCCESS; } @@ -4210,12 +4211,13 @@ s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, E1000_WRITE_REG(hw, E1000_MPHY_DATA, data); /* Disable access to mPHY if it was originally disabled */ - if (locked) { + if (locked) ready = e1000_is_mphy_ready(hw); - if (!ready) - return -E1000_ERR_PHY; - } - E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); + if (!ready) + return -E1000_ERR_PHY; + E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, + E1000_MPHY_DIS_ACCESS); + return E1000_SUCCESS; } diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index b8e9750efa37..7e2690eae084 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -193,6 +193,12 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_LBG_I219_LM3, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM4, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V4, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM5, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V5, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index 0a16e6e8957d..5843f0345e0a 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -83,6 +83,7 @@ struct vmbus_chanpkt_hdr { #define VMBUS_CHANPKT_TYPE_GPA 0x0009 #define VMBUS_CHANPKT_TYPE_COMP 0x000b +#define VMBUS_CHANPKT_FLAG_NONE 0 #define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */ #define VMBUS_CHANPKT_CONST_DATA(pkt) \ diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index c1d1c487fa96..38242ceba10f 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -73,9 +73,6 @@ static void hv_nv_on_receive(netvsc_dev *net_dev, static void hn_nvs_sent_none(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, const struct nvsp_msg_ *msg, int); -static void hn_nvs_sent_xact(struct hn_send_ctx *sndc, - struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, - const struct nvsp_msg_ *msg, int dlen); static struct hn_send_ctx hn_send_ctx_none = HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); @@ -121,7 +118,7 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev) unsigned long bitsmap_words = net_dev->bitsmap_words; unsigned long *bitsmap = net_dev->send_section_bitsmap; unsigned long idx; - int ret = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + int ret = HN_NVS_CHIM_IDX_INVALID; int i; for (i = 0; i < bitsmap_words; i++) { @@ -209,9 +206,8 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); vmbus_xact_activate(xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - conn, sizeof(*conn), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + conn, sizeof(*conn), &sndc); if (error != 0) { if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n", error); @@ -316,9 +312,8 @@ hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); vmbus_xact_activate(xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - chim, sizeof(*chim), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + chim, sizeof(*chim), &sndc); if (error) { if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n", error); @@ -396,9 +391,10 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN; disconn.nvs_sig = HN_NVS_RXBUF_SIG; - ret = vmbus_chan_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn), - (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + ret = hn_nvs_send(net_dev->sc->hn_prichan, + VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), + &hn_send_ctx_none); if (ret != 0) { if_printf(net_dev->sc->hn_ifp, "send rxbuf disconn failed: %d\n", ret); @@ -436,33 +432,25 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev) { - nvsp_msg *revoke_pkt; int ret = 0; - /* - * If we got a section count, it means we received a - * send_rx_buf_complete msg - * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore, - * we need to send a revoke msg here - */ if (net_dev->send_section_size) { - /* Send the revoke send buffer */ - revoke_pkt = &net_dev->revoke_packet; - memset(revoke_pkt, 0, sizeof(nvsp_msg)); + struct hn_nvs_chim_disconn disconn; - revoke_pkt->hdr.msg_type = - nvsp_msg_1_type_revoke_send_buf; - revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id = - NETVSC_SEND_BUFFER_ID; - - ret = vmbus_chan_send(net_dev->sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), - (uint64_t)(uintptr_t)&hn_send_ctx_none); /* - * If we failed here, we might as well return and have a leak - * rather than continue and a bugchk + * Disconnect chimney sending buffer from NVS. */ + memset(&disconn, 0, sizeof(disconn)); + disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN; + disconn.nvs_sig = HN_NVS_CHIM_SIG; + + /* NOTE: No response. */ + ret = hn_nvs_send(net_dev->sc->hn_prichan, + VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn), + &hn_send_ctx_none); if (ret != 0) { + if_printf(net_dev->sc->hn_ifp, + "send chim disconn failed: %d\n", ret); return (ret); } } @@ -521,9 +509,8 @@ hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, vmbus_xact_activate(xact); hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); - error = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - init, sizeof(*init), (uint64_t)(uintptr_t)&sndc); + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + init, sizeof(*init), &sndc); if (error) { if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error); vmbus_xact_deactivate(xact); @@ -572,8 +559,9 @@ hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) conf.nvs_mtu = mtu; conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN; - error = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, - &conf, sizeof(conf), (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, + &conf, sizeof(conf), &hn_send_ctx_none); if (error) if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error); return (error); @@ -639,8 +627,9 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) else ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30; - ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, - &ndis, sizeof(ndis), (uint64_t)(uintptr_t)&hn_send_ctx_none); + /* NOTE: No response. */ + ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE, + &ndis, sizeof(ndis), &hn_send_ctx_none); if (ret != 0) { if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret); goto cleanup; @@ -765,16 +754,6 @@ hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) } void -hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused, - struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused, - const struct nvsp_msg_ *msg, int dlen __unused) -{ - /* Copy the response back */ - memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg)); - sema_post(&net_dev->channel_init_sema); -} - -static void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg, int dlen) @@ -835,33 +814,23 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, * Returns 0 on success, non-zero on failure. */ int -hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, +hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt) { - nvsp_msg send_msg; + struct hn_nvs_rndis rndis; int ret; - send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; - if (is_data_pkt) { - /* 0 is RMC_DATA */ - send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0; - } else { - /* 1 is RMC_CONTROL */ - send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; - } - - send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = - sndc->hn_chim_idx; - send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = - sndc->hn_chim_sz; + rndis.nvs_type = HN_NVS_TYPE_RNDIS; + rndis.nvs_rndis_mtype = rndis_mtype; + rndis.nvs_chim_idx = sndc->hn_chim_idx; + rndis.nvs_chim_sz = sndc->hn_chim_sz; if (gpa_cnt) { - ret = vmbus_chan_send_sglist(chan, gpa, gpa_cnt, - &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); + ret = hn_nvs_send_sglist(chan, gpa, gpa_cnt, + &rndis, sizeof(rndis), sndc); } else { - ret = vmbus_chan_send(chan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); + ret = hn_nvs_send(chan, VMBUS_CHANPKT_FLAG_RC, + &rndis, sizeof(rndis), sndc); } return (ret); @@ -878,19 +847,18 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) { const struct vmbus_chanpkt_rxbuf *pkt; - const nvsp_msg *nvsp_msg_pkt; + const struct hn_nvs_hdr *nvs_hdr; netvsc_packet vsc_pkt; netvsc_packet *net_vsc_pkt = &vsc_pkt; int count = 0; int i = 0; int status = nvsp_status_success; - nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkthdr); - - /* Make sure this is a valid nvsp packet */ - if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { - if_printf(rxr->hn_ifp, "packet hdr type %u is invalid!\n", - nvsp_msg_pkt->hdr.msg_type); + /* Make sure that this is a RNDIS message. */ + nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); + if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { + if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", + nvs_hdr->nvs_type); return; } diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index a861c3e18d53..c5dc3b2b9adb 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1256,7 +1256,7 @@ netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc, void *additional_info, struct hn_rx_ring *rxr); int hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel); -int hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, +int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); int hv_nv_get_next_send_section(netvsc_dev *net_dev); void hv_nv_subchan_attach(struct vmbus_channel *chan, diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 4653e776da92..7cf9c54f60d9 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -798,7 +798,7 @@ hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct hn_txdesc *txd = sndc->hn_cbarg; struct hn_tx_ring *txr; - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); txr = txd->txr; @@ -988,8 +988,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) txr->hn_tx_chimney_tried++; send_buf_section_idx = hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { uint8_t *dest = ((uint8_t *)net_dev->send_buf + (send_buf_section_idx * net_dev->send_section_size)); @@ -1045,7 +1044,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) gpa->gpa_len = segs[i].ds_len; } - send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID; send_buf_section_size = 0; done: txd->m = m_head; @@ -1072,8 +1071,8 @@ again: * Make sure that txd is not freed before ETHER_BPF_MTAP. */ hn_txdesc_hold(txd); - error = hv_nv_on_send(txr->hn_chan, true, &txd->send_ctx, - txr->hn_gpa, txr->hn_gpa_cnt); + error = hv_nv_on_send(txr->hn_chan, HN_NVS_RNDIS_MTYPE_DATA, + &txd->send_ctx, txr->hn_gpa, txr->hn_gpa_cnt); if (!error) { ETHER_BPF_MTAP(ifp, txd->m); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 7daf7b282f5f..644b017c0516 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -46,9 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include "hv_net_vsc.h" -#include "hv_rndis.h" -#include "hv_rndis_filter.h" +#include +#include +#include +#include +#include struct hv_rf_recvinfo { const ndis_8021q_info *vlan_info; @@ -275,8 +277,7 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, if (tot_data_buf_len < net_dev->send_section_size) { send_buf_section_idx = hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { char *dest = ((char *)net_dev->send_buf + send_buf_section_idx * net_dev->send_section_size); @@ -287,14 +288,14 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, } /* Failed to allocate chimney send buffer; move on */ } - send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID; send_buf_section_size = 0; sendit: hn_send_ctx_init(&request->send_ctx, cb, request, send_buf_section_idx, send_buf_section_size); - return hv_nv_on_send(device->net_dev->sc->hn_prichan, false, - &request->send_ctx, gpa, gpa_cnt); + return hv_nv_on_send(device->net_dev->sc->hn_prichan, + HN_NVS_RNDIS_MTYPE_CTRL, &request->send_ctx, gpa, gpa_cnt); } /* @@ -1060,12 +1061,16 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int ret; netvsc_dev *net_dev; rndis_device *rndis_dev; - nvsp_msg *init_pkt; rndis_offload_params offloads; struct rndis_recv_scale_cap rsscaps; uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; device_t dev = sc->hn_dev; + struct hn_nvs_subch_req *req; + const struct hn_nvs_subch_resp *resp; + size_t resp_len; + struct vmbus_xact *xact; + uint32_t status, nsubch; rndis_dev = hv_get_rndis_device(); if (rndis_dev == NULL) { @@ -1153,36 +1158,64 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, goto out; } - /* request host to create sub channels */ - init_pkt = &net_dev->channel_init_packet; - memset(init_pkt, 0, sizeof(nvsp_msg)); + /* + * Ask NVS to allocate sub-channels. + */ + xact = vmbus_xact_get(sc->hn_xact, sizeof(*req)); + if (xact == NULL) { + if_printf(sc->hn_ifp, "no xact for nvs subch req\n"); + ret = ENXIO; + goto out; + } - init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel; - init_pkt->msgs.vers_5_msgs.subchannel_request.op = - NVSP_SUBCHANNE_ALLOCATE; - init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels = - net_dev->num_channel - 1; + req = vmbus_xact_req_data(xact); + req->nvs_type = HN_NVS_TYPE_SUBCH_REQ; + req->nvs_op = HN_NVS_SUBCH_OP_ALLOC; + req->nvs_nsubch = net_dev->num_channel - 1; - hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); - ret = vmbus_chan_send(sc->hn_prichan, - VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, - init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); + hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); + vmbus_xact_activate(xact); + + ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, + req, sizeof(*req), &sndc); if (ret != 0) { - device_printf(dev, "Fail to allocate subchannel\n"); + if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret); + vmbus_xact_deactivate(xact); + vmbus_xact_put(xact); goto out; } - sema_wait(&net_dev->channel_init_sema); - - if (init_pkt->msgs.vers_5_msgs.subchn_complete.status != - nvsp_status_success) { - ret = ENODEV; - device_printf(dev, "sub channel complete error\n"); + resp = vmbus_xact_wait(xact, &resp_len); + if (resp_len < sizeof(*resp)) { + if_printf(sc->hn_ifp, "invalid subch resp length %zu\n", + resp_len); + vmbus_xact_put(xact); + ret = EINVAL; + goto out; + } + if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) { + if_printf(sc->hn_ifp, "not subch resp, type %u\n", + resp->nvs_type); + vmbus_xact_put(xact); + ret = EINVAL; goto out; } - net_dev->num_channel = 1 + - init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels; + status = resp->nvs_status; + nsubch = resp->nvs_nsubch; + vmbus_xact_put(xact); + + if (status != HN_NVS_STATUS_OK) { + if_printf(sc->hn_ifp, "subch req failed: %x\n", status); + ret = EIO; + goto out; + } + if (nsubch > net_dev->num_channel - 1) { + if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n", + nsubch, net_dev->num_channel - 1); + nsubch = net_dev->num_channel - 1; + } + net_dev->num_channel = nsubch + 1; ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel); @@ -1242,7 +1275,7 @@ hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused, int dlen __unused) { - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); } @@ -1253,7 +1286,7 @@ hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, { rndis_request *request = sndc->hn_cbarg; - if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) + if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) hn_chim_free(net_dev, sndc->hn_chim_idx); /* diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index abe371a36915..7d86e9e18d02 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -35,8 +35,19 @@ #define HN_NVS_RXBUF_SIG 0xcafe #define HN_NVS_CHIM_SIG 0xface +#define HN_NVS_CHIM_IDX_INVALID 0xffffffff + +#define HN_NVS_RNDIS_MTYPE_DATA 0 +#define HN_NVS_RNDIS_MTYPE_CTRL 1 + +/* + * NVS message transacion status codes. + */ #define HN_NVS_STATUS_OK 1 +/* + * NVS request/response message types. + */ #define HN_NVS_TYPE_INIT 1 #define HN_NVS_TYPE_INIT_RESP 2 #define HN_NVS_TYPE_NDIS_INIT 100 @@ -45,7 +56,11 @@ #define HN_NVS_TYPE_RXBUF_DISCONN 103 #define HN_NVS_TYPE_CHIM_CONN 104 #define HN_NVS_TYPE_CHIM_CONNRESP 105 +#define HN_NVS_TYPE_CHIM_DISCONN 106 +#define HN_NVS_TYPE_RNDIS 107 #define HN_NVS_TYPE_NDIS_CONF 125 +#define HN_NVS_TYPE_SUBCH_REQ 133 +#define HN_NVS_TYPE_SUBCH_RESP 133 /* same as SUBCH_REQ */ /* * Any size less than this one will _not_ work, e.g. hn_nvs_init @@ -54,6 +69,11 @@ */ #define HN_NVS_REQSIZE_MIN 32 +/* NVS message common header */ +struct hn_nvs_hdr { + uint32_t nvs_type; +} __packed; + struct hn_nvs_init { uint32_t nvs_type; /* HN_NVS_TYPE_INIT */ uint32_t nvs_ver_min; @@ -135,4 +155,45 @@ struct hn_nvs_chim_connresp { uint32_t nvs_sectsz; /* section size */ } __packed; +/* No response */ +struct hn_nvs_chim_disconn { + uint32_t nvs_type; /* HN_NVS_TYPE_CHIM_DISCONN */ + uint16_t nvs_sig; /* HN_NVS_CHIM_SIG */ + uint8_t nvs_rsvd[26]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_chim_disconn) >= HN_NVS_REQSIZE_MIN); + +#define HN_NVS_SUBCH_OP_ALLOC 1 + +struct hn_nvs_subch_req { + uint32_t nvs_type; /* HN_NVS_TYPE_SUBCH_REQ */ + uint32_t nvs_op; /* HN_NVS_SUBCH_OP_ */ + uint32_t nvs_nsubch; + uint8_t nvs_rsvd[20]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_subch_req) >= HN_NVS_REQSIZE_MIN); + +struct hn_nvs_subch_resp { + uint32_t nvs_type; /* HN_NVS_TYPE_SUBCH_RESP */ + uint32_t nvs_status; /* HN_NVS_STATUS_ */ + uint32_t nvs_nsubch; +} __packed; + +struct hn_nvs_rndis { + uint32_t nvs_type; /* HN_NVS_TYPE_RNDIS */ + uint32_t nvs_rndis_mtype;/* HN_NVS_RNDIS_MTYPE_ */ + /* + * Chimney sending buffer index and size. + * + * NOTE: + * If nvs_chim_idx is set to HN_NVS_CHIM_IDX_INVALID + * and nvs_chim_sz is set to 0, then chimney sending + * buffer is _not_ used by this RNDIS message. + */ + uint32_t nvs_chim_idx; + uint32_t nvs_chim_sz; + uint8_t nvs_rsvd[16]; +} __packed; +CTASSERT(sizeof(struct hn_nvs_rndis) >= HN_NVS_REQSIZE_MIN); + #endif /* !_IF_HNREG_H_ */ diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 9d2c1267ff73..d6aef5fb81ca 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -30,7 +30,9 @@ #define _IF_HNVAR_H_ #include -#include + +#include +#include struct netvsc_dev_; struct nvsp_msg_; @@ -49,18 +51,19 @@ struct hn_send_ctx { int hn_chim_sz; }; -#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \ -{ \ - .hn_cb = cb, \ - .hn_cbarg = cbarg, \ - .hn_chim_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, \ - .hn_chim_sz = 0 \ +#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \ +{ \ + .hn_cb = cb, \ + .hn_cbarg = cbarg, \ + .hn_chim_idx = HN_NVS_CHIM_IDX_INVALID, \ + .hn_chim_sz = 0 \ } static __inline void hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg, uint32_t chim_idx, int chim_sz) { + sndc->hn_cb = cb; sndc->hn_cbarg = cbarg; sndc->hn_chim_idx = chim_idx; @@ -71,11 +74,29 @@ static __inline void hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb, void *cbarg) { - hn_send_ctx_init(sndc, cb, cbarg, - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0); + + hn_send_ctx_init(sndc, cb, cbarg, HN_NVS_CHIM_IDX_INVALID, 0); } -void hn_nvs_sent_wakeup(struct hn_send_ctx *sndc, +static __inline int +hn_nvs_send(struct vmbus_channel *chan, uint16_t flags, + void *nvs_msg, int nvs_msglen, struct hn_send_ctx *sndc) +{ + + return (vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, flags, + nvs_msg, nvs_msglen, (uint64_t)(uintptr_t)sndc)); +} + +static __inline int +hn_nvs_send_sglist(struct vmbus_channel *chan, struct vmbus_gpa sg[], int sglen, + void *nvs_msg, int nvs_msglen, struct hn_send_ctx *sndc) +{ + + return (vmbus_chan_send_sglist(chan, sg, sglen, nvs_msg, nvs_msglen, + (uint64_t)(uintptr_t)sndc)); +} + +void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, const struct nvsp_msg_ *msg, int dlen); void hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx); diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c deleted file mode 100644 index dacbb3d3e2f0..000000000000 --- a/sys/dev/mcd/mcd.c +++ /dev/null @@ -1,1652 +0,0 @@ -/*- - * Copyright 1993 by Holger Veit (data part) - * Copyright 1993 by Brian Moore (audio part) - * Changes Copyright 1993 by Gary Clark II - * Changes Copyright (C) 1994-1995 by Andrey A. Chernov, Moscow, Russia - * - * Rewrote probe routine to work on newer Mitsumi drives. - * Additional changes (C) 1994 by Jordan K. Hubbard - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This software was developed by Holger Veit and Brian Moore - * for use with "386BSD" and similar operating systems. - * "Similar operating systems" includes mainly non-profit oriented - * systems for research and education, including but not restricted to - * "NetBSD", "FreeBSD", "Mach" (by CMU). - * 4. Neither the name of the developer(s) nor the name "386BSD" - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(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 DEVELOPER(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$"); -static const char __used COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#define MCD_TRACE(format, args...) \ -{ \ - if (sc->debug) { \ - device_printf(sc->dev, "status=0x%02x: ", \ - sc->data.status); \ - printf(format, ## args); \ - } \ -} - -#define RAW_PART 2 - -/* flags */ -#define MCDVALID 0x0001 /* parameters loaded */ -#define MCDINIT 0x0002 /* device is init'd */ -#define MCDNEWMODEL 0x0004 /* device is new model */ -#define MCDLABEL 0x0008 /* label is read */ -#define MCDPROBING 0x0010 /* probing */ -#define MCDREADRAW 0x0020 /* read raw mode (2352 bytes) */ -#define MCDVOLINFO 0x0040 /* already read volinfo */ -#define MCDTOC 0x0080 /* already read toc */ -#define MCDMBXBSY 0x0100 /* local mbx is busy */ - -/* status */ -#define MCDAUDIOBSY MCD_ST_AUDIOBSY /* playing audio */ -#define MCDDSKCHNG MCD_ST_DSKCHNG /* sensed change of disk */ -#define MCDDSKIN MCD_ST_DSKIN /* sensed disk in drive */ -#define MCDDOOROPEN MCD_ST_DOOROPEN /* sensed door open */ - -/* These are apparently the different states a mitsumi can get up to */ -#define MCDCDABSENT 0x0030 -#define MCDCDPRESENT 0x0020 -#define MCDSCLOSED 0x0080 -#define MCDSOPEN 0x00a0 - -#define MCD_MD_UNKNOWN (-1) - -#define MCD_TYPE_UNKNOWN 0 -#define MCD_TYPE_LU002S 1 -#define MCD_TYPE_LU005S 2 -#define MCD_TYPE_LU006S 3 -#define MCD_TYPE_FX001 4 -#define MCD_TYPE_FX001D 5 - -/* reader state machine */ -#define MCD_S_BEGIN 0 -#define MCD_S_BEGIN1 1 -#define MCD_S_WAITSTAT 2 -#define MCD_S_WAITMODE 3 -#define MCD_S_WAITREAD 4 - -/* prototypes */ -static void mcd_start(struct mcd_softc *); -#ifdef NOTYET -static void mcd_configure(struct mcd_softc *sc); -#endif -static int mcd_get(struct mcd_softc *, char *buf, int nmax); -static int mcd_setflags(struct mcd_softc *); -static int mcd_getstat(struct mcd_softc *,int sflg); -static int mcd_send(struct mcd_softc *, int cmd,int nretrys); -static void hsg2msf(int hsg, bcd_t *msf); -static int msf2hsg(bcd_t *msf, int relative); -static int mcd_volinfo(struct mcd_softc *); -static int mcd_waitrdy(struct mcd_softc *,int dly); -static void mcd_timeout(void *arg); -static void mcd_doread(struct mcd_softc *, int state, struct mcd_mbx *mbxin); -static void mcd_soft_reset(struct mcd_softc *); -static int mcd_hard_reset(struct mcd_softc *); -static int mcd_setmode(struct mcd_softc *, int mode); -static int mcd_getqchan(struct mcd_softc *, struct mcd_qchninfo *q); -static int mcd_subchan(struct mcd_softc *, struct ioc_read_subchannel *sc, - int nocopyout); -static int mcd_toc_header(struct mcd_softc *, struct ioc_toc_header *th); -static int mcd_read_toc(struct mcd_softc *); -static int mcd_toc_entrys(struct mcd_softc *, struct ioc_read_toc_entry *te); -#if 0 -static int mcd_toc_entry(struct mcd_softc *, struct ioc_read_toc_single_entry *te); -#endif -static int mcd_stop(struct mcd_softc *); -static int mcd_eject(struct mcd_softc *); -static int mcd_inject(struct mcd_softc *); -static int mcd_playtracks(struct mcd_softc *, struct ioc_play_track *pt); -static int mcd_play(struct mcd_softc *, struct mcd_read2 *pb); -static int mcd_playmsf(struct mcd_softc *, struct ioc_play_msf *pt); -static int mcd_playblocks(struct mcd_softc *, struct ioc_play_blocks *); -static int mcd_pause(struct mcd_softc *); -static int mcd_resume(struct mcd_softc *); -static int mcd_lock_door(struct mcd_softc *, int lock); -static int mcd_close_tray(struct mcd_softc *); -static int mcd_size(struct cdev *dev); - -static d_open_t mcdopen; -static d_close_t mcdclose; -static d_ioctl_t mcdioctl; -static d_strategy_t mcdstrategy; - -static struct cdevsw mcd_cdevsw = { - .d_version = D_VERSION, - .d_open = mcdopen, - .d_close = mcdclose, - .d_read = physread, - .d_ioctl = mcdioctl, - .d_strategy = mcdstrategy, - .d_name = "mcd", - .d_flags = D_DISK, -}; - -#define MCD_RETRYS 5 -#define MCD_RDRETRYS 8 - -#define CLOSE_TRAY_SECS 8 -#define DISK_SENSE_SECS 3 -#define WAIT_FRAC 4 - -/* several delays */ -#define RDELAY_WAITSTAT 300 -#define RDELAY_WAITMODE 300 -#define RDELAY_WAITREAD 800 - -#define MIN_DELAY 15 -#define DELAY_GETREPLY 5000000 - -int -mcd_attach(struct mcd_softc *sc) -{ - int unit; - - unit = device_get_unit(sc->dev); - - MCD_LOCK(sc); - sc->data.flags |= MCDINIT; - mcd_soft_reset(sc); - bioq_init(&sc->data.head); - -#ifdef NOTYET - /* wire controller for interrupts and dma */ - mcd_configure(sc); -#endif - MCD_UNLOCK(sc); - /* name filled in probe */ - sc->mcd_dev_t = make_dev(&mcd_cdevsw, 8 * unit, - UID_ROOT, GID_OPERATOR, 0640, "mcd%d", unit); - - sc->mcd_dev_t->si_drv1 = (void *)sc; - callout_init_mtx(&sc->timer, &sc->mtx, 0); - - return (0); -} - -static int -mcdopen(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mcd_softc *sc; - int r,retry; - - sc = (struct mcd_softc *)dev->si_drv1; - - /* invalidated in the meantime? mark all open part's invalid */ - MCD_LOCK(sc); - if (!(sc->data.flags & MCDVALID) && sc->data.openflags) { - MCD_UNLOCK(sc); - return (ENXIO); - } - - if (mcd_getstat(sc, 1) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) - for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdsn1", hz/WAIT_FRAC); - if ((r = mcd_getstat(sc, 1)) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - if (r != -2) - break; - } - - if (sc->data.status & MCDDOOROPEN) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "door is open\n"); - return (ENXIO); - } - if (!(sc->data.status & MCDDSKIN)) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "no CD inside\n"); - return (ENXIO); - } - if (sc->data.status & MCDDSKCHNG) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "CD not sensed\n"); - return (ENXIO); - } - - if (mcd_size(dev) < 0) { - MCD_UNLOCK(sc); - device_printf(sc->dev, "failed to get disk size\n"); - return (ENXIO); - } - - sc->data.openflags = 1; - sc->data.partflags |= MCDREADRAW; - sc->data.flags |= MCDVALID; - - (void) mcd_lock_door(sc, MCD_LK_LOCK); - if (!(sc->data.flags & MCDVALID)) { - MCD_UNLOCK(sc); - return (ENXIO); - } - - r = mcd_read_toc(sc); - MCD_UNLOCK(sc); - return (r); -} - -static int -mcdclose(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)dev->si_drv1; - - MCD_LOCK(sc); - KASSERT(sc->data.openflags, ("device not open")); - - (void) mcd_lock_door(sc, MCD_LK_UNLOCK); - sc->data.openflags = 0; - sc->data.partflags &= ~MCDREADRAW; - MCD_UNLOCK(sc); - - return (0); -} - -static void -mcdstrategy(struct bio *bp) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)bp->bio_dev->si_drv1; - - /* if device invalidated (e.g. media change, door open), error */ - MCD_LOCK(sc); - if (!(sc->data.flags & MCDVALID)) { - device_printf(sc->dev, "media changed\n"); - bp->bio_error = EIO; - goto bad; - } - - /* read only */ - if (!(bp->bio_cmd == BIO_READ)) { - bp->bio_error = EROFS; - goto bad; - } - - /* no data to read */ - if (bp->bio_bcount == 0) - goto done; - - if (!(sc->data.flags & MCDTOC)) { - bp->bio_error = EIO; - goto bad; - } - - bp->bio_resid = 0; - - /* queue it */ - bioq_disksort(&sc->data.head, bp); - - /* now check whether we can perform processing */ - mcd_start(sc); - MCD_UNLOCK(sc); - return; - -bad: - bp->bio_flags |= BIO_ERROR; -done: - MCD_UNLOCK(sc); - bp->bio_resid = bp->bio_bcount; - biodone(bp); - return; -} - -static void -mcd_start(struct mcd_softc *sc) -{ - struct bio *bp; - - MCD_ASSERT_LOCKED(sc); - if (sc->data.flags & MCDMBXBSY) { - return; - } - - bp = bioq_takefirst(&sc->data.head); - if (bp != 0) { - /* block found to process, dequeue */ - /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ - sc->data.flags |= MCDMBXBSY; - } else { - /* nothing to do */ - return; - } - - sc->data.mbx.retry = MCD_RETRYS; - sc->data.mbx.bp = bp; - - mcd_doread(sc, MCD_S_BEGIN,&(sc->data.mbx)); - return; -} - -static int -mcdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) -{ - struct mcd_softc *sc; - int retry,r; - - sc = (struct mcd_softc *)dev->si_drv1; - - MCD_LOCK(sc); - if (mcd_getstat(sc, 1) == -1) { /* detect disk change too */ - MCD_UNLOCK(sc); - return (EIO); - } -MCD_TRACE("ioctl called 0x%lx\n", cmd); - - switch (cmd) { - case CDIOCSETPATCH: - case CDIOCGETVOL: - case CDIOCSETVOL: - case CDIOCSETMONO: - case CDIOCSETSTERIO: - case CDIOCSETMUTE: - case CDIOCSETLEFT: - case CDIOCSETRIGHT: - MCD_UNLOCK(sc); - return (EINVAL); - case CDIOCEJECT: - r = mcd_eject(sc); - MCD_UNLOCK(sc); - return (r); - case CDIOCSETDEBUG: - sc->data.debug = 1; - MCD_UNLOCK(sc); - return (0); - case CDIOCCLRDEBUG: - sc->data.debug = 0; - MCD_UNLOCK(sc); - return (0); - case CDIOCRESET: - r = mcd_hard_reset(sc); - MCD_UNLOCK(sc); - return (r); - case CDIOCALLOW: - r = mcd_lock_door(sc, MCD_LK_UNLOCK); - MCD_UNLOCK(sc); - return (r); - case CDIOCPREVENT: - r = mcd_lock_door(sc, MCD_LK_LOCK); - MCD_UNLOCK(sc); - return (r); - case CDIOCCLOSE: - r = mcd_inject(sc); - MCD_UNLOCK(sc); - return (r); - } - - if (!(sc->data.flags & MCDVALID)) { - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) - for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdsn2", hz/WAIT_FRAC); - if ((r = mcd_getstat(sc, 1)) == -1) { - MCD_UNLOCK(sc); - return (EIO); - } - if (r != -2) - break; - } - if ( (sc->data.status & (MCDDOOROPEN|MCDDSKCHNG)) - || !(sc->data.status & MCDDSKIN) - || mcd_size(dev) < 0 - ) { - MCD_UNLOCK(sc); - return (ENXIO); - } - sc->data.flags |= MCDVALID; - sc->data.partflags |= MCDREADRAW; - (void) mcd_lock_door(sc, MCD_LK_LOCK); - if (!(sc->data.flags & MCDVALID)) { - MCD_UNLOCK(sc); - return (ENXIO); - } - } - - switch (cmd) { - case DIOCGMEDIASIZE: - *(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize; - r = 0; - break; - case DIOCGSECTORSIZE: - *(u_int *)addr = sc->data.blksize; - r = 0; - break; - case CDIOCPLAYTRACKS: - r = mcd_playtracks(sc, (struct ioc_play_track *) addr); - break; - case CDIOCPLAYBLOCKS: - r = mcd_playblocks(sc, (struct ioc_play_blocks *) addr); - break; - case CDIOCPLAYMSF: - r = mcd_playmsf(sc, (struct ioc_play_msf *) addr); - break; - case CDIOCREADSUBCHANNEL_SYSSPACE: - return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 1); - case CDIOCREADSUBCHANNEL: - return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 0); - case CDIOREADTOCHEADER: - r = mcd_toc_header(sc, (struct ioc_toc_header *) addr); - break; - case CDIOREADTOCENTRYS: - return mcd_toc_entrys(sc, (struct ioc_read_toc_entry *) addr); - case CDIOCRESUME: - r = mcd_resume(sc); - break; - case CDIOCPAUSE: - r = mcd_pause(sc); - break; - case CDIOCSTART: - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - r = EIO; - else - r = 0; - break; - case CDIOCSTOP: - r = mcd_stop(sc); - break; - default: - r = ENOTTY; - } - MCD_UNLOCK(sc); - return (r); -} - -static int -mcd_size(struct cdev *dev) -{ - struct mcd_softc *sc; - int size; - - sc = (struct mcd_softc *)dev->si_drv1; - - if (mcd_volinfo(sc) == 0) { - sc->data.blksize = MCDBLK; - size = msf2hsg(sc->data.volinfo.vol_msf, 0); - sc->data.disksize = size * (MCDBLK/DEV_BSIZE); - return (0); - } - return (-1); -} - -/*************************************************************** - * lower level of driver starts here - **************************************************************/ - -#ifdef NOTDEF -static char -irqs[] = { - 0x00,0x00,0x10,0x20,0x00,0x30,0x00,0x00, - 0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00 -}; - -static char -drqs[] = { - 0x00,0x01,0x00,0x03,0x00,0x05,0x06,0x07, -}; -#endif - -#ifdef NOT_YET -static void -mcd_configure(struct mcd_softc *sc) -{ - MCD_WRITE(sc, MCD_REG_CONFIG, sc->data.config); -} -#endif - -/* Wait for non-busy - return 0 on timeout */ -static int -twiddle_thumbs(struct mcd_softc *sc, int count, char *whine) -{ - int i; - - for (i = 0; i < count; i++) { - if (!(MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL)) - return (1); - } - if (bootverbose) - device_printf(sc->dev, "timeout %s\n", whine); - return (0); -} - -/* check to see if a Mitsumi CD-ROM is attached to the ISA bus */ - -int -mcd_probe(struct mcd_softc *sc) -{ - int i, j; - unsigned char stbytes[3]; - - sc->data.flags = MCDPROBING; - -#ifdef NOTDEF - /* get irq/drq configuration word */ - sc->data.config = irqs[dev->id_irq]; /* | drqs[dev->id_drq];*/ -#else - sc->data.config = 0; -#endif - - /* send a reset */ - MCD_WRITE(sc, MCD_FLAGS, M_RESET); - - /* - * delay awhile by getting any pending garbage (old data) and - * throwing it away. - */ - for (i = 1000000; i != 0; i--) - (void)MCD_READ(sc, MCD_FLAGS); - - /* Get status */ - MCD_WRITE(sc, MCD_DATA, MCD_CMDGETSTAT); - if (!twiddle_thumbs(sc, 1000000, "getting status")) - return (ENXIO); /* Timeout */ - /* Get version information */ - MCD_WRITE(sc, MCD_DATA, MCD_CMDCONTINFO); - for (j = 0; j < 3; j++) { - if (!twiddle_thumbs(sc, 3000, "getting version info")) - return (ENXIO); - stbytes[j] = (MCD_READ(sc, MCD_DATA) & 0xFF); - } - if (stbytes[1] == stbytes[2]) - return (ENXIO); - if (stbytes[2] >= 4 || stbytes[1] != 'M') { - MCD_WRITE(sc, MCD_CTRL, M_PICKLE); - sc->data.flags |= MCDNEWMODEL; - } - sc->data.read_command = MCD_CMDSINGLESPEEDREAD; - switch (stbytes[1]) { - case 'M': - if (stbytes[2] <= 2) { - sc->data.type = MCD_TYPE_LU002S; - sc->data.name = "Mitsumi LU002S"; - } else if (stbytes[2] <= 5) { - sc->data.type = MCD_TYPE_LU005S; - sc->data.name = "Mitsumi LU005S"; - } else { - sc->data.type = MCD_TYPE_LU006S; - sc->data.name = "Mitsumi LU006S"; - } - break; - case 'F': - sc->data.type = MCD_TYPE_FX001; - sc->data.name = "Mitsumi FX001"; - break; - case 'D': - sc->data.type = MCD_TYPE_FX001D; - sc->data.name = "Mitsumi FX001D"; - sc->data.read_command = MCD_CMDDOUBLESPEEDREAD; - break; - default: - sc->data.type = MCD_TYPE_UNKNOWN; - sc->data.name = "Mitsumi ???"; - break; - } - - if (bootverbose) - device_printf(sc->dev, "type %s, version info: %c %x\n", - sc->data.name, stbytes[1], stbytes[2]); - - return (0); -} - - -static int -mcd_waitrdy(struct mcd_softc *sc, int dly) -{ - int i; - - /* wait until flag port senses status ready */ - for (i=0; idev, "timeout getreply\n"); - return (-1); - } - - /* get the data */ - return (MCD_READ(sc, MCD_REG_STATUS) & 0xFF); -} - -static int -mcd_getstat(struct mcd_softc *sc, int sflg) -{ - int i; - - /* get the status */ - if (sflg) - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT); - i = mcd_getreply(sc, DELAY_GETREPLY); - if (i<0 || (i & MCD_ST_CMDCHECK)) { - sc->data.curr_mode = MCD_MD_UNKNOWN; - return (-1); - } - - sc->data.status = i; - - if (mcd_setflags(sc) < 0) - return (-2); - return (sc->data.status); -} - -static int -mcd_setflags(struct mcd_softc *sc) -{ - - /* check flags */ - if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) - || !(sc->data.status & MCDDSKIN)) { - MCD_TRACE("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n"); - mcd_soft_reset(sc); - return (-1); - } - - if (sc->data.status & MCDAUDIOBSY) - sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS; - else if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS) - sc->data.audio_status = CD_AS_PLAY_COMPLETED; - return (0); -} - -static int -mcd_get(struct mcd_softc *sc, char *buf, int nmax) -{ - int i,k; - - for (i=0; idev, "timeout mcd_get\n"); - return (-1); - } - buf[i] = k; - } - return (i); -} - -static int -mcd_send(struct mcd_softc *sc, int cmd,int nretrys) -{ - int i,k=0; - -/*MCD_TRACE("mcd_send: command = 0x%02x\n",cmd,0,0,0);*/ - for (i=0; idev, "media changed\n"); - return (-1); - } - if (i == nretrys) { - device_printf(sc->dev, "mcd_send retry cnt exceeded\n"); - return (-1); - } -/*MCD_TRACE("mcd_send: done\n",0,0,0,0);*/ - return (0); -} - -static void -hsg2msf(int hsg, bcd_t *msf) -{ - hsg += 150; - F_msf(msf) = bin2bcd(hsg % 75); - hsg /= 75; - S_msf(msf) = bin2bcd(hsg % 60); - hsg /= 60; - M_msf(msf) = bin2bcd(hsg); -} - -static int -msf2hsg(bcd_t *msf, int relative) -{ - return (bcd2bin(M_msf(msf)) * 60 + bcd2bin(S_msf(msf))) * 75 + - bcd2bin(F_msf(msf)) - (!relative) * 150; -} - -static int -mcd_volinfo(struct mcd_softc *sc) -{ - - /* Just return if we already have it */ - if (sc->data.flags & MCDVOLINFO) return (0); - -/*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/ - - /* send volume info command */ - if (mcd_send(sc, MCD_CMDGETVOLINFO,MCD_RETRYS) < 0) - return (EIO); - - /* get data */ - if (mcd_get(sc, (char*) &sc->data.volinfo,sizeof(struct mcd_volinfo)) < 0) { - device_printf(sc->dev, "mcd_volinfo: error read data\n"); - return (EIO); - } - - if (sc->data.volinfo.trk_low > 0 && - sc->data.volinfo.trk_high >= sc->data.volinfo.trk_low - ) { - sc->data.flags |= MCDVOLINFO; /* volinfo is OK */ - return (0); - } - - return (EINVAL); -} - -/* state machine to process read requests - * initialize with MCD_S_BEGIN: calculate sizes, and read status - * MCD_S_WAITSTAT: wait for status reply, set mode - * MCD_S_WAITMODE: waits for status reply from set mode, set read command - * MCD_S_WAITREAD: wait for read ready, read data - */ -static void -mcd_timeout(void *arg) -{ - struct mcd_softc *sc; - - sc = (struct mcd_softc *)arg; - - MCD_ASSERT_LOCKED(sc); - mcd_doread(sc, sc->ch_state, sc->ch_mbxsave); -} - -static void -mcd_doread(struct mcd_softc *sc, int state, struct mcd_mbx *mbxin) -{ - struct mcd_mbx *mbx; - struct bio *bp; - int rm, i, k; - struct mcd_read2 rbuf; - int blknum; - caddr_t addr; - - MCD_ASSERT_LOCKED(sc); - mbx = (state!=MCD_S_BEGIN) ? sc->ch_mbxsave : mbxin; - bp = mbx->bp; - -loop: - switch (state) { - case MCD_S_BEGIN: - mbx = sc->ch_mbxsave = mbxin; - - case MCD_S_BEGIN1: -retry_status: - /* get status */ - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT); - mbx->count = RDELAY_WAITSTAT; - sc->ch_state = MCD_S_WAITSTAT; - callout_reset(&sc->timer, hz/100, mcd_timeout, sc); /* XXX */ - return; - case MCD_S_WAITSTAT: - sc->ch_state = MCD_S_WAITSTAT; - callout_stop(&sc->timer); - if (mbx->count-- >= 0) { - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) { - sc->ch_state = MCD_S_WAITSTAT; - callout_reset(&sc->timer, hz/100, - mcd_timeout, sc); /* XXX */ - return; - } - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) - goto retry_status; - if (mcd_setflags(sc) < 0) - goto changed; - MCD_TRACE("got WAITSTAT delay=%d\n", - RDELAY_WAITSTAT-mbx->count); - /* reject, if audio active */ - if (sc->data.status & MCDAUDIOBSY) { - device_printf(sc->dev, "audio is active\n"); - goto readerr; - } - -retry_mode: - /* to check for raw/cooked mode */ - if (sc->data.flags & MCDREADRAW) { - rm = MCD_MD_RAW; - mbx->sz = MCDRBLK; - } else { - rm = MCD_MD_COOKED; - mbx->sz = sc->data.blksize; - } - - if (rm == sc->data.curr_mode) - goto modedone; - - mbx->count = RDELAY_WAITMODE; - - sc->data.curr_mode = MCD_MD_UNKNOWN; - mbx->mode = rm; - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE); - MCD_WRITE(sc, MCD_REG_COMMAND, rm); - - sc->ch_state = MCD_S_WAITMODE; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - } else { - device_printf(sc->dev, "timeout getstatus\n"); - goto readerr; - } - - case MCD_S_WAITMODE: - sc->ch_state = MCD_S_WAITMODE; - callout_stop(&sc->timer); - if (mbx->count-- < 0) { - device_printf(sc->dev, "timeout set mode\n"); - goto readerr; - } - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) { - sc->ch_state = MCD_S_WAITMODE; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); - return; - } - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) { - sc->data.curr_mode = MCD_MD_UNKNOWN; - goto retry_mode; - } - if (mcd_setflags(sc) < 0) - goto changed; - sc->data.curr_mode = mbx->mode; - MCD_TRACE("got WAITMODE delay=%d\n", - RDELAY_WAITMODE-mbx->count); -modedone: - /* for first block */ - mbx->nblk = howmany(bp->bio_bcount, mbx->sz); - mbx->skip = 0; - -nextblock: - blknum = bp->bio_offset / mbx->sz + mbx->skip/mbx->sz; - - MCD_TRACE("mcd_doread: read blknum=%d for bp=%p\n", - blknum, bp); - - /* build parameter block */ - hsg2msf(blknum,rbuf.start_msf); -retry_read: - /* send the read command */ - MCD_WRITE(sc, MCD_REG_COMMAND, sc->data.read_command); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[2]); - MCD_WRITE(sc, MCD_REG_COMMAND, 0); - MCD_WRITE(sc, MCD_REG_COMMAND, 0); - MCD_WRITE(sc, MCD_REG_COMMAND, 1); - - /* Spin briefly (<= 2ms) to avoid missing next block */ - for (i = 0; i < 20; i++) { - k = MCD_READ(sc, MCD_FLAGS); - if (!(k & MFL_DATA_NOT_AVAIL)) - goto got_it; - DELAY(100); - } - - mbx->count = RDELAY_WAITREAD; - sc->ch_state = MCD_S_WAITREAD; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - case MCD_S_WAITREAD: - sc->ch_state = MCD_S_WAITREAD; - callout_stop(&sc->timer); - if (mbx->count-- > 0) { - k = MCD_READ(sc, MCD_FLAGS); - if (!(k & MFL_DATA_NOT_AVAIL)) { /* XXX */ - MCD_TRACE("got data delay=%d\n", - RDELAY_WAITREAD-mbx->count); - got_it: - /* data is ready */ - addr = bp->bio_data + mbx->skip; - - MCD_WRITE(sc, MCD_REG_CTL2,0x04); /* XXX */ - for (i=0; isz; i++) - *addr++ = MCD_READ(sc, MCD_REG_RDATA); - MCD_WRITE(sc, MCD_REG_CTL2,0x0c); /* XXX */ - - k = MCD_READ(sc, MCD_FLAGS); - /* If we still have some junk, read it too */ - if (!(k & MFL_DATA_NOT_AVAIL)) { - MCD_WRITE(sc, MCD_REG_CTL2, 0x04); /* XXX */ - (void)MCD_READ(sc, MCD_REG_RDATA); - (void)MCD_READ(sc, MCD_REG_RDATA); - MCD_WRITE(sc, MCD_REG_CTL2, 0x0c); /* XXX */ - } - - if (--mbx->nblk > 0) { - mbx->skip += mbx->sz; - goto nextblock; - } - - /* return buffer */ - bp->bio_resid = 0; - biodone(bp); - - sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW); - mcd_start(sc); - return; - } - if (!(k & MFL_STATUS_NOT_AVAIL)) { - sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF; - if (sc->data.status & MCD_ST_CMDCHECK) - goto retry_read; - if (mcd_setflags(sc) < 0) - goto changed; - } - sc->ch_state = MCD_S_WAITREAD; - callout_reset(&sc->timer, hz / 100, mcd_timeout, sc); /* XXX */ - return; - } else { - device_printf(sc->dev, "timeout read data\n"); - goto readerr; - } - } - -readerr: - if (mbx->retry-- > 0) { - device_printf(sc->dev, "retrying\n"); - state = MCD_S_BEGIN1; - goto loop; - } -harderr: - /* invalidate the buffer */ - bp->bio_flags |= BIO_ERROR; - bp->bio_resid = bp->bio_bcount; - biodone(bp); - - sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW); - mcd_start(sc); - return; - -changed: - device_printf(sc->dev, "media changed\n"); - goto harderr; - -#ifdef NOTDEF - device_printf(sc->dev, "unit timeout, resetting\n"); - MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET); - DELAY(300000); - (void)mcd_getstat(sc, 1); - (void)mcd_getstat(sc, 1); - /*sc->data.status &= ~MCDDSKCHNG; */ - sc->data.debug = 1; /* preventive set debug mode */ - -#endif - -} - -static int -mcd_lock_door(struct mcd_softc *sc, int lock) -{ - - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDLOCKDRV); - MCD_WRITE(sc, MCD_REG_COMMAND, lock); - if (mcd_getstat(sc, 0) == -1) - return (EIO); - return (0); -} - -static int -mcd_close_tray(struct mcd_softc *sc) -{ - int retry, r; - - if (mcd_getstat(sc, 1) == -1) - return (EIO); - if (sc->data.status & MCDDOOROPEN) { - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDCLOSETRAY); - for (retry = 0; retry < CLOSE_TRAY_SECS * WAIT_FRAC; retry++) { - if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) - (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH, - "mcdcls", hz/WAIT_FRAC); - else { - if ((r = mcd_getstat(sc, 0)) == -1) - return (EIO); - return (0); - } - } - return (ENXIO); - } - return (0); -} - -static int -mcd_eject(struct mcd_softc *sc) -{ - int r; - - if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ - return (EIO); - if (sc->data.status & MCDDOOROPEN) - return (0); - if ((r = mcd_stop(sc)) == EIO) - return (r); - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDEJECTDISK); - if (mcd_getstat(sc, 0) == -1) - return (EIO); - return (0); -} - -static int -mcd_inject(struct mcd_softc *sc) -{ - - if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ - return (EIO); - if (sc->data.status & MCDDOOROPEN) - return mcd_close_tray(sc); - return (0); -} - -static int -mcd_hard_reset(struct mcd_softc *sc) -{ - - MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET); - sc->data.curr_mode = MCD_MD_UNKNOWN; - sc->data.audio_status = CD_AS_AUDIO_INVALID; - return (0); -} - -static void -mcd_soft_reset(struct mcd_softc *sc) -{ - - sc->data.flags &= (MCDINIT|MCDPROBING|MCDNEWMODEL); - sc->data.curr_mode = MCD_MD_UNKNOWN; - sc->data.partflags = 0; - sc->data.audio_status = CD_AS_AUDIO_INVALID; -} - -static int -mcd_setmode(struct mcd_softc *sc, int mode) -{ - int retry, st; - - if (sc->data.curr_mode == mode) - return (0); - if (sc->data.debug) - device_printf(sc->dev, "setting mode to %d\n", mode); - for(retry=0; retrydata.curr_mode = MCD_MD_UNKNOWN; - MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE); - MCD_WRITE(sc, MCD_REG_COMMAND, mode); - if ((st = mcd_getstat(sc, 0)) >= 0) { - sc->data.curr_mode = mode; - return (0); - } - if (st == -2) { - device_printf(sc->dev, "media changed\n"); - break; - } - } - - return (-1); -} - -static int -mcd_toc_header(struct mcd_softc *sc, struct ioc_toc_header *th) -{ - int r; - - if ((r = mcd_volinfo(sc)) != 0) - return (r); - - th->starting_track = bcd2bin(sc->data.volinfo.trk_low); - th->ending_track = bcd2bin(sc->data.volinfo.trk_high); - th->len = 2 * sizeof(u_char) /* start & end tracks */ + - (th->ending_track + 1 - th->starting_track + 1) * - sizeof(struct cd_toc_entry); - - return (0); -} - -static int -mcd_read_toc(struct mcd_softc *sc) -{ - struct ioc_toc_header th; - struct mcd_qchninfo q; - int rc, trk, idx, retry; - - /* Only read TOC if needed */ - if (sc->data.flags & MCDTOC) - return (0); - - if (sc->data.debug) - device_printf(sc->dev, "reading toc header\n"); - - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) - return (EIO); - - if (mcd_setmode(sc, MCD_MD_TOC) != 0) - return (EIO); - - if (sc->data.debug) - device_printf(sc->dev, "get_toc reading qchannel info\n"); - - for(trk=th.starting_track; trk<=th.ending_track; trk++) - sc->data.toc[trk].idx_no = 0; - trk = th.ending_track - th.starting_track + 1; - for(retry=0; retry<600 && trk>0; retry++) - { - if (mcd_getqchan(sc, &q) < 0) break; - idx = bcd2bin(q.idx_no); - if (idx>=th.starting_track && idx<=th.ending_track && q.trk_no==0) { - if (sc->data.toc[idx].idx_no == 0) { - sc->data.toc[idx] = q; - trk--; - } - } - } - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - if (trk != 0) - return (ENXIO); - - /* add a fake last+1 */ - idx = th.ending_track + 1; - sc->data.toc[idx].control = sc->data.toc[idx-1].control; - sc->data.toc[idx].addr_type = sc->data.toc[idx-1].addr_type; - sc->data.toc[idx].trk_no = 0; - sc->data.toc[idx].idx_no = MCD_LASTPLUS1; - sc->data.toc[idx].hd_pos_msf[0] = sc->data.volinfo.vol_msf[0]; - sc->data.toc[idx].hd_pos_msf[1] = sc->data.volinfo.vol_msf[1]; - sc->data.toc[idx].hd_pos_msf[2] = sc->data.volinfo.vol_msf[2]; - - if (sc->data.debug) - { int i; - for (i = th.starting_track; i <= idx; i++) - device_printf(sc->dev, "trk %d idx %d pos %d %d %d\n", - i, - sc->data.toc[i].idx_no > 0x99 ? sc->data.toc[i].idx_no : - bcd2bin(sc->data.toc[i].idx_no), - bcd2bin(sc->data.toc[i].hd_pos_msf[0]), - bcd2bin(sc->data.toc[i].hd_pos_msf[1]), - bcd2bin(sc->data.toc[i].hd_pos_msf[2])); - } - - sc->data.flags |= MCDTOC; - - return (0); -} - -#if 0 -static int -mcd_toc_entry(struct mcd_softc *sc, struct ioc_read_toc_single_entry *te) -{ - struct ioc_toc_header th; - int rc, trk; - - if (te->address_format != CD_MSF_FORMAT - && te->address_format != CD_LBA_FORMAT) - return (EINVAL); - - /* Copy the toc header */ - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - /* verify starting track */ - trk = te->track; - if (trk == 0) - trk = th.starting_track; - else if (trk == MCD_LASTPLUS1) - trk = th.ending_track + 1; - else if (trk < th.starting_track || trk > th.ending_track + 1) - return (EINVAL); - - /* Make sure we have a valid toc */ - if ((rc=mcd_read_toc(sc)) != 0) - return (rc); - - /* Copy the TOC data. */ - if (sc->data.toc[trk].idx_no == 0) - return (EIO); - - te->entry.control = sc->data.toc[trk].control; - te->entry.addr_type = sc->data.toc[trk].addr_type; - te->entry.track = - sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : - bcd2bin(sc->data.toc[trk].idx_no); - switch (te->address_format) { - case CD_MSF_FORMAT: - te->entry.addr.msf.unused = 0; - te->entry.addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); - te->entry.addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); - te->entry.addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - te->entry.addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); - break; - } - return (0); -} -#endif - -static int -mcd_toc_entrys(struct mcd_softc *sc, struct ioc_read_toc_entry *te) -{ - struct cd_toc_entry entries[MCD_MAXTOCS]; - struct ioc_toc_header th; - int rc, n, trk, len; - - if ( te->data_len < sizeof(entries[0]) - || (te->data_len % sizeof(entries[0])) != 0 - || (te->address_format != CD_MSF_FORMAT - && te->address_format != CD_LBA_FORMAT) - ) - return (EINVAL); - - /* Copy the toc header */ - if ((rc = mcd_toc_header(sc, &th)) != 0) - return (rc); - - /* verify starting track */ - trk = te->starting_track; - if (trk == 0) - trk = th.starting_track; - else if (trk == MCD_LASTPLUS1) - trk = th.ending_track + 1; - else if (trk < th.starting_track || trk > th.ending_track + 1) - return (EINVAL); - - len = ((th.ending_track + 1 - trk) + 1) * - sizeof(entries[0]); - if (te->data_len < len) - len = te->data_len; - if (len > sizeof(entries)) - return (EINVAL); - - /* Make sure we have a valid toc */ - if ((rc=mcd_read_toc(sc)) != 0) - return (rc); - - /* Copy the TOC data. */ - for (n = 0; len > 0 && trk <= th.ending_track + 1; trk++) { - if (sc->data.toc[trk].idx_no == 0) - continue; - entries[n].control = sc->data.toc[trk].control; - entries[n].addr_type = sc->data.toc[trk].addr_type; - entries[n].track = - sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : - bcd2bin(sc->data.toc[trk].idx_no); - switch (te->address_format) { - case CD_MSF_FORMAT: - entries[n].addr.msf.unused = 0; - entries[n].addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); - entries[n].addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); - entries[n].addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - entries[n].addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); - break; - } - len -= sizeof(struct cd_toc_entry); - n++; - } - - /* copy the data back */ - MCD_UNLOCK(sc); - return copyout(entries, te->data, n * sizeof(struct cd_toc_entry)); -} - -static int -mcd_stop(struct mcd_softc *sc) -{ - - /* Verify current status */ - if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS && - sc->data.audio_status != CD_AS_PLAY_PAUSED && - sc->data.audio_status != CD_AS_PLAY_COMPLETED) { - if (sc->data.debug) - device_printf(sc->dev, - "stop attempted when not playing, audio status %d\n", - sc->data.audio_status); - return (EINVAL); - } - if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS) - if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) - return (EIO); - sc->data.audio_status = CD_AS_PLAY_COMPLETED; - return (0); -} - -static int -mcd_getqchan(struct mcd_softc *sc, struct mcd_qchninfo *q) -{ - - if (mcd_send(sc, MCD_CMDGETQCHN, MCD_RETRYS) < 0) - return (-1); - if (mcd_get(sc, (char *) q, sizeof(struct mcd_qchninfo)) < 0) - return (-1); - if (sc->data.debug) { - device_printf(sc->dev, - "getqchan control=0x%x addr_type=0x%x trk=%d ind=%d ttm=%d:%d.%d dtm=%d:%d.%d\n", - q->control, q->addr_type, - bcd2bin(q->trk_no), - bcd2bin(q->idx_no), - bcd2bin(q->trk_size_msf[0]), - bcd2bin(q->trk_size_msf[1]), - bcd2bin(q->trk_size_msf[2]), - bcd2bin(q->hd_pos_msf[0]), - bcd2bin(q->hd_pos_msf[1]), - bcd2bin(q->hd_pos_msf[2])); - } - return (0); -} - -static int -mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout) -{ - struct mcd_qchninfo q; - struct cd_sub_channel_info data; - int lba; - - if (sc->data.debug) - device_printf(sc->dev, "subchan af=%d, df=%d\n", - sch->address_format, - sch->data_format); - - if (sch->address_format != CD_MSF_FORMAT && - sch->address_format != CD_LBA_FORMAT) - return (EINVAL); - - if (sch->data_format != CD_CURRENT_POSITION && - sch->data_format != CD_MEDIA_CATALOG) - return (EINVAL); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - if (mcd_getqchan(sc, &q) < 0) - return (EIO); - - data.header.audio_status = sc->data.audio_status; - data.what.position.data_format = sch->data_format; - - switch (sch->data_format) { - case CD_MEDIA_CATALOG: - data.what.media_catalog.mc_valid = 1; - data.what.media_catalog.mc_number[0] = '\0'; - break; - - case CD_CURRENT_POSITION: - data.what.position.control = q.control; - data.what.position.addr_type = q.addr_type; - data.what.position.track_number = bcd2bin(q.trk_no); - data.what.position.index_number = bcd2bin(q.idx_no); - switch (sch->address_format) { - case CD_MSF_FORMAT: - data.what.position.reladdr.msf.unused = 0; - data.what.position.reladdr.msf.minute = bcd2bin(q.trk_size_msf[0]); - data.what.position.reladdr.msf.second = bcd2bin(q.trk_size_msf[1]); - data.what.position.reladdr.msf.frame = bcd2bin(q.trk_size_msf[2]); - data.what.position.absaddr.msf.unused = 0; - data.what.position.absaddr.msf.minute = bcd2bin(q.hd_pos_msf[0]); - data.what.position.absaddr.msf.second = bcd2bin(q.hd_pos_msf[1]); - data.what.position.absaddr.msf.frame = bcd2bin(q.hd_pos_msf[2]); - break; - case CD_LBA_FORMAT: - lba = msf2hsg(q.trk_size_msf, 1); - /* - * Pre-gap has index number of 0, and decreasing MSF - * address. Must be converted to negative LBA, per - * SCSI spec. - */ - if (data.what.position.index_number == 0) - lba = -lba; - data.what.position.reladdr.lba = htonl(lba); - data.what.position.absaddr.lba = htonl(msf2hsg(q.hd_pos_msf, 0)); - break; - } - break; - } - - MCD_UNLOCK(sc); - if (nocopyout == 0) - return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); - bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); - return (0); -} - -static int -mcd_playmsf(struct mcd_softc *sc, struct ioc_play_msf *p) -{ - struct mcd_read2 pb; - - if (sc->data.debug) - device_printf(sc->dev, "playmsf: from %d:%d.%d to %d:%d.%d\n", - p->start_m, p->start_s, p->start_f, - p->end_m, p->end_s, p->end_f); - - if ((p->start_m * 60 * 75 + p->start_s * 75 + p->start_f) >= - (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) || - (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) > - M_msf(sc->data.volinfo.vol_msf) * 60 * 75 + - S_msf(sc->data.volinfo.vol_msf) * 75 + - F_msf(sc->data.volinfo.vol_msf)) - return (EINVAL); - - pb.start_msf[0] = bin2bcd(p->start_m); - pb.start_msf[1] = bin2bcd(p->start_s); - pb.start_msf[2] = bin2bcd(p->start_f); - pb.end_msf[0] = bin2bcd(p->end_m); - pb.end_msf[1] = bin2bcd(p->end_s); - pb.end_msf[2] = bin2bcd(p->end_f); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *pt) -{ - struct mcd_read2 pb; - int a = pt->start_track; - int z = pt->end_track; - int rc, i; - - if ((rc = mcd_read_toc(sc)) != 0) - return (rc); - - if (sc->data.debug) - device_printf(sc->dev, "playtracks from %d:%d to %d:%d\n", - a, pt->start_index, z, pt->end_index); - - if ( a < bcd2bin(sc->data.volinfo.trk_low) - || a > bcd2bin(sc->data.volinfo.trk_high) - || a > z - || z < bcd2bin(sc->data.volinfo.trk_low) - || z > bcd2bin(sc->data.volinfo.trk_high)) - return (EINVAL); - - for (i = 0; i < 3; i++) { - pb.start_msf[i] = sc->data.toc[a].hd_pos_msf[i]; - pb.end_msf[i] = sc->data.toc[z+1].hd_pos_msf[i]; - } - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_playblocks(struct mcd_softc *sc, struct ioc_play_blocks *p) -{ - struct mcd_read2 pb; - - if (sc->data.debug) - device_printf(sc->dev, "playblocks: blkno %d length %d\n", - p->blk, p->len); - - if (p->blk > sc->data.disksize || p->len > sc->data.disksize || - p->blk < 0 || p->len < 0 || - (p->blk + p->len) > sc->data.disksize) - return (EINVAL); - - hsg2msf(p->blk, pb.start_msf); - hsg2msf(p->blk + p->len, pb.end_msf); - - if (mcd_setmode(sc, MCD_MD_COOKED) != 0) - return (EIO); - - return mcd_play(sc, &pb); -} - -static int -mcd_play(struct mcd_softc *sc, struct mcd_read2 *pb) -{ - int retry, st = -1, status; - - sc->data.lastpb = *pb; - for(retry=0; retrystart_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[2]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[0]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[1]); - MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[2]); - critical_exit(); - - status=mcd_getstat(sc, 0); - if (status == -1) - continue; - else if (status != -2) - st = 0; - break; - } - - if (status == -2) { - device_printf(sc->dev, "media changed\n"); - return (ENXIO); - } - if (sc->data.debug) - device_printf(sc->dev, - "mcd_play retry=%d, status=0x%02x\n", retry, status); - if (st < 0) - return (ENXIO); - sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS; - return (0); -} - -static int -mcd_pause(struct mcd_softc *sc) -{ - struct mcd_qchninfo q; - int rc; - - /* Verify current status */ - if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS && - sc->data.audio_status != CD_AS_PLAY_PAUSED) { - if (sc->data.debug) - device_printf(sc->dev, - "pause attempted when not playing, audio status %d\n", - sc->data.audio_status); - return (EINVAL); - } - - /* Get the current position */ - if (mcd_getqchan(sc, &q) < 0) - return (EIO); - - /* Copy it into lastpb */ - sc->data.lastpb.start_msf[0] = q.hd_pos_msf[0]; - sc->data.lastpb.start_msf[1] = q.hd_pos_msf[1]; - sc->data.lastpb.start_msf[2] = q.hd_pos_msf[2]; - - /* Stop playing */ - if ((rc=mcd_stop(sc)) != 0) - return (rc); - - /* Set the proper status and exit */ - sc->data.audio_status = CD_AS_PLAY_PAUSED; - return (0); -} - -static int -mcd_resume(struct mcd_softc *sc) -{ - - if (sc->data.audio_status != CD_AS_PLAY_PAUSED) - return (EINVAL); - return mcd_play(sc, &sc->data.lastpb); -} diff --git a/sys/dev/mcd/mcd_isa.c b/sys/dev/mcd/mcd_isa.c deleted file mode 100644 index 92e8adb57192..000000000000 --- a/sys/dev/mcd/mcd_isa.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include -#include - -static int mcd_isa_probe (device_t); -static int mcd_isa_attach (device_t); -static int mcd_isa_detach (device_t); - -static int mcd_alloc_resources (device_t); -static void mcd_release_resources (device_t); - -static int -mcd_isa_probe (device_t dev) -{ - struct mcd_softc * sc; - int error; - - /* No pnp support */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - /* IO port must be configured. */ - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - return (ENXIO); - - sc = device_get_softc(dev); - sc->dev = dev; - sc->port_rid = 0; - sc->port_type = SYS_RES_IOPORT; - error = mcd_alloc_resources(dev); - if (error) - goto fail; - - error = mcd_probe(sc); - if (error) { - device_printf(dev, "Probe failed.\n"); - goto fail; - } - - device_set_desc(dev, sc->data.name); - -fail: - mcd_release_resources(dev); - return (error); -} - -static int -mcd_isa_attach (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - - sc->dev = dev; - sc->port_rid = 0; - sc->port_type = SYS_RES_IOPORT; - error = mcd_alloc_resources(dev); - if (error) - goto fail; - - error = mcd_probe(sc); - if (error) { - device_printf(dev, "Re-Probe failed.\n"); - goto fail; - } - - error = mcd_attach(sc); - if (error) { - device_printf(dev, "Attach failed.\n"); - goto fail; - } - - return (0); -fail: - mcd_release_resources(dev); - return (error); -} - -static int -mcd_isa_detach (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - - destroy_dev(sc->mcd_dev_t); - - mcd_release_resources(dev); - - return (error); -} - -static int -mcd_alloc_resources (device_t dev) -{ - struct mcd_softc * sc; - int error; - - sc = device_get_softc(dev); - error = 0; - mtx_init(&sc->mtx, "mcd", NULL, MTX_DEF); - - if (sc->port_type) { - sc->port = bus_alloc_resource_any(dev, sc->port_type, - &sc->port_rid, RF_ACTIVE); - if (sc->port == NULL) { - device_printf(dev, "Unable to allocate PORT resource.\n"); - error = ENOMEM; - goto bad; - } - } - - if (sc->irq_type) { - sc->irq = bus_alloc_resource_any(dev, sc->irq_type, - &sc->irq_rid, RF_ACTIVE); - if (sc->irq == NULL) { - device_printf(dev, "Unable to allocate IRQ resource.\n"); - error = ENOMEM; - goto bad; - } - } - - if (sc->drq_type) { - sc->drq = bus_alloc_resource_any(dev, sc->drq_type, - &sc->drq_rid, RF_ACTIVE); - if (sc->drq == NULL) { - device_printf(dev, "Unable to allocate DRQ resource.\n"); - error = ENOMEM; - goto bad; - } - } - -bad: - return (error); -} - -static void -mcd_release_resources (device_t dev) -{ - struct mcd_softc * sc; - - sc = device_get_softc(dev); - - if (sc->irq_ih) - bus_teardown_intr(dev, sc->irq, sc->irq_ih); - if (sc->port) - bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); - if (sc->irq) - bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq); - if (sc->drq) - bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq); - - mtx_destroy(&sc->mtx); - - return; -} - -static device_method_t mcd_isa_methods[] = { - DEVMETHOD(device_probe, mcd_isa_probe), - DEVMETHOD(device_attach, mcd_isa_attach), - DEVMETHOD(device_detach, mcd_isa_detach), - - { 0, 0 } -}; - -static driver_t mcd_isa_driver = { - "mcd", - mcd_isa_methods, - sizeof(struct mcd_softc) -}; - -static devclass_t mcd_devclass; - -DRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0); diff --git a/sys/dev/mcd/mcdreg.h b/sys/dev/mcd/mcdreg.h deleted file mode 100644 index 451fc5de76c3..000000000000 --- a/sys/dev/mcd/mcdreg.h +++ /dev/null @@ -1,219 +0,0 @@ -/*- - * Copyright 1993 by Holger Veit (data part) - * Copyright 1993 by Brian Moore (audio part) - * Changes Copyright 1993 by Gary Clark II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This software was developed by Holger Veit and Brian Moore - * for use with "386BSD" and similar operating systems. - * "Similar operating systems" includes mainly non-profit oriented - * systems for research and education, including but not restricted to - * "NetBSD", "FreeBSD", "Mach" (by CMU). - * 4. Neither the name of the developer(s) nor the name "386BSD" - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(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 DEVELOPER(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. - * - * This file contains definitions for some cdrom control commands - * and status codes. This info was "inherited" from the DOS MTMCDE.SYS - * driver, and is thus not complete (and may even be wrong). Some day - * the manufacturer or anyone else might provide better documentation, - * so this file (and the driver) will then have a better quality. - * - * $FreeBSD$ - */ - -#ifndef MCD_H -#define MCD_H - -/* toc */ -#define MCD_MAXTOCS 104 /* from the Linux driver */ -#define MCD_LASTPLUS1 170 /* special toc entry */ - -typedef unsigned char bcd_t; -#define M_msf(msf) msf[0] -#define S_msf(msf) msf[1] -#define F_msf(msf) msf[2] - -/* io lines used */ -#define MCD_IO_BASE 0x300 - -#define MCD_REG_COMMAND 0 -#define MCD_REG_STATUS 0 -#define MCD_REG_RDATA 0 - -#define MCD_REG_RESET 1 -#define MCD_REG_CTL2 2 /* XXX Is this right? */ -#define MCD_REG_CONFIG 3 - -#define MCD_MASK_DMA 0x07 /* bits 2-0 = DMA channel */ -#define MCD_MASK_IRQ 0x70 /* bits 6-4 = INT number */ - /* 001 = int 2,9 */ - /* 010 = int 3 */ - /* 011 = int 5 */ - /* 100 = int 10 */ - /* 101 = int 11 */ -/* flags */ -#define MFL_DATA_NOT_AVAIL 0x02 -#define MFL_STATUS_NOT_AVAIL 0x04 - -/* New Commands */ -#define M_RESET 0x00 -#define M_PICKLE 0x04 - -/* ports */ -#define MCD_DATA 0 -#define MCD_FLAGS 1 -#define MCD_CTRL 2 -#define CHANNEL 3 /* XXX ??? */ - -/* Status bits */ -#define MCD_ST_DOOROPEN 0x80 -#define MCD_ST_DSKIN 0x40 -#define MCD_ST_DSKCHNG 0x20 -#define MCD_ST_SPINNING 0x10 -#define MCD_ST_AUDIODISK 0x08 /* Audio Disk is in */ -#define MCD_ST_BUSY 0x04 -#define MCD_ST_AUDIOBSY 0x02 /* Audio Disk is Playing */ -#define MCD_ST_CMDCHECK 0x01 /* Command error */ - -/* commands known by the controller */ -#define MCD_CMDRESET 0x00 -#define MCD_CMDGETVOLINFO 0x10 /* gets mcd_volinfo */ -#define MCD_CMDGETDISKINFO 0x11 /* gets mcd_disk information */ -#define MCD_CMDGETQCHN 0x20 /* gets mcd_qchninfo */ -#define MCD_CMDGETSENSE 0x30 /* gets sense info */ -#define MCD_CMDGETSTAT 0x40 /* gets a byte of status */ - -#define MCD_CMDSETMODE 0x50 /* set transmission mode, needs byte */ - -#define MCD_MDBIT_TESTMODE 0x80 /* 0 = DATALENGTH setting is valid */ -#define MCD_MDBIT_DATALENGTH 0x40 /* 0 = Read User Data Only */ - /* 1 = Read Raw sectors (2352 bytes) */ - -#define MCDBLK 2048 /* for cooked mode */ -#define MCDRBLK sizeof(struct mcd_rawsector) /* for raw mode */ - -#define MCD_MDBIT_ECCMODE 0x20 /* 0 = Use secondary correction */ - /* 1 = Don't use secondary ECC */ -#define MCD_MDBIT_SPINDOWN 0x08 /* 0 = Spin Up, 1 = Spin Down */ -#define MCD_MDBIT_GET_TOC 0x04 /* 0 = Get UPC on next GETQCHAN */ - /* 1 = Get TOC on GETQCHAN */ -#define MCD_MDBIT_MUTEDATA 0x01 /* 1 = Don't play back Data as audio */ - -#define MCD_MD_RAW (MCD_MDBIT_DATALENGTH|MCD_MDBIT_ECCMODE|MCD_MDBIT_MUTEDATA) -#define MCD_MD_COOKED (MCD_MDBIT_MUTEDATA) -#define MCD_MD_TOC (MCD_MDBIT_GET_TOC|MCD_MDBIT_MUTEDATA) - -#define MCD_CMDSTOPAUDIO 0x70 -#define MCD_CMDSTOPAUDIOTIME 0x80 -#define MCD_CMDGETVOLUME 0x8E /* gets mcd_volume */ -#define MCD_CMDSETDRIVEMODE 0xA0 /* Set drive mode */ -#define MCD_READUPC 0xA2 /* Get UPC info */ -#define MCD_CMDSETVOLUME 0xAE /* sets mcd_volume */ -#define MCD_CMDREAD1 0xB0 /* read n sectors */ -#define MCD_CMDSINGLESPEEDREAD 0xC0 /* read from-to */ -#define MCD_CMDSTARTAUDIOMSF 0xC1 /* read audio data */ -#define MCD_CMDDOUBLESPEEDREAD 0xC1 /* Read lots of data from the drive */ -#define MCD_CMDGETDRIVEMODE 0xC2 /* Get the drive mode */ -#define MCD_CMDREAD 0xC3 /* Read data from the drive */ -#define MCD_CMDSETINTERLEAVE 0xC8 /* Adjust the interleave */ -#define MCD_CMDCONTINFO 0xDC /* Get controller info */ -#define MCD_CMDSTOP 0xF0 /* Stop everything */ -#define MCD_CMDEJECTDISK 0xF6 -#define MCD_CMDCLOSETRAY 0xF8 - -#define MCD_CMDLOCKDRV 0xFE /* needs byte */ -#define MCD_LK_UNLOCK 0x00 -#define MCD_LK_LOCK 0x01 -#define MCD_LK_TEST 0x02 - -/* DMA Enable Stuff */ -#define MCD_DMA_IRQFLAGS 0x10 /* Set data0 for IRQ click */ - -#define MCD_DMA_PREIRQ 0x01 /* All of these are for */ -#define MCD_DMA_POSTIRQ 0x02 /* MCD_DMA_IRQFLAG... */ -#define MCD_DMA_ERRIRQ 0x04 /* */ - -#define MCD_DMA_TIMEOUT 0x08 /* Set data0 for DMA timeout */ -#define MCD_DMA_UPCFLAG 0x04 /* 1 = Next command will be READUPC */ - -#define MCD_DMA_DMAMODE 0x02 /* 1 = Data uses DMA */ -#define MCD_DMA_TRANSFERLENGTH 0x01 /* data0 = MSB, data1 = LSB of block length */ - -struct mcd_dma_mode { - u_char dma_mode; - u_char data0; /* If dma_mode & 0x10: Use IRQ settings */ - u_char data1; /* Used if dma_mode & 0x01 */ -} __packed; - -struct mcd_volinfo { - bcd_t trk_low; - bcd_t trk_high; - bcd_t vol_msf[3]; - bcd_t trk1_msf[3]; -} __packed; - -struct mcd_qchninfo { - u_char addr_type:4; - u_char control:4; - u_char trk_no; - u_char idx_no; - bcd_t trk_size_msf[3]; - u_char :8; - bcd_t hd_pos_msf[3]; -} __packed; - -struct mcd_volume { - u_char v0l; - u_char v0rs; - u_char v0r; - u_char v0ls; -} __packed; - -struct mcd_holdtime { - u_char units_of_ten_seconds; - /* If this is 0, the default (12) is used */ -} __packed; - -struct mcd_read1 { - bcd_t start_msf[3]; - u_char nsec[3]; -} __packed; - -struct mcd_read2 { - bcd_t start_msf[3]; - bcd_t end_msf[3]; -} __packed; - -struct mcd_rawsector { - u_char sync1[12]; - u_char header[4]; - u_char subheader1[4]; - u_char subheader2[4]; - u_char data[MCDBLK]; - u_char ecc_bits[280]; -} __packed; - -#endif /* MCD_H */ diff --git a/sys/dev/mcd/mcdvar.h b/sys/dev/mcd/mcdvar.h deleted file mode 100644 index 71e45d0b0bd2..000000000000 --- a/sys/dev/mcd/mcdvar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * $FreeBSD$ - */ - -struct mcd_mbx { - short retry; - short nblk; - int sz; - u_long skip; - struct bio * bp; - short count; - short mode; -}; - -struct mcd_data { - short type; - char * name; - short config; - short flags; - u_char read_command; - short status; - int blksize; - u_long disksize; - int partflags; - int openflags; - struct mcd_volinfo volinfo; - struct mcd_qchninfo toc[MCD_MAXTOCS]; - short audio_status; - short curr_mode; - struct mcd_read2 lastpb; - short debug; - struct bio_queue_head head; /* head of bio queue */ - struct mcd_mbx mbx; -}; - -struct mcd_softc { - device_t dev; - struct cdev *mcd_dev_t; - int debug; - - struct resource * port; - int port_rid; - int port_type; - - struct resource * irq; - int irq_rid; - int irq_type; - void * irq_ih; - - struct resource * drq; - int drq_rid; - int drq_type; - - struct mtx mtx; - - struct callout timer; - int ch_state; - struct mcd_mbx * ch_mbxsave; - - struct mcd_data data; -}; - -#define MCD_LOCK(_sc) mtx_lock(&_sc->mtx) -#define MCD_UNLOCK(_sc) mtx_unlock(&_sc->mtx) -#define MCD_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) - -#define MCD_READ(_sc, _reg) bus_read_1(_sc->port, _reg) -#define MCD_WRITE(_sc, _reg, _val) bus_write_1(_sc->port, _reg, _val) - -int mcd_probe (struct mcd_softc *); -int mcd_attach (struct mcd_softc *); diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 063083e0b41d..58d6a0c43efc 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -172,8 +172,6 @@ SYSCTL_INT(_machdep, OID_AUTO, enable_panic_key, CTLFLAG_RW, &enable_panic_key, #define VTY_WCHAN(sc, vty) (&SC_DEV(sc, vty)) -static int debugger; - /* prototypes */ static int sc_allocate_keyboard(sc_softc_t *sc, int unit); static int scvidprobe(int unit, int flags, int cons); @@ -1647,56 +1645,67 @@ sc_cnterm(struct consdev *cp) sc_console = NULL; } +struct sc_cnstate; /* not used yet */ +static void sccnclose(sc_softc_t *sc, struct sc_cnstate *sp); +static void sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags); + static void -sc_cngrab(struct consdev *cp) +sccnopen(sc_softc_t *sc, struct sc_cnstate *sp, int flags) { - scr_stat *scp; + int kbd_mode; if (!cold && - sc_console->sc->cur_scp->index != sc_console->index && - sc_console->sc->cur_scp->smode.mode == VT_AUTO && + sc->cur_scp->index != sc_console->index && + sc->cur_scp->smode.mode == VT_AUTO && sc_console->smode.mode == VT_AUTO) - sc_switch_scr(sc_console->sc, sc_console->index); + sc_switch_scr(sc, sc_console->index); - scp = sc_console->sc->cur_scp; - - if (scp->sc->kbd == NULL) - return; - - if (scp->grabbed++ > 0) + if (sc->kbd == NULL) return; /* * Make sure the keyboard is accessible even when the kbd device * driver is disabled. */ - kbdd_enable(scp->sc->kbd); + kbdd_enable(sc->kbd); - /* we shall always use the keyboard in the XLATE mode here */ - scp->kbd_prev_mode = scp->kbd_mode; - scp->kbd_mode = K_XLATE; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + /* Switch the keyboard to console mode (K_XLATE, polled) on all scp's. */ + kbd_mode = K_XLATE; + (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&kbd_mode); + kbdd_poll(sc->kbd, TRUE); +} - kbdd_poll(scp->sc->kbd, TRUE); +static void +sccnclose(sc_softc_t *sc, struct sc_cnstate *sp) +{ + if (sc->kbd == NULL) + return; + + /* Restore keyboard mode (for the current, possibly-changed scp). */ + kbdd_poll(sc->kbd, FALSE); + (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&sc->cur_scp->kbd_mode); + + kbdd_disable(sc->kbd); +} + +static void +sc_cngrab(struct consdev *cp) +{ + sc_softc_t *sc; + + sc = sc_console->sc; + if (sc->grab_level++ == 0) + sccnopen(sc, NULL, 0); } static void sc_cnungrab(struct consdev *cp) { - scr_stat *scp; + sc_softc_t *sc; - scp = sc_console->sc->cur_scp; /* XXX */ - if (scp->sc->kbd == NULL) - return; - - if (--scp->grabbed > 0) - return; - - kbdd_poll(scp->sc->kbd, FALSE); - - scp->kbd_mode = scp->kbd_prev_mode; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); - kbdd_disable(scp->sc->kbd); + sc = sc_console->sc; + if (--sc->grab_level == 0) + sccnclose(sc, NULL); } static void @@ -1815,7 +1824,7 @@ sccnupdate(scr_stat *scp) if (suspend_in_progress || scp->sc->font_loading_in_progress) return; - if (debugger > 0 || panicstr || shutdown_in_progress) { + if (kdb_active || panicstr || shutdown_in_progress) { sc_touch_scrn_saver(); } else if (scp != scp->sc->cur_scp) { return; @@ -1884,7 +1893,7 @@ scrn_timer(void *arg) #endif /* PC98 */ /* should we stop the screen saver? */ - if (debugger > 0 || panicstr || shutdown_in_progress) + if (kdb_active || panicstr || shutdown_in_progress) sc_touch_scrn_saver(); if (run_scrn_saver) { if (time_uptime > sc->scrn_time_stamp + scrn_blank_time) @@ -2279,7 +2288,7 @@ stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int)) mark_all(sc->cur_scp); if (sc->delayed_next_scr) sc_switch_scr(sc, sc->delayed_next_scr - 1); - if (debugger == 0) + if (!kdb_active) wakeup(&scrn_blanked); } @@ -2474,7 +2483,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) DPRINTF(5, ("error 2, requested vty isn't open!\n")); return EINVAL; } - if ((debugger > 0) && (SC_STAT(tp)->smode.mode == VT_PROCESS)) { + if (kdb_active && SC_STAT(tp)->smode.mode == VT_PROCESS) { splx(s); DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n")); return EINVAL; @@ -2495,7 +2504,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) * is supposed to be locked by splhigh(), but the debugger may * be invoked at splhigh(). */ - if (debugger == 0) + if (!kdb_active) wakeup(VTY_WCHAN(sc,next_scr)); splx(s); DPRINTF(5, ("switch done (new == old)\n")); @@ -2518,7 +2527,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) s = spltty(); /* wake up processes waiting for this vty */ - if (debugger == 0) + if (!kdb_active) wakeup(VTY_WCHAN(sc,next_scr)); /* wait for the controlling process to acknowledge, if necessary */ @@ -2669,7 +2678,7 @@ exchange_scr(sc_softc_t *sc) sc_set_border(scp, scp->border); /* set up the keyboard for the new screen */ - if (sc->old_scp->kbd_mode != scp->kbd_mode) + if (sc->grab_level == 0 && sc->old_scp->kbd_mode != scp->kbd_mode) (void)kbdd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); update_kbd_state(scp, scp->status, LOCK_MASK); @@ -2688,13 +2697,13 @@ sc_puts(scr_stat *scp, u_char *buf, int len, int kernel) #endif if (scp->tsw) { - if (!kdb_active && !mtx_owned(&scp->scr_lock)) { + if (!kdb_active && !mtx_owned(&scp->sc->scr_lock)) { need_unlock = 1; - mtx_lock_spin(&scp->scr_lock); + mtx_lock_spin(&scp->sc->scr_lock); } (*scp->tsw->te_puts)(scp, buf, len, kernel); if (need_unlock) - mtx_unlock_spin(&scp->scr_lock); + mtx_unlock_spin(&scp->sc->scr_lock); } if (scp->sc->delayed_next_scr) @@ -2859,8 +2868,10 @@ scinit(int unit, int flags) * disappeared... */ sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE); - if ((sc->flags & SC_INIT_DONE) == 0) + if ((sc->flags & SC_INIT_DONE) == 0) { + mtx_init(&sc->scr_lock, "scrlock", NULL, MTX_SPIN); SC_VIDEO_LOCKINIT(sc); + } adp = NULL; if (sc->adapter >= 0) { @@ -3077,7 +3088,8 @@ scterm(int unit, int flags) (*scp->tsw->te_term)(scp, &scp->ts); if (scp->ts != NULL) free(scp->ts, M_DEVBUF); - mtx_destroy(&scp->scr_lock); + mtx_destroy(&sc->scr_lock); + mtx_destroy(&sc->video_mtx); /* clear the structure */ if (!(flags & SC_KERNEL_CONSOLE)) { @@ -3302,8 +3314,6 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp) scp->history = NULL; scp->history_pos = 0; scp->history_size = 0; - - mtx_init(&scp->scr_lock, "scrlock", NULL, MTX_SPIN); } int @@ -3413,7 +3423,7 @@ next_code: if (!(flags & SCGETC_CN)) random_harvest_queue(&c, sizeof(c), 1, RANDOM_KEYBOARD); - if (scp->kbd_mode != K_XLATE) + if (sc->grab_level == 0 && scp->kbd_mode != K_XLATE) return KEYCHAR(c); /* if scroll-lock pressed allow history browsing */ @@ -3506,8 +3516,9 @@ next_code: scp->status |= CURSOR_ENABLED; sc_draw_cursor_image(scp); } + /* Only safe in Giant-locked context. */ tp = SC_DEV(sc, scp->index); - if (!kdb_active && tty_opened_ns(tp)) + if (!(flags & SCGETC_CN) && tty_opened_ns(tp)) sctty_outwakeup(tp); #endif } @@ -3558,21 +3569,21 @@ next_code: case RBT: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(0); #endif break; case HALT: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(RB_HALT); #endif break; case PDWN: #ifndef SC_DISABLE_REBOOT - if (enable_reboot) + if (enable_reboot && !(flags & SCGETC_CN)) shutdown_nice(RB_HALT|RB_POWEROFF); #endif break; @@ -3843,7 +3854,7 @@ sc_respond(scr_stat *scp, const u_char *p, int count, int wakeup) void sc_bell(scr_stat *scp, int pitch, int duration) { - if (cold || shutdown_in_progress || !enable_bell) + if (cold || kdb_active || shutdown_in_progress || !enable_bell) return; if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 06e104595c2e..e0aa0beb4328 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -230,6 +230,8 @@ typedef struct sc_softc { char switch_in_progress; char write_in_progress; char blink_in_progress; + int grab_level; + struct mtx scr_lock; /* mutex for sc_puts() */ struct mtx video_mtx; long scrn_time_stamp; @@ -303,9 +305,7 @@ typedef struct scr_stat { void *ts; int status; /* status (bitfield) */ - int grabbed; int kbd_mode; /* keyboard I/O mode */ - int kbd_prev_mode; /* keyboard I/O mode */ int cursor_pos; /* cursor buffer position */ int cursor_oldpos; /* cursor old buffer position */ @@ -344,7 +344,6 @@ typedef struct scr_stat { int splash_save_mode; /* saved mode for splash screen */ int splash_save_status; /* saved status for splash screen */ - struct mtx scr_lock; /* mutex for sc_puts() */ #ifdef _SCR_MD_STAT_DECLARED_ scr_md_stat_t md; /* machine dependent vars */ #endif diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 04be9672deb3..9ab5db614ded 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1897,6 +1897,7 @@ struct vop_vector msdosfs_vnodeops = { .vop_close = msdosfs_close, .vop_create = msdosfs_create, .vop_fsync = msdosfs_fsync, + .vop_fdatasync = vop_stdfdatasync_buf, .vop_getattr = msdosfs_getattr, .vop_inactive = msdosfs_inactive, .vop_link = msdosfs_link, diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index c4c9ca96c36f..c3caf07a9106 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -69,6 +69,5 @@ void ppro_reenable_apic(void); void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec); union savefpu *get_pcb_user_save_td(struct thread *td); union savefpu *get_pcb_user_save_pcb(struct pcb *pcb); -struct pcb *get_pcb_td(struct thread *td); #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 091305205101..d0a0daa77233 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #include "opt_compat.h" @@ -596,4 +596,5 @@ struct sysent sysent[] = { { AS(utimensat_args), (sy_call_t *)sys_utimensat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 547 = utimensat */ { AS(numa_getaffinity_args), (sy_call_t *)sys_numa_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 548 = numa_getaffinity */ { AS(numa_setaffinity_args), (sy_call_t *)sys_numa_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 549 = numa_setaffinity */ + { AS(fdatasync_args), (sy_call_t *)sys_fdatasync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 550 = fdatasync */ }; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 3873c5a8f1d9..e573672f9f72 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -984,8 +984,9 @@ exec_map_first_page(imgp) #if VM_NRESERVLEVEL > 0 vm_object_color(object, 0); #endif - ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL); + ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (ma[0]->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(ma[0]); if (!vm_pager_has_page(object, 0, NULL, &after)) { vm_page_lock(ma[0]); vm_page_free(ma[0]); @@ -1021,10 +1022,10 @@ exec_map_first_page(imgp) VM_OBJECT_WUNLOCK(object); return (EIO); } + vm_page_xunbusy(ma[0]); for (i = 1; i < initial_pagein; i++) vm_page_readahead_finish(ma[i]); } - vm_page_xunbusy(ma[0]); vm_page_lock(ma[0]); vm_page_hold(ma[0]); vm_page_activate(ma[0]); diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 8471591e648d..33eb8bca43cc 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -3123,7 +3123,6 @@ do_sem_wake(struct thread *td, struct _usem *sem) umtxq_busy(&key); cnt = umtxq_count(&key); if (cnt > 0) { - umtxq_signal(&key, 1); /* * Check if count is greater than 0, this means the memory is * still being referenced by user code, so we can safely @@ -3136,6 +3135,7 @@ do_sem_wake(struct thread *td, struct _usem *sem) if (error == -1) error = EFAULT; } + umtxq_signal(&key, 1); } umtxq_unbusy(&key); umtxq_unlock(&key); @@ -3235,8 +3235,6 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem) umtxq_busy(&key); cnt = umtxq_count(&key); if (cnt > 0) { - umtxq_signal(&key, 1); - /* * If this was the last sleeping thread, clear the waiters * flag in _count. @@ -3251,6 +3249,8 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem) error = EFAULT; umtxq_lock(&key); } + + umtxq_signal(&key, 1); } umtxq_unbusy(&key); umtxq_unlock(&key); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 3463236f4e1d..8b5f1897b6ac 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ const char *syscallnames[] = { @@ -557,4 +557,5 @@ const char *syscallnames[] = { "utimensat", /* 547 = utimensat */ "numa_getaffinity", /* 548 = numa_getaffinity */ "numa_setaffinity", /* 549 = numa_setaffinity */ + "fdatasync", /* 550 = fdatasync */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 08c0e0e533fc..2c5840639077 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -993,8 +993,9 @@ id_t id, \ struct vm_domain_policy_entry *policy); } 549 AUE_NULL STD { int numa_setaffinity(cpuwhich_t which, \ - id_t id, \ - const struct vm_domain_policy_entry *policy); } + id_t id, const struct \ + vm_domain_policy_entry *policy); } +550 AUE_FSYNC STD { int fdatasync(int fd); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index 38e1924dfcac..82ec68449296 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -3326,6 +3326,13 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 3; break; } + /* fdatasync */ + case 550: { + struct fdatasync_args *p = params; + iarg[0] = p->fd; /* int */ + *n_args = 1; + break; + } default: *n_args = 0; break; @@ -8862,6 +8869,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* fdatasync */ + case 550: + switch(ndx) { + case 0: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10778,6 +10795,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* fdatasync */ + case 550: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 1096a168f33a..be922edf0b0b 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -182,8 +182,9 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) * lock to page out tobj's pages because tobj is a OBJT_SWAP * type object. */ - m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL); + m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (m->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(m); if (vm_pager_has_page(obj, idx, NULL, NULL)) { rv = vm_pager_get_pages(obj, &m, 1, NULL, NULL); if (rv != VM_PAGER_OK) { @@ -198,8 +199,8 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) } } else vm_page_zero_invalid(m, TRUE); + vm_page_xunbusy(m); } - vm_page_xunbusy(m); vm_page_lock(m); vm_page_hold(m); if (m->queue == PQ_NONE) { diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 8679ad782a74..b4e5a9d28358 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -83,6 +83,7 @@ static int vop_stdset_text(struct vop_set_text_args *ap); static int vop_stdunset_text(struct vop_unset_text_args *ap); static int vop_stdget_writecount(struct vop_get_writecount_args *ap); static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); +static int vop_stdfdatasync(struct vop_fdatasync_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); /* @@ -111,6 +112,7 @@ struct vop_vector default_vnodeops = { .vop_bmap = vop_stdbmap, .vop_close = VOP_NULL, .vop_fsync = VOP_NULL, + .vop_fdatasync = vop_stdfdatasync, .vop_getpages = vop_stdgetpages, .vop_getpages_async = vop_stdgetpages_async, .vop_getwritemount = vop_stdgetwritemount, @@ -640,7 +642,6 @@ int vop_stdfsync(ap) struct vop_fsync_args /* { struct vnode *a_vp; - struct ucred *a_cred; int a_waitfor; struct thread *a_td; } */ *ap; @@ -727,6 +728,24 @@ loop2: return (error); } +static int +vop_stdfdatasync(struct vop_fdatasync_args *ap) +{ + + return (VOP_FSYNC(ap->a_vp, MNT_WAIT, ap->a_td)); +} + +int +vop_stdfdatasync_buf(struct vop_fdatasync_args *ap) +{ + struct vop_fsync_args apf; + + apf.a_vp = ap->a_vp; + apf.a_waitfor = MNT_WAIT; + apf.a_td = ap->a_td; + return (vop_stdfsync(&apf)); +} + /* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */ int vop_stdgetpages(ap) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 68950e127e05..bcf74853b823 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3354,20 +3354,8 @@ freebsd6_ftruncate(struct thread *td, struct freebsd6_ftruncate_args *uap) } #endif -/* - * Sync an open file. - */ -#ifndef _SYS_SYSPROTO_H_ -struct fsync_args { - int fd; -}; -#endif int -sys_fsync(td, uap) - struct thread *td; - struct fsync_args /* { - int fd; - } */ *uap; +kern_fsync(struct thread *td, int fd, bool fullsync) { struct vnode *vp; struct mount *mp; @@ -3375,11 +3363,15 @@ sys_fsync(td, uap) cap_rights_t rights; int error, lock_flags; - AUDIT_ARG_FD(uap->fd); - error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FSYNC), &fp); + AUDIT_ARG_FD(fd); + error = getvnode(td, fd, cap_rights_init(&rights, CAP_FSYNC), &fp); if (error != 0) return (error); vp = fp->f_vnode; +#if 0 + if (!fullsync) + /* XXXKIB: compete outstanding aio writes */; +#endif error = vn_start_write(vp, &mp, V_WAIT | PCATCH); if (error != 0) goto drop; @@ -3396,8 +3388,7 @@ sys_fsync(td, uap) vm_object_page_clean(vp->v_object, 0, 0, 0); VM_OBJECT_WUNLOCK(vp->v_object); } - error = VOP_FSYNC(vp, MNT_WAIT, td); - + error = fullsync ? VOP_FSYNC(vp, MNT_WAIT, td) : VOP_FDATASYNC(vp, td); VOP_UNLOCK(vp, 0); vn_finished_write(mp); drop: @@ -3405,6 +3396,28 @@ drop: return (error); } +/* + * Sync an open file. + */ +#ifndef _SYS_SYSPROTO_H_ +struct fsync_args { + int fd; +}; +#endif +int +sys_fsync(struct thread *td, struct fsync_args *uap) +{ + + return (kern_fsync(td, uap->fd, true)); +} + +int +sys_fdatasync(struct thread *td, struct fdatasync_args *uap) +{ + + return (kern_fsync(td, uap->fd, false)); +} + /* * Rename files. Source and destination must either both be directories, or * both not be directories. If target is a directory, it must be empty. diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 9f3aa140d7ed..648de9a11263 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -703,6 +703,14 @@ vop_add_writecount { IN int inc; }; +%% fdatasync vp L L L + +vop_fdatasync { + IN struct vnode *vp; + IN struct thread *td; +}; + + # The VOPs below are spares at the end of the table to allow new VOPs to be # added in stable branches without breaking the KBI. New VOPs in HEAD should # be added above these spares. When merging a new VOP to a stable branch, diff --git a/sys/mips/mips/cpu.c b/sys/mips/mips/cpu.c index c43ba08c61b8..05f546467e3d 100644 --- a/sys/mips/mips/cpu.c +++ b/sys/mips/mips/cpu.c @@ -164,6 +164,8 @@ mips_get_identity(struct mips_cpuinfo *cpuinfo) cfg1 = mips_rd_config1(); /* Get the Config2 and Config3 registers as well. */ + cfg2 = 0; + cfg3 = 0; if (cfg1 & MIPS_CONFIG1_M) { cfg2 = mips_rd_config2(); if (cfg2 & MIPS_CONFIG2_M) diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 93d33d948abf..c6c76f90d215 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -224,7 +224,6 @@ SUBDIR= \ mac_stub \ mac_test \ malo \ - mcd \ md \ mdio \ mem \ diff --git a/sys/modules/mcd/Makefile b/sys/modules/mcd/Makefile deleted file mode 100644 index 1602c0304c7f..000000000000 --- a/sys/modules/mcd/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../dev/mcd - -KMOD= mcd -SRCS= mcd.c mcd_isa.c \ - bus_if.h device_if.h isa_if.h - -.include diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 148b0478a1fb..6d263ed63be3 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1280,6 +1280,7 @@ sctp_iterator_work(struct sctp_iterator *it) SCTP_INP_INFO_RLOCK(); SCTP_ITERATOR_LOCK(); + sctp_it_ctl.cur_it = it; if (it->inp) { SCTP_INP_RLOCK(it->inp); SCTP_INP_DECR_REF(it->inp); @@ -1287,6 +1288,7 @@ sctp_iterator_work(struct sctp_iterator *it) if (it->inp == NULL) { /* iterator is complete */ done_with_iterator: + sctp_it_ctl.cur_it = NULL; SCTP_ITERATOR_UNLOCK(); SCTP_INP_INFO_RUNLOCK(); if (it->function_atend != NULL) { @@ -1427,13 +1429,11 @@ sctp_iterator_worker(void) sctp_it_ctl.iterator_running = 1; TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { - sctp_it_ctl.cur_it = it; /* now lets work on this one */ TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); SCTP_IPI_ITERATOR_WQ_UNLOCK(); CURVNET_SET(it->vn); sctp_iterator_work(it); - sctp_it_ctl.cur_it = NULL; CURVNET_RESTORE(); SCTP_IPI_ITERATOR_WQ_LOCK(); /* sa_ignore FREED_MEMORY */ diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index c09b8b9aa1d2..01d5c0adeae5 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -71,6 +73,14 @@ static void tcp_lro_rx_done(struct lro_ctrl *lc); static int tcp_lro_rx2(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum, int use_hash); +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, lro, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "TCP LRO"); + +static unsigned tcp_lro_entries = TCP_LRO_ENTRIES; +SYSCTL_UINT(_net_inet_tcp_lro, OID_AUTO, entries, + CTLFLAG_RDTUN | CTLFLAG_MPSAFE, &tcp_lro_entries, 0, + "default number of LRO entries"); + static __inline void tcp_lro_active_insert(struct lro_ctrl *lc, struct lro_head *bucket, struct lro_entry *le) @@ -91,7 +101,7 @@ tcp_lro_active_remove(struct lro_entry *le) int tcp_lro_init(struct lro_ctrl *lc) { - return (tcp_lro_init_args(lc, NULL, TCP_LRO_ENTRIES, 0)); + return (tcp_lro_init_args(lc, NULL, tcp_lro_entries, 0)); } int diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index a9cd81925dac..097a1e3bbf84 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1187,9 +1187,6 @@ tcp_newtcpcb(struct inpcb *inp) tp->t_fb = tcp_func_set_ptr; refcount_acquire(&tp->t_fb->tfb_refcnt); rw_runlock(&tcp_function_lock); - if (tp->t_fb->tfb_tcp_fb_init) { - (*tp->t_fb->tfb_tcp_fb_init)(tp); - } /* * Use the current system default CC algorithm. */ @@ -1201,7 +1198,7 @@ tcp_newtcpcb(struct inpcb *inp) if (CC_ALGO(tp)->cb_init != NULL) if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) { if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1210,7 +1207,7 @@ tcp_newtcpcb(struct inpcb *inp) tp->osd = &tm->osd; if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1271,6 +1268,9 @@ tcp_newtcpcb(struct inpcb *inp) */ tcp_pcap_tcpcb_init(tp); #endif + if (tp->t_fb->tfb_tcp_fb_init) { + (*tp->t_fb->tfb_tcp_fb_init)(tp); + } return (tp); /* XXX */ } @@ -1484,7 +1484,7 @@ tcp_discardcb(struct tcpcb *tp) if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on tcpcb, let's free it. */ if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_inpcb = NULL; uma_zfree(V_tcpcb_zone, tp); @@ -1513,7 +1513,7 @@ tcp_timer_discard(void *ptp) if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on this tcpcb, let's free it. */ if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_inpcb = NULL; uma_zfree(V_tcpcb_zone, tp); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 5bb18b0d8d35..e74db3adda50 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -842,7 +842,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) KASSERT(rblk != NULL, ("cannot find blk %p out of syncache?", blk)); if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 0); refcount_release(&tp->t_fb->tfb_refcnt); tp->t_fb = rblk; if (tp->t_fb->tfb_tcp_fb_init) { diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 837913e190eb..5f231c079784 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -294,11 +294,6 @@ tcp_timer_delack(void *xtp) CURVNET_RESTORE(); return; } - KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, - ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_DELACK) != 0, - ("%s: tp %p delack callout should be running", __func__, tp)); - tp->t_flags |= TF_ACKNOW; TCPSTAT_INC(tcps_delack); (void) tp->t_fb->tfb_tcp_output(tp); @@ -306,6 +301,58 @@ tcp_timer_delack(void *xtp) CURVNET_RESTORE(); } +/* + * When a timer wants to remove a TCB it must + * hold the INP_INFO_RLOCK(). The timer function + * should only have grabbed the INP_WLOCK() when + * it entered. To safely switch to holding both the + * INP_INFO_RLOCK() and the INP_WLOCK() we must first + * grab a reference on the inp, which will hold the inp + * so that it can't be removed. We then unlock the INP_WLOCK(), + * and grab the INP_INFO_RLOCK() lock. Once we have the INP_INFO_RLOCK() + * we proceed again to get the INP_WLOCK() (this preserves proper + * lock order). After acquiring the INP_WLOCK we must check if someone + * else deleted the pcb i.e. the inp_flags check. + * If so we return 1 otherwise we return 0. + * + * No matter what the tcp_inpinfo_lock_add() function + * returns the caller must afterwards call tcp_inpinfo_lock_del() + * to drop the locks and reference properly. + */ + +int +tcp_inpinfo_lock_add(struct inpcb *inp) +{ + in_pcbref(inp); + INP_WUNLOCK(inp); + INP_INFO_RLOCK(&V_tcbinfo); + INP_WLOCK(inp); + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { + return(1); + } + return(0); + +} + +void +tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp) +{ + INP_INFO_RUNLOCK(&V_tcbinfo); + if (inp && (tp == NULL)) { + /* + * If tcp_close/drop() gets called and tp + * returns NULL, then the function dropped + * the inp lock, we hold a reference keeping + * this around, so we must re-aquire the + * INP_WLOCK() in order to proceed with + * our dropping the inp reference. + */ + INP_WLOCK(inp); + } + if (inp && in_pcbrele_wlocked(inp) == 0) + INP_WUNLOCK(inp); +} + void tcp_timer_2msl(void *xtp) { @@ -317,7 +364,6 @@ tcp_timer_2msl(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); @@ -325,21 +371,17 @@ tcp_timer_2msl(void *xtp) if (callout_pending(&tp->t_timers->tt_2msl) || !callout_active(&tp->t_timers->tt_2msl)) { INP_WUNLOCK(tp->t_inpcb); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_2msl); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_2MSL) != 0, - ("%s: tp %p 2msl callout should be running", __func__, tp)); /* * 2 MSL timeout in shutdown went off. If we're closed but * still waiting for peer to close and connection has been idle @@ -355,7 +397,6 @@ tcp_timer_2msl(void *xtp) */ if ((inp->inp_flags & INP_TIMEWAIT) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } @@ -363,15 +404,26 @@ tcp_timer_2msl(void *xtp) tp->t_inpcb && tp->t_inpcb->inp_socket && (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) { TCPSTAT_INC(tcps_finwait2_drops); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_close(tp); + tcp_inpinfo_lock_del(inp, tp); + goto out; } else { if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) { - if (!callout_reset(&tp->t_timers->tt_2msl, - TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) { - tp->t_timers->tt_flags &= ~TT_2MSL_RST; + callout_reset(&tp->t_timers->tt_2msl, + TP_KEEPINTVL(tp), tcp_timer_2msl, tp); + } else { + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; } - } else - tp = tcp_close(tp); + tp = tcp_close(tp); + tcp_inpinfo_lock_del(inp, tp); + goto out; + } } #ifdef TCPDEBUG @@ -383,7 +435,7 @@ tcp_timer_2msl(void *xtp) if (tp != NULL) INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); +out: CURVNET_RESTORE(); } @@ -399,28 +451,23 @@ tcp_timer_keep(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_keep) || !callout_active(&tp->t_timers->tt_keep)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_keep); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_KEEP) != 0, - ("%s: tp %p keep callout should be running", __func__, tp)); /* * Keep-alive timer went off; send something * or drop connection if idle for too long. @@ -452,14 +499,11 @@ tcp_timer_keep(void *xtp) tp->rcv_nxt, tp->snd_una - 1, 0); free(t_template, M_TEMP); } - if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), - tcp_timer_keep, tp)) { - tp->t_timers->tt_flags &= ~TT_KEEP_RST; - } - } else if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), - tcp_timer_keep, tp)) { - tp->t_timers->tt_flags &= ~TT_KEEP_RST; - } + callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), + tcp_timer_keep, tp); + } else + callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), + tcp_timer_keep, tp); #ifdef TCPDEBUG if (inp->inp_socket->so_options & SO_DEBUG) @@ -468,12 +512,16 @@ tcp_timer_keep(void *xtp) #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; dropit: TCPSTAT_INC(tcps_keepdrops); + + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); #ifdef TCPDEBUG @@ -482,9 +530,8 @@ dropit: PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(tp->t_inpcb); - INP_INFO_RUNLOCK(&V_tcbinfo); + tcp_inpinfo_lock_del(inp, tp); +out: CURVNET_RESTORE(); } @@ -499,28 +546,23 @@ tcp_timer_persist(void *xtp) ostate = tp->t_state; #endif - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_persist) || !callout_active(&tp->t_timers->tt_persist)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_persist); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0, - ("%s: tp %p persist callout should be running", __func__, tp)); /* * Persistence timer into zero window. * Force a byte to be output, if possible. @@ -537,7 +579,12 @@ tcp_timer_persist(void *xtp) (ticks - tp->t_rcvtime >= tcp_maxpersistidle || ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { TCPSTAT_INC(tcps_persistdrop); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); + tcp_inpinfo_lock_del(inp, tp); goto out; } /* @@ -547,7 +594,12 @@ tcp_timer_persist(void *xtp) if (tp->t_state > TCPS_CLOSE_WAIT && (ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) { TCPSTAT_INC(tcps_persistdrop); + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, ETIMEDOUT); + tcp_inpinfo_lock_del(inp, tp); goto out; } tcp_setpersist(tp); @@ -555,15 +607,13 @@ tcp_timer_persist(void *xtp) (void) tp->t_fb->tfb_tcp_output(tp); tp->t_flags &= ~TF_FORCEDATA; -out: #ifdef TCPDEBUG if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); + INP_WUNLOCK(inp); +out: CURVNET_RESTORE(); } @@ -573,36 +623,29 @@ tcp_timer_rexmt(void * xtp) struct tcpcb *tp = xtp; CURVNET_SET(tp->t_vnet); int rexmt; - int headlocked; struct inpcb *inp; #ifdef TCPDEBUG int ostate; ostate = tp->t_state; #endif - - INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_rexmt) || !callout_active(&tp->t_timers->tt_rexmt)) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_rexmt); if ((inp->inp_flags & INP_DROPPED) != 0) { INP_WUNLOCK(inp); - INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); return; } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); - KASSERT((tp->t_timers->tt_flags & TT_REXMT) != 0, - ("%s: tp %p rexmt callout should be running", __func__, tp)); tcp_free_sackholes(tp); if (tp->t_fb->tfb_tcp_rexmit_tmr) { /* The stack has a timer action too. */ @@ -616,14 +659,15 @@ tcp_timer_rexmt(void * xtp) if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; TCPSTAT_INC(tcps_timeoutdrop); - + if (tcp_inpinfo_lock_add(inp)) { + tcp_inpinfo_lock_del(inp, tp); + goto out; + } tp = tcp_drop(tp, tp->t_softerror ? tp->t_softerror : ETIMEDOUT); - headlocked = 1; + tcp_inpinfo_lock_del(inp, tp); goto out; } - INP_INFO_RUNLOCK(&V_tcbinfo); - headlocked = 0; if (tp->t_state == TCPS_SYN_SENT) { /* * If the SYN was retransmitted, indicate CWND to be @@ -811,17 +855,14 @@ tcp_timer_rexmt(void * xtp) (void) tp->t_fb->tfb_tcp_output(tp); -out: #ifdef TCPDEBUG if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0, PRU_SLOWTIMO); #endif TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO); - if (tp != NULL) - INP_WUNLOCK(inp); - if (headlocked) - INP_INFO_RUNLOCK(&V_tcbinfo); + INP_WUNLOCK(inp); +out: CURVNET_RESTORE(); } @@ -832,7 +873,6 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) timeout_t *f_callout; struct inpcb *inp = tp->t_inpcb; int cpu = inp_to_cpuid(inp); - uint32_t f_reset; #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE) @@ -846,27 +886,22 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) case TT_DELACK: t_callout = &tp->t_timers->tt_delack; f_callout = tcp_timer_delack; - f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; f_callout = tcp_timer_rexmt; - f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; f_callout = tcp_timer_persist; - f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; f_callout = tcp_timer_keep; - f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; f_callout = tcp_timer_2msl; - f_reset = TT_2MSL_RST; break; default: if (tp->t_fb->tfb_tcp_timer_activate) { @@ -876,24 +911,9 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta) panic("tp %p bad timer_type %#x", tp, timer_type); } if (delta == 0) { - if ((tp->t_timers->tt_flags & timer_type) && - (callout_stop(t_callout) > 0) && - (tp->t_timers->tt_flags & f_reset)) { - tp->t_timers->tt_flags &= ~(timer_type | f_reset); - } + callout_stop(t_callout); } else { - if ((tp->t_timers->tt_flags & timer_type) == 0) { - tp->t_timers->tt_flags |= (timer_type | f_reset); - callout_reset_on(t_callout, delta, f_callout, tp, cpu); - } else { - /* Reset already running callout on the same CPU. */ - if (!callout_reset(t_callout, delta, f_callout, tp)) { - /* - * Callout not cancelled, consider it as not - * properly restarted. */ - tp->t_timers->tt_flags &= ~f_reset; - } - } + callout_reset_on(t_callout, delta, f_callout, tp, cpu); } } @@ -931,30 +951,23 @@ void tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) { struct callout *t_callout; - uint32_t f_reset; tp->t_timers->tt_flags |= TT_STOPPED; - switch (timer_type) { case TT_DELACK: t_callout = &tp->t_timers->tt_delack; - f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; - f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; - f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; - f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; - f_reset = TT_2MSL_RST; break; default: if (tp->t_fb->tfb_tcp_timer_stop) { @@ -968,15 +981,13 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) panic("tp %p bad timer_type %#x", tp, timer_type); } - if (tp->t_timers->tt_flags & timer_type) { - if (callout_async_drain(t_callout, tcp_timer_discard) == 0) { - /* - * Can't stop the callout, defer tcpcb actual deletion - * to the last one. We do this using the async drain - * function and incrementing the count in - */ - tp->t_timers->tt_draincnt++; - } + if (callout_async_drain(t_callout, tcp_timer_discard) == 0) { + /* + * Can't stop the callout, defer tcpcb actual deletion + * to the last one. We do this using the async drain + * function and incrementing the count in + */ + tp->t_timers->tt_draincnt++; } } diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 12481b5708a8..bb78062ddea4 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -191,6 +191,9 @@ extern int tcp_syn_backoff[]; extern int tcp_finwait2_timeout; extern int tcp_fast_finwait2_recycle; +int tcp_inpinfo_lock_add(struct inpcb *inp); +void tcp_inpinfo_lock_del(struct inpcb *inp, struct tcpcb *tp); + void tcp_timer_init(void); void tcp_timer_2msl(void *xtp); void tcp_timer_discard(void *); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 204c354ccfb2..ce5cbee7ee1b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1420,40 +1420,59 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) if (error) return (error); INP_WLOCK_RECHECK(inp); - if (tp->t_state != TCPS_CLOSED) { - /* - * The user has advanced the state - * past the initial point, we can't - * switch since we are down the road - * and a new set of functions may - * not be compatibile. - */ - INP_WUNLOCK(inp); - return(EINVAL); - } blk = find_and_ref_tcp_functions(&fsn); if (blk == NULL) { INP_WUNLOCK(inp); return (ENOENT); } - if (tp->t_fb != blk) { - if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { + if (tp->t_fb == blk) { + /* You already have this */ + refcount_release(&blk->tfb_refcnt); + INP_WUNLOCK(inp); + return (0); + } + if (tp->t_state != TCPS_CLOSED) { + int error=EINVAL; + /* + * The user has advanced the state + * past the initial point, we may not + * be able to switch. + */ + if (blk->tfb_tcp_handoff_ok != NULL) { + /* + * Does the stack provide a + * query mechanism, if so it may + * still be possible? + */ + error = (*blk->tfb_tcp_handoff_ok)(tp); + } + if (error) { refcount_release(&blk->tfb_refcnt); INP_WUNLOCK(inp); - return (ENOENT); + return(error); } + } + if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { + refcount_release(&blk->tfb_refcnt); + INP_WUNLOCK(inp); + return (ENOENT); + } + /* + * Release the old refcnt, the + * lookup acquired a ref on the + * new one already. + */ + if (tp->t_fb->tfb_tcp_fb_fini) { /* - * Release the old refcnt, the - * lookup acquires a ref on the - * new one. + * Tell the stack to cleanup with 0 i.e. + * the tcb is not going away. */ - if (tp->t_fb->tfb_tcp_fb_fini) - (*tp->t_fb->tfb_tcp_fb_fini)(tp); - refcount_release(&tp->t_fb->tfb_refcnt); - tp->t_fb = blk; - if (tp->t_fb->tfb_tcp_fb_init) { - (*tp->t_fb->tfb_tcp_fb_init)(tp); - } + (*tp->t_fb->tfb_tcp_fb_fini)(tp, 0); + } + refcount_release(&tp->t_fb->tfb_refcnt); + tp->t_fb = blk; + if (tp->t_fb->tfb_tcp_fb_init) { + (*tp->t_fb->tfb_tcp_fb_init)(tp); } #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE) { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index abfa21ab216f..5dcd35b8979f 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -116,6 +116,18 @@ struct socket; * does not know your callbacks you must provide a * stop_all function that loops through and calls * tcp_timer_stop() with each of your defined timers. + * Adding a tfb_tcp_handoff_ok function allows the socket + * option to change stacks to query you even if the + * connection is in a later stage. You return 0 to + * say you can take over and run your stack, you return + * non-zero (an error number) to say no you can't. + * If the function is undefined you can only change + * in the early states (before connect or listen). + * tfb_tcp_fb_fini is changed to add a flag to tell + * the old stack if the tcb is being destroyed or + * not. A one in the flag means the TCB is being + * destroyed, a zero indicates its transitioning to + * another stack (via socket option). */ struct tcp_function_block { char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX]; @@ -128,7 +140,7 @@ struct tcp_function_block { struct inpcb *inp, struct tcpcb *tp); /* Optional memory allocation/free routine */ void (*tfb_tcp_fb_init)(struct tcpcb *); - void (*tfb_tcp_fb_fini)(struct tcpcb *); + void (*tfb_tcp_fb_fini)(struct tcpcb *, int); /* Optional timers, must define all if you define one */ int (*tfb_tcp_timer_stop_all)(struct tcpcb *); void (*tfb_tcp_timer_activate)(struct tcpcb *, @@ -136,6 +148,7 @@ struct tcp_function_block { int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); + int (*tfb_tcp_handoff_ok)(struct tcpcb *); volatile uint32_t tfb_refcnt; uint32_t tfb_flags; }; diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 8031e311e89d..0823316e0884 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -1420,8 +1420,10 @@ manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3, if (rh->range.head.length != sizeof(ipfw_range_tlv)) return (1); - if (rh->range.set >= IPFW_MAX_SETS || - rh->range.new_set >= IPFW_MAX_SETS) + /* enable_sets() expects bitmasks. */ + if (op3->opcode != IP_FW_SET_ENABLE && + (rh->range.set >= IPFW_MAX_SETS || + rh->range.new_set >= IPFW_MAX_SETS)) return (EINVAL); ret = 0; diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 0efc396062ad..2d32b7a288cc 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -2600,8 +2600,8 @@ pf_match_addr_range(struct pf_addr *b, struct pf_addr *e, switch (af) { #ifdef INET case AF_INET: - if ((a->addr32[0] < b->addr32[0]) || - (a->addr32[0] > e->addr32[0])) + if ((ntohl(a->addr32[0]) < ntohl(b->addr32[0])) || + (ntohl(a->addr32[0]) > ntohl(e->addr32[0]))) return (0); break; #endif /* INET */ @@ -2611,15 +2611,15 @@ pf_match_addr_range(struct pf_addr *b, struct pf_addr *e, /* check a >= b */ for (i = 0; i < 4; ++i) - if (a->addr32[i] > b->addr32[i]) + if (ntohl(a->addr32[i]) > ntohl(b->addr32[i])) break; - else if (a->addr32[i] < b->addr32[i]) + else if (ntohl(a->addr32[i]) < ntohl(b->addr32[i])) return (0); /* check a <= e */ for (i = 0; i < 4; ++i) - if (a->addr32[i] < e->addr32[i]) + if (ntohl(a->addr32[i]) < ntohl(e->addr32[i])) break; - else if (a->addr32[i] > e->addr32[i]) + else if (ntohl(a->addr32[i]) > ntohl(e->addr32[i])) return (0); break; } diff --git a/sys/sys/queue.h b/sys/sys/queue.h index 1be9e9cc737d..f26c492af1c7 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -76,6 +76,10 @@ * * For details on the use of these macros, see the queue(3) manual page. * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) * * SLIST LIST STAILQ TAILQ * _HEAD + + + + @@ -101,10 +105,10 @@ * _INSERT_BEFORE - + - + * _INSERT_AFTER + + + + * _INSERT_TAIL - - + + - * _CONCAT - - + + + * _CONCAT s s + + * _REMOVE_AFTER + - + - * _REMOVE_HEAD + - + - - * _REMOVE + + + + + * _REMOVE s + s + * _SWAP + + + + * */ @@ -183,6 +187,19 @@ struct { \ /* * Singly-linked List functions. */ +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) @@ -447,6 +464,23 @@ struct { \ #define QMD_LIST_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index d2cc1bfe479d..599524be83cc 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #define SYS_syscall 0 @@ -467,4 +467,5 @@ #define SYS_utimensat 547 #define SYS_numa_getaffinity 548 #define SYS_numa_setaffinity 549 -#define SYS_MAXSYSCALL 550 +#define SYS_fdatasync 550 +#define SYS_MAXSYSCALL 551 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 9332dcda230c..7c7f8af1ef8e 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,7 +1,7 @@ # FreeBSD system call object files. # DO NOT EDIT-- this file is automatically generated. # $FreeBSD$ -# created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery +# created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib MIASM = \ syscall.o \ exit.o \ @@ -395,4 +395,5 @@ MIASM = \ futimens.o \ utimensat.o \ numa_getaffinity.o \ - numa_setaffinity.o + numa_setaffinity.o \ + fdatasync.o diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index a0e58e9e79c1..42ee5159e977 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -100,6 +100,7 @@ int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); int kern_fstat(struct thread *td, int fd, struct stat *sbp); int kern_fstatfs(struct thread *td, int fd, struct statfs *buf); +int kern_fsync(struct thread *td, int fd, bool fullsync); int kern_ftruncate(struct thread *td, int fd, off_t length); int kern_futimes(struct thread *td, int fd, struct timeval *tptr, enum uio_seg tptrseg); diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index fab19ad6570e..5e9a8d37aace 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 303729 2016-08-03 18:48:56Z bdrewery + * created from FreeBSD: head/sys/kern/syscalls.master 304176 2016-08-15 19:08:51Z kib */ #ifndef _SYS_SYSPROTO_H_ @@ -1788,6 +1788,9 @@ struct numa_setaffinity_args { char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; char policy_l_[PADL_(const struct vm_domain_policy_entry *)]; const struct vm_domain_policy_entry * policy; char policy_r_[PADR_(const struct vm_domain_policy_entry *)]; }; +struct fdatasync_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2174,6 +2177,7 @@ int sys_futimens(struct thread *, struct futimens_args *); int sys_utimensat(struct thread *, struct utimensat_args *); int sys_numa_getaffinity(struct thread *, struct numa_getaffinity_args *); int sys_numa_setaffinity(struct thread *, struct numa_setaffinity_args *); +int sys_fdatasync(struct thread *, struct fdatasync_args *); #ifdef COMPAT_43 @@ -2951,6 +2955,7 @@ int freebsd10_pipe(struct thread *, struct freebsd10_pipe_args *); #define SYS_AUE_utimensat AUE_FUTIMESAT #define SYS_AUE_numa_getaffinity AUE_NULL #define SYS_AUE_numa_setaffinity AUE_NULL +#define SYS_AUE_fdatasync AUE_FSYNC #undef PAD_ #undef PADL_ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 02707117d21b..181ec7f1d5e0 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -720,6 +720,7 @@ int vfs_write_suspend(struct mount *mp, int flags); int vfs_write_suspend_umnt(struct mount *mp); void vnlru_free(int, struct vfsops *); int vop_stdbmap(struct vop_bmap_args *); +int vop_stdfdatasync_buf(struct vop_fdatasync_args *); int vop_stdfsync(struct vop_fsync_args *); int vop_stdgetwritemount(struct vop_getwritemount_args *); int vop_stdgetpages(struct vop_getpages_args *); diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 8551085b50a7..04e0ae93b232 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -255,6 +255,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, gbflags); @@ -309,7 +311,7 @@ retry: if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -325,6 +327,8 @@ retry: } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0); @@ -386,7 +390,7 @@ retry: flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -401,6 +405,8 @@ retry: goto fail; } nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags); @@ -478,10 +484,16 @@ fail: * We shall not leave the freed blocks on the vnode * buffer object lists. */ - bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { - bp->b_flags |= (B_INVAL | B_RELBUF); - bp->b_flags &= ~B_ASYNC; + KASSERT(bp->b_blkno == fsbtodb(fs, *blkp), + ("mismatch1 l %jd %jd b %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, + (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp))); + bp->b_flags |= B_INVAL | B_RELBUF | B_NOCACHE; + bp->b_flags &= ~(B_ASYNC | B_CACHE); brelse(bp); } deallocated += fs->fs_bsize; @@ -524,6 +536,18 @@ fail: * cleared, free the blocks. */ for (blkp = allociblk; blkp < allocblk; blkp++) { +#ifdef INVARIANTS + if (blkp == allociblk) + lbns_remfree = lbns; + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); + if (bp != NULL) { + panic("zombie1 %jd %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp)); + } + lbns_remfree++; +#endif ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number, vp->v_type, NULL); } @@ -818,6 +842,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, @@ -873,7 +899,7 @@ retry: if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -889,6 +915,8 @@ retry: } pref = newb + fs->fs_frag; nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, @@ -951,7 +979,7 @@ retry: flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); - if (++reclaimed == 1) { + if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); @@ -966,6 +994,8 @@ retry: goto fail; } nb = newb; + MPASS(allocblk < allociblk + nitems(allociblk)); + MPASS(lbns_remfree < lbns + nitems(lbns)); *allocblk++ = nb; *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags); @@ -1049,10 +1079,16 @@ fail: * We shall not leave the freed blocks on the vnode * buffer object lists. */ - bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); if (bp != NULL) { - bp->b_flags |= (B_INVAL | B_RELBUF); - bp->b_flags &= ~B_ASYNC; + KASSERT(bp->b_blkno == fsbtodb(fs, *blkp), + ("mismatch2 l %jd %jd b %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)*lbns_remfree, + (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp))); + bp->b_flags |= B_INVAL | B_RELBUF | B_NOCACHE; + bp->b_flags &= ~(B_ASYNC | B_CACHE); brelse(bp); } deallocated += fs->fs_bsize; @@ -1095,6 +1131,18 @@ fail: * cleared, free the blocks. */ for (blkp = allociblk; blkp < allocblk; blkp++) { +#ifdef INVARIANTS + if (blkp == allociblk) + lbns_remfree = lbns; + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, + GB_NOCREAT | GB_UNMAPPED); + if (bp != NULL) { + panic("zombie2 %jd %ju %ju", + (intmax_t)bp->b_lblkno, (uintmax_t)bp->b_blkno, + (uintmax_t)fsbtodb(fs, *blkp)); + } + lbns_remfree++; +#endif ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number, vp->v_type, NULL); } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index b4ec348f3329..203bc6684d01 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -174,6 +174,11 @@ void softdep_freework(struct workhead *); * deadlock when flushing snapshot inodes while holding snaplk. */ #define NO_INO_UPDT 0x00000001 +/* + * Request data sync only from ffs_syncvnode(), not touching even more + * metadata than NO_INO_UPDT. + */ +#define DATA_ONLY 0x00000002 int ffs_rdonly(struct inode *); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 69182850ffe2..27654804046d 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -103,6 +103,7 @@ __FBSDID("$FreeBSD$"); extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone); #endif static vop_fsync_t ffs_fsync; +static vop_fdatasync_t ffs_fdatasync; static vop_lock1_t ffs_lock; static vop_read_t ffs_read; static vop_write_t ffs_write; @@ -123,6 +124,7 @@ static vop_vptofh_t ffs_vptofh; struct vop_vector ffs_vnodeops1 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_getpages = vnode_pager_local_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, @@ -135,6 +137,7 @@ struct vop_vector ffs_vnodeops1 = { struct vop_vector ffs_fifoops1 = { .vop_default = &ufs_fifoops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_reallocblks = ffs_reallocblks, /* XXX: really ??? */ .vop_vptofh = ffs_vptofh, }; @@ -143,6 +146,7 @@ struct vop_vector ffs_fifoops1 = { struct vop_vector ffs_vnodeops2 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_getpages = vnode_pager_local_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, @@ -161,6 +165,7 @@ struct vop_vector ffs_vnodeops2 = { struct vop_vector ffs_fifoops2 = { .vop_default = &ufs_fifoops, .vop_fsync = ffs_fsync, + .vop_fdatasync = ffs_fdatasync, .vop_lock1 = ffs_lock, .vop_reallocblks = ffs_reallocblks, .vop_strategy = ffsext_strategy, @@ -216,10 +221,10 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags) { struct inode *ip; struct bufobj *bo; - struct buf *bp; - struct buf *nbp; + struct buf *bp, *nbp; ufs_lbn_t lbn; - int error, wait, passes; + int error, passes; + bool still_dirty, wait; ip = VTOI(vp); ip->i_flag &= ~IN_NEEDSYNC; @@ -238,7 +243,7 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags) */ error = 0; passes = 0; - wait = 0; /* Always do an async pass first. */ + wait = false; /* Always do an async pass first. */ lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); BO_LOCK(bo); loop: @@ -254,15 +259,23 @@ loop: if ((bp->b_vflags & BV_SCANNED) != 0) continue; bp->b_vflags |= BV_SCANNED; - /* Flush indirects in order. */ + /* + * Flush indirects in order, if requested. + * + * Note that if only datasync is requested, we can + * skip indirect blocks when softupdates are not + * active. Otherwise we must flush them with data, + * since dependencies prevent data block writes. + */ if (waitfor == MNT_WAIT && bp->b_lblkno <= -NDADDR && - lbn_level(bp->b_lblkno) >= passes) + (lbn_level(bp->b_lblkno) >= passes || + ((flags & DATA_ONLY) != 0 && !DOINGSOFTDEP(vp)))) continue; if (bp->b_lblkno > lbn) panic("ffs_syncvnode: syncing truncated data."); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) == 0) { BO_UNLOCK(bo); - } else if (wait != 0) { + } else if (wait) { if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, BO_LOCKPTR(bo)) != 0) { @@ -330,30 +343,58 @@ next: * these will be done with one sync and one async pass. */ if (bo->bo_dirty.bv_cnt > 0) { - /* Write the inode after sync passes to flush deps. */ - if (wait && DOINGSOFTDEP(vp) && (flags & NO_INO_UPDT) == 0) { - BO_UNLOCK(bo); - ffs_update(vp, 1); - BO_LOCK(bo); + if ((flags & DATA_ONLY) == 0) { + still_dirty = true; + } else { + /* + * For data-only sync, dirty indirect buffers + * are ignored. + */ + still_dirty = false; + TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) { + if (bp->b_lblkno > -NDADDR) { + still_dirty = true; + break; + } + } } - /* switch between sync/async. */ - wait = !wait; - if (wait == 1 || ++passes < NIADDR + 2) - goto loop; + + if (still_dirty) { + /* Write the inode after sync passes to flush deps. */ + if (wait && DOINGSOFTDEP(vp) && + (flags & NO_INO_UPDT) == 0) { + BO_UNLOCK(bo); + ffs_update(vp, 1); + BO_LOCK(bo); + } + /* switch between sync/async. */ + wait = !wait; + if (wait || ++passes < NIADDR + 2) + goto loop; #ifdef INVARIANTS - if (!vn_isdisk(vp, NULL)) - vn_printf(vp, "ffs_fsync: dirty "); + if (!vn_isdisk(vp, NULL)) + vn_printf(vp, "ffs_fsync: dirty "); #endif + } } BO_UNLOCK(bo); error = 0; - if ((flags & NO_INO_UPDT) == 0) - error = ffs_update(vp, 1); - if (DOINGSUJ(vp)) - softdep_journal_fsync(VTOI(vp)); + if ((flags & DATA_ONLY) == 0) { + if ((flags & NO_INO_UPDT) == 0) + error = ffs_update(vp, 1); + if (DOINGSUJ(vp)) + softdep_journal_fsync(VTOI(vp)); + } return (error); } +static int +ffs_fdatasync(struct vop_fdatasync_args *ap) +{ + + return (ffs_syncvnode(ap->a_vp, MNT_WAIT, DATA_ONLY)); +} + static int ffs_lock(ap) struct vop_lock1_args /* { diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 33b997a261f7..60b822e63079 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -236,8 +236,9 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) VM_OBJECT_WLOCK(object); pindex = OFF_TO_IDX(offset); - m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); + m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (m->valid != VM_PAGE_BITS_ALL) { + vm_page_xbusy(m); rv = vm_pager_get_pages(object, &m, 1, NULL, NULL); if (rv != VM_PAGER_OK) { vm_page_lock(m); @@ -246,8 +247,8 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) m = NULL; goto out; } + vm_page_xunbusy(m); } - vm_page_xunbusy(m); vm_page_lock(m); vm_page_hold(m); vm_page_activate(m); diff --git a/usr.bin/nfsstat/nfsstat.c b/usr.bin/nfsstat/nfsstat.c index d0bda7d6f911..90be2953ffd8 100644 --- a/usr.bin/nfsstat/nfsstat.c +++ b/usr.bin/nfsstat/nfsstat.c @@ -130,7 +130,8 @@ static void compute_new_stats(struct nfsstatsv1 *cur_stats, struct stattypes { int stat_type; int nfs_type; -} static statstruct[] = { +}; +static struct stattypes statstruct[] = { {STAT_TYPE_READ, NFSV4OP_READ}, {STAT_TYPE_WRITE, NFSV4OP_WRITE}, {STAT_TYPE_COMMIT, NFSV4OP_COMMIT} diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c index 32e47a07e6f9..78bc610ae8e0 100644 --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -82,11 +82,11 @@ static char pathbuf[MAXPATHLEN + 1]; static const char *allv[] = { "rpcgen", "-s", "udp", "-s", "tcp", }; -static int allc = sizeof (allv)/sizeof (allv[0]); +static int allc = nitems(allv); static const char *allnv[] = { "rpcgen", "-s", "netpath", }; -static int allnc = sizeof (allnv)/sizeof (allnv[0]); +static int allnc = nitems(allnv); /* * machinations for handling expanding argument list diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 4c55ff4cfe29..74195f606aec 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -261,7 +261,7 @@ display(void) int i, j; /* Get the load average over the last minute. */ - (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); + (void) getloadavg(avenrun, nitems(avenrun)); (*curcmd->c_fetch)(); if (curcmd->c_flags & CF_LOADAV) { j = 5.0*avenrun[0] + 0.5; @@ -293,7 +293,7 @@ display(void) GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc[5]); GETSYSCTL("kstat.zfs.misc.arcstats.other_size", arc[6]); wmove(wload, 0, 0); wclrtoeol(wload); - for (i = 0 ; i < sizeof(arc) / sizeof(arc[0]) ; i++) { + for (i = 0 ; i < nitems(arc); i++) { if (arc[i] > 10llu * 1024 * 1024 * 1024 ) { wprintw(wload, "%7lluG", arc[i] >> 30); } @@ -318,7 +318,7 @@ void load(void) { - (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); + (void) getloadavg(avenrun, nitems(avenrun)); mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", avenrun[0], avenrun[1], avenrun[2]); clrtoeol(); diff --git a/usr.bin/tty/tty.c b/usr.bin/tty/tty.c index 450722a66984..fac74d034b5d 100644 --- a/usr.bin/tty/tty.c +++ b/usr.bin/tty/tty.c @@ -63,17 +63,18 @@ main(int argc, char *argv[]) case '?': default: usage(); + /* NOTREACHED */ } - t = ttyname(0); + t = ttyname(STDIN_FILENO); if (!sflag) puts(t ? t : "not a tty"); - exit(t ? 0 : 1); + exit(t ? EXIT_SUCCESS : EXIT_FAILURE); } static void usage(void) { - fprintf(stderr, "usage: tty [-s]\n"); + fprintf(stderr, "usage: %s [-s]\n", getprogname()); exit(2); } diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c index 04c8ceac994f..89d75294e2a3 100644 --- a/usr.sbin/bsdinstall/partedit/gpart_ops.c +++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -795,6 +795,7 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) { struct gconfig *gc; struct gprovider *pp, **providers; + intmax_t sectorsize, stripesize, offset; intmax_t lastend; intmax_t start, end; intmax_t maxsize, maxstart; @@ -845,12 +846,25 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; - /* Compute beginning of new partition and maximum available space */ - if (pp->lg_stripesize > 0 && - (maxstart*pp->lg_sectorsize % pp->lg_stripesize) != 0) { - intmax_t offset = (pp->lg_stripesize - - ((maxstart*pp->lg_sectorsize) % pp->lg_stripesize)) / - pp->lg_sectorsize; + /* + * Round the start and size of the largest available space up to + * the nearest multiple of the adjusted stripe size. + * + * The adjusted stripe size is the least common multiple of the + * actual stripe size, or the sector size if no stripe size was + * reported, and 4096. The reason for this is that contemporary + * disks often have 4096-byte physical sectors but report 512 + * bytes instead for compatibility with older / broken operating + * systems and BIOSes. For the same reasons, virtualized storage + * may also report a 512-byte stripe size, or none at all. + */ + sectorsize = pp->lg_sectorsize; + if ((stripesize = pp->lg_stripesize) == 0) + stripesize = sectorsize; + while (stripesize % 4096 != 0) + stripesize *= 2; + if ((offset = maxstart * sectorsize % stripesize) != 0) { + offset = (stripesize - offset) / sectorsize; maxstart += offset; maxsize -= offset; }