mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-20 15:43:16 +00:00
MFhead @ r304232
This commit is contained in:
commit
532c3cde6a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/netbsd-tests-update-12/; revision=304233
@ -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} \
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -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 <l_node> probe_specifier_list
|
||||
%type <l_node> probe_specifier
|
||||
%type <l_node> statement_list
|
||||
%type <l_node> statement_list_impl
|
||||
%type <l_node> statement_or_block
|
||||
%type <l_node> statement
|
||||
%type <l_node> declaration
|
||||
%type <l_node> 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:
|
||||
|
@ -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? */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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 <sys/types.h>
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
@ -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 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
|
||||
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, "<bad node %p, kind %d>\n",
|
||||
(void *)dnp, dnp->dn_kind);
|
||||
|
@ -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 *);
|
||||
|
||||
|
516
cddl/contrib/opensolaris/lib/libdtrace/common/dt_sugar.c
Normal file
516
cddl/contrib/opensolaris/lib/libdtrace/common/dt_sugar.c
Normal file
@ -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 <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <dt_module.h>
|
||||
#include <dt_program.h>
|
||||
#include <dt_provider.h>
|
||||
#include <dt_printf.h>
|
||||
#include <dt_pid.h>
|
||||
#include <dt_grammar.h>
|
||||
#include <dt_ident.h>
|
||||
#include <dt_string.h>
|
||||
#include <dt_impl.h>
|
||||
|
||||
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_<condid>", 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_<newcond> =
|
||||
* (this->%condition_<condid> && 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 <pred>, 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_<condid> && pred) */
|
||||
value = dt_node_op2(DT_TOK_LAND,
|
||||
dt_sugar_new_condition_var(condid), pred);
|
||||
}
|
||||
|
||||
/* body is "this->%condition_<retval> = <value>;" */
|
||||
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_<condid>/
|
||||
* {
|
||||
* 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);
|
||||
}
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -69,6 +69,7 @@ TESTS_SUBDIRS+= aggs \
|
||||
strlen \
|
||||
strtoll \
|
||||
struct \
|
||||
sugar \
|
||||
syscall \
|
||||
tick-n \
|
||||
trace \
|
||||
|
@ -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 \
|
||||
|
25
cddl/usr.sbin/dtrace/tests/common/sugar/Makefile
Normal file
25
cddl/usr.sbin/dtrace/tests/common/sugar/Makefile
Normal file
@ -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"
|
@ -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
|
||||
|
@ -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] == '$') {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -183,6 +183,8 @@
|
||||
..
|
||||
struct
|
||||
..
|
||||
sugar
|
||||
..
|
||||
syscall
|
||||
..
|
||||
sysevent
|
||||
|
@ -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
|
||||
|
@ -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_)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -104,6 +104,11 @@ FBSD_1.4 {
|
||||
explicit_bzero;
|
||||
};
|
||||
|
||||
FBSD_1.5 {
|
||||
timingsafe_bcmp;
|
||||
timingsafe_memcmp;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
__strtok_r;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
92
lib/libc/string/timingsafe_bcmp.3
Normal file
92
lib/libc/string/timingsafe_bcmp.3
Normal file
@ -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 .
|
36
lib/libc/string/timingsafe_bcmp.c
Normal file
36
lib/libc/string/timingsafe_bcmp.c
Normal file
@ -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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <string.h>
|
||||
|
||||
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);
|
53
lib/libc/string/timingsafe_memcmp.c
Normal file
53
lib/libc/string/timingsafe_memcmp.c
Normal file
@ -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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
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);
|
@ -37,6 +37,7 @@ INTERPOSED = \
|
||||
close \
|
||||
connect \
|
||||
fcntl \
|
||||
fdatasync \
|
||||
fsync \
|
||||
fork \
|
||||
kevent \
|
||||
|
@ -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;
|
||||
|
46
lib/libc/sys/fdatasync.c
Normal file
46
lib/libc/sys/fdatasync.c
Normal file
@ -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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "libc_private.h"
|
||||
|
||||
int
|
||||
fdatasync(int fd)
|
||||
{
|
||||
|
||||
return (((int (*)(int))__libc_interposing[INTERPOS_fdatasync])(fd));
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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)) =
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -269,7 +269,6 @@ MAN= aac.4 \
|
||||
mac_stub.4 \
|
||||
mac_test.4 \
|
||||
malo.4 \
|
||||
mcd.4 \
|
||||
md.4 \
|
||||
mdio.4 \
|
||||
me.4 \
|
||||
|
@ -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 .
|
@ -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"
|
||||
|
@ -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 .
|
||||
|
@ -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월
|
||||
|
@ -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¿ù
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
一月
|
||||
|
@ -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)
|
||||
一月
|
||||
|
@ -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)
|
||||
一月
|
||||
|
@ -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月
|
||||
|
@ -4,32 +4,32 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# 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月
|
||||
2月
|
||||
3月
|
||||
4月
|
||||
5月
|
||||
6月
|
||||
7月
|
||||
8月
|
||||
9月
|
||||
10月
|
||||
11月
|
||||
12月
|
||||
1る
|
||||
2る
|
||||
3る
|
||||
4る
|
||||
5る
|
||||
6る
|
||||
7る
|
||||
8る
|
||||
9る
|
||||
10る
|
||||
11る
|
||||
12る
|
||||
#
|
||||
# Short weekday names
|
||||
週日
|
||||
@ -62,21 +62,22 @@
|
||||
上午
|
||||
下午
|
||||
#
|
||||
# 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月
|
||||
1る
|
||||
2る
|
||||
3る
|
||||
4る
|
||||
5る
|
||||
6る
|
||||
7る
|
||||
8る
|
||||
9る
|
||||
10る
|
||||
11る
|
||||
12る
|
||||
#
|
||||
# md_order
|
||||
md
|
||||
|
@ -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月
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
||||
continue;
|
||||
}
|
||||
|
||||
c = dtrace_load8(src + i++);
|
||||
c = (i >= lim) ? '\0' : dtrace_load8(src + i++);
|
||||
|
||||
if (c == '/') {
|
||||
/*
|
||||
@ -5549,7 +5678,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
||||
continue;
|
||||
}
|
||||
|
||||
c = dtrace_load8(src + i++);
|
||||
c = (i >= lim) ? '\0' : dtrace_load8(src + i++);
|
||||
|
||||
if (c == '/') {
|
||||
/*
|
||||
@ -5572,7 +5701,7 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
||||
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);
|
||||
}
|
||||
|
@ -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() */
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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); }
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
};
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 @@ hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
* 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);
|
||||
|
@ -46,9 +46,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <dev/hyperv/include/hyperv.h>
|
||||
#include "hv_net_vsc.h"
|
||||
#include "hv_rndis.h"
|
||||
#include "hv_rndis_filter.h"
|
||||
#include <dev/hyperv/include/vmbus_xact.h>
|
||||
#include <dev/hyperv/netvsc/hv_net_vsc.h>
|
||||
#include <dev/hyperv/netvsc/hv_rndis.h>
|
||||
#include <dev/hyperv/netvsc/hv_rndis_filter.h>
|
||||
#include <dev/hyperv/netvsc/if_hnreg.h>
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -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_ */
|
||||
|
@ -30,7 +30,9 @@
|
||||
#define _IF_HNVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <dev/hyperv/netvsc/hv_net_vsc.h>
|
||||
|
||||
#include <dev/hyperv/include/vmbus.h>
|
||||
#include <dev/hyperv/netvsc/if_hnreg.h>
|
||||
|
||||
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);
|
||||
|
1652
sys/dev/mcd/mcd.c
1652
sys/dev/mcd/mcd.c
File diff suppressed because it is too large
Load Diff
@ -1,202 +0,0 @@
|
||||
/*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <dev/mcd/mcdreg.h>
|
||||
#include <dev/mcd/mcdvar.h>
|
||||
|
||||
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);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user