From 7963abc2703b3638ff8858b6fea868d6643e4b7a Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Mon, 4 Nov 2013 20:28:10 +0000 Subject: [PATCH 001/172] Vendor import of tzdata2013h. - Libya didn't go back to DST. - Fix Morocco 2038 issue. - Brazil/Acre and ?Western Amazonas are chaning timezones. Obtained from: ftp://ftp.iana.org/tz/releases/ --- africa | 91 +++++++++++++++++++++++++++++++++++++--------------- southamerica | 15 +++++++-- 2 files changed, 78 insertions(+), 28 deletions(-) diff --git a/africa b/africa index 9a5d93bff030..029e5c22467b 100644 --- a/africa +++ b/africa @@ -451,6 +451,14 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882 # (either two days before them or five days after them, so as to fall on # lastFri instead of lastSun). +# From Even Scharning (2013-10-25): +# The scheduled end of DST in Libya on Friday, October 25, 2013 was +# cancelled yesterday.... +# http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/ +# +# From Paul Eggert (2013-10-25): +# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Libya 1951 only - Oct 14 2:00 1:00 S Rule Libya 1952 only - Jan 1 0:00 0 - @@ -467,8 +475,8 @@ Rule Libya 1987 1989 - Apr 1 0:00 1:00 S Rule Libya 1987 1989 - Oct 1 0:00 0 - Rule Libya 1997 only - Apr 4 0:00 1:00 S Rule Libya 1997 only - Oct 4 0:00 0 - -Rule Libya 2013 max - Mar lastFri 1:00 1:00 S -Rule Libya 2013 max - Oct lastFri 2:00 0 - +Rule Libya 2013 only - Mar lastFri 1:00 1:00 S +Rule Libya 2013 only - Oct lastFri 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Tripoli 0:52:44 - LMT 1920 1:00 Libya CE%sT 1959 @@ -479,7 +487,8 @@ Zone Africa/Tripoli 0:52:44 - LMT 1920 2:00 - EET 1996 Sep 30 1:00 Libya CE%sT 1997 Oct 4 2:00 - EET 2012 Nov 10 2:00 - 1:00 Libya CE%sT + 1:00 Libya CE%sT 2013 Oct 25 2:00 + 2:00 - EET # Madagascar # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -684,15 +693,6 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search # -# From Alex Krivenyshev (2008-05-09): -# Is Western Sahara (part which administrated by Morocco) going to follow -# Morocco DST changes? Any information? What about other part of -# Western Sahara - under administration of POLISARIO Front (also named -# SADR Saharawi Arab Democratic Republic)? - -# From Arthur David Olson (2008-05-09): -# XXX--guess that it is only Morocco for now; guess only 2008 for now. - # From Steffen Thorsen (2008-08-27): # Morocco will change the clocks back on the midnight between August 31 # and September 1. They originally planned to observe DST to near the end @@ -858,13 +858,23 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # transitions would be 2013-07-07 and 2013-08-10; see: # http://www.maroc.ma/en/news/morocco-suspends-daylight-saving-time-july-7-aug10 -# From Paul Eggert (2013-07-03): +# From Steffen Thorsen (2013-09-28): +# Morocco extends DST by one month, on very short notice, just 1 day +# before it was going to end. There is a new decree (2.13.781) for +# this, where DST from now on goes from last Sunday of March at 02:00 +# to last Sunday of October at 03:00, similar to EU rules. Official +# source (French): +# http://www.maroc.gov.ma/fr/actualites/lhoraire-dete-gmt1-maintenu-jusquau-27-octobre-2013 +# Another source (specifying the time for start and end in the decree): +# http://www.lemag.ma/Heure-d-ete-au-Maroc-jusqu-au-27-octobre_a75620.html + +# From Paul Eggert (2013-10-03): # To estimate what the Moroccan government will do in future years, -# transition dates for 2014 through 2021 were determined by running +# transition dates for 2014 through 2038 were determined by running # the following program under GNU Emacs 24.3: # # (let ((islamic-year 1435)) -# (while (< islamic-year 1444) +# (while (< islamic-year 1461) # (let ((a # (calendar-gregorian-from-absolute # (calendar-islamic-to-absolute (list 9 1 islamic-year)))) @@ -879,13 +889,18 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) # (setq islamic-year (+ 1 islamic-year)))) # -# with the results hand-edited for 2020-2022, when the normal spring-forward -# date falls during the estimated Ramadan. -# -# From 2023 through 2038 Ramadan is not predicted to overlap with -# daylight saving time. Starting in 2039 there will be overlap again, -# but 32-bit time_t values roll around in 2038 so for now do not worry -# about dates after 2038. +# with spring-forward transitions removed for 2023-2025, when the +# normal spring-forward date falls during the estimated Ramadan; with +# all transitions removed for 2026-2035, where the estimated Ramadan +# falls entirely outside daylight-saving time; and with fall-back +# transitions removed for 2036-2037, where the normal fall-back +# date falls during the estimated Ramadan. Normally, the table would +# stop after 2037 because 32-bit time_t values roll around early in 2038, +# but that would imply a prediction of perpetual DST after March 2038 +# due to the year-2037 glitches. So, this table instead stops after +# 2038, the first non-glitchy year after the 32-bit rollover. +# An advantage of stopping after 2038 is that it lets zic guess +# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future. # RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -912,12 +927,14 @@ Rule Morocco 2010 only - May 2 0:00 1:00 S Rule Morocco 2010 only - Aug 8 0:00 0 - Rule Morocco 2011 only - Apr 3 0:00 1:00 S Rule Morocco 2011 only - Jul 31 0 0 - -Rule Morocco 2012 2019 - Apr lastSun 2:00 1:00 S -Rule Morocco 2012 max - Sep lastSun 3:00 0 - +Rule Morocco 2012 2013 - Apr lastSun 2:00 1:00 S +Rule Morocco 2012 only - Sep 30 3:00 0 - Rule Morocco 2012 only - Jul 20 3:00 0 - Rule Morocco 2012 only - Aug 20 2:00 1:00 S Rule Morocco 2013 only - Jul 7 3:00 0 - Rule Morocco 2013 only - Aug 10 2:00 1:00 S +Rule Morocco 2013 2035 - Oct lastSun 3:00 0 - +Rule Morocco 2014 2022 - Mar lastSun 2:00 1:00 S Rule Morocco 2014 only - Jun 29 3:00 0 - Rule Morocco 2014 only - Jul 29 2:00 1:00 S Rule Morocco 2015 only - Jun 18 3:00 0 - @@ -930,20 +947,42 @@ Rule Morocco 2018 only - May 16 3:00 0 - Rule Morocco 2018 only - Jun 15 2:00 1:00 S Rule Morocco 2019 only - May 6 3:00 0 - Rule Morocco 2019 only - Jun 5 2:00 1:00 S +Rule Morocco 2020 only - Apr 24 3:00 0 - Rule Morocco 2020 only - May 24 2:00 1:00 S +Rule Morocco 2021 only - Apr 13 3:00 0 - Rule Morocco 2021 only - May 13 2:00 1:00 S +Rule Morocco 2022 only - Apr 3 3:00 0 - Rule Morocco 2022 only - May 3 2:00 1:00 S -Rule Morocco 2023 max - Apr lastSun 2:00 1:00 S +Rule Morocco 2023 only - Apr 22 2:00 1:00 S +Rule Morocco 2024 only - Apr 10 2:00 1:00 S +Rule Morocco 2025 only - Mar 31 2:00 1:00 S +Rule Morocco 2026 max - Mar lastSun 2:00 1:00 S +Rule Morocco 2036 only - Oct 21 3:00 0 - +Rule Morocco 2037 only - Oct 11 3:00 0 - +Rule Morocco 2038 only - Sep 30 3:00 0 - +Rule Morocco 2038 only - Oct 30 2:00 1:00 S +Rule Morocco 2038 max - Oct lastSun 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 0:00 Morocco WE%sT 1984 Mar 16 1:00 - CET 1986 0:00 Morocco WE%sT + # Western Sahara +# +# From Gwillim Law (2013-10-22): +# A correspondent who is usually well informed about time zone matters +# ... says that Western Sahara observes daylight saving time, just as +# Morocco does. +# +# From Paul Eggert (2013-10-23): +# Assume that this has been true since Western Sahara switched to GMT, +# since most of it was then controlled by Morocco. + Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan -1:00 - WAT 1976 Apr 14 - 0:00 - WET + 0:00 Morocco WE%sT # Mozambique # Zone NAME GMTOFF RULES FORMAT [UNTIL] diff --git a/southamerica b/southamerica index 3b25ce39c80a..2d77bf7b53a6 100644 --- a/southamerica +++ b/southamerica @@ -851,6 +851,15 @@ Zone America/La_Paz -4:32:36 - LMT 1890 # We will keep this article updated when this is confirmed: # http://www.timeanddate.com/news/time/brazil-starts-dst-2013.html +# From Steffen Thorsen (2013-10-17): +# http://www.timeanddate.com/news/time/acre-amazonas-change-time-zone.html +# Senator Jorge Viana announced that Acre will change time zone on November 10. +# He did not specify the time of the change, nor if western parts of Amazonas +# will change as well. +# +# From Paul Eggert (2013-10-17): +# For now, assume western Amazonas will change as well. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S # Decree 20,466 (1931-10-01) # Decree 21,896 (1932-01-10) @@ -1139,13 +1148,15 @@ Zone America/Eirunepe -4:39:28 - LMT 1914 -5:00 - ACT 1993 Sep 28 -5:00 Brazil AC%sT 1994 Sep 22 -5:00 - ACT 2008 Jun 24 00:00 - -4:00 - AMT + -4:00 - AMT 2013 Nov 10 + -5:00 - ACT # # Acre (AC) Zone America/Rio_Branco -4:31:12 - LMT 1914 -5:00 Brazil AC%sT 1988 Sep 12 -5:00 - ACT 2008 Jun 24 00:00 - -4:00 - AMT + -4:00 - AMT 2013 Nov 10 + -5:00 - ACT # Chile From 432048d13087fe5f7e9b8af85c8682bbdaae7a61 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 4 Dec 2013 14:49:20 +0000 Subject: [PATCH 002/172] 3580 Want zvols to return volblocksize when queried for physical block size illumos/illumos-gate@a0b60564dfc644f4bfaef1ce26d343b44cf68bc5 --- uts/common/fs/zfs/zvol.c | 83 +++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/uts/common/fs/zfs/zvol.c b/uts/common/fs/zfs/zvol.c index ee227467c655..2984eeef4b22 100644 --- a/uts/common/fs/zfs/zvol.c +++ b/uts/common/fs/zfs/zvol.c @@ -1627,8 +1627,6 @@ int zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) { zvol_state_t *zv; - struct dk_cinfo dki; - struct dk_minfo dkm; struct dk_callback *dkc; int error = 0; rl_t *rl; @@ -1646,6 +1644,9 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) switch (cmd) { case DKIOCINFO: + { + struct dk_cinfo dki; + bzero(&dki, sizeof (dki)); (void) strcpy(dki.dki_cname, "zvol"); (void) strcpy(dki.dki_dname, "zvol"); @@ -1656,8 +1657,12 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag)) error = SET_ERROR(EFAULT); return (error); + } case DKIOCGMEDIAINFO: + { + struct dk_minfo dkm; + bzero(&dkm, sizeof (dkm)); dkm.dki_lbsize = 1U << zv->zv_min_bs; dkm.dki_capacity = zv->zv_volsize >> zv->zv_min_bs; @@ -1666,16 +1671,32 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) if (ddi_copyout(&dkm, (void *)arg, sizeof (dkm), flag)) error = SET_ERROR(EFAULT); return (error); + } + + case DKIOCGMEDIAINFOEXT: + { + struct dk_minfo_ext dkmext; + + bzero(&dkmext, sizeof (dkmext)); + dkmext.dki_lbsize = 1U << zv->zv_min_bs; + dkmext.dki_pbsize = zv->zv_volblocksize; + dkmext.dki_capacity = zv->zv_volsize >> zv->zv_min_bs; + dkmext.dki_media_type = DK_UNKNOWN; + mutex_exit(&zfsdev_state_lock); + if (ddi_copyout(&dkmext, (void *)arg, sizeof (dkmext), flag)) + error = SET_ERROR(EFAULT); + return (error); + } case DKIOCGETEFI: - { - uint64_t vs = zv->zv_volsize; - uint8_t bs = zv->zv_min_bs; + { + uint64_t vs = zv->zv_volsize; + uint8_t bs = zv->zv_min_bs; - mutex_exit(&zfsdev_state_lock); - error = zvol_getefi((void *)arg, flag, vs, bs); - return (error); - } + mutex_exit(&zfsdev_state_lock); + error = zvol_getefi((void *)arg, flag, vs, bs); + return (error); + } case DKIOCFLUSHWRITECACHE: dkc = (struct dk_callback *)arg; @@ -1688,31 +1709,31 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) return (error); case DKIOCGETWCE: - { - int wce = (zv->zv_flags & ZVOL_WCE) ? 1 : 0; - if (ddi_copyout(&wce, (void *)arg, sizeof (int), - flag)) - error = SET_ERROR(EFAULT); + { + int wce = (zv->zv_flags & ZVOL_WCE) ? 1 : 0; + if (ddi_copyout(&wce, (void *)arg, sizeof (int), + flag)) + error = SET_ERROR(EFAULT); + break; + } + case DKIOCSETWCE: + { + int wce; + if (ddi_copyin((void *)arg, &wce, sizeof (int), + flag)) { + error = SET_ERROR(EFAULT); break; } - case DKIOCSETWCE: - { - int wce; - if (ddi_copyin((void *)arg, &wce, sizeof (int), - flag)) { - error = SET_ERROR(EFAULT); - break; - } - if (wce) { - zv->zv_flags |= ZVOL_WCE; - mutex_exit(&zfsdev_state_lock); - } else { - zv->zv_flags &= ~ZVOL_WCE; - mutex_exit(&zfsdev_state_lock); - zil_commit(zv->zv_zilog, ZVOL_OBJ); - } - return (0); + if (wce) { + zv->zv_flags |= ZVOL_WCE; + mutex_exit(&zfsdev_state_lock); + } else { + zv->zv_flags &= ~ZVOL_WCE; + mutex_exit(&zfsdev_state_lock); + zil_commit(zv->zv_zilog, ZVOL_OBJ); } + return (0); + } case DKIOCGGEOM: case DKIOCGVTOC: From 58be4f12bb8d52dc6db916e142b01158383d683d Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 4 Dec 2013 14:50:43 +0000 Subject: [PATCH 003/172] 4188 assertion failed in dmu_tx_hold_free(): dn_datablkshift != 0 illumos/illumos-gate@bb411a08b05466bfe0c7095b6373bbc1587e259a --- uts/common/fs/zfs/dmu_tx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/uts/common/fs/zfs/dmu_tx.c b/uts/common/fs/zfs/dmu_tx.c index 44350f7b3b33..70c91aca8d0c 100644 --- a/uts/common/fs/zfs/dmu_tx.c +++ b/uts/common/fs/zfs/dmu_tx.c @@ -635,9 +635,16 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len) uint64_t start = off >> shift; uint64_t end = (off + len) >> shift; - ASSERT(dn->dn_datablkshift != 0); ASSERT(dn->dn_indblkshift != 0); + /* + * dnode_reallocate() can result in an object with indirect + * blocks having an odd data block size. In this case, + * just check the single block. + */ + if (dn->dn_datablkshift == 0) + start = end = 0; + zio = zio_root(tx->tx_pool->dp_spa, NULL, NULL, ZIO_FLAG_CANFAIL); for (uint64_t i = start; i <= end; i++) { From d8278f57f8113302695efe8a82a6802491a0bc36 Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Wed, 11 Dec 2013 03:39:50 +0000 Subject: [PATCH 004/172] Add tap.test.mk. This file provides support to build test programs that comply with the Test Anything Protocol. Its main goal is to support the painless integration of existing tests from tools/regression/ into the Kyua-based test suite. Approved by: rpaulo (mentor) --- share/mk/Makefile | 1 + share/mk/tap.test.mk | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 share/mk/tap.test.mk diff --git a/share/mk/Makefile b/share/mk/Makefile index d854cca705b7..c776134e0b34 100644 --- a/share/mk/Makefile +++ b/share/mk/Makefile @@ -46,6 +46,7 @@ FILESDIR= ${BINDIR}/mk .if ${MK_TESTS} != "no" FILES+= atf.test.mk FILES+= plain.test.mk +FILES+= tap.test.mk .endif .include diff --git a/share/mk/tap.test.mk b/share/mk/tap.test.mk new file mode 100644 index 000000000000..394f6857e4e2 --- /dev/null +++ b/share/mk/tap.test.mk @@ -0,0 +1,64 @@ +# $FreeBSD$ +# +# Logic to build and install TAP-compliant test programs. +# +# This is provided to support existing tests in the FreeBSD source tree +# (particularly those coming from tools/regression/) that comply with the +# Test Anything Protocol. It should not be used for new tests. + +.include + +# List of C, C++ and shell test programs to build. +# +# Programs listed here are built according to the semantics of bsd.prog.mk for +# PROGS, PROGS_CXX and SCRIPTS, respectively. +# +# Test programs registered in this manner are set to be installed into TESTSDIR +# (which should be overriden by the Makefile) and are not required to provide a +# manpage. +TAP_TESTS_C?= +TAP_TESTS_CXX?= +TAP_TESTS_SH?= + +.if !empty(TAP_TESTS_C) +PROGS+= ${TAP_TESTS_C} +_TESTS+= ${TAP_TESTS_C} +.for _T in ${TAP_TESTS_C} +BINDIR.${_T}= ${TESTSDIR} +MAN.${_T}?= # empty +SRCS.${_T}?= ${_T}.c +TEST_INTERFACE.${_T}= tap +.endfor +.endif + +.if !empty(TAP_TESTS_CXX) +PROGS_CXX+= ${TAP_TESTS_CXX} +_TESTS+= ${TAP_TESTS_CXX} +.for _T in ${TAP_TESTS_CXX} +BINDIR.${_T}= ${TESTSDIR} +MAN.${_T}?= # empty +SRCS.${_T}?= ${_T}.cc +TEST_INTERFACE.${_T}= tap +.endfor +.endif + +.if !empty(TAP_TESTS_SH) +SCRIPTS+= ${TAP_TESTS_SH} +_TESTS+= ${TAP_TESTS_SH} +.for _T in ${TAP_TESTS_SH} +SCRIPTSDIR_${_T}= ${TESTSDIR} +TEST_INTERFACE.${_T}= tap +CLEANFILES+= ${_T} ${_T}.tmp +# TODO(jmmv): It seems to me that this SED and SRC functionality should +# exist in bsd.prog.mk along the support for SCRIPTS. Move it there if +# this proves to be useful within the tests. +TAP_TESTS_SH_SED_${_T}?= # empty +TAP_TESTS_SH_SRC_${_T}?= ${_T}.sh +${_T}: ${TAP_TESTS_SH_SRC_${_T}} + cat ${.ALLSRC} | sed ${TAP_TESTS_SH_SED_${_T}} >${.TARGET}.tmp + chmod +x ${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} +.endfor +.endif + +.include From f4a4cdd1664df604cc6b0d45fb6bdbd991c97f00 Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Wed, 11 Dec 2013 03:41:07 +0000 Subject: [PATCH 005/172] Make bsd.progs.mk work in directories with SCRIPTS but no PROGS. This change fixes some cases where bsd.progs.mk would fail to handle directories with SCRIPTS but no PROGS. In particular, "install" did not handle such scripts nor dependent files when bsd.subdir.mk was added to the mix. This is "make tinderbox" clean. Reviewed by: freebsd-testing Approved by: rpaulo (mentor) --- share/mk/bsd.progs.mk | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/share/mk/bsd.progs.mk b/share/mk/bsd.progs.mk index 2f3e9c68af3a..c5e8c3d85adc 100644 --- a/share/mk/bsd.progs.mk +++ b/share/mk/bsd.progs.mk @@ -73,7 +73,7 @@ UPDATE_DEPENDFILE = NO # handle being called [bsd.]progs.mk .include -.ifndef PROG +.ifndef _RECURSING_PROGS # tell progs.mk we might want to install things PROGS_TARGETS+= cleandepend cleandir cleanobj depend install @@ -84,11 +84,13 @@ x.$p= PROG_CXX=$p .endif $p ${p}_p: .PHONY .MAKE - (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} PROG=$p ${x.$p}) + (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} _RECURSING_PROGS= \ + SUBDIR= PROG=$p ${x.$p}) .for t in ${PROGS_TARGETS:O:u} $p.$t: .PHONY .MAKE - (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} PROG=$p ${x.$p} ${@:E}) + (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} _RECURSING_PROGS= \ + SUBDIR= PROG=$p ${x.$p} ${@:E}) .endfor .endfor @@ -96,4 +98,18 @@ $p.$t: .PHONY .MAKE $t: ${PROGS:%=%.$t} .endfor +SCRIPTS_TARGETS+= cleandepend cleandir cleanobj depend install + +.for p in ${SCRIPTS} +.for t in ${SCRIPTS_TARGETS:O:u} +$p.$t: .PHONY .MAKE + (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} _RECURSING_PROGS= \ + SUBDIR= SCRIPT=$p ${x.$p} ${@:E}) +.endfor +.endfor + +.for t in ${SCRIPTS_TARGETS:O:u} +$t: ${SCRIPTS:%=%.$t} +.endfor + .endif From 13de33a5dc2304b13d595d75d48c51793958474f Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Wed, 11 Dec 2013 04:09:17 +0000 Subject: [PATCH 006/172] Migrate tools/regression/bin/ tests to the new layout. This change is a proof of concept on how to easily integrate existing tests from the tools/regression/ hierarchy into the /usr/tests/ test suite and on how to adapt them to the new layout for src. To achieve these goals, this change: - Moves tests from tools/regression/bin// to bin//tests/. - Renames the previous regress.sh files to legacy_test.sh. - Adds Makefiles to build and install the tests and all their supporting data files into /usr/tests/bin/. - Plugs the legacy_test test programs into the test suite using the new TAP backend for Kyua (appearing in 0.8) so that the code of the test programs does not have to change. - Registers the new directories in the BSD.test.dist mtree file. Reviewed by: freebsd-testing Approved by: rpaulo (mentor) --- bin/Makefile | 4 + bin/date/Makefile | 6 + bin/date/tests/Makefile | 9 ++ .../date/tests/legacy_test.sh | 0 bin/mv/Makefile | 6 + bin/mv/tests/Makefile | 9 ++ .../regress.sh => bin/mv/tests/legacy_test.sh | 0 bin/pax/Makefile | 6 + bin/pax/tests/Makefile | 9 ++ .../regress.t => bin/pax/tests/legacy_test.sh | 0 bin/sh/Makefile | 7 +- bin/sh/tests/Makefile | 12 ++ bin/sh/tests/builtins/Makefile | 147 ++++++++++++++++++ .../bin/sh => bin/sh/tests}/builtins/alias.0 | 0 .../sh/tests}/builtins/alias.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/alias.1 | 0 .../sh/tests}/builtins/alias.1.stderr | 0 .../bin/sh => bin/sh/tests}/builtins/alias3.0 | 0 .../sh/tests}/builtins/alias3.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/alias4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/break1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/break2.0 | 0 .../sh/tests}/builtins/break2.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/break3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/break4.4 | 0 .../bin/sh => bin/sh/tests}/builtins/break5.4 | 0 .../sh => bin/sh/tests}/builtins/builtin1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case10.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case11.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case12.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case13.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case14.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case15.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case16.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case17.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case18.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case19.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case7.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case8.0 | 0 .../bin/sh => bin/sh/tests}/builtins/case9.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd7.0 | 0 .../bin/sh => bin/sh/tests}/builtins/cd8.0 | 0 .../sh => bin/sh/tests}/builtins/command1.0 | 0 .../sh => bin/sh/tests}/builtins/command10.0 | 0 .../sh => bin/sh/tests}/builtins/command11.0 | 0 .../sh => bin/sh/tests}/builtins/command12.0 | 0 .../sh => bin/sh/tests}/builtins/command2.0 | 0 .../sh => bin/sh/tests}/builtins/command3.0 | 0 .../sh/tests}/builtins/command3.0.stdout | 0 .../sh => bin/sh/tests}/builtins/command4.0 | 0 .../sh => bin/sh/tests}/builtins/command5.0 | 0 .../sh/tests}/builtins/command5.0.stdout | 0 .../sh => bin/sh/tests}/builtins/command6.0 | 0 .../sh/tests}/builtins/command6.0.stdout | 0 .../sh => bin/sh/tests}/builtins/command7.0 | 0 .../sh => bin/sh/tests}/builtins/command8.0 | 0 .../sh => bin/sh/tests}/builtins/command9.0 | 0 .../bin/sh => bin/sh/tests}/builtins/dot1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/dot2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/dot3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/dot4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/eval6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/exec1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/exec2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/exit1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/exit2.8 | 0 .../bin/sh => bin/sh/tests}/builtins/exit3.0 | 0 .../sh => bin/sh/tests}/builtins/export1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/fc1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/fc2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/for1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/for2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/for3.0 | 0 .../sh => bin/sh/tests}/builtins/getopts1.0 | 0 .../sh/tests}/builtins/getopts1.0.stdout | 0 .../sh => bin/sh/tests}/builtins/getopts2.0 | 0 .../sh/tests}/builtins/getopts2.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/hash1.0 | 0 .../sh/tests}/builtins/hash1.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/hash2.0 | 0 .../sh/tests}/builtins/hash2.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/hash3.0 | 0 .../sh/tests}/builtins/hash3.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/hash4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/jobid1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/jobid2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/lineno.0 | 0 .../sh/tests}/builtins/lineno.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/local1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/local2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/local3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/local4.0 | 0 .../sh => bin/sh/tests}/builtins/locale1.0 | 0 .../sh => bin/sh/tests}/builtins/printf1.0 | 0 .../sh => bin/sh/tests}/builtins/printf2.0 | 0 .../sh => bin/sh/tests}/builtins/printf3.0 | 0 .../sh => bin/sh/tests}/builtins/printf4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/read1.0 | 0 .../sh/tests}/builtins/read1.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/read2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/read3.0 | 0 .../sh/tests}/builtins/read3.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/read4.0 | 0 .../sh/tests}/builtins/read4.0.stdout | 0 .../bin/sh => bin/sh/tests}/builtins/read5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/read6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/read7.0 | 0 .../sh => bin/sh/tests}/builtins/return1.0 | 0 .../sh => bin/sh/tests}/builtins/return2.1 | 0 .../sh => bin/sh/tests}/builtins/return3.1 | 0 .../sh => bin/sh/tests}/builtins/return4.0 | 0 .../sh => bin/sh/tests}/builtins/return5.0 | 0 .../sh => bin/sh/tests}/builtins/return6.4 | 0 .../sh => bin/sh/tests}/builtins/return7.4 | 0 .../sh => bin/sh/tests}/builtins/return8.0 | 0 .../bin/sh => bin/sh/tests}/builtins/set1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/set2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap10.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap11.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap12.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap13.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap14.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap7.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap8.0 | 0 .../bin/sh => bin/sh/tests}/builtins/trap9.0 | 0 .../bin/sh => bin/sh/tests}/builtins/type1.0 | 0 .../sh/tests}/builtins/type1.0.stderr | 0 .../bin/sh => bin/sh/tests}/builtins/type2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/type3.0 | 0 .../sh => bin/sh/tests}/builtins/unalias.0 | 0 .../sh => bin/sh/tests}/builtins/var-assign.0 | 0 .../sh/tests}/builtins/var-assign2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait1.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait10.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait2.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait3.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait4.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait5.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait6.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait7.0 | 0 .../bin/sh => bin/sh/tests}/builtins/wait8.0 | 0 .../sh => bin/sh/tests}/builtins/wait9.127 | 0 bin/sh/tests/errors/Makefile | 30 ++++ .../sh/tests}/errors/assignment-error1.0 | 0 .../sh/tests}/errors/assignment-error2.0 | 0 .../sh/tests}/errors/backquote-error1.0 | 0 .../sh/tests}/errors/backquote-error2.0 | 0 .../sh/tests}/errors/bad-binary1.126 | 0 .../sh => bin/sh/tests}/errors/bad-keyword1.0 | 0 .../sh/tests}/errors/bad-parm-exp1.0 | 0 .../sh/tests}/errors/bad-parm-exp2.2 | 0 .../sh/tests}/errors/bad-parm-exp2.2.stderr | 0 .../sh/tests}/errors/bad-parm-exp3.2 | 0 .../sh/tests}/errors/bad-parm-exp3.2.stderr | 0 .../sh/tests}/errors/bad-parm-exp4.2 | 0 .../sh/tests}/errors/bad-parm-exp4.2.stderr | 0 .../sh/tests}/errors/bad-parm-exp5.2 | 0 .../sh/tests}/errors/bad-parm-exp5.2.stderr | 0 .../sh/tests}/errors/bad-parm-exp6.2 | 0 .../sh/tests}/errors/bad-parm-exp6.2.stderr | 0 .../sh => bin/sh/tests}/errors/option-error.0 | 0 .../sh/tests}/errors/redirection-error.0 | 0 .../sh/tests}/errors/redirection-error2.2 | 0 .../sh/tests}/errors/redirection-error3.0 | 0 .../sh/tests}/errors/redirection-error4.0 | 0 .../sh/tests}/errors/redirection-error5.0 | 0 .../sh/tests}/errors/redirection-error6.0 | 0 .../sh/tests}/errors/redirection-error7.0 | 0 .../sh => bin/sh/tests}/errors/write-error1.0 | 0 bin/sh/tests/execution/Makefile | 53 +++++++ .../bin/sh => bin/sh/tests}/execution/bg1.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg10.0 | 0 .../sh/tests}/execution/bg10.0.stdout | 0 .../bin/sh => bin/sh/tests}/execution/bg2.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg3.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg4.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg5.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg6.0 | 0 .../sh/tests}/execution/bg6.0.stdout | 0 .../bin/sh => bin/sh/tests}/execution/bg7.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg8.0 | 0 .../bin/sh => bin/sh/tests}/execution/bg9.0 | 0 .../bin/sh => bin/sh/tests}/execution/fork1.0 | 0 .../bin/sh => bin/sh/tests}/execution/fork2.0 | 0 .../bin/sh => bin/sh/tests}/execution/fork3.0 | 0 .../bin/sh => bin/sh/tests}/execution/func1.0 | 0 .../bin/sh => bin/sh/tests}/execution/func2.0 | 0 .../bin/sh => bin/sh/tests}/execution/func3.0 | 0 .../bin/sh => bin/sh/tests}/execution/hash1.0 | 0 .../sh => bin/sh/tests}/execution/int-cmd1.0 | 0 .../sh => bin/sh/tests}/execution/killed1.0 | 0 .../sh => bin/sh/tests}/execution/killed2.0 | 0 .../bin/sh => bin/sh/tests}/execution/not1.0 | 0 .../bin/sh => bin/sh/tests}/execution/not2.0 | 0 .../bin/sh => bin/sh/tests}/execution/path1.0 | 0 .../sh => bin/sh/tests}/execution/redir1.0 | 0 .../sh => bin/sh/tests}/execution/redir2.0 | 0 .../sh => bin/sh/tests}/execution/redir3.0 | 0 .../sh => bin/sh/tests}/execution/redir4.0 | 0 .../sh => bin/sh/tests}/execution/redir5.0 | 0 .../sh => bin/sh/tests}/execution/redir6.0 | 0 .../sh => bin/sh/tests}/execution/redir7.0 | 0 .../sh => bin/sh/tests}/execution/set-n1.0 | 0 .../sh => bin/sh/tests}/execution/set-n2.0 | 0 .../sh => bin/sh/tests}/execution/set-n3.0 | 0 .../sh => bin/sh/tests}/execution/set-n4.0 | 0 .../sh => bin/sh/tests}/execution/set-x1.0 | 0 .../sh => bin/sh/tests}/execution/set-x2.0 | 0 .../sh => bin/sh/tests}/execution/set-x3.0 | 0 .../sh/tests}/execution/shellproc1.0 | 0 .../sh => bin/sh/tests}/execution/subshell1.0 | 0 .../sh/tests}/execution/subshell1.0.stdout | 0 .../sh => bin/sh/tests}/execution/subshell2.0 | 0 .../sh => bin/sh/tests}/execution/subshell3.0 | 0 .../sh => bin/sh/tests}/execution/subshell4.0 | 0 .../sh => bin/sh/tests}/execution/unknown1.0 | 0 .../sh/tests}/execution/var-assign1.0 | 0 bin/sh/tests/expansion/Makefile | 86 ++++++++++ .../sh => bin/sh/tests}/expansion/arith1.0 | 0 .../sh => bin/sh/tests}/expansion/arith10.0 | 0 .../sh => bin/sh/tests}/expansion/arith11.0 | 0 .../sh => bin/sh/tests}/expansion/arith12.0 | 0 .../sh => bin/sh/tests}/expansion/arith13.0 | 0 .../sh => bin/sh/tests}/expansion/arith2.0 | 0 .../sh => bin/sh/tests}/expansion/arith3.0 | 0 .../sh => bin/sh/tests}/expansion/arith4.0 | 0 .../sh => bin/sh/tests}/expansion/arith5.0 | 0 .../sh => bin/sh/tests}/expansion/arith6.0 | 0 .../sh => bin/sh/tests}/expansion/arith7.0 | 0 .../sh => bin/sh/tests}/expansion/arith8.0 | 0 .../sh => bin/sh/tests}/expansion/arith9.0 | 0 .../sh => bin/sh/tests}/expansion/assign1.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst1.0 | 0 .../sh/tests}/expansion/cmdsubst10.0 | 0 .../sh/tests}/expansion/cmdsubst11.0 | 0 .../sh/tests}/expansion/cmdsubst12.0 | 0 .../sh/tests}/expansion/cmdsubst13.0 | 0 .../sh/tests}/expansion/cmdsubst14.0 | 0 .../sh/tests}/expansion/cmdsubst15.0 | 0 .../sh/tests}/expansion/cmdsubst16.0 | 0 .../sh/tests}/expansion/cmdsubst17.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst2.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst3.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst4.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst5.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst6.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst7.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst8.0 | 0 .../sh => bin/sh/tests}/expansion/cmdsubst9.0 | 0 .../sh => bin/sh/tests}/expansion/export1.0 | 0 .../sh => bin/sh/tests}/expansion/export2.0 | 0 .../sh => bin/sh/tests}/expansion/export3.0 | 0 .../sh => bin/sh/tests}/expansion/heredoc1.0 | 0 .../sh => bin/sh/tests}/expansion/heredoc2.0 | 0 .../bin/sh => bin/sh/tests}/expansion/ifs1.0 | 0 .../bin/sh => bin/sh/tests}/expansion/ifs2.0 | 0 .../bin/sh => bin/sh/tests}/expansion/ifs3.0 | 0 .../bin/sh => bin/sh/tests}/expansion/ifs4.0 | 0 .../sh => bin/sh/tests}/expansion/length1.0 | 0 .../sh => bin/sh/tests}/expansion/length2.0 | 0 .../sh => bin/sh/tests}/expansion/length3.0 | 0 .../sh => bin/sh/tests}/expansion/length4.0 | 0 .../sh => bin/sh/tests}/expansion/length5.0 | 0 .../sh => bin/sh/tests}/expansion/length6.0 | 0 .../sh => bin/sh/tests}/expansion/length7.0 | 0 .../sh => bin/sh/tests}/expansion/length8.0 | 0 .../sh => bin/sh/tests}/expansion/local1.0 | 0 .../sh => bin/sh/tests}/expansion/local2.0 | 0 .../sh => bin/sh/tests}/expansion/pathname1.0 | 0 .../sh => bin/sh/tests}/expansion/pathname2.0 | 0 .../sh => bin/sh/tests}/expansion/pathname3.0 | 0 .../sh => bin/sh/tests}/expansion/pathname4.0 | 0 .../sh/tests}/expansion/plus-minus1.0 | 0 .../sh/tests}/expansion/plus-minus2.0 | 0 .../sh/tests}/expansion/plus-minus3.0 | 0 .../sh/tests}/expansion/plus-minus4.0 | 0 .../sh/tests}/expansion/plus-minus5.0 | 0 .../sh/tests}/expansion/plus-minus6.0 | 0 .../sh/tests}/expansion/plus-minus7.0 | 0 .../sh/tests}/expansion/plus-minus8.0 | 0 .../sh => bin/sh/tests}/expansion/question1.0 | 0 .../sh => bin/sh/tests}/expansion/readonly1.0 | 0 .../sh => bin/sh/tests}/expansion/set-u1.0 | 0 .../sh => bin/sh/tests}/expansion/set-u2.0 | 0 .../sh => bin/sh/tests}/expansion/set-u3.0 | 0 .../sh => bin/sh/tests}/expansion/tilde1.0 | 0 .../sh => bin/sh/tests}/expansion/tilde2.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim1.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim2.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim3.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim4.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim5.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim6.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim7.0 | 0 .../bin/sh => bin/sh/tests}/expansion/trim8.0 | 0 .../regress.sh => bin/sh/tests/legacy_test.sh | 16 +- bin/sh/tests/parameters/Makefile | 18 +++ .../bin/sh => bin/sh/tests}/parameters/env1.0 | 0 .../sh/tests}/parameters/exitstatus1.0 | 0 .../sh => bin/sh/tests}/parameters/mail1.0 | 0 .../sh => bin/sh/tests}/parameters/mail2.0 | 0 .../sh => bin/sh/tests}/parameters/optind1.0 | 0 .../sh/tests}/parameters/positional1.0 | 0 .../sh/tests}/parameters/positional2.0 | 0 .../bin/sh => bin/sh/tests}/parameters/pwd1.0 | 0 .../bin/sh => bin/sh/tests}/parameters/pwd2.0 | 0 bin/sh/tests/parser/Makefile | 59 +++++++ .../bin/sh => bin/sh/tests}/parser/alias1.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias10.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias2.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias3.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias4.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias5.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias6.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias7.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias8.0 | 0 .../bin/sh => bin/sh/tests}/parser/alias9.0 | 0 .../sh => bin/sh/tests}/parser/and-pipe-not.0 | 0 .../bin/sh => bin/sh/tests}/parser/case1.0 | 0 .../bin/sh => bin/sh/tests}/parser/case2.0 | 0 .../sh/tests}/parser/dollar-quote1.0 | 0 .../sh/tests}/parser/dollar-quote10.0 | 0 .../sh/tests}/parser/dollar-quote11.0 | 0 .../sh/tests}/parser/dollar-quote2.0 | 0 .../sh/tests}/parser/dollar-quote3.0 | 0 .../sh/tests}/parser/dollar-quote4.0 | 0 .../sh/tests}/parser/dollar-quote5.0 | 0 .../sh/tests}/parser/dollar-quote6.0 | 0 .../sh/tests}/parser/dollar-quote7.0 | 0 .../sh/tests}/parser/dollar-quote8.0 | 0 .../sh/tests}/parser/dollar-quote9.0 | 0 .../sh/tests}/parser/empty-braces1.0 | 0 .../sh => bin/sh/tests}/parser/empty-cmd1.0 | 0 .../bin/sh => bin/sh/tests}/parser/for1.0 | 0 .../bin/sh => bin/sh/tests}/parser/for2.0 | 0 .../bin/sh => bin/sh/tests}/parser/func1.0 | 0 .../bin/sh => bin/sh/tests}/parser/func2.0 | 0 .../bin/sh => bin/sh/tests}/parser/func3.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc1.0 | 0 .../sh => bin/sh/tests}/parser/heredoc10.0 | 0 .../sh => bin/sh/tests}/parser/heredoc11.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc2.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc3.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc4.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc5.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc6.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc7.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc8.0 | 0 .../bin/sh => bin/sh/tests}/parser/heredoc9.0 | 0 .../sh => bin/sh/tests}/parser/no-space1.0 | 0 .../sh => bin/sh/tests}/parser/no-space2.0 | 0 .../sh => bin/sh/tests}/parser/only-redir1.0 | 0 .../sh => bin/sh/tests}/parser/only-redir2.0 | 0 .../sh => bin/sh/tests}/parser/only-redir3.0 | 0 .../sh => bin/sh/tests}/parser/only-redir4.0 | 0 .../sh => bin/sh/tests}/parser/pipe-not1.0 | 0 .../sh => bin/sh/tests}/parser/var-assign1.0 | 0 bin/sh/tests/set-e/Makefile | 44 ++++++ .../bin/sh => bin/sh/tests}/set-e/and1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/and2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/and3.0 | 0 .../bin/sh => bin/sh/tests}/set-e/and4.0 | 0 .../sh => bin/sh/tests}/set-e/background1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/cmd1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/cmd2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/elif1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/elif2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/eval1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/eval2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/for1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/func1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/func2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/if1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/if2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/if3.0 | 0 .../bin/sh => bin/sh/tests}/set-e/not1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/not2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/or1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/or2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/or3.1 | 0 .../bin/sh => bin/sh/tests}/set-e/pipe1.1 | 0 .../bin/sh => bin/sh/tests}/set-e/pipe2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/return1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/semi1.1 | 0 .../bin/sh => bin/sh/tests}/set-e/semi2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/subshell1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/subshell2.1 | 0 .../bin/sh => bin/sh/tests}/set-e/until1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/until2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/until3.0 | 0 .../bin/sh => bin/sh/tests}/set-e/while1.0 | 0 .../bin/sh => bin/sh/tests}/set-e/while2.0 | 0 .../bin/sh => bin/sh/tests}/set-e/while3.0 | 0 bin/test/Makefile | 6 + bin/test/tests/Makefile | 9 ++ .../test/tests/legacy_test.sh | 0 bin/tests/Makefile | 10 ++ etc/mtree/BSD.tests.dist | 26 ++++ tools/regression/bin/Makefile | 5 - tools/regression/bin/date/Makefile | 4 - tools/regression/bin/date/regress.t | 6 - tools/regression/bin/mv/Makefile | 4 - tools/regression/bin/mv/regress.t | 6 - tools/regression/bin/pax/Makefile | 8 - tools/regression/bin/sh/Makefile | 7 - tools/regression/bin/sh/regress.t | 8 - tools/regression/bin/test/Makefile | 4 - tools/regression/bin/test/regress.t | 6 - 431 files changed, 564 insertions(+), 66 deletions(-) create mode 100644 bin/date/tests/Makefile rename tools/regression/bin/date/regress.sh => bin/date/tests/legacy_test.sh (100%) create mode 100644 bin/mv/tests/Makefile rename tools/regression/bin/mv/regress.sh => bin/mv/tests/legacy_test.sh (100%) create mode 100644 bin/pax/tests/Makefile rename tools/regression/bin/pax/regress.t => bin/pax/tests/legacy_test.sh (100%) mode change 100755 => 100644 create mode 100644 bin/sh/tests/Makefile create mode 100644 bin/sh/tests/builtins/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias.1.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias3.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/alias4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break2.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break4.4 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/break5.4 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/builtin1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case12.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case13.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case14.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case15.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case16.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case17.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case18.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case19.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/case9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/cd8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command12.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command3.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command5.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command6.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/command9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/dot1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/dot2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/dot3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/dot4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/eval6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/exec1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/exec2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/exit1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/exit2.8 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/exit3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/export1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/fc1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/fc2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/for1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/for2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/for3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/getopts1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/getopts1.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/getopts2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/getopts2.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash1.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash2.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash3.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/hash4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/jobid1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/jobid2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/lineno.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/lineno.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/local1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/local2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/local3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/local4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/locale1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/printf1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/printf2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/printf3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/printf4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read1.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read3.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read4.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/read7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return3.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return6.4 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return7.4 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/return8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/set1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/set2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap12.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap13.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap14.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/trap9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/type1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/type1.0.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/type2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/type3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/unalias.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/var-assign.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/var-assign2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/builtins/wait9.127 (100%) create mode 100644 bin/sh/tests/errors/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/errors/assignment-error1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/assignment-error2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/backquote-error1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/backquote-error2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-binary1.126 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-keyword1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp2.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp2.2.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp3.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp3.2.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp4.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp4.2.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp5.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp5.2.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp6.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/bad-parm-exp6.2.stderr (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/option-error.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error2.2 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/redirection-error7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/errors/write-error1.0 (100%) create mode 100644 bin/sh/tests/execution/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg10.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg6.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/bg9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/fork1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/fork2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/fork3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/func1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/func2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/func3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/hash1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/int-cmd1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/killed1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/killed2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/not1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/not2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/path1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/redir7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-n1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-n2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-n3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-n4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-x1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-x2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/set-x3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/shellproc1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/subshell1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/subshell1.0.stdout (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/subshell2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/subshell3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/subshell4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/unknown1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/execution/var-assign1.0 (100%) create mode 100644 bin/sh/tests/expansion/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith12.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith13.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/arith9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/assign1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst12.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst13.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst14.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst15.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst16.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst17.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/cmdsubst9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/export1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/export2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/export3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/heredoc1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/heredoc2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/ifs1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/ifs2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/ifs3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/ifs4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/length8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/local1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/local2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/pathname1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/pathname2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/pathname3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/pathname4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/plus-minus8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/question1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/readonly1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/set-u1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/set-u2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/set-u3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/tilde1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/tilde2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/expansion/trim8.0 (100%) rename tools/regression/bin/sh/regress.sh => bin/sh/tests/legacy_test.sh (64%) create mode 100644 bin/sh/tests/parameters/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/parameters/env1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/exitstatus1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/mail1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/mail2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/optind1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/positional1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/positional2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/pwd1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parameters/pwd2.0 (100%) create mode 100644 bin/sh/tests/parser/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/alias9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/and-pipe-not.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/case1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/case2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/dollar-quote9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/empty-braces1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/empty-cmd1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/for1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/for2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/func1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/func2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/func3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc10.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc11.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc5.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc6.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc7.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc8.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/heredoc9.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/no-space1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/no-space2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/only-redir1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/only-redir2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/only-redir3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/only-redir4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/pipe-not1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/parser/var-assign1.0 (100%) create mode 100644 bin/sh/tests/set-e/Makefile rename {tools/regression/bin/sh => bin/sh/tests}/set-e/and1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/and2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/and3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/and4.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/background1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/cmd1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/cmd2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/elif1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/elif2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/eval1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/eval2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/for1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/func1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/func2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/if1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/if2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/if3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/not1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/not2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/or1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/or2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/or3.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/pipe1.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/pipe2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/return1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/semi1.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/semi2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/subshell1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/subshell2.1 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/until1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/until2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/until3.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/while1.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/while2.0 (100%) rename {tools/regression/bin/sh => bin/sh/tests}/set-e/while3.0 (100%) create mode 100644 bin/test/tests/Makefile rename tools/regression/bin/test/regress.sh => bin/test/tests/legacy_test.sh (100%) create mode 100644 bin/tests/Makefile delete mode 100644 tools/regression/bin/Makefile delete mode 100644 tools/regression/bin/date/Makefile delete mode 100644 tools/regression/bin/date/regress.t delete mode 100644 tools/regression/bin/mv/Makefile delete mode 100644 tools/regression/bin/mv/regress.t delete mode 100644 tools/regression/bin/pax/Makefile delete mode 100644 tools/regression/bin/sh/Makefile delete mode 100644 tools/regression/bin/sh/regress.t delete mode 100644 tools/regression/bin/test/Makefile delete mode 100644 tools/regression/bin/test/regress.t diff --git a/bin/Makefile b/bin/Makefile index 7b6a4ab8c8c0..e4bc281db638 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -52,6 +52,10 @@ SUBDIR+= rmail SUBDIR+= csh .endif +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include SUBDIR:= ${SUBDIR:O} diff --git a/bin/date/Makefile b/bin/date/Makefile index 4f5c3fea3a58..6da5848e16ab 100644 --- a/bin/date/Makefile +++ b/bin/date/Makefile @@ -1,7 +1,13 @@ # @(#)Makefile 8.1 (Berkeley) 5/31/93 # $FreeBSD$ +.include + PROG= date SRCS= date.c netdate.c vary.c +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/bin/date/tests/Makefile b/bin/date/tests/Makefile new file mode 100644 index 000000000000..540008be2899 --- /dev/null +++ b/bin/date/tests/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin/date + +TAP_TESTS_SH= legacy_test + +.include diff --git a/tools/regression/bin/date/regress.sh b/bin/date/tests/legacy_test.sh similarity index 100% rename from tools/regression/bin/date/regress.sh rename to bin/date/tests/legacy_test.sh diff --git a/bin/mv/Makefile b/bin/mv/Makefile index 840578276d5a..ad8cc4f02d44 100644 --- a/bin/mv/Makefile +++ b/bin/mv/Makefile @@ -1,6 +1,12 @@ # @(#)Makefile 8.2 (Berkeley) 4/2/94 # $FreeBSD$ +.include + PROG= mv +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/bin/mv/tests/Makefile b/bin/mv/tests/Makefile new file mode 100644 index 000000000000..051a3b6177e9 --- /dev/null +++ b/bin/mv/tests/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin/mv + +TAP_TESTS_SH= legacy_test + +.include diff --git a/tools/regression/bin/mv/regress.sh b/bin/mv/tests/legacy_test.sh similarity index 100% rename from tools/regression/bin/mv/regress.sh rename to bin/mv/tests/legacy_test.sh diff --git a/bin/pax/Makefile b/bin/pax/Makefile index 9e8d4e111862..95f18bba1c06 100644 --- a/bin/pax/Makefile +++ b/bin/pax/Makefile @@ -1,6 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 5/31/93 # $FreeBSD$ +.include + # To install on versions prior to BSD 4.4 the following may have to be # defined with CFLAGS += # @@ -30,4 +32,8 @@ SRCS= ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c \ gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c \ tables.c tar.c tty_subs.c +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/bin/pax/tests/Makefile b/bin/pax/tests/Makefile new file mode 100644 index 000000000000..b3c4b85d7175 --- /dev/null +++ b/bin/pax/tests/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin/pax + +TAP_TESTS_SH= legacy_test + +.include diff --git a/tools/regression/bin/pax/regress.t b/bin/pax/tests/legacy_test.sh old mode 100755 new mode 100644 similarity index 100% rename from tools/regression/bin/pax/regress.t rename to bin/pax/tests/legacy_test.sh diff --git a/bin/sh/Makefile b/bin/sh/Makefile index 00d34fa749da..e1ce5feb1851 100644 --- a/bin/sh/Makefile +++ b/bin/sh/Makefile @@ -1,6 +1,8 @@ # @(#)Makefile 8.4 (Berkeley) 5/5/95 # $FreeBSD$ +.include + PROG= sh INSTALLFLAGS= -S SHSRCS= alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \ @@ -59,7 +61,8 @@ syntax.c syntax.h: mksyntax token.h: mktokens sh ${.CURDIR}/mktokens -regress: - cd ${.CURDIR}/../../tools/regression/bin/sh && ${MAKE} SH=${.OBJDIR}/sh +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif .include diff --git a/bin/sh/tests/Makefile b/bin/sh/tests/Makefile new file mode 100644 index 000000000000..cd8b7a2958bc --- /dev/null +++ b/bin/sh/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin/sh + +TAP_TESTS_SH= legacy_test +TAP_TESTS_SH_SED_legacy_test= -e 's,__SH__,/bin/sh,g' + +SUBDIR+= builtins errors execution expansion parameters parser set-e + +.include diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile new file mode 100644 index 000000000000..3b1d24b2a959 --- /dev/null +++ b/bin/sh/tests/builtins/Makefile @@ -0,0 +1,147 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/builtins +KYUAFILE= no + +FILES= alias.0 alias.0.stdout +FILES+= alias.1 alias.1.stderr +FILES+= alias3.0 alias3.0.stdout +FILES+= alias4.0 +FILES+= break1.0 +FILES+= break2.0 break2.0.stdout +FILES+= break3.0 +FILES+= break4.4 +FILES+= break5.4 +FILES+= builtin1.0 +FILES+= case1.0 +FILES+= case2.0 +FILES+= case3.0 +FILES+= case4.0 +FILES+= case5.0 +FILES+= case6.0 +FILES+= case7.0 +FILES+= case8.0 +FILES+= case9.0 +FILES+= case10.0 +FILES+= case11.0 +FILES+= case12.0 +FILES+= case13.0 +FILES+= case14.0 +FILES+= case15.0 +FILES+= case16.0 +FILES+= case17.0 +FILES+= case18.0 +FILES+= case19.0 +FILES+= cd1.0 +FILES+= cd2.0 +FILES+= cd3.0 +FILES+= cd4.0 +FILES+= cd5.0 +FILES+= cd6.0 +FILES+= cd7.0 +FILES+= cd8.0 +FILES+= command1.0 +FILES+= command2.0 +FILES+= command3.0 +FILES+= command3.0.stdout +FILES+= command4.0 +FILES+= command5.0 +FILES+= command5.0.stdout +FILES+= command6.0 +FILES+= command6.0.stdout +FILES+= command7.0 +FILES+= command8.0 +FILES+= command9.0 +FILES+= command10.0 +FILES+= command11.0 +FILES+= command12.0 +FILES+= dot1.0 +FILES+= dot2.0 +FILES+= dot3.0 +FILES+= dot4.0 +FILES+= eval1.0 +FILES+= eval2.0 +FILES+= eval3.0 +FILES+= eval4.0 +FILES+= eval5.0 +FILES+= eval6.0 +FILES+= exec1.0 +FILES+= exec2.0 +FILES+= exit1.0 +FILES+= exit2.8 +FILES+= exit3.0 +FILES+= export1.0 +FILES+= fc1.0 +FILES+= fc2.0 +FILES+= for1.0 +FILES+= for2.0 +FILES+= for3.0 +FILES+= getopts1.0 getopts1.0.stdout +FILES+= getopts2.0 getopts2.0.stdout +FILES+= hash1.0 hash1.0.stdout +FILES+= hash2.0 hash2.0.stdout +FILES+= hash3.0 hash3.0.stdout +FILES+= hash4.0 +FILES+= jobid1.0 +FILES+= jobid2.0 +FILES+= lineno.0 lineno.0.stdout +FILES+= local1.0 +FILES+= local2.0 +FILES+= local3.0 +FILES+= local4.0 +FILES+= locale1.0 +FILES+= printf1.0 +FILES+= printf2.0 +FILES+= printf3.0 +FILES+= printf4.0 +FILES+= read1.0 read1.0.stdout +FILES+= read2.0 +FILES+= read3.0 read3.0.stdout +FILES+= read4.0 read4.0.stdout +FILES+= read5.0 +FILES+= read6.0 +FILES+= read7.0 +FILES+= return1.0 +FILES+= return2.1 +FILES+= return3.1 +FILES+= return4.0 +FILES+= return5.0 +FILES+= return6.4 +FILES+= return7.4 +FILES+= return8.0 +FILES+= set1.0 +FILES+= set2.0 +FILES+= trap1.0 +FILES+= trap10.0 +FILES+= trap11.0 +FILES+= trap12.0 +FILES+= trap13.0 +FILES+= trap14.0 +FILES+= trap2.0 +FILES+= trap3.0 +FILES+= trap4.0 +FILES+= trap5.0 +FILES+= trap6.0 +FILES+= trap7.0 +FILES+= trap8.0 +FILES+= trap9.0 +FILES+= type1.0 type1.0.stderr +FILES+= type2.0 +FILES+= type3.0 +FILES+= unalias.0 +FILES+= var-assign.0 +FILES+= var-assign2.0 +FILES+= wait1.0 +FILES+= wait2.0 +FILES+= wait3.0 +FILES+= wait4.0 +FILES+= wait5.0 +FILES+= wait6.0 +FILES+= wait7.0 +FILES+= wait8.0 +FILES+= wait9.127 +FILES+= wait10.0 + +.include diff --git a/tools/regression/bin/sh/builtins/alias.0 b/bin/sh/tests/builtins/alias.0 similarity index 100% rename from tools/regression/bin/sh/builtins/alias.0 rename to bin/sh/tests/builtins/alias.0 diff --git a/tools/regression/bin/sh/builtins/alias.0.stdout b/bin/sh/tests/builtins/alias.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/alias.0.stdout rename to bin/sh/tests/builtins/alias.0.stdout diff --git a/tools/regression/bin/sh/builtins/alias.1 b/bin/sh/tests/builtins/alias.1 similarity index 100% rename from tools/regression/bin/sh/builtins/alias.1 rename to bin/sh/tests/builtins/alias.1 diff --git a/tools/regression/bin/sh/builtins/alias.1.stderr b/bin/sh/tests/builtins/alias.1.stderr similarity index 100% rename from tools/regression/bin/sh/builtins/alias.1.stderr rename to bin/sh/tests/builtins/alias.1.stderr diff --git a/tools/regression/bin/sh/builtins/alias3.0 b/bin/sh/tests/builtins/alias3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/alias3.0 rename to bin/sh/tests/builtins/alias3.0 diff --git a/tools/regression/bin/sh/builtins/alias3.0.stdout b/bin/sh/tests/builtins/alias3.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/alias3.0.stdout rename to bin/sh/tests/builtins/alias3.0.stdout diff --git a/tools/regression/bin/sh/builtins/alias4.0 b/bin/sh/tests/builtins/alias4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/alias4.0 rename to bin/sh/tests/builtins/alias4.0 diff --git a/tools/regression/bin/sh/builtins/break1.0 b/bin/sh/tests/builtins/break1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/break1.0 rename to bin/sh/tests/builtins/break1.0 diff --git a/tools/regression/bin/sh/builtins/break2.0 b/bin/sh/tests/builtins/break2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/break2.0 rename to bin/sh/tests/builtins/break2.0 diff --git a/tools/regression/bin/sh/builtins/break2.0.stdout b/bin/sh/tests/builtins/break2.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/break2.0.stdout rename to bin/sh/tests/builtins/break2.0.stdout diff --git a/tools/regression/bin/sh/builtins/break3.0 b/bin/sh/tests/builtins/break3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/break3.0 rename to bin/sh/tests/builtins/break3.0 diff --git a/tools/regression/bin/sh/builtins/break4.4 b/bin/sh/tests/builtins/break4.4 similarity index 100% rename from tools/regression/bin/sh/builtins/break4.4 rename to bin/sh/tests/builtins/break4.4 diff --git a/tools/regression/bin/sh/builtins/break5.4 b/bin/sh/tests/builtins/break5.4 similarity index 100% rename from tools/regression/bin/sh/builtins/break5.4 rename to bin/sh/tests/builtins/break5.4 diff --git a/tools/regression/bin/sh/builtins/builtin1.0 b/bin/sh/tests/builtins/builtin1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/builtin1.0 rename to bin/sh/tests/builtins/builtin1.0 diff --git a/tools/regression/bin/sh/builtins/case1.0 b/bin/sh/tests/builtins/case1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case1.0 rename to bin/sh/tests/builtins/case1.0 diff --git a/tools/regression/bin/sh/builtins/case10.0 b/bin/sh/tests/builtins/case10.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case10.0 rename to bin/sh/tests/builtins/case10.0 diff --git a/tools/regression/bin/sh/builtins/case11.0 b/bin/sh/tests/builtins/case11.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case11.0 rename to bin/sh/tests/builtins/case11.0 diff --git a/tools/regression/bin/sh/builtins/case12.0 b/bin/sh/tests/builtins/case12.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case12.0 rename to bin/sh/tests/builtins/case12.0 diff --git a/tools/regression/bin/sh/builtins/case13.0 b/bin/sh/tests/builtins/case13.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case13.0 rename to bin/sh/tests/builtins/case13.0 diff --git a/tools/regression/bin/sh/builtins/case14.0 b/bin/sh/tests/builtins/case14.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case14.0 rename to bin/sh/tests/builtins/case14.0 diff --git a/tools/regression/bin/sh/builtins/case15.0 b/bin/sh/tests/builtins/case15.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case15.0 rename to bin/sh/tests/builtins/case15.0 diff --git a/tools/regression/bin/sh/builtins/case16.0 b/bin/sh/tests/builtins/case16.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case16.0 rename to bin/sh/tests/builtins/case16.0 diff --git a/tools/regression/bin/sh/builtins/case17.0 b/bin/sh/tests/builtins/case17.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case17.0 rename to bin/sh/tests/builtins/case17.0 diff --git a/tools/regression/bin/sh/builtins/case18.0 b/bin/sh/tests/builtins/case18.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case18.0 rename to bin/sh/tests/builtins/case18.0 diff --git a/tools/regression/bin/sh/builtins/case19.0 b/bin/sh/tests/builtins/case19.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case19.0 rename to bin/sh/tests/builtins/case19.0 diff --git a/tools/regression/bin/sh/builtins/case2.0 b/bin/sh/tests/builtins/case2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case2.0 rename to bin/sh/tests/builtins/case2.0 diff --git a/tools/regression/bin/sh/builtins/case3.0 b/bin/sh/tests/builtins/case3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case3.0 rename to bin/sh/tests/builtins/case3.0 diff --git a/tools/regression/bin/sh/builtins/case4.0 b/bin/sh/tests/builtins/case4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case4.0 rename to bin/sh/tests/builtins/case4.0 diff --git a/tools/regression/bin/sh/builtins/case5.0 b/bin/sh/tests/builtins/case5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case5.0 rename to bin/sh/tests/builtins/case5.0 diff --git a/tools/regression/bin/sh/builtins/case6.0 b/bin/sh/tests/builtins/case6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case6.0 rename to bin/sh/tests/builtins/case6.0 diff --git a/tools/regression/bin/sh/builtins/case7.0 b/bin/sh/tests/builtins/case7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case7.0 rename to bin/sh/tests/builtins/case7.0 diff --git a/tools/regression/bin/sh/builtins/case8.0 b/bin/sh/tests/builtins/case8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case8.0 rename to bin/sh/tests/builtins/case8.0 diff --git a/tools/regression/bin/sh/builtins/case9.0 b/bin/sh/tests/builtins/case9.0 similarity index 100% rename from tools/regression/bin/sh/builtins/case9.0 rename to bin/sh/tests/builtins/case9.0 diff --git a/tools/regression/bin/sh/builtins/cd1.0 b/bin/sh/tests/builtins/cd1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd1.0 rename to bin/sh/tests/builtins/cd1.0 diff --git a/tools/regression/bin/sh/builtins/cd2.0 b/bin/sh/tests/builtins/cd2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd2.0 rename to bin/sh/tests/builtins/cd2.0 diff --git a/tools/regression/bin/sh/builtins/cd3.0 b/bin/sh/tests/builtins/cd3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd3.0 rename to bin/sh/tests/builtins/cd3.0 diff --git a/tools/regression/bin/sh/builtins/cd4.0 b/bin/sh/tests/builtins/cd4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd4.0 rename to bin/sh/tests/builtins/cd4.0 diff --git a/tools/regression/bin/sh/builtins/cd5.0 b/bin/sh/tests/builtins/cd5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd5.0 rename to bin/sh/tests/builtins/cd5.0 diff --git a/tools/regression/bin/sh/builtins/cd6.0 b/bin/sh/tests/builtins/cd6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd6.0 rename to bin/sh/tests/builtins/cd6.0 diff --git a/tools/regression/bin/sh/builtins/cd7.0 b/bin/sh/tests/builtins/cd7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd7.0 rename to bin/sh/tests/builtins/cd7.0 diff --git a/tools/regression/bin/sh/builtins/cd8.0 b/bin/sh/tests/builtins/cd8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/cd8.0 rename to bin/sh/tests/builtins/cd8.0 diff --git a/tools/regression/bin/sh/builtins/command1.0 b/bin/sh/tests/builtins/command1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command1.0 rename to bin/sh/tests/builtins/command1.0 diff --git a/tools/regression/bin/sh/builtins/command10.0 b/bin/sh/tests/builtins/command10.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command10.0 rename to bin/sh/tests/builtins/command10.0 diff --git a/tools/regression/bin/sh/builtins/command11.0 b/bin/sh/tests/builtins/command11.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command11.0 rename to bin/sh/tests/builtins/command11.0 diff --git a/tools/regression/bin/sh/builtins/command12.0 b/bin/sh/tests/builtins/command12.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command12.0 rename to bin/sh/tests/builtins/command12.0 diff --git a/tools/regression/bin/sh/builtins/command2.0 b/bin/sh/tests/builtins/command2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command2.0 rename to bin/sh/tests/builtins/command2.0 diff --git a/tools/regression/bin/sh/builtins/command3.0 b/bin/sh/tests/builtins/command3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command3.0 rename to bin/sh/tests/builtins/command3.0 diff --git a/tools/regression/bin/sh/builtins/command3.0.stdout b/bin/sh/tests/builtins/command3.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/command3.0.stdout rename to bin/sh/tests/builtins/command3.0.stdout diff --git a/tools/regression/bin/sh/builtins/command4.0 b/bin/sh/tests/builtins/command4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command4.0 rename to bin/sh/tests/builtins/command4.0 diff --git a/tools/regression/bin/sh/builtins/command5.0 b/bin/sh/tests/builtins/command5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command5.0 rename to bin/sh/tests/builtins/command5.0 diff --git a/tools/regression/bin/sh/builtins/command5.0.stdout b/bin/sh/tests/builtins/command5.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/command5.0.stdout rename to bin/sh/tests/builtins/command5.0.stdout diff --git a/tools/regression/bin/sh/builtins/command6.0 b/bin/sh/tests/builtins/command6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command6.0 rename to bin/sh/tests/builtins/command6.0 diff --git a/tools/regression/bin/sh/builtins/command6.0.stdout b/bin/sh/tests/builtins/command6.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/command6.0.stdout rename to bin/sh/tests/builtins/command6.0.stdout diff --git a/tools/regression/bin/sh/builtins/command7.0 b/bin/sh/tests/builtins/command7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command7.0 rename to bin/sh/tests/builtins/command7.0 diff --git a/tools/regression/bin/sh/builtins/command8.0 b/bin/sh/tests/builtins/command8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command8.0 rename to bin/sh/tests/builtins/command8.0 diff --git a/tools/regression/bin/sh/builtins/command9.0 b/bin/sh/tests/builtins/command9.0 similarity index 100% rename from tools/regression/bin/sh/builtins/command9.0 rename to bin/sh/tests/builtins/command9.0 diff --git a/tools/regression/bin/sh/builtins/dot1.0 b/bin/sh/tests/builtins/dot1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/dot1.0 rename to bin/sh/tests/builtins/dot1.0 diff --git a/tools/regression/bin/sh/builtins/dot2.0 b/bin/sh/tests/builtins/dot2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/dot2.0 rename to bin/sh/tests/builtins/dot2.0 diff --git a/tools/regression/bin/sh/builtins/dot3.0 b/bin/sh/tests/builtins/dot3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/dot3.0 rename to bin/sh/tests/builtins/dot3.0 diff --git a/tools/regression/bin/sh/builtins/dot4.0 b/bin/sh/tests/builtins/dot4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/dot4.0 rename to bin/sh/tests/builtins/dot4.0 diff --git a/tools/regression/bin/sh/builtins/eval1.0 b/bin/sh/tests/builtins/eval1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval1.0 rename to bin/sh/tests/builtins/eval1.0 diff --git a/tools/regression/bin/sh/builtins/eval2.0 b/bin/sh/tests/builtins/eval2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval2.0 rename to bin/sh/tests/builtins/eval2.0 diff --git a/tools/regression/bin/sh/builtins/eval3.0 b/bin/sh/tests/builtins/eval3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval3.0 rename to bin/sh/tests/builtins/eval3.0 diff --git a/tools/regression/bin/sh/builtins/eval4.0 b/bin/sh/tests/builtins/eval4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval4.0 rename to bin/sh/tests/builtins/eval4.0 diff --git a/tools/regression/bin/sh/builtins/eval5.0 b/bin/sh/tests/builtins/eval5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval5.0 rename to bin/sh/tests/builtins/eval5.0 diff --git a/tools/regression/bin/sh/builtins/eval6.0 b/bin/sh/tests/builtins/eval6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/eval6.0 rename to bin/sh/tests/builtins/eval6.0 diff --git a/tools/regression/bin/sh/builtins/exec1.0 b/bin/sh/tests/builtins/exec1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/exec1.0 rename to bin/sh/tests/builtins/exec1.0 diff --git a/tools/regression/bin/sh/builtins/exec2.0 b/bin/sh/tests/builtins/exec2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/exec2.0 rename to bin/sh/tests/builtins/exec2.0 diff --git a/tools/regression/bin/sh/builtins/exit1.0 b/bin/sh/tests/builtins/exit1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/exit1.0 rename to bin/sh/tests/builtins/exit1.0 diff --git a/tools/regression/bin/sh/builtins/exit2.8 b/bin/sh/tests/builtins/exit2.8 similarity index 100% rename from tools/regression/bin/sh/builtins/exit2.8 rename to bin/sh/tests/builtins/exit2.8 diff --git a/tools/regression/bin/sh/builtins/exit3.0 b/bin/sh/tests/builtins/exit3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/exit3.0 rename to bin/sh/tests/builtins/exit3.0 diff --git a/tools/regression/bin/sh/builtins/export1.0 b/bin/sh/tests/builtins/export1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/export1.0 rename to bin/sh/tests/builtins/export1.0 diff --git a/tools/regression/bin/sh/builtins/fc1.0 b/bin/sh/tests/builtins/fc1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/fc1.0 rename to bin/sh/tests/builtins/fc1.0 diff --git a/tools/regression/bin/sh/builtins/fc2.0 b/bin/sh/tests/builtins/fc2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/fc2.0 rename to bin/sh/tests/builtins/fc2.0 diff --git a/tools/regression/bin/sh/builtins/for1.0 b/bin/sh/tests/builtins/for1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/for1.0 rename to bin/sh/tests/builtins/for1.0 diff --git a/tools/regression/bin/sh/builtins/for2.0 b/bin/sh/tests/builtins/for2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/for2.0 rename to bin/sh/tests/builtins/for2.0 diff --git a/tools/regression/bin/sh/builtins/for3.0 b/bin/sh/tests/builtins/for3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/for3.0 rename to bin/sh/tests/builtins/for3.0 diff --git a/tools/regression/bin/sh/builtins/getopts1.0 b/bin/sh/tests/builtins/getopts1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/getopts1.0 rename to bin/sh/tests/builtins/getopts1.0 diff --git a/tools/regression/bin/sh/builtins/getopts1.0.stdout b/bin/sh/tests/builtins/getopts1.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/getopts1.0.stdout rename to bin/sh/tests/builtins/getopts1.0.stdout diff --git a/tools/regression/bin/sh/builtins/getopts2.0 b/bin/sh/tests/builtins/getopts2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/getopts2.0 rename to bin/sh/tests/builtins/getopts2.0 diff --git a/tools/regression/bin/sh/builtins/getopts2.0.stdout b/bin/sh/tests/builtins/getopts2.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/getopts2.0.stdout rename to bin/sh/tests/builtins/getopts2.0.stdout diff --git a/tools/regression/bin/sh/builtins/hash1.0 b/bin/sh/tests/builtins/hash1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/hash1.0 rename to bin/sh/tests/builtins/hash1.0 diff --git a/tools/regression/bin/sh/builtins/hash1.0.stdout b/bin/sh/tests/builtins/hash1.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/hash1.0.stdout rename to bin/sh/tests/builtins/hash1.0.stdout diff --git a/tools/regression/bin/sh/builtins/hash2.0 b/bin/sh/tests/builtins/hash2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/hash2.0 rename to bin/sh/tests/builtins/hash2.0 diff --git a/tools/regression/bin/sh/builtins/hash2.0.stdout b/bin/sh/tests/builtins/hash2.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/hash2.0.stdout rename to bin/sh/tests/builtins/hash2.0.stdout diff --git a/tools/regression/bin/sh/builtins/hash3.0 b/bin/sh/tests/builtins/hash3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/hash3.0 rename to bin/sh/tests/builtins/hash3.0 diff --git a/tools/regression/bin/sh/builtins/hash3.0.stdout b/bin/sh/tests/builtins/hash3.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/hash3.0.stdout rename to bin/sh/tests/builtins/hash3.0.stdout diff --git a/tools/regression/bin/sh/builtins/hash4.0 b/bin/sh/tests/builtins/hash4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/hash4.0 rename to bin/sh/tests/builtins/hash4.0 diff --git a/tools/regression/bin/sh/builtins/jobid1.0 b/bin/sh/tests/builtins/jobid1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/jobid1.0 rename to bin/sh/tests/builtins/jobid1.0 diff --git a/tools/regression/bin/sh/builtins/jobid2.0 b/bin/sh/tests/builtins/jobid2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/jobid2.0 rename to bin/sh/tests/builtins/jobid2.0 diff --git a/tools/regression/bin/sh/builtins/lineno.0 b/bin/sh/tests/builtins/lineno.0 similarity index 100% rename from tools/regression/bin/sh/builtins/lineno.0 rename to bin/sh/tests/builtins/lineno.0 diff --git a/tools/regression/bin/sh/builtins/lineno.0.stdout b/bin/sh/tests/builtins/lineno.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/lineno.0.stdout rename to bin/sh/tests/builtins/lineno.0.stdout diff --git a/tools/regression/bin/sh/builtins/local1.0 b/bin/sh/tests/builtins/local1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/local1.0 rename to bin/sh/tests/builtins/local1.0 diff --git a/tools/regression/bin/sh/builtins/local2.0 b/bin/sh/tests/builtins/local2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/local2.0 rename to bin/sh/tests/builtins/local2.0 diff --git a/tools/regression/bin/sh/builtins/local3.0 b/bin/sh/tests/builtins/local3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/local3.0 rename to bin/sh/tests/builtins/local3.0 diff --git a/tools/regression/bin/sh/builtins/local4.0 b/bin/sh/tests/builtins/local4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/local4.0 rename to bin/sh/tests/builtins/local4.0 diff --git a/tools/regression/bin/sh/builtins/locale1.0 b/bin/sh/tests/builtins/locale1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/locale1.0 rename to bin/sh/tests/builtins/locale1.0 diff --git a/tools/regression/bin/sh/builtins/printf1.0 b/bin/sh/tests/builtins/printf1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/printf1.0 rename to bin/sh/tests/builtins/printf1.0 diff --git a/tools/regression/bin/sh/builtins/printf2.0 b/bin/sh/tests/builtins/printf2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/printf2.0 rename to bin/sh/tests/builtins/printf2.0 diff --git a/tools/regression/bin/sh/builtins/printf3.0 b/bin/sh/tests/builtins/printf3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/printf3.0 rename to bin/sh/tests/builtins/printf3.0 diff --git a/tools/regression/bin/sh/builtins/printf4.0 b/bin/sh/tests/builtins/printf4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/printf4.0 rename to bin/sh/tests/builtins/printf4.0 diff --git a/tools/regression/bin/sh/builtins/read1.0 b/bin/sh/tests/builtins/read1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read1.0 rename to bin/sh/tests/builtins/read1.0 diff --git a/tools/regression/bin/sh/builtins/read1.0.stdout b/bin/sh/tests/builtins/read1.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/read1.0.stdout rename to bin/sh/tests/builtins/read1.0.stdout diff --git a/tools/regression/bin/sh/builtins/read2.0 b/bin/sh/tests/builtins/read2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read2.0 rename to bin/sh/tests/builtins/read2.0 diff --git a/tools/regression/bin/sh/builtins/read3.0 b/bin/sh/tests/builtins/read3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read3.0 rename to bin/sh/tests/builtins/read3.0 diff --git a/tools/regression/bin/sh/builtins/read3.0.stdout b/bin/sh/tests/builtins/read3.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/read3.0.stdout rename to bin/sh/tests/builtins/read3.0.stdout diff --git a/tools/regression/bin/sh/builtins/read4.0 b/bin/sh/tests/builtins/read4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read4.0 rename to bin/sh/tests/builtins/read4.0 diff --git a/tools/regression/bin/sh/builtins/read4.0.stdout b/bin/sh/tests/builtins/read4.0.stdout similarity index 100% rename from tools/regression/bin/sh/builtins/read4.0.stdout rename to bin/sh/tests/builtins/read4.0.stdout diff --git a/tools/regression/bin/sh/builtins/read5.0 b/bin/sh/tests/builtins/read5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read5.0 rename to bin/sh/tests/builtins/read5.0 diff --git a/tools/regression/bin/sh/builtins/read6.0 b/bin/sh/tests/builtins/read6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read6.0 rename to bin/sh/tests/builtins/read6.0 diff --git a/tools/regression/bin/sh/builtins/read7.0 b/bin/sh/tests/builtins/read7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/read7.0 rename to bin/sh/tests/builtins/read7.0 diff --git a/tools/regression/bin/sh/builtins/return1.0 b/bin/sh/tests/builtins/return1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/return1.0 rename to bin/sh/tests/builtins/return1.0 diff --git a/tools/regression/bin/sh/builtins/return2.1 b/bin/sh/tests/builtins/return2.1 similarity index 100% rename from tools/regression/bin/sh/builtins/return2.1 rename to bin/sh/tests/builtins/return2.1 diff --git a/tools/regression/bin/sh/builtins/return3.1 b/bin/sh/tests/builtins/return3.1 similarity index 100% rename from tools/regression/bin/sh/builtins/return3.1 rename to bin/sh/tests/builtins/return3.1 diff --git a/tools/regression/bin/sh/builtins/return4.0 b/bin/sh/tests/builtins/return4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/return4.0 rename to bin/sh/tests/builtins/return4.0 diff --git a/tools/regression/bin/sh/builtins/return5.0 b/bin/sh/tests/builtins/return5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/return5.0 rename to bin/sh/tests/builtins/return5.0 diff --git a/tools/regression/bin/sh/builtins/return6.4 b/bin/sh/tests/builtins/return6.4 similarity index 100% rename from tools/regression/bin/sh/builtins/return6.4 rename to bin/sh/tests/builtins/return6.4 diff --git a/tools/regression/bin/sh/builtins/return7.4 b/bin/sh/tests/builtins/return7.4 similarity index 100% rename from tools/regression/bin/sh/builtins/return7.4 rename to bin/sh/tests/builtins/return7.4 diff --git a/tools/regression/bin/sh/builtins/return8.0 b/bin/sh/tests/builtins/return8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/return8.0 rename to bin/sh/tests/builtins/return8.0 diff --git a/tools/regression/bin/sh/builtins/set1.0 b/bin/sh/tests/builtins/set1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/set1.0 rename to bin/sh/tests/builtins/set1.0 diff --git a/tools/regression/bin/sh/builtins/set2.0 b/bin/sh/tests/builtins/set2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/set2.0 rename to bin/sh/tests/builtins/set2.0 diff --git a/tools/regression/bin/sh/builtins/trap1.0 b/bin/sh/tests/builtins/trap1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap1.0 rename to bin/sh/tests/builtins/trap1.0 diff --git a/tools/regression/bin/sh/builtins/trap10.0 b/bin/sh/tests/builtins/trap10.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap10.0 rename to bin/sh/tests/builtins/trap10.0 diff --git a/tools/regression/bin/sh/builtins/trap11.0 b/bin/sh/tests/builtins/trap11.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap11.0 rename to bin/sh/tests/builtins/trap11.0 diff --git a/tools/regression/bin/sh/builtins/trap12.0 b/bin/sh/tests/builtins/trap12.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap12.0 rename to bin/sh/tests/builtins/trap12.0 diff --git a/tools/regression/bin/sh/builtins/trap13.0 b/bin/sh/tests/builtins/trap13.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap13.0 rename to bin/sh/tests/builtins/trap13.0 diff --git a/tools/regression/bin/sh/builtins/trap14.0 b/bin/sh/tests/builtins/trap14.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap14.0 rename to bin/sh/tests/builtins/trap14.0 diff --git a/tools/regression/bin/sh/builtins/trap2.0 b/bin/sh/tests/builtins/trap2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap2.0 rename to bin/sh/tests/builtins/trap2.0 diff --git a/tools/regression/bin/sh/builtins/trap3.0 b/bin/sh/tests/builtins/trap3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap3.0 rename to bin/sh/tests/builtins/trap3.0 diff --git a/tools/regression/bin/sh/builtins/trap4.0 b/bin/sh/tests/builtins/trap4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap4.0 rename to bin/sh/tests/builtins/trap4.0 diff --git a/tools/regression/bin/sh/builtins/trap5.0 b/bin/sh/tests/builtins/trap5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap5.0 rename to bin/sh/tests/builtins/trap5.0 diff --git a/tools/regression/bin/sh/builtins/trap6.0 b/bin/sh/tests/builtins/trap6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap6.0 rename to bin/sh/tests/builtins/trap6.0 diff --git a/tools/regression/bin/sh/builtins/trap7.0 b/bin/sh/tests/builtins/trap7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap7.0 rename to bin/sh/tests/builtins/trap7.0 diff --git a/tools/regression/bin/sh/builtins/trap8.0 b/bin/sh/tests/builtins/trap8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap8.0 rename to bin/sh/tests/builtins/trap8.0 diff --git a/tools/regression/bin/sh/builtins/trap9.0 b/bin/sh/tests/builtins/trap9.0 similarity index 100% rename from tools/regression/bin/sh/builtins/trap9.0 rename to bin/sh/tests/builtins/trap9.0 diff --git a/tools/regression/bin/sh/builtins/type1.0 b/bin/sh/tests/builtins/type1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/type1.0 rename to bin/sh/tests/builtins/type1.0 diff --git a/tools/regression/bin/sh/builtins/type1.0.stderr b/bin/sh/tests/builtins/type1.0.stderr similarity index 100% rename from tools/regression/bin/sh/builtins/type1.0.stderr rename to bin/sh/tests/builtins/type1.0.stderr diff --git a/tools/regression/bin/sh/builtins/type2.0 b/bin/sh/tests/builtins/type2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/type2.0 rename to bin/sh/tests/builtins/type2.0 diff --git a/tools/regression/bin/sh/builtins/type3.0 b/bin/sh/tests/builtins/type3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/type3.0 rename to bin/sh/tests/builtins/type3.0 diff --git a/tools/regression/bin/sh/builtins/unalias.0 b/bin/sh/tests/builtins/unalias.0 similarity index 100% rename from tools/regression/bin/sh/builtins/unalias.0 rename to bin/sh/tests/builtins/unalias.0 diff --git a/tools/regression/bin/sh/builtins/var-assign.0 b/bin/sh/tests/builtins/var-assign.0 similarity index 100% rename from tools/regression/bin/sh/builtins/var-assign.0 rename to bin/sh/tests/builtins/var-assign.0 diff --git a/tools/regression/bin/sh/builtins/var-assign2.0 b/bin/sh/tests/builtins/var-assign2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/var-assign2.0 rename to bin/sh/tests/builtins/var-assign2.0 diff --git a/tools/regression/bin/sh/builtins/wait1.0 b/bin/sh/tests/builtins/wait1.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait1.0 rename to bin/sh/tests/builtins/wait1.0 diff --git a/tools/regression/bin/sh/builtins/wait10.0 b/bin/sh/tests/builtins/wait10.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait10.0 rename to bin/sh/tests/builtins/wait10.0 diff --git a/tools/regression/bin/sh/builtins/wait2.0 b/bin/sh/tests/builtins/wait2.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait2.0 rename to bin/sh/tests/builtins/wait2.0 diff --git a/tools/regression/bin/sh/builtins/wait3.0 b/bin/sh/tests/builtins/wait3.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait3.0 rename to bin/sh/tests/builtins/wait3.0 diff --git a/tools/regression/bin/sh/builtins/wait4.0 b/bin/sh/tests/builtins/wait4.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait4.0 rename to bin/sh/tests/builtins/wait4.0 diff --git a/tools/regression/bin/sh/builtins/wait5.0 b/bin/sh/tests/builtins/wait5.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait5.0 rename to bin/sh/tests/builtins/wait5.0 diff --git a/tools/regression/bin/sh/builtins/wait6.0 b/bin/sh/tests/builtins/wait6.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait6.0 rename to bin/sh/tests/builtins/wait6.0 diff --git a/tools/regression/bin/sh/builtins/wait7.0 b/bin/sh/tests/builtins/wait7.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait7.0 rename to bin/sh/tests/builtins/wait7.0 diff --git a/tools/regression/bin/sh/builtins/wait8.0 b/bin/sh/tests/builtins/wait8.0 similarity index 100% rename from tools/regression/bin/sh/builtins/wait8.0 rename to bin/sh/tests/builtins/wait8.0 diff --git a/tools/regression/bin/sh/builtins/wait9.127 b/bin/sh/tests/builtins/wait9.127 similarity index 100% rename from tools/regression/bin/sh/builtins/wait9.127 rename to bin/sh/tests/builtins/wait9.127 diff --git a/bin/sh/tests/errors/Makefile b/bin/sh/tests/errors/Makefile new file mode 100644 index 000000000000..9f8b0f2045d9 --- /dev/null +++ b/bin/sh/tests/errors/Makefile @@ -0,0 +1,30 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/errors +KYUAFILE= no + +FILES= assignment-error1.0 +FILES+= assignment-error2.0 +FILES+= backquote-error1.0 +FILES+= backquote-error2.0 +FILES+= bad-binary1.126 +FILES+= bad-keyword1.0 +FILES+= bad-parm-exp1.0 +FILES+= bad-parm-exp2.2 bad-parm-exp2.2.stderr +FILES+= bad-parm-exp3.2 bad-parm-exp3.2.stderr +FILES+= bad-parm-exp4.2 bad-parm-exp4.2.stderr +FILES+= bad-parm-exp5.2 bad-parm-exp5.2.stderr +FILES+= bad-parm-exp6.2 bad-parm-exp6.2.stderr +FILES+= option-error.0 +FILES+= redirection-error.0 +FILES+= redirection-error2.2 +FILES+= redirection-error3.0 +FILES+= redirection-error4.0 +FILES+= redirection-error5.0 +FILES+= redirection-error6.0 +FILES+= redirection-error7.0 +FILES+= write-error1.0 + +.include diff --git a/tools/regression/bin/sh/errors/assignment-error1.0 b/bin/sh/tests/errors/assignment-error1.0 similarity index 100% rename from tools/regression/bin/sh/errors/assignment-error1.0 rename to bin/sh/tests/errors/assignment-error1.0 diff --git a/tools/regression/bin/sh/errors/assignment-error2.0 b/bin/sh/tests/errors/assignment-error2.0 similarity index 100% rename from tools/regression/bin/sh/errors/assignment-error2.0 rename to bin/sh/tests/errors/assignment-error2.0 diff --git a/tools/regression/bin/sh/errors/backquote-error1.0 b/bin/sh/tests/errors/backquote-error1.0 similarity index 100% rename from tools/regression/bin/sh/errors/backquote-error1.0 rename to bin/sh/tests/errors/backquote-error1.0 diff --git a/tools/regression/bin/sh/errors/backquote-error2.0 b/bin/sh/tests/errors/backquote-error2.0 similarity index 100% rename from tools/regression/bin/sh/errors/backquote-error2.0 rename to bin/sh/tests/errors/backquote-error2.0 diff --git a/tools/regression/bin/sh/errors/bad-binary1.126 b/bin/sh/tests/errors/bad-binary1.126 similarity index 100% rename from tools/regression/bin/sh/errors/bad-binary1.126 rename to bin/sh/tests/errors/bad-binary1.126 diff --git a/tools/regression/bin/sh/errors/bad-keyword1.0 b/bin/sh/tests/errors/bad-keyword1.0 similarity index 100% rename from tools/regression/bin/sh/errors/bad-keyword1.0 rename to bin/sh/tests/errors/bad-keyword1.0 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp1.0 b/bin/sh/tests/errors/bad-parm-exp1.0 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp1.0 rename to bin/sh/tests/errors/bad-parm-exp1.0 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp2.2 b/bin/sh/tests/errors/bad-parm-exp2.2 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp2.2 rename to bin/sh/tests/errors/bad-parm-exp2.2 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp2.2.stderr b/bin/sh/tests/errors/bad-parm-exp2.2.stderr similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp2.2.stderr rename to bin/sh/tests/errors/bad-parm-exp2.2.stderr diff --git a/tools/regression/bin/sh/errors/bad-parm-exp3.2 b/bin/sh/tests/errors/bad-parm-exp3.2 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp3.2 rename to bin/sh/tests/errors/bad-parm-exp3.2 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp3.2.stderr b/bin/sh/tests/errors/bad-parm-exp3.2.stderr similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp3.2.stderr rename to bin/sh/tests/errors/bad-parm-exp3.2.stderr diff --git a/tools/regression/bin/sh/errors/bad-parm-exp4.2 b/bin/sh/tests/errors/bad-parm-exp4.2 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp4.2 rename to bin/sh/tests/errors/bad-parm-exp4.2 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp4.2.stderr b/bin/sh/tests/errors/bad-parm-exp4.2.stderr similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp4.2.stderr rename to bin/sh/tests/errors/bad-parm-exp4.2.stderr diff --git a/tools/regression/bin/sh/errors/bad-parm-exp5.2 b/bin/sh/tests/errors/bad-parm-exp5.2 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp5.2 rename to bin/sh/tests/errors/bad-parm-exp5.2 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp5.2.stderr b/bin/sh/tests/errors/bad-parm-exp5.2.stderr similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp5.2.stderr rename to bin/sh/tests/errors/bad-parm-exp5.2.stderr diff --git a/tools/regression/bin/sh/errors/bad-parm-exp6.2 b/bin/sh/tests/errors/bad-parm-exp6.2 similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp6.2 rename to bin/sh/tests/errors/bad-parm-exp6.2 diff --git a/tools/regression/bin/sh/errors/bad-parm-exp6.2.stderr b/bin/sh/tests/errors/bad-parm-exp6.2.stderr similarity index 100% rename from tools/regression/bin/sh/errors/bad-parm-exp6.2.stderr rename to bin/sh/tests/errors/bad-parm-exp6.2.stderr diff --git a/tools/regression/bin/sh/errors/option-error.0 b/bin/sh/tests/errors/option-error.0 similarity index 100% rename from tools/regression/bin/sh/errors/option-error.0 rename to bin/sh/tests/errors/option-error.0 diff --git a/tools/regression/bin/sh/errors/redirection-error.0 b/bin/sh/tests/errors/redirection-error.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error.0 rename to bin/sh/tests/errors/redirection-error.0 diff --git a/tools/regression/bin/sh/errors/redirection-error2.2 b/bin/sh/tests/errors/redirection-error2.2 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error2.2 rename to bin/sh/tests/errors/redirection-error2.2 diff --git a/tools/regression/bin/sh/errors/redirection-error3.0 b/bin/sh/tests/errors/redirection-error3.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error3.0 rename to bin/sh/tests/errors/redirection-error3.0 diff --git a/tools/regression/bin/sh/errors/redirection-error4.0 b/bin/sh/tests/errors/redirection-error4.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error4.0 rename to bin/sh/tests/errors/redirection-error4.0 diff --git a/tools/regression/bin/sh/errors/redirection-error5.0 b/bin/sh/tests/errors/redirection-error5.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error5.0 rename to bin/sh/tests/errors/redirection-error5.0 diff --git a/tools/regression/bin/sh/errors/redirection-error6.0 b/bin/sh/tests/errors/redirection-error6.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error6.0 rename to bin/sh/tests/errors/redirection-error6.0 diff --git a/tools/regression/bin/sh/errors/redirection-error7.0 b/bin/sh/tests/errors/redirection-error7.0 similarity index 100% rename from tools/regression/bin/sh/errors/redirection-error7.0 rename to bin/sh/tests/errors/redirection-error7.0 diff --git a/tools/regression/bin/sh/errors/write-error1.0 b/bin/sh/tests/errors/write-error1.0 similarity index 100% rename from tools/regression/bin/sh/errors/write-error1.0 rename to bin/sh/tests/errors/write-error1.0 diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile new file mode 100644 index 000000000000..302d0d824c41 --- /dev/null +++ b/bin/sh/tests/execution/Makefile @@ -0,0 +1,53 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/execution +KYUAFILE= no + +FILES= bg1.0 +FILES+= bg2.0 +FILES+= bg3.0 +FILES+= bg4.0 +FILES+= bg5.0 +FILES+= bg6.0 bg6.0.stdout +FILES+= bg7.0 +FILES+= bg8.0 +FILES+= bg9.0 +FILES+= bg10.0 bg10.0.stdout +FILES+= fork1.0 +FILES+= fork2.0 +FILES+= fork3.0 +FILES+= func1.0 +FILES+= func2.0 +FILES+= func3.0 +FILES+= hash1.0 +FILES+= int-cmd1.0 +FILES+= killed1.0 +FILES+= killed2.0 +FILES+= not1.0 +FILES+= not2.0 +FILES+= path1.0 +FILES+= redir1.0 +FILES+= redir2.0 +FILES+= redir3.0 +FILES+= redir4.0 +FILES+= redir5.0 +FILES+= redir6.0 +FILES+= redir7.0 +FILES+= set-n1.0 +FILES+= set-n2.0 +FILES+= set-n3.0 +FILES+= set-n4.0 +FILES+= set-x1.0 +FILES+= set-x2.0 +FILES+= set-x3.0 +FILES+= shellproc1.0 +FILES+= subshell1.0 subshell1.0.stdout +FILES+= subshell2.0 +FILES+= subshell3.0 +FILES+= subshell4.0 +FILES+= unknown1.0 +FILES+= var-assign1.0 + +.include diff --git a/tools/regression/bin/sh/execution/bg1.0 b/bin/sh/tests/execution/bg1.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg1.0 rename to bin/sh/tests/execution/bg1.0 diff --git a/tools/regression/bin/sh/execution/bg10.0 b/bin/sh/tests/execution/bg10.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg10.0 rename to bin/sh/tests/execution/bg10.0 diff --git a/tools/regression/bin/sh/execution/bg10.0.stdout b/bin/sh/tests/execution/bg10.0.stdout similarity index 100% rename from tools/regression/bin/sh/execution/bg10.0.stdout rename to bin/sh/tests/execution/bg10.0.stdout diff --git a/tools/regression/bin/sh/execution/bg2.0 b/bin/sh/tests/execution/bg2.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg2.0 rename to bin/sh/tests/execution/bg2.0 diff --git a/tools/regression/bin/sh/execution/bg3.0 b/bin/sh/tests/execution/bg3.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg3.0 rename to bin/sh/tests/execution/bg3.0 diff --git a/tools/regression/bin/sh/execution/bg4.0 b/bin/sh/tests/execution/bg4.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg4.0 rename to bin/sh/tests/execution/bg4.0 diff --git a/tools/regression/bin/sh/execution/bg5.0 b/bin/sh/tests/execution/bg5.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg5.0 rename to bin/sh/tests/execution/bg5.0 diff --git a/tools/regression/bin/sh/execution/bg6.0 b/bin/sh/tests/execution/bg6.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg6.0 rename to bin/sh/tests/execution/bg6.0 diff --git a/tools/regression/bin/sh/execution/bg6.0.stdout b/bin/sh/tests/execution/bg6.0.stdout similarity index 100% rename from tools/regression/bin/sh/execution/bg6.0.stdout rename to bin/sh/tests/execution/bg6.0.stdout diff --git a/tools/regression/bin/sh/execution/bg7.0 b/bin/sh/tests/execution/bg7.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg7.0 rename to bin/sh/tests/execution/bg7.0 diff --git a/tools/regression/bin/sh/execution/bg8.0 b/bin/sh/tests/execution/bg8.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg8.0 rename to bin/sh/tests/execution/bg8.0 diff --git a/tools/regression/bin/sh/execution/bg9.0 b/bin/sh/tests/execution/bg9.0 similarity index 100% rename from tools/regression/bin/sh/execution/bg9.0 rename to bin/sh/tests/execution/bg9.0 diff --git a/tools/regression/bin/sh/execution/fork1.0 b/bin/sh/tests/execution/fork1.0 similarity index 100% rename from tools/regression/bin/sh/execution/fork1.0 rename to bin/sh/tests/execution/fork1.0 diff --git a/tools/regression/bin/sh/execution/fork2.0 b/bin/sh/tests/execution/fork2.0 similarity index 100% rename from tools/regression/bin/sh/execution/fork2.0 rename to bin/sh/tests/execution/fork2.0 diff --git a/tools/regression/bin/sh/execution/fork3.0 b/bin/sh/tests/execution/fork3.0 similarity index 100% rename from tools/regression/bin/sh/execution/fork3.0 rename to bin/sh/tests/execution/fork3.0 diff --git a/tools/regression/bin/sh/execution/func1.0 b/bin/sh/tests/execution/func1.0 similarity index 100% rename from tools/regression/bin/sh/execution/func1.0 rename to bin/sh/tests/execution/func1.0 diff --git a/tools/regression/bin/sh/execution/func2.0 b/bin/sh/tests/execution/func2.0 similarity index 100% rename from tools/regression/bin/sh/execution/func2.0 rename to bin/sh/tests/execution/func2.0 diff --git a/tools/regression/bin/sh/execution/func3.0 b/bin/sh/tests/execution/func3.0 similarity index 100% rename from tools/regression/bin/sh/execution/func3.0 rename to bin/sh/tests/execution/func3.0 diff --git a/tools/regression/bin/sh/execution/hash1.0 b/bin/sh/tests/execution/hash1.0 similarity index 100% rename from tools/regression/bin/sh/execution/hash1.0 rename to bin/sh/tests/execution/hash1.0 diff --git a/tools/regression/bin/sh/execution/int-cmd1.0 b/bin/sh/tests/execution/int-cmd1.0 similarity index 100% rename from tools/regression/bin/sh/execution/int-cmd1.0 rename to bin/sh/tests/execution/int-cmd1.0 diff --git a/tools/regression/bin/sh/execution/killed1.0 b/bin/sh/tests/execution/killed1.0 similarity index 100% rename from tools/regression/bin/sh/execution/killed1.0 rename to bin/sh/tests/execution/killed1.0 diff --git a/tools/regression/bin/sh/execution/killed2.0 b/bin/sh/tests/execution/killed2.0 similarity index 100% rename from tools/regression/bin/sh/execution/killed2.0 rename to bin/sh/tests/execution/killed2.0 diff --git a/tools/regression/bin/sh/execution/not1.0 b/bin/sh/tests/execution/not1.0 similarity index 100% rename from tools/regression/bin/sh/execution/not1.0 rename to bin/sh/tests/execution/not1.0 diff --git a/tools/regression/bin/sh/execution/not2.0 b/bin/sh/tests/execution/not2.0 similarity index 100% rename from tools/regression/bin/sh/execution/not2.0 rename to bin/sh/tests/execution/not2.0 diff --git a/tools/regression/bin/sh/execution/path1.0 b/bin/sh/tests/execution/path1.0 similarity index 100% rename from tools/regression/bin/sh/execution/path1.0 rename to bin/sh/tests/execution/path1.0 diff --git a/tools/regression/bin/sh/execution/redir1.0 b/bin/sh/tests/execution/redir1.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir1.0 rename to bin/sh/tests/execution/redir1.0 diff --git a/tools/regression/bin/sh/execution/redir2.0 b/bin/sh/tests/execution/redir2.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir2.0 rename to bin/sh/tests/execution/redir2.0 diff --git a/tools/regression/bin/sh/execution/redir3.0 b/bin/sh/tests/execution/redir3.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir3.0 rename to bin/sh/tests/execution/redir3.0 diff --git a/tools/regression/bin/sh/execution/redir4.0 b/bin/sh/tests/execution/redir4.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir4.0 rename to bin/sh/tests/execution/redir4.0 diff --git a/tools/regression/bin/sh/execution/redir5.0 b/bin/sh/tests/execution/redir5.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir5.0 rename to bin/sh/tests/execution/redir5.0 diff --git a/tools/regression/bin/sh/execution/redir6.0 b/bin/sh/tests/execution/redir6.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir6.0 rename to bin/sh/tests/execution/redir6.0 diff --git a/tools/regression/bin/sh/execution/redir7.0 b/bin/sh/tests/execution/redir7.0 similarity index 100% rename from tools/regression/bin/sh/execution/redir7.0 rename to bin/sh/tests/execution/redir7.0 diff --git a/tools/regression/bin/sh/execution/set-n1.0 b/bin/sh/tests/execution/set-n1.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-n1.0 rename to bin/sh/tests/execution/set-n1.0 diff --git a/tools/regression/bin/sh/execution/set-n2.0 b/bin/sh/tests/execution/set-n2.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-n2.0 rename to bin/sh/tests/execution/set-n2.0 diff --git a/tools/regression/bin/sh/execution/set-n3.0 b/bin/sh/tests/execution/set-n3.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-n3.0 rename to bin/sh/tests/execution/set-n3.0 diff --git a/tools/regression/bin/sh/execution/set-n4.0 b/bin/sh/tests/execution/set-n4.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-n4.0 rename to bin/sh/tests/execution/set-n4.0 diff --git a/tools/regression/bin/sh/execution/set-x1.0 b/bin/sh/tests/execution/set-x1.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-x1.0 rename to bin/sh/tests/execution/set-x1.0 diff --git a/tools/regression/bin/sh/execution/set-x2.0 b/bin/sh/tests/execution/set-x2.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-x2.0 rename to bin/sh/tests/execution/set-x2.0 diff --git a/tools/regression/bin/sh/execution/set-x3.0 b/bin/sh/tests/execution/set-x3.0 similarity index 100% rename from tools/regression/bin/sh/execution/set-x3.0 rename to bin/sh/tests/execution/set-x3.0 diff --git a/tools/regression/bin/sh/execution/shellproc1.0 b/bin/sh/tests/execution/shellproc1.0 similarity index 100% rename from tools/regression/bin/sh/execution/shellproc1.0 rename to bin/sh/tests/execution/shellproc1.0 diff --git a/tools/regression/bin/sh/execution/subshell1.0 b/bin/sh/tests/execution/subshell1.0 similarity index 100% rename from tools/regression/bin/sh/execution/subshell1.0 rename to bin/sh/tests/execution/subshell1.0 diff --git a/tools/regression/bin/sh/execution/subshell1.0.stdout b/bin/sh/tests/execution/subshell1.0.stdout similarity index 100% rename from tools/regression/bin/sh/execution/subshell1.0.stdout rename to bin/sh/tests/execution/subshell1.0.stdout diff --git a/tools/regression/bin/sh/execution/subshell2.0 b/bin/sh/tests/execution/subshell2.0 similarity index 100% rename from tools/regression/bin/sh/execution/subshell2.0 rename to bin/sh/tests/execution/subshell2.0 diff --git a/tools/regression/bin/sh/execution/subshell3.0 b/bin/sh/tests/execution/subshell3.0 similarity index 100% rename from tools/regression/bin/sh/execution/subshell3.0 rename to bin/sh/tests/execution/subshell3.0 diff --git a/tools/regression/bin/sh/execution/subshell4.0 b/bin/sh/tests/execution/subshell4.0 similarity index 100% rename from tools/regression/bin/sh/execution/subshell4.0 rename to bin/sh/tests/execution/subshell4.0 diff --git a/tools/regression/bin/sh/execution/unknown1.0 b/bin/sh/tests/execution/unknown1.0 similarity index 100% rename from tools/regression/bin/sh/execution/unknown1.0 rename to bin/sh/tests/execution/unknown1.0 diff --git a/tools/regression/bin/sh/execution/var-assign1.0 b/bin/sh/tests/execution/var-assign1.0 similarity index 100% rename from tools/regression/bin/sh/execution/var-assign1.0 rename to bin/sh/tests/execution/var-assign1.0 diff --git a/bin/sh/tests/expansion/Makefile b/bin/sh/tests/expansion/Makefile new file mode 100644 index 000000000000..bd2431971f4a --- /dev/null +++ b/bin/sh/tests/expansion/Makefile @@ -0,0 +1,86 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/expansion +KYUAFILE= no + +FILES= arith1.0 +FILES+= arith2.0 +FILES+= arith3.0 +FILES+= arith4.0 +FILES+= arith5.0 +FILES+= arith6.0 +FILES+= arith7.0 +FILES+= arith8.0 +FILES+= arith9.0 +FILES+= arith10.0 +FILES+= arith11.0 +FILES+= arith12.0 +FILES+= arith13.0 +FILES+= assign1.0 +FILES+= cmdsubst1.0 +FILES+= cmdsubst2.0 +FILES+= cmdsubst3.0 +FILES+= cmdsubst4.0 +FILES+= cmdsubst5.0 +FILES+= cmdsubst6.0 +FILES+= cmdsubst7.0 +FILES+= cmdsubst8.0 +FILES+= cmdsubst9.0 +FILES+= cmdsubst10.0 +FILES+= cmdsubst11.0 +FILES+= cmdsubst12.0 +FILES+= cmdsubst13.0 +FILES+= cmdsubst14.0 +FILES+= cmdsubst15.0 +FILES+= cmdsubst16.0 +FILES+= cmdsubst17.0 +FILES+= export1.0 +FILES+= export2.0 +FILES+= export3.0 +FILES+= heredoc1.0 +FILES+= heredoc2.0 +FILES+= ifs1.0 +FILES+= ifs2.0 +FILES+= ifs3.0 +FILES+= ifs4.0 +FILES+= length1.0 +FILES+= length2.0 +FILES+= length3.0 +FILES+= length4.0 +FILES+= length5.0 +FILES+= length6.0 +FILES+= length7.0 +FILES+= length8.0 +FILES+= local1.0 +FILES+= local2.0 +FILES+= pathname1.0 +FILES+= pathname2.0 +FILES+= pathname3.0 +FILES+= pathname4.0 +FILES+= plus-minus1.0 +FILES+= plus-minus2.0 +FILES+= plus-minus3.0 +FILES+= plus-minus4.0 +FILES+= plus-minus5.0 +FILES+= plus-minus6.0 +FILES+= plus-minus7.0 +FILES+= plus-minus8.0 +FILES+= question1.0 +FILES+= readonly1.0 +FILES+= set-u1.0 +FILES+= set-u2.0 +FILES+= set-u3.0 +FILES+= tilde1.0 +FILES+= tilde2.0 +FILES+= trim1.0 +FILES+= trim2.0 +FILES+= trim3.0 +FILES+= trim4.0 +FILES+= trim5.0 +FILES+= trim6.0 +FILES+= trim7.0 +FILES+= trim8.0 + +.include diff --git a/tools/regression/bin/sh/expansion/arith1.0 b/bin/sh/tests/expansion/arith1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith1.0 rename to bin/sh/tests/expansion/arith1.0 diff --git a/tools/regression/bin/sh/expansion/arith10.0 b/bin/sh/tests/expansion/arith10.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith10.0 rename to bin/sh/tests/expansion/arith10.0 diff --git a/tools/regression/bin/sh/expansion/arith11.0 b/bin/sh/tests/expansion/arith11.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith11.0 rename to bin/sh/tests/expansion/arith11.0 diff --git a/tools/regression/bin/sh/expansion/arith12.0 b/bin/sh/tests/expansion/arith12.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith12.0 rename to bin/sh/tests/expansion/arith12.0 diff --git a/tools/regression/bin/sh/expansion/arith13.0 b/bin/sh/tests/expansion/arith13.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith13.0 rename to bin/sh/tests/expansion/arith13.0 diff --git a/tools/regression/bin/sh/expansion/arith2.0 b/bin/sh/tests/expansion/arith2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith2.0 rename to bin/sh/tests/expansion/arith2.0 diff --git a/tools/regression/bin/sh/expansion/arith3.0 b/bin/sh/tests/expansion/arith3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith3.0 rename to bin/sh/tests/expansion/arith3.0 diff --git a/tools/regression/bin/sh/expansion/arith4.0 b/bin/sh/tests/expansion/arith4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith4.0 rename to bin/sh/tests/expansion/arith4.0 diff --git a/tools/regression/bin/sh/expansion/arith5.0 b/bin/sh/tests/expansion/arith5.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith5.0 rename to bin/sh/tests/expansion/arith5.0 diff --git a/tools/regression/bin/sh/expansion/arith6.0 b/bin/sh/tests/expansion/arith6.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith6.0 rename to bin/sh/tests/expansion/arith6.0 diff --git a/tools/regression/bin/sh/expansion/arith7.0 b/bin/sh/tests/expansion/arith7.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith7.0 rename to bin/sh/tests/expansion/arith7.0 diff --git a/tools/regression/bin/sh/expansion/arith8.0 b/bin/sh/tests/expansion/arith8.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith8.0 rename to bin/sh/tests/expansion/arith8.0 diff --git a/tools/regression/bin/sh/expansion/arith9.0 b/bin/sh/tests/expansion/arith9.0 similarity index 100% rename from tools/regression/bin/sh/expansion/arith9.0 rename to bin/sh/tests/expansion/arith9.0 diff --git a/tools/regression/bin/sh/expansion/assign1.0 b/bin/sh/tests/expansion/assign1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/assign1.0 rename to bin/sh/tests/expansion/assign1.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst1.0 b/bin/sh/tests/expansion/cmdsubst1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst1.0 rename to bin/sh/tests/expansion/cmdsubst1.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst10.0 b/bin/sh/tests/expansion/cmdsubst10.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst10.0 rename to bin/sh/tests/expansion/cmdsubst10.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst11.0 b/bin/sh/tests/expansion/cmdsubst11.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst11.0 rename to bin/sh/tests/expansion/cmdsubst11.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst12.0 b/bin/sh/tests/expansion/cmdsubst12.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst12.0 rename to bin/sh/tests/expansion/cmdsubst12.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst13.0 b/bin/sh/tests/expansion/cmdsubst13.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst13.0 rename to bin/sh/tests/expansion/cmdsubst13.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst14.0 b/bin/sh/tests/expansion/cmdsubst14.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst14.0 rename to bin/sh/tests/expansion/cmdsubst14.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst15.0 b/bin/sh/tests/expansion/cmdsubst15.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst15.0 rename to bin/sh/tests/expansion/cmdsubst15.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst16.0 b/bin/sh/tests/expansion/cmdsubst16.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst16.0 rename to bin/sh/tests/expansion/cmdsubst16.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst17.0 b/bin/sh/tests/expansion/cmdsubst17.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst17.0 rename to bin/sh/tests/expansion/cmdsubst17.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst2.0 b/bin/sh/tests/expansion/cmdsubst2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst2.0 rename to bin/sh/tests/expansion/cmdsubst2.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst3.0 b/bin/sh/tests/expansion/cmdsubst3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst3.0 rename to bin/sh/tests/expansion/cmdsubst3.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst4.0 b/bin/sh/tests/expansion/cmdsubst4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst4.0 rename to bin/sh/tests/expansion/cmdsubst4.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst5.0 b/bin/sh/tests/expansion/cmdsubst5.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst5.0 rename to bin/sh/tests/expansion/cmdsubst5.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst6.0 b/bin/sh/tests/expansion/cmdsubst6.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst6.0 rename to bin/sh/tests/expansion/cmdsubst6.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst7.0 b/bin/sh/tests/expansion/cmdsubst7.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst7.0 rename to bin/sh/tests/expansion/cmdsubst7.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst8.0 b/bin/sh/tests/expansion/cmdsubst8.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst8.0 rename to bin/sh/tests/expansion/cmdsubst8.0 diff --git a/tools/regression/bin/sh/expansion/cmdsubst9.0 b/bin/sh/tests/expansion/cmdsubst9.0 similarity index 100% rename from tools/regression/bin/sh/expansion/cmdsubst9.0 rename to bin/sh/tests/expansion/cmdsubst9.0 diff --git a/tools/regression/bin/sh/expansion/export1.0 b/bin/sh/tests/expansion/export1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/export1.0 rename to bin/sh/tests/expansion/export1.0 diff --git a/tools/regression/bin/sh/expansion/export2.0 b/bin/sh/tests/expansion/export2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/export2.0 rename to bin/sh/tests/expansion/export2.0 diff --git a/tools/regression/bin/sh/expansion/export3.0 b/bin/sh/tests/expansion/export3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/export3.0 rename to bin/sh/tests/expansion/export3.0 diff --git a/tools/regression/bin/sh/expansion/heredoc1.0 b/bin/sh/tests/expansion/heredoc1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/heredoc1.0 rename to bin/sh/tests/expansion/heredoc1.0 diff --git a/tools/regression/bin/sh/expansion/heredoc2.0 b/bin/sh/tests/expansion/heredoc2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/heredoc2.0 rename to bin/sh/tests/expansion/heredoc2.0 diff --git a/tools/regression/bin/sh/expansion/ifs1.0 b/bin/sh/tests/expansion/ifs1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/ifs1.0 rename to bin/sh/tests/expansion/ifs1.0 diff --git a/tools/regression/bin/sh/expansion/ifs2.0 b/bin/sh/tests/expansion/ifs2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/ifs2.0 rename to bin/sh/tests/expansion/ifs2.0 diff --git a/tools/regression/bin/sh/expansion/ifs3.0 b/bin/sh/tests/expansion/ifs3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/ifs3.0 rename to bin/sh/tests/expansion/ifs3.0 diff --git a/tools/regression/bin/sh/expansion/ifs4.0 b/bin/sh/tests/expansion/ifs4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/ifs4.0 rename to bin/sh/tests/expansion/ifs4.0 diff --git a/tools/regression/bin/sh/expansion/length1.0 b/bin/sh/tests/expansion/length1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length1.0 rename to bin/sh/tests/expansion/length1.0 diff --git a/tools/regression/bin/sh/expansion/length2.0 b/bin/sh/tests/expansion/length2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length2.0 rename to bin/sh/tests/expansion/length2.0 diff --git a/tools/regression/bin/sh/expansion/length3.0 b/bin/sh/tests/expansion/length3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length3.0 rename to bin/sh/tests/expansion/length3.0 diff --git a/tools/regression/bin/sh/expansion/length4.0 b/bin/sh/tests/expansion/length4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length4.0 rename to bin/sh/tests/expansion/length4.0 diff --git a/tools/regression/bin/sh/expansion/length5.0 b/bin/sh/tests/expansion/length5.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length5.0 rename to bin/sh/tests/expansion/length5.0 diff --git a/tools/regression/bin/sh/expansion/length6.0 b/bin/sh/tests/expansion/length6.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length6.0 rename to bin/sh/tests/expansion/length6.0 diff --git a/tools/regression/bin/sh/expansion/length7.0 b/bin/sh/tests/expansion/length7.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length7.0 rename to bin/sh/tests/expansion/length7.0 diff --git a/tools/regression/bin/sh/expansion/length8.0 b/bin/sh/tests/expansion/length8.0 similarity index 100% rename from tools/regression/bin/sh/expansion/length8.0 rename to bin/sh/tests/expansion/length8.0 diff --git a/tools/regression/bin/sh/expansion/local1.0 b/bin/sh/tests/expansion/local1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/local1.0 rename to bin/sh/tests/expansion/local1.0 diff --git a/tools/regression/bin/sh/expansion/local2.0 b/bin/sh/tests/expansion/local2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/local2.0 rename to bin/sh/tests/expansion/local2.0 diff --git a/tools/regression/bin/sh/expansion/pathname1.0 b/bin/sh/tests/expansion/pathname1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/pathname1.0 rename to bin/sh/tests/expansion/pathname1.0 diff --git a/tools/regression/bin/sh/expansion/pathname2.0 b/bin/sh/tests/expansion/pathname2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/pathname2.0 rename to bin/sh/tests/expansion/pathname2.0 diff --git a/tools/regression/bin/sh/expansion/pathname3.0 b/bin/sh/tests/expansion/pathname3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/pathname3.0 rename to bin/sh/tests/expansion/pathname3.0 diff --git a/tools/regression/bin/sh/expansion/pathname4.0 b/bin/sh/tests/expansion/pathname4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/pathname4.0 rename to bin/sh/tests/expansion/pathname4.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus1.0 b/bin/sh/tests/expansion/plus-minus1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus1.0 rename to bin/sh/tests/expansion/plus-minus1.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus2.0 b/bin/sh/tests/expansion/plus-minus2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus2.0 rename to bin/sh/tests/expansion/plus-minus2.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus3.0 b/bin/sh/tests/expansion/plus-minus3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus3.0 rename to bin/sh/tests/expansion/plus-minus3.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus4.0 b/bin/sh/tests/expansion/plus-minus4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus4.0 rename to bin/sh/tests/expansion/plus-minus4.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus5.0 b/bin/sh/tests/expansion/plus-minus5.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus5.0 rename to bin/sh/tests/expansion/plus-minus5.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus6.0 b/bin/sh/tests/expansion/plus-minus6.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus6.0 rename to bin/sh/tests/expansion/plus-minus6.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus7.0 b/bin/sh/tests/expansion/plus-minus7.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus7.0 rename to bin/sh/tests/expansion/plus-minus7.0 diff --git a/tools/regression/bin/sh/expansion/plus-minus8.0 b/bin/sh/tests/expansion/plus-minus8.0 similarity index 100% rename from tools/regression/bin/sh/expansion/plus-minus8.0 rename to bin/sh/tests/expansion/plus-minus8.0 diff --git a/tools/regression/bin/sh/expansion/question1.0 b/bin/sh/tests/expansion/question1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/question1.0 rename to bin/sh/tests/expansion/question1.0 diff --git a/tools/regression/bin/sh/expansion/readonly1.0 b/bin/sh/tests/expansion/readonly1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/readonly1.0 rename to bin/sh/tests/expansion/readonly1.0 diff --git a/tools/regression/bin/sh/expansion/set-u1.0 b/bin/sh/tests/expansion/set-u1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/set-u1.0 rename to bin/sh/tests/expansion/set-u1.0 diff --git a/tools/regression/bin/sh/expansion/set-u2.0 b/bin/sh/tests/expansion/set-u2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/set-u2.0 rename to bin/sh/tests/expansion/set-u2.0 diff --git a/tools/regression/bin/sh/expansion/set-u3.0 b/bin/sh/tests/expansion/set-u3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/set-u3.0 rename to bin/sh/tests/expansion/set-u3.0 diff --git a/tools/regression/bin/sh/expansion/tilde1.0 b/bin/sh/tests/expansion/tilde1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/tilde1.0 rename to bin/sh/tests/expansion/tilde1.0 diff --git a/tools/regression/bin/sh/expansion/tilde2.0 b/bin/sh/tests/expansion/tilde2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/tilde2.0 rename to bin/sh/tests/expansion/tilde2.0 diff --git a/tools/regression/bin/sh/expansion/trim1.0 b/bin/sh/tests/expansion/trim1.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim1.0 rename to bin/sh/tests/expansion/trim1.0 diff --git a/tools/regression/bin/sh/expansion/trim2.0 b/bin/sh/tests/expansion/trim2.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim2.0 rename to bin/sh/tests/expansion/trim2.0 diff --git a/tools/regression/bin/sh/expansion/trim3.0 b/bin/sh/tests/expansion/trim3.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim3.0 rename to bin/sh/tests/expansion/trim3.0 diff --git a/tools/regression/bin/sh/expansion/trim4.0 b/bin/sh/tests/expansion/trim4.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim4.0 rename to bin/sh/tests/expansion/trim4.0 diff --git a/tools/regression/bin/sh/expansion/trim5.0 b/bin/sh/tests/expansion/trim5.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim5.0 rename to bin/sh/tests/expansion/trim5.0 diff --git a/tools/regression/bin/sh/expansion/trim6.0 b/bin/sh/tests/expansion/trim6.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim6.0 rename to bin/sh/tests/expansion/trim6.0 diff --git a/tools/regression/bin/sh/expansion/trim7.0 b/bin/sh/tests/expansion/trim7.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim7.0 rename to bin/sh/tests/expansion/trim7.0 diff --git a/tools/regression/bin/sh/expansion/trim8.0 b/bin/sh/tests/expansion/trim8.0 similarity index 100% rename from tools/regression/bin/sh/expansion/trim8.0 rename to bin/sh/tests/expansion/trim8.0 diff --git a/tools/regression/bin/sh/regress.sh b/bin/sh/tests/legacy_test.sh similarity index 64% rename from tools/regression/bin/sh/regress.sh rename to bin/sh/tests/legacy_test.sh index 60e580589a54..d43f5ddd8aab 100644 --- a/tools/regression/bin/sh/regress.sh +++ b/bin/sh/tests/legacy_test.sh @@ -1,10 +1,13 @@ # $FreeBSD$ -if [ -z "${SH}" ]; then - echo '${SH} is not set, please correct and re-run.' - exit 1 -fi -export SH=${SH} +: ${SH:="__SH__"} +export SH + +# TODO(jmmv): The Kyua TAP interface should be passing us the value of +# "srcdir" as an environment variable, just as it does with the ATF +# interface in the form of a configuration variable. For now, just try +# to guess this. +: ${TESTS_DATA:=$(dirname ${0})} COUNTER=1 @@ -17,6 +20,7 @@ do_test() { rm tmp.stdout tmp.stderr return fi + sed -I '' -e "s|^${TESTS_DATA}|.|" tmp.stderr for i in stdout stderr; do if [ -f ${1}.${i} ]; then if ! cmp -s tmp.${i} ${1}.${i}; then @@ -34,7 +38,7 @@ do_test() { rm tmp.stdout tmp.stderr } -TESTS=$(find -Es . -regex ".*\.[0-9]+") +TESTS=$(find -Es ${TESTS_DATA} -regex ".*\.[0-9]+") printf "1..%d\n" $(echo ${TESTS} | wc -w) for i in ${TESTS} ; do diff --git a/bin/sh/tests/parameters/Makefile b/bin/sh/tests/parameters/Makefile new file mode 100644 index 000000000000..cb76474fa292 --- /dev/null +++ b/bin/sh/tests/parameters/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/parameters +KYUAFILE= no + +FILES= env1.0 +FILES+= exitstatus1.0 +FILES+= mail1.0 +FILES+= mail2.0 +FILES+= optind1.0 +FILES+= positional1.0 +FILES+= positional2.0 +FILES+= pwd1.0 +FILES+= pwd2.0 + +.include diff --git a/tools/regression/bin/sh/parameters/env1.0 b/bin/sh/tests/parameters/env1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/env1.0 rename to bin/sh/tests/parameters/env1.0 diff --git a/tools/regression/bin/sh/parameters/exitstatus1.0 b/bin/sh/tests/parameters/exitstatus1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/exitstatus1.0 rename to bin/sh/tests/parameters/exitstatus1.0 diff --git a/tools/regression/bin/sh/parameters/mail1.0 b/bin/sh/tests/parameters/mail1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/mail1.0 rename to bin/sh/tests/parameters/mail1.0 diff --git a/tools/regression/bin/sh/parameters/mail2.0 b/bin/sh/tests/parameters/mail2.0 similarity index 100% rename from tools/regression/bin/sh/parameters/mail2.0 rename to bin/sh/tests/parameters/mail2.0 diff --git a/tools/regression/bin/sh/parameters/optind1.0 b/bin/sh/tests/parameters/optind1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/optind1.0 rename to bin/sh/tests/parameters/optind1.0 diff --git a/tools/regression/bin/sh/parameters/positional1.0 b/bin/sh/tests/parameters/positional1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/positional1.0 rename to bin/sh/tests/parameters/positional1.0 diff --git a/tools/regression/bin/sh/parameters/positional2.0 b/bin/sh/tests/parameters/positional2.0 similarity index 100% rename from tools/regression/bin/sh/parameters/positional2.0 rename to bin/sh/tests/parameters/positional2.0 diff --git a/tools/regression/bin/sh/parameters/pwd1.0 b/bin/sh/tests/parameters/pwd1.0 similarity index 100% rename from tools/regression/bin/sh/parameters/pwd1.0 rename to bin/sh/tests/parameters/pwd1.0 diff --git a/tools/regression/bin/sh/parameters/pwd2.0 b/bin/sh/tests/parameters/pwd2.0 similarity index 100% rename from tools/regression/bin/sh/parameters/pwd2.0 rename to bin/sh/tests/parameters/pwd2.0 diff --git a/bin/sh/tests/parser/Makefile b/bin/sh/tests/parser/Makefile new file mode 100644 index 000000000000..71bd370b0206 --- /dev/null +++ b/bin/sh/tests/parser/Makefile @@ -0,0 +1,59 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/parser +KYUAFILE= no + +FILES= alias1.0 +FILES+= alias2.0 +FILES+= alias3.0 +FILES+= alias4.0 +FILES+= alias5.0 +FILES+= alias6.0 +FILES+= alias7.0 +FILES+= alias8.0 +FILES+= alias9.0 +FILES+= alias10.0 +FILES+= and-pipe-not.0 +FILES+= case1.0 +FILES+= case2.0 +FILES+= dollar-quote1.0 +FILES+= dollar-quote2.0 +FILES+= dollar-quote3.0 +FILES+= dollar-quote4.0 +FILES+= dollar-quote5.0 +FILES+= dollar-quote6.0 +FILES+= dollar-quote7.0 +FILES+= dollar-quote8.0 +FILES+= dollar-quote9.0 +FILES+= dollar-quote10.0 +FILES+= dollar-quote11.0 +FILES+= empty-braces1.0 +FILES+= empty-cmd1.0 +FILES+= for1.0 +FILES+= for2.0 +FILES+= func1.0 +FILES+= func2.0 +FILES+= func3.0 +FILES+= heredoc1.0 +FILES+= heredoc2.0 +FILES+= heredoc3.0 +FILES+= heredoc4.0 +FILES+= heredoc5.0 +FILES+= heredoc6.0 +FILES+= heredoc7.0 +FILES+= heredoc8.0 +FILES+= heredoc9.0 +FILES+= heredoc10.0 +FILES+= heredoc11.0 +FILES+= no-space1.0 +FILES+= no-space2.0 +FILES+= only-redir1.0 +FILES+= only-redir2.0 +FILES+= only-redir3.0 +FILES+= only-redir4.0 +FILES+= pipe-not1.0 +FILES+= var-assign1.0 + +.include diff --git a/tools/regression/bin/sh/parser/alias1.0 b/bin/sh/tests/parser/alias1.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias1.0 rename to bin/sh/tests/parser/alias1.0 diff --git a/tools/regression/bin/sh/parser/alias10.0 b/bin/sh/tests/parser/alias10.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias10.0 rename to bin/sh/tests/parser/alias10.0 diff --git a/tools/regression/bin/sh/parser/alias2.0 b/bin/sh/tests/parser/alias2.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias2.0 rename to bin/sh/tests/parser/alias2.0 diff --git a/tools/regression/bin/sh/parser/alias3.0 b/bin/sh/tests/parser/alias3.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias3.0 rename to bin/sh/tests/parser/alias3.0 diff --git a/tools/regression/bin/sh/parser/alias4.0 b/bin/sh/tests/parser/alias4.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias4.0 rename to bin/sh/tests/parser/alias4.0 diff --git a/tools/regression/bin/sh/parser/alias5.0 b/bin/sh/tests/parser/alias5.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias5.0 rename to bin/sh/tests/parser/alias5.0 diff --git a/tools/regression/bin/sh/parser/alias6.0 b/bin/sh/tests/parser/alias6.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias6.0 rename to bin/sh/tests/parser/alias6.0 diff --git a/tools/regression/bin/sh/parser/alias7.0 b/bin/sh/tests/parser/alias7.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias7.0 rename to bin/sh/tests/parser/alias7.0 diff --git a/tools/regression/bin/sh/parser/alias8.0 b/bin/sh/tests/parser/alias8.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias8.0 rename to bin/sh/tests/parser/alias8.0 diff --git a/tools/regression/bin/sh/parser/alias9.0 b/bin/sh/tests/parser/alias9.0 similarity index 100% rename from tools/regression/bin/sh/parser/alias9.0 rename to bin/sh/tests/parser/alias9.0 diff --git a/tools/regression/bin/sh/parser/and-pipe-not.0 b/bin/sh/tests/parser/and-pipe-not.0 similarity index 100% rename from tools/regression/bin/sh/parser/and-pipe-not.0 rename to bin/sh/tests/parser/and-pipe-not.0 diff --git a/tools/regression/bin/sh/parser/case1.0 b/bin/sh/tests/parser/case1.0 similarity index 100% rename from tools/regression/bin/sh/parser/case1.0 rename to bin/sh/tests/parser/case1.0 diff --git a/tools/regression/bin/sh/parser/case2.0 b/bin/sh/tests/parser/case2.0 similarity index 100% rename from tools/regression/bin/sh/parser/case2.0 rename to bin/sh/tests/parser/case2.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote1.0 b/bin/sh/tests/parser/dollar-quote1.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote1.0 rename to bin/sh/tests/parser/dollar-quote1.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote10.0 b/bin/sh/tests/parser/dollar-quote10.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote10.0 rename to bin/sh/tests/parser/dollar-quote10.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote11.0 b/bin/sh/tests/parser/dollar-quote11.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote11.0 rename to bin/sh/tests/parser/dollar-quote11.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote2.0 b/bin/sh/tests/parser/dollar-quote2.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote2.0 rename to bin/sh/tests/parser/dollar-quote2.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote3.0 b/bin/sh/tests/parser/dollar-quote3.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote3.0 rename to bin/sh/tests/parser/dollar-quote3.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote4.0 b/bin/sh/tests/parser/dollar-quote4.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote4.0 rename to bin/sh/tests/parser/dollar-quote4.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote5.0 b/bin/sh/tests/parser/dollar-quote5.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote5.0 rename to bin/sh/tests/parser/dollar-quote5.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote6.0 b/bin/sh/tests/parser/dollar-quote6.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote6.0 rename to bin/sh/tests/parser/dollar-quote6.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote7.0 b/bin/sh/tests/parser/dollar-quote7.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote7.0 rename to bin/sh/tests/parser/dollar-quote7.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote8.0 b/bin/sh/tests/parser/dollar-quote8.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote8.0 rename to bin/sh/tests/parser/dollar-quote8.0 diff --git a/tools/regression/bin/sh/parser/dollar-quote9.0 b/bin/sh/tests/parser/dollar-quote9.0 similarity index 100% rename from tools/regression/bin/sh/parser/dollar-quote9.0 rename to bin/sh/tests/parser/dollar-quote9.0 diff --git a/tools/regression/bin/sh/parser/empty-braces1.0 b/bin/sh/tests/parser/empty-braces1.0 similarity index 100% rename from tools/regression/bin/sh/parser/empty-braces1.0 rename to bin/sh/tests/parser/empty-braces1.0 diff --git a/tools/regression/bin/sh/parser/empty-cmd1.0 b/bin/sh/tests/parser/empty-cmd1.0 similarity index 100% rename from tools/regression/bin/sh/parser/empty-cmd1.0 rename to bin/sh/tests/parser/empty-cmd1.0 diff --git a/tools/regression/bin/sh/parser/for1.0 b/bin/sh/tests/parser/for1.0 similarity index 100% rename from tools/regression/bin/sh/parser/for1.0 rename to bin/sh/tests/parser/for1.0 diff --git a/tools/regression/bin/sh/parser/for2.0 b/bin/sh/tests/parser/for2.0 similarity index 100% rename from tools/regression/bin/sh/parser/for2.0 rename to bin/sh/tests/parser/for2.0 diff --git a/tools/regression/bin/sh/parser/func1.0 b/bin/sh/tests/parser/func1.0 similarity index 100% rename from tools/regression/bin/sh/parser/func1.0 rename to bin/sh/tests/parser/func1.0 diff --git a/tools/regression/bin/sh/parser/func2.0 b/bin/sh/tests/parser/func2.0 similarity index 100% rename from tools/regression/bin/sh/parser/func2.0 rename to bin/sh/tests/parser/func2.0 diff --git a/tools/regression/bin/sh/parser/func3.0 b/bin/sh/tests/parser/func3.0 similarity index 100% rename from tools/regression/bin/sh/parser/func3.0 rename to bin/sh/tests/parser/func3.0 diff --git a/tools/regression/bin/sh/parser/heredoc1.0 b/bin/sh/tests/parser/heredoc1.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc1.0 rename to bin/sh/tests/parser/heredoc1.0 diff --git a/tools/regression/bin/sh/parser/heredoc10.0 b/bin/sh/tests/parser/heredoc10.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc10.0 rename to bin/sh/tests/parser/heredoc10.0 diff --git a/tools/regression/bin/sh/parser/heredoc11.0 b/bin/sh/tests/parser/heredoc11.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc11.0 rename to bin/sh/tests/parser/heredoc11.0 diff --git a/tools/regression/bin/sh/parser/heredoc2.0 b/bin/sh/tests/parser/heredoc2.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc2.0 rename to bin/sh/tests/parser/heredoc2.0 diff --git a/tools/regression/bin/sh/parser/heredoc3.0 b/bin/sh/tests/parser/heredoc3.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc3.0 rename to bin/sh/tests/parser/heredoc3.0 diff --git a/tools/regression/bin/sh/parser/heredoc4.0 b/bin/sh/tests/parser/heredoc4.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc4.0 rename to bin/sh/tests/parser/heredoc4.0 diff --git a/tools/regression/bin/sh/parser/heredoc5.0 b/bin/sh/tests/parser/heredoc5.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc5.0 rename to bin/sh/tests/parser/heredoc5.0 diff --git a/tools/regression/bin/sh/parser/heredoc6.0 b/bin/sh/tests/parser/heredoc6.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc6.0 rename to bin/sh/tests/parser/heredoc6.0 diff --git a/tools/regression/bin/sh/parser/heredoc7.0 b/bin/sh/tests/parser/heredoc7.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc7.0 rename to bin/sh/tests/parser/heredoc7.0 diff --git a/tools/regression/bin/sh/parser/heredoc8.0 b/bin/sh/tests/parser/heredoc8.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc8.0 rename to bin/sh/tests/parser/heredoc8.0 diff --git a/tools/regression/bin/sh/parser/heredoc9.0 b/bin/sh/tests/parser/heredoc9.0 similarity index 100% rename from tools/regression/bin/sh/parser/heredoc9.0 rename to bin/sh/tests/parser/heredoc9.0 diff --git a/tools/regression/bin/sh/parser/no-space1.0 b/bin/sh/tests/parser/no-space1.0 similarity index 100% rename from tools/regression/bin/sh/parser/no-space1.0 rename to bin/sh/tests/parser/no-space1.0 diff --git a/tools/regression/bin/sh/parser/no-space2.0 b/bin/sh/tests/parser/no-space2.0 similarity index 100% rename from tools/regression/bin/sh/parser/no-space2.0 rename to bin/sh/tests/parser/no-space2.0 diff --git a/tools/regression/bin/sh/parser/only-redir1.0 b/bin/sh/tests/parser/only-redir1.0 similarity index 100% rename from tools/regression/bin/sh/parser/only-redir1.0 rename to bin/sh/tests/parser/only-redir1.0 diff --git a/tools/regression/bin/sh/parser/only-redir2.0 b/bin/sh/tests/parser/only-redir2.0 similarity index 100% rename from tools/regression/bin/sh/parser/only-redir2.0 rename to bin/sh/tests/parser/only-redir2.0 diff --git a/tools/regression/bin/sh/parser/only-redir3.0 b/bin/sh/tests/parser/only-redir3.0 similarity index 100% rename from tools/regression/bin/sh/parser/only-redir3.0 rename to bin/sh/tests/parser/only-redir3.0 diff --git a/tools/regression/bin/sh/parser/only-redir4.0 b/bin/sh/tests/parser/only-redir4.0 similarity index 100% rename from tools/regression/bin/sh/parser/only-redir4.0 rename to bin/sh/tests/parser/only-redir4.0 diff --git a/tools/regression/bin/sh/parser/pipe-not1.0 b/bin/sh/tests/parser/pipe-not1.0 similarity index 100% rename from tools/regression/bin/sh/parser/pipe-not1.0 rename to bin/sh/tests/parser/pipe-not1.0 diff --git a/tools/regression/bin/sh/parser/var-assign1.0 b/bin/sh/tests/parser/var-assign1.0 similarity index 100% rename from tools/regression/bin/sh/parser/var-assign1.0 rename to bin/sh/tests/parser/var-assign1.0 diff --git a/bin/sh/tests/set-e/Makefile b/bin/sh/tests/set-e/Makefile new file mode 100644 index 000000000000..55d79174f98a --- /dev/null +++ b/bin/sh/tests/set-e/Makefile @@ -0,0 +1,44 @@ +# $FreeBSD$ + +.include + +FILESDIR= ${TESTSBASE}/bin/sh/set-e +KYUAFILE= no + +FILES= and1.0 +FILES+= and2.1 +FILES+= and3.0 +FILES+= and4.0 +FILES+= background1.0 +FILES+= cmd1.0 +FILES+= cmd2.1 +FILES+= elif1.0 +FILES+= elif2.0 +FILES+= eval1.0 +FILES+= eval2.1 +FILES+= for1.0 +FILES+= func1.0 +FILES+= func2.1 +FILES+= if1.0 +FILES+= if2.0 +FILES+= if3.0 +FILES+= not1.0 +FILES+= not2.0 +FILES+= or1.0 +FILES+= or2.0 +FILES+= or3.1 +FILES+= pipe1.1 +FILES+= pipe2.0 +FILES+= return1.0 +FILES+= semi1.1 +FILES+= semi2.1 +FILES+= subshell1.0 +FILES+= subshell2.1 +FILES+= until1.0 +FILES+= until2.0 +FILES+= until3.0 +FILES+= while1.0 +FILES+= while2.0 +FILES+= while3.0 + +.include diff --git a/tools/regression/bin/sh/set-e/and1.0 b/bin/sh/tests/set-e/and1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/and1.0 rename to bin/sh/tests/set-e/and1.0 diff --git a/tools/regression/bin/sh/set-e/and2.1 b/bin/sh/tests/set-e/and2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/and2.1 rename to bin/sh/tests/set-e/and2.1 diff --git a/tools/regression/bin/sh/set-e/and3.0 b/bin/sh/tests/set-e/and3.0 similarity index 100% rename from tools/regression/bin/sh/set-e/and3.0 rename to bin/sh/tests/set-e/and3.0 diff --git a/tools/regression/bin/sh/set-e/and4.0 b/bin/sh/tests/set-e/and4.0 similarity index 100% rename from tools/regression/bin/sh/set-e/and4.0 rename to bin/sh/tests/set-e/and4.0 diff --git a/tools/regression/bin/sh/set-e/background1.0 b/bin/sh/tests/set-e/background1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/background1.0 rename to bin/sh/tests/set-e/background1.0 diff --git a/tools/regression/bin/sh/set-e/cmd1.0 b/bin/sh/tests/set-e/cmd1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/cmd1.0 rename to bin/sh/tests/set-e/cmd1.0 diff --git a/tools/regression/bin/sh/set-e/cmd2.1 b/bin/sh/tests/set-e/cmd2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/cmd2.1 rename to bin/sh/tests/set-e/cmd2.1 diff --git a/tools/regression/bin/sh/set-e/elif1.0 b/bin/sh/tests/set-e/elif1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/elif1.0 rename to bin/sh/tests/set-e/elif1.0 diff --git a/tools/regression/bin/sh/set-e/elif2.0 b/bin/sh/tests/set-e/elif2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/elif2.0 rename to bin/sh/tests/set-e/elif2.0 diff --git a/tools/regression/bin/sh/set-e/eval1.0 b/bin/sh/tests/set-e/eval1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/eval1.0 rename to bin/sh/tests/set-e/eval1.0 diff --git a/tools/regression/bin/sh/set-e/eval2.1 b/bin/sh/tests/set-e/eval2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/eval2.1 rename to bin/sh/tests/set-e/eval2.1 diff --git a/tools/regression/bin/sh/set-e/for1.0 b/bin/sh/tests/set-e/for1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/for1.0 rename to bin/sh/tests/set-e/for1.0 diff --git a/tools/regression/bin/sh/set-e/func1.0 b/bin/sh/tests/set-e/func1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/func1.0 rename to bin/sh/tests/set-e/func1.0 diff --git a/tools/regression/bin/sh/set-e/func2.1 b/bin/sh/tests/set-e/func2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/func2.1 rename to bin/sh/tests/set-e/func2.1 diff --git a/tools/regression/bin/sh/set-e/if1.0 b/bin/sh/tests/set-e/if1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/if1.0 rename to bin/sh/tests/set-e/if1.0 diff --git a/tools/regression/bin/sh/set-e/if2.0 b/bin/sh/tests/set-e/if2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/if2.0 rename to bin/sh/tests/set-e/if2.0 diff --git a/tools/regression/bin/sh/set-e/if3.0 b/bin/sh/tests/set-e/if3.0 similarity index 100% rename from tools/regression/bin/sh/set-e/if3.0 rename to bin/sh/tests/set-e/if3.0 diff --git a/tools/regression/bin/sh/set-e/not1.0 b/bin/sh/tests/set-e/not1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/not1.0 rename to bin/sh/tests/set-e/not1.0 diff --git a/tools/regression/bin/sh/set-e/not2.0 b/bin/sh/tests/set-e/not2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/not2.0 rename to bin/sh/tests/set-e/not2.0 diff --git a/tools/regression/bin/sh/set-e/or1.0 b/bin/sh/tests/set-e/or1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/or1.0 rename to bin/sh/tests/set-e/or1.0 diff --git a/tools/regression/bin/sh/set-e/or2.0 b/bin/sh/tests/set-e/or2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/or2.0 rename to bin/sh/tests/set-e/or2.0 diff --git a/tools/regression/bin/sh/set-e/or3.1 b/bin/sh/tests/set-e/or3.1 similarity index 100% rename from tools/regression/bin/sh/set-e/or3.1 rename to bin/sh/tests/set-e/or3.1 diff --git a/tools/regression/bin/sh/set-e/pipe1.1 b/bin/sh/tests/set-e/pipe1.1 similarity index 100% rename from tools/regression/bin/sh/set-e/pipe1.1 rename to bin/sh/tests/set-e/pipe1.1 diff --git a/tools/regression/bin/sh/set-e/pipe2.0 b/bin/sh/tests/set-e/pipe2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/pipe2.0 rename to bin/sh/tests/set-e/pipe2.0 diff --git a/tools/regression/bin/sh/set-e/return1.0 b/bin/sh/tests/set-e/return1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/return1.0 rename to bin/sh/tests/set-e/return1.0 diff --git a/tools/regression/bin/sh/set-e/semi1.1 b/bin/sh/tests/set-e/semi1.1 similarity index 100% rename from tools/regression/bin/sh/set-e/semi1.1 rename to bin/sh/tests/set-e/semi1.1 diff --git a/tools/regression/bin/sh/set-e/semi2.1 b/bin/sh/tests/set-e/semi2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/semi2.1 rename to bin/sh/tests/set-e/semi2.1 diff --git a/tools/regression/bin/sh/set-e/subshell1.0 b/bin/sh/tests/set-e/subshell1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/subshell1.0 rename to bin/sh/tests/set-e/subshell1.0 diff --git a/tools/regression/bin/sh/set-e/subshell2.1 b/bin/sh/tests/set-e/subshell2.1 similarity index 100% rename from tools/regression/bin/sh/set-e/subshell2.1 rename to bin/sh/tests/set-e/subshell2.1 diff --git a/tools/regression/bin/sh/set-e/until1.0 b/bin/sh/tests/set-e/until1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/until1.0 rename to bin/sh/tests/set-e/until1.0 diff --git a/tools/regression/bin/sh/set-e/until2.0 b/bin/sh/tests/set-e/until2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/until2.0 rename to bin/sh/tests/set-e/until2.0 diff --git a/tools/regression/bin/sh/set-e/until3.0 b/bin/sh/tests/set-e/until3.0 similarity index 100% rename from tools/regression/bin/sh/set-e/until3.0 rename to bin/sh/tests/set-e/until3.0 diff --git a/tools/regression/bin/sh/set-e/while1.0 b/bin/sh/tests/set-e/while1.0 similarity index 100% rename from tools/regression/bin/sh/set-e/while1.0 rename to bin/sh/tests/set-e/while1.0 diff --git a/tools/regression/bin/sh/set-e/while2.0 b/bin/sh/tests/set-e/while2.0 similarity index 100% rename from tools/regression/bin/sh/set-e/while2.0 rename to bin/sh/tests/set-e/while2.0 diff --git a/tools/regression/bin/sh/set-e/while3.0 b/bin/sh/tests/set-e/while3.0 similarity index 100% rename from tools/regression/bin/sh/set-e/while3.0 rename to bin/sh/tests/set-e/while3.0 diff --git a/bin/test/Makefile b/bin/test/Makefile index 7c64b40347ef..e9a0507f0cac 100644 --- a/bin/test/Makefile +++ b/bin/test/Makefile @@ -1,8 +1,14 @@ # @(#)Makefile 8.1 (Berkeley) 5/31/93 # $FreeBSD$ +.include + PROG= test LINKS= ${BINDIR}/test ${BINDIR}/[ MLINKS= test.1 [.1 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/bin/test/tests/Makefile b/bin/test/tests/Makefile new file mode 100644 index 000000000000..c5743de39c70 --- /dev/null +++ b/bin/test/tests/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin/test + +TAP_TESTS_SH= legacy_test + +.include diff --git a/tools/regression/bin/test/regress.sh b/bin/test/tests/legacy_test.sh similarity index 100% rename from tools/regression/bin/test/regress.sh rename to bin/test/tests/legacy_test.sh diff --git a/bin/tests/Makefile b/bin/tests/Makefile new file mode 100644 index 000000000000..7a59b1029513 --- /dev/null +++ b/bin/tests/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/bin + +.PATH: ${.CURDIR:H:H}/tests +KYUAFILE= yes + +.include diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 65f909023a97..b7ebbb9949a6 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -20,6 +20,32 @@ .. .. tests + bin + date + .. + mv + .. + pax + .. + sh + builtins + .. + errors + .. + execution + .. + expansion + .. + parameters + .. + parser + .. + set-e + .. + .. + test + .. + .. lib atf libatf-c diff --git a/tools/regression/bin/Makefile b/tools/regression/bin/Makefile deleted file mode 100644 index 1dcdbb396c6d..000000000000 --- a/tools/regression/bin/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# $FreeBSD$ - -SUBDIR= date mv pax sh test - -.include diff --git a/tools/regression/bin/date/Makefile b/tools/regression/bin/date/Makefile deleted file mode 100644 index 2c9ca5943505..000000000000 --- a/tools/regression/bin/date/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# $FreeBSD$ - -all: - sh regress.sh diff --git a/tools/regression/bin/date/regress.t b/tools/regression/bin/date/regress.t deleted file mode 100644 index c36d8342d32a..000000000000 --- a/tools/regression/bin/date/regress.t +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -sh regress.sh diff --git a/tools/regression/bin/mv/Makefile b/tools/regression/bin/mv/Makefile deleted file mode 100644 index 2c9ca5943505..000000000000 --- a/tools/regression/bin/mv/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# $FreeBSD$ - -all: - sh regress.sh diff --git a/tools/regression/bin/mv/regress.t b/tools/regression/bin/mv/regress.t deleted file mode 100644 index c36d8342d32a..000000000000 --- a/tools/regression/bin/mv/regress.t +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -sh regress.sh diff --git a/tools/regression/bin/pax/Makefile b/tools/regression/bin/pax/Makefile deleted file mode 100644 index 6855bca9706e..000000000000 --- a/tools/regression/bin/pax/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -all test: - prove -vmw regress.t - -clean: - rm -rf ustar-pathnames-[12] - rm -f ustar.ok ustar.fail* diff --git a/tools/regression/bin/sh/Makefile b/tools/regression/bin/sh/Makefile deleted file mode 100644 index 82b9c09f2c2e..000000000000 --- a/tools/regression/bin/sh/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -# Allow one to specify the 'sh' to regress. -SH?= /bin/sh - -all: - env SH=${SH} ${SH} regress.sh diff --git a/tools/regression/bin/sh/regress.t b/tools/regression/bin/sh/regress.t deleted file mode 100644 index 89b1828e8da7..000000000000 --- a/tools/regression/bin/sh/regress.t +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -export SH="${SH:-sh}" - -cd `dirname $0` - -${SH} regress.sh diff --git a/tools/regression/bin/test/Makefile b/tools/regression/bin/test/Makefile deleted file mode 100644 index 2c9ca5943505..000000000000 --- a/tools/regression/bin/test/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# $FreeBSD$ - -all: - sh regress.sh diff --git a/tools/regression/bin/test/regress.t b/tools/regression/bin/test/regress.t deleted file mode 100644 index c36d8342d32a..000000000000 --- a/tools/regression/bin/test/regress.t +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -sh regress.sh From e53c69c1f57ec41116604481b1f3af01bcb18c38 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 11 Dec 2013 04:31:40 +0000 Subject: [PATCH 007/172] Correct the check for errors from proc_rwmem(). MFC after: 2 weeks --- sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c | 2 +- sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c index 0063a4ba708d..c803a01a79f4 100644 --- a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c +++ b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c @@ -75,7 +75,7 @@ proc_ops(int op, proc_t *p, void *kaddr, off_t uaddr, size_t len) uio.uio_td = curthread; uio.uio_rw = op; PHOLD(p); - if (proc_rwmem(p, &uio) < 0) { + if (proc_rwmem(p, &uio) != 0) { PRELE(p); return (-1); } diff --git a/sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c index c035c99f55a9..f076f5d8040e 100644 --- a/sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c +++ b/sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c @@ -60,7 +60,7 @@ proc_ops(int op, proc_t *p, void *kaddr, off_t uaddr, size_t len) uio.uio_td = curthread; uio.uio_rw = op; PHOLD(p); - if (proc_rwmem(p, &uio) < 0) { + if (proc_rwmem(p, &uio) != 0) { PRELE(p); return (-1); } From 19dab280ccd35b44207eea72d45a14d0771df73b Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 11 Dec 2013 05:32:29 +0000 Subject: [PATCH 008/172] Fix one race and one fence post error. When the TX buffer was completely full, we'd not complete any of the mbufs due to the fence post error (this creates a large leak). When this is fixed, we still leak, but at a much smaller rate due to a race between ateintr and atestart_locked as well as an asymmetry where atestart_locked is called from elsewhere. Ensure that we free in-flight packets that have completed there as well. Also remove needless check for NULL on mb, checked earlier in the loop and simplify a redundant if. MFC after: 3 days --- sys/arm/at91/if_ate.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index ea3d791f4644..ce34028208e8 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -947,10 +947,8 @@ ate_intr(void *xsc) } while (!done); - if (mb != NULL) { - ifp->if_ipackets++; - (*ifp->if_input)(ifp, mb); - } + ifp->if_ipackets++; + (*ifp->if_input)(ifp, mb); } } @@ -974,16 +972,14 @@ ate_intr(void *xsc) sc->tx_descs[sc->txtail + 1].status |= ETHB_TX_USED; } - while (sc->txtail != sc->txhead && - sc->tx_descs[sc->txtail].status & ETHB_TX_USED ) { - + while ((sc->tx_descs[sc->txtail].status & ETHB_TX_USED) && + sc->sent_mbuf[sc->txtail] != NULL) { bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail], BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]); m_freem(sc->sent_mbuf[sc->txtail]); sc->tx_descs[sc->txtail].addr = 0; sc->sent_mbuf[sc->txtail] = NULL; - ifp->if_opackets++; sc->txtail = NEXT_TX_IDX(sc, sc->txtail); } @@ -1118,12 +1114,10 @@ atestart_locked(struct ifnet *ifp) * xmit packets. We use OACTIVE to indicate "we can stuff more * into our buffers (clear) or not (set)." */ - if (!sc->is_emacb) { - /* RM9200 has only two hardware entries */ - if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - return; - } + /* RM9200 has only two hardware entries */ + if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + return; } IFQ_DRV_DEQUEUE(&ifp->if_snd, m); @@ -1146,6 +1140,21 @@ atestart_locked(struct ifnet *ifp) m_freem(m); continue; } + + /* + * There's a small race between the loop in ate_intr finishing + * and the check above to see if the packet was finished, as well + * as when atestart gets called via other paths. Loose the race + * gracefully and free the mbuf... + */ + if (sc->sent_mbuf[sc->txhead] != NULL) { + bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail], + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]); + m_free(sc->sent_mbuf[sc->txhead]); + ifp->if_opackets++; + } + sc->sent_mbuf[sc->txhead] = m; bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txhead], From a83011d2e752558fc473f2d63e73299cf222f112 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Wed, 11 Dec 2013 06:28:44 +0000 Subject: [PATCH 009/172] Fix typo when initializing the vlapic version register ('<<' instead of '<'). --- sys/amd64/vmm/io/vlapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index f0306e2eb308..71bc1424f745 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -260,7 +260,7 @@ vlapic_init_ipi(struct vlapic *vlapic) { struct LAPIC *lapic = &vlapic->apic; lapic->version = VLAPIC_VERSION; - lapic->version |= (VLAPIC_MAXLVT_ENTRIES < MAXLVTSHIFT); + lapic->version |= (VLAPIC_MAXLVT_ENTRIES << MAXLVTSHIFT); lapic->dfr = 0xffffffff; lapic->svr = APIC_SVR_VECTOR; vlapic_mask_lvts(&lapic->lvt_timer, VLAPIC_MAXLVT_ENTRIES+1); From e892b3fe36cbf5aff5352b4e1f6dbde630cead67 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 11 Dec 2013 13:20:32 +0000 Subject: [PATCH 010/172] USB method structures for USB controllers and USB pipes should be constant and does not need to be modified. This also saves a small amount of RAM. --- sys/dev/usb/controller/at91dci.c | 20 ++++++++--------- sys/dev/usb/controller/atmegadci.c | 12 +++++----- sys/dev/usb/controller/avr32dci.c | 12 +++++----- sys/dev/usb/controller/dwc_otg.c | 12 +++++----- sys/dev/usb/controller/ehci.c | 34 ++++++++++++++--------------- sys/dev/usb/controller/musb_otg.c | 20 ++++++++--------- sys/dev/usb/controller/ohci.c | 28 ++++++++++++------------ sys/dev/usb/controller/uhci.c | 26 +++++++++++----------- sys/dev/usb/controller/uss820dci.c | 20 ++++++++--------- sys/dev/usb/controller/xhci.c | 6 ++--- sys/dev/usb/template/usb_template.c | 2 +- sys/dev/usb/usb_bus.h | 2 +- sys/dev/usb/usb_device.c | 2 +- sys/dev/usb/usb_device.h | 2 +- sys/dev/usb/usb_hub.c | 2 +- sys/dev/usb/usb_transfer.c | 2 +- sys/dev/usb/usbdi.h | 2 +- 17 files changed, 102 insertions(+), 102 deletions(-) diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c index 6ebd37c3d08b..0d5f176a3589 100644 --- a/sys/dev/usb/controller/at91dci.c +++ b/sys/dev/usb/controller/at91dci.c @@ -103,11 +103,11 @@ SYSCTL_INT(_hw_usb_at91dci, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods at91dci_bus_methods; -struct usb_pipe_methods at91dci_device_bulk_methods; -struct usb_pipe_methods at91dci_device_ctrl_methods; -struct usb_pipe_methods at91dci_device_intr_methods; -struct usb_pipe_methods at91dci_device_isoc_fs_methods; +static const struct usb_bus_methods at91dci_bus_methods; +static const struct usb_pipe_methods at91dci_device_bulk_methods; +static const struct usb_pipe_methods at91dci_device_ctrl_methods; +static const struct usb_pipe_methods at91dci_device_intr_methods; +static const struct usb_pipe_methods at91dci_device_isoc_fs_methods; static at91dci_cmd_t at91dci_setup_rx; static at91dci_cmd_t at91dci_data_rx; @@ -1515,7 +1515,7 @@ at91dci_device_bulk_start(struct usb_xfer *xfer) at91dci_start_standard_chain(xfer); } -struct usb_pipe_methods at91dci_device_bulk_methods = +static const struct usb_pipe_methods at91dci_device_bulk_methods = { .open = at91dci_device_bulk_open, .close = at91dci_device_bulk_close, @@ -1552,7 +1552,7 @@ at91dci_device_ctrl_start(struct usb_xfer *xfer) at91dci_start_standard_chain(xfer); } -struct usb_pipe_methods at91dci_device_ctrl_methods = +static const struct usb_pipe_methods at91dci_device_ctrl_methods = { .open = at91dci_device_ctrl_open, .close = at91dci_device_ctrl_close, @@ -1589,7 +1589,7 @@ at91dci_device_intr_start(struct usb_xfer *xfer) at91dci_start_standard_chain(xfer); } -struct usb_pipe_methods at91dci_device_intr_methods = +static const struct usb_pipe_methods at91dci_device_intr_methods = { .open = at91dci_device_intr_open, .close = at91dci_device_intr_close, @@ -1671,7 +1671,7 @@ at91dci_device_isoc_fs_start(struct usb_xfer *xfer) at91dci_start_standard_chain(xfer); } -struct usb_pipe_methods at91dci_device_isoc_fs_methods = +static const struct usb_pipe_methods at91dci_device_isoc_fs_methods = { .open = at91dci_device_isoc_fs_open, .close = at91dci_device_isoc_fs_close, @@ -2318,7 +2318,7 @@ at91dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) } } -struct usb_bus_methods at91dci_bus_methods = +static const struct usb_bus_methods at91dci_bus_methods = { .endpoint_init = &at91dci_ep_init, .xfer_setup = &at91dci_xfer_setup, diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c index 0dc726ca7aa6..856d0bd916cf 100644 --- a/sys/dev/usb/controller/atmegadci.c +++ b/sys/dev/usb/controller/atmegadci.c @@ -96,9 +96,9 @@ SYSCTL_INT(_hw_usb_atmegadci, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods atmegadci_bus_methods; -struct usb_pipe_methods atmegadci_device_non_isoc_methods; -struct usb_pipe_methods atmegadci_device_isoc_fs_methods; +static const struct usb_bus_methods atmegadci_bus_methods; +static const struct usb_pipe_methods atmegadci_device_non_isoc_methods; +static const struct usb_pipe_methods atmegadci_device_isoc_fs_methods; static atmegadci_cmd_t atmegadci_setup_rx; static atmegadci_cmd_t atmegadci_data_rx; @@ -1410,7 +1410,7 @@ atmegadci_device_non_isoc_start(struct usb_xfer *xfer) atmegadci_start_standard_chain(xfer); } -struct usb_pipe_methods atmegadci_device_non_isoc_methods = +static const struct usb_pipe_methods atmegadci_device_non_isoc_methods = { .open = atmegadci_device_non_isoc_open, .close = atmegadci_device_non_isoc_close, @@ -1496,7 +1496,7 @@ atmegadci_device_isoc_fs_start(struct usb_xfer *xfer) atmegadci_start_standard_chain(xfer); } -struct usb_pipe_methods atmegadci_device_isoc_fs_methods = +static const struct usb_pipe_methods atmegadci_device_isoc_fs_methods = { .open = atmegadci_device_isoc_fs_open, .close = atmegadci_device_isoc_fs_close, @@ -2140,7 +2140,7 @@ atmegadci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) } } -struct usb_bus_methods atmegadci_bus_methods = +static const struct usb_bus_methods atmegadci_bus_methods = { .endpoint_init = &atmegadci_ep_init, .xfer_setup = &atmegadci_xfer_setup, diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c index 1d2ce87c7623..c7c25046a445 100644 --- a/sys/dev/usb/controller/avr32dci.c +++ b/sys/dev/usb/controller/avr32dci.c @@ -94,9 +94,9 @@ SYSCTL_INT(_hw_usb_avr32dci, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods avr32dci_bus_methods; -struct usb_pipe_methods avr32dci_device_non_isoc_methods; -struct usb_pipe_methods avr32dci_device_isoc_fs_methods; +static const struct usb_bus_methods avr32dci_bus_methods; +static const struct usb_pipe_methods avr32dci_device_non_isoc_methods; +static const struct usb_pipe_methods avr32dci_device_isoc_fs_methods; static avr32dci_cmd_t avr32dci_setup_rx; static avr32dci_cmd_t avr32dci_data_rx; @@ -1340,7 +1340,7 @@ avr32dci_device_non_isoc_start(struct usb_xfer *xfer) avr32dci_start_standard_chain(xfer); } -struct usb_pipe_methods avr32dci_device_non_isoc_methods = +static const struct usb_pipe_methods avr32dci_device_non_isoc_methods = { .open = avr32dci_device_non_isoc_open, .close = avr32dci_device_non_isoc_close, @@ -1425,7 +1425,7 @@ avr32dci_device_isoc_fs_start(struct usb_xfer *xfer) avr32dci_start_standard_chain(xfer); } -struct usb_pipe_methods avr32dci_device_isoc_fs_methods = +static const struct usb_pipe_methods avr32dci_device_isoc_fs_methods = { .open = avr32dci_device_isoc_fs_open, .close = avr32dci_device_isoc_fs_close, @@ -2084,7 +2084,7 @@ avr32dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) } } -struct usb_bus_methods avr32dci_bus_methods = +static const struct usb_bus_methods avr32dci_bus_methods = { .endpoint_init = &avr32dci_ep_init, .xfer_setup = &avr32dci_xfer_setup, diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c index 7c3b881bafd6..3bbe3c6d46fd 100644 --- a/sys/dev/usb/controller/dwc_otg.c +++ b/sys/dev/usb/controller/dwc_otg.c @@ -122,9 +122,9 @@ SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods dwc_otg_bus_methods; -struct usb_pipe_methods dwc_otg_device_non_isoc_methods; -struct usb_pipe_methods dwc_otg_device_isoc_methods; +static const struct usb_bus_methods dwc_otg_bus_methods; +static const struct usb_pipe_methods dwc_otg_device_non_isoc_methods; +static const struct usb_pipe_methods dwc_otg_device_isoc_methods; static dwc_otg_cmd_t dwc_otg_setup_rx; static dwc_otg_cmd_t dwc_otg_data_rx; @@ -3327,7 +3327,7 @@ dwc_otg_device_non_isoc_start(struct usb_xfer *xfer) dwc_otg_start_standard_chain(xfer); } -struct usb_pipe_methods dwc_otg_device_non_isoc_methods = +static const struct usb_pipe_methods dwc_otg_device_non_isoc_methods = { .open = dwc_otg_device_non_isoc_open, .close = dwc_otg_device_non_isoc_close, @@ -3422,7 +3422,7 @@ dwc_otg_device_isoc_start(struct usb_xfer *xfer) dwc_otg_start_standard_chain(xfer); } -struct usb_pipe_methods dwc_otg_device_isoc_methods = +static const struct usb_pipe_methods dwc_otg_device_isoc_methods = { .open = dwc_otg_device_isoc_open, .close = dwc_otg_device_isoc_close, @@ -4201,7 +4201,7 @@ dwc_otg_device_suspend(struct usb_device *udev) USB_BUS_UNLOCK(udev->bus); } -struct usb_bus_methods dwc_otg_bus_methods = +static const struct usb_bus_methods dwc_otg_bus_methods = { .endpoint_init = &dwc_otg_ep_init, .xfer_setup = &dwc_otg_xfer_setup, diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c index b8aa2ad27477..0fdbdce45163 100644 --- a/sys/dev/usb/controller/ehci.c +++ b/sys/dev/usb/controller/ehci.c @@ -119,12 +119,12 @@ static void ehci_dump_sqh(ehci_softc_t *sc, ehci_qh_t *sqh); #define EHCI_INTR_ENDPT 1 -extern struct usb_bus_methods ehci_bus_methods; -extern struct usb_pipe_methods ehci_device_bulk_methods; -extern struct usb_pipe_methods ehci_device_ctrl_methods; -extern struct usb_pipe_methods ehci_device_intr_methods; -extern struct usb_pipe_methods ehci_device_isoc_fs_methods; -extern struct usb_pipe_methods ehci_device_isoc_hs_methods; +static const struct usb_bus_methods ehci_bus_methods; +static const struct usb_pipe_methods ehci_device_bulk_methods; +static const struct usb_pipe_methods ehci_device_ctrl_methods; +static const struct usb_pipe_methods ehci_device_intr_methods; +static const struct usb_pipe_methods ehci_device_isoc_fs_methods; +static const struct usb_pipe_methods ehci_device_isoc_hs_methods; static void ehci_do_poll(struct usb_bus *); static void ehci_device_done(struct usb_xfer *, usb_error_t); @@ -1275,7 +1275,7 @@ ehci_non_isoc_done(struct usb_xfer *xfer) static uint8_t ehci_check_transfer(struct usb_xfer *xfer) { - struct usb_pipe_methods *methods = xfer->endpoint->methods; + const struct usb_pipe_methods *methods = xfer->endpoint->methods; ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus); uint32_t status; @@ -1756,7 +1756,7 @@ static void ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last) { struct ehci_std_temp temp; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; ehci_qh_t *qh; ehci_qtd_t *td; uint32_t qh_endp; @@ -2164,7 +2164,7 @@ ehci_isoc_hs_done(ehci_softc_t *sc, struct usb_xfer *xfer) static void ehci_device_done(struct usb_xfer *xfer, usb_error_t error) { - struct usb_pipe_methods *methods = xfer->endpoint->methods; + const struct usb_pipe_methods *methods = xfer->endpoint->methods; ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus); USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); @@ -2258,7 +2258,7 @@ ehci_device_bulk_start(struct usb_xfer *xfer) EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD); } -struct usb_pipe_methods ehci_device_bulk_methods = +static const struct usb_pipe_methods ehci_device_bulk_methods = { .open = ehci_device_bulk_open, .close = ehci_device_bulk_close, @@ -2299,7 +2299,7 @@ ehci_device_ctrl_start(struct usb_xfer *xfer) ehci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ehci_device_ctrl_methods = +static const struct usb_pipe_methods ehci_device_ctrl_methods = { .open = ehci_device_ctrl_open, .close = ehci_device_ctrl_close, @@ -2380,7 +2380,7 @@ ehci_device_intr_start(struct usb_xfer *xfer) ehci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ehci_device_intr_methods = +static const struct usb_pipe_methods ehci_device_intr_methods = { .open = ehci_device_intr_open, .close = ehci_device_intr_close, @@ -2672,7 +2672,7 @@ ehci_device_isoc_fs_start(struct usb_xfer *xfer) ehci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ehci_device_isoc_fs_methods = +static const struct usb_pipe_methods ehci_device_isoc_fs_methods = { .open = ehci_device_isoc_fs_open, .close = ehci_device_isoc_fs_close, @@ -2952,7 +2952,7 @@ ehci_device_isoc_hs_start(struct usb_xfer *xfer) ehci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ehci_device_isoc_hs_methods = +static const struct usb_pipe_methods ehci_device_isoc_hs_methods = { .open = ehci_device_isoc_hs_open, .close = ehci_device_isoc_hs_close, @@ -3759,7 +3759,7 @@ ehci_device_resume(struct usb_device *udev) { ehci_softc_t *sc = EHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; DPRINTF("\n"); @@ -3793,7 +3793,7 @@ ehci_device_suspend(struct usb_device *udev) { ehci_softc_t *sc = EHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; DPRINTF("\n"); @@ -3872,7 +3872,7 @@ ehci_set_hw_power(struct usb_bus *bus) return; } -struct usb_bus_methods ehci_bus_methods = +static const struct usb_bus_methods ehci_bus_methods = { .endpoint_init = ehci_ep_init, .xfer_setup = ehci_xfer_setup, diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c index 6944a599eef9..a59ecf47fe3e 100644 --- a/sys/dev/usb/controller/musb_otg.c +++ b/sys/dev/usb/controller/musb_otg.c @@ -99,11 +99,11 @@ SYSCTL_INT(_hw_usb_musbotg, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods musbotg_bus_methods; -struct usb_pipe_methods musbotg_device_bulk_methods; -struct usb_pipe_methods musbotg_device_ctrl_methods; -struct usb_pipe_methods musbotg_device_intr_methods; -struct usb_pipe_methods musbotg_device_isoc_methods; +static const struct usb_bus_methods musbotg_bus_methods; +static const struct usb_pipe_methods musbotg_device_bulk_methods; +static const struct usb_pipe_methods musbotg_device_ctrl_methods; +static const struct usb_pipe_methods musbotg_device_intr_methods; +static const struct usb_pipe_methods musbotg_device_isoc_methods; /* Control transfers: Device mode */ static musbotg_cmd_t musbotg_dev_ctrl_setup_rx; @@ -3335,7 +3335,7 @@ musbotg_device_bulk_start(struct usb_xfer *xfer) musbotg_start_standard_chain(xfer); } -struct usb_pipe_methods musbotg_device_bulk_methods = +static const struct usb_pipe_methods musbotg_device_bulk_methods = { .open = musbotg_device_bulk_open, .close = musbotg_device_bulk_close, @@ -3372,7 +3372,7 @@ musbotg_device_ctrl_start(struct usb_xfer *xfer) musbotg_start_standard_chain(xfer); } -struct usb_pipe_methods musbotg_device_ctrl_methods = +static const struct usb_pipe_methods musbotg_device_ctrl_methods = { .open = musbotg_device_ctrl_open, .close = musbotg_device_ctrl_close, @@ -3409,7 +3409,7 @@ musbotg_device_intr_start(struct usb_xfer *xfer) musbotg_start_standard_chain(xfer); } -struct usb_pipe_methods musbotg_device_intr_methods = +static const struct usb_pipe_methods musbotg_device_intr_methods = { .open = musbotg_device_intr_open, .close = musbotg_device_intr_close, @@ -3498,7 +3498,7 @@ musbotg_device_isoc_start(struct usb_xfer *xfer) musbotg_start_standard_chain(xfer); } -struct usb_pipe_methods musbotg_device_isoc_methods = +static const struct usb_pipe_methods musbotg_device_isoc_methods = { .open = musbotg_device_isoc_open, .close = musbotg_device_isoc_close, @@ -4218,7 +4218,7 @@ musbotg_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) } } -struct usb_bus_methods musbotg_bus_methods = +static const struct usb_bus_methods musbotg_bus_methods = { .endpoint_init = &musbotg_ep_init, .get_dma_delay = &musbotg_get_dma_delay, diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c index e78c9e9ee765..86fca1eeaa3b 100644 --- a/sys/dev/usb/controller/ohci.c +++ b/sys/dev/usb/controller/ohci.c @@ -111,11 +111,11 @@ static void ohci_dump_itds(ohci_itd_t *); #define OHCI_INTR_ENDPT 1 -extern struct usb_bus_methods ohci_bus_methods; -extern struct usb_pipe_methods ohci_device_bulk_methods; -extern struct usb_pipe_methods ohci_device_ctrl_methods; -extern struct usb_pipe_methods ohci_device_intr_methods; -extern struct usb_pipe_methods ohci_device_isoc_methods; +static const struct usb_bus_methods ohci_bus_methods; +static const struct usb_pipe_methods ohci_device_bulk_methods; +static const struct usb_pipe_methods ohci_device_ctrl_methods; +static const struct usb_pipe_methods ohci_device_intr_methods; +static const struct usb_pipe_methods ohci_device_isoc_methods; static void ohci_do_poll(struct usb_bus *bus); static void ohci_device_done(struct usb_xfer *xfer, usb_error_t error); @@ -1393,7 +1393,7 @@ static void ohci_setup_standard_chain(struct usb_xfer *xfer, ohci_ed_t **ed_last) { struct ohci_std_temp temp; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; ohci_ed_t *ed; ohci_td_t *td; uint32_t ed_flags; @@ -1632,7 +1632,7 @@ ohci_root_intr(ohci_softc_t *sc) static void ohci_device_done(struct usb_xfer *xfer, usb_error_t error) { - struct usb_pipe_methods *methods = xfer->endpoint->methods; + const struct usb_pipe_methods *methods = xfer->endpoint->methods; ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus); ohci_ed_t *ed; @@ -1698,7 +1698,7 @@ ohci_device_bulk_start(struct usb_xfer *xfer) ohci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ohci_device_bulk_methods = +static const struct usb_pipe_methods ohci_device_bulk_methods = { .open = ohci_device_bulk_open, .close = ohci_device_bulk_close, @@ -1739,7 +1739,7 @@ ohci_device_ctrl_start(struct usb_xfer *xfer) ohci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ohci_device_ctrl_methods = +static const struct usb_pipe_methods ohci_device_ctrl_methods = { .open = ohci_device_ctrl_open, .close = ohci_device_ctrl_close, @@ -1811,7 +1811,7 @@ ohci_device_intr_start(struct usb_xfer *xfer) ohci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ohci_device_intr_methods = +static const struct usb_pipe_methods ohci_device_intr_methods = { .open = ohci_device_intr_open, .close = ohci_device_intr_close, @@ -2019,7 +2019,7 @@ ohci_device_isoc_start(struct usb_xfer *xfer) ohci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods ohci_device_isoc_methods = +static const struct usb_pipe_methods ohci_device_isoc_methods = { .open = ohci_device_isoc_open, .close = ohci_device_isoc_close, @@ -2598,7 +2598,7 @@ ohci_device_resume(struct usb_device *udev) { struct ohci_softc *sc = OHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; ohci_ed_t *ed; DPRINTF("\n"); @@ -2636,7 +2636,7 @@ ohci_device_suspend(struct usb_device *udev) { struct ohci_softc *sc = OHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; ohci_ed_t *ed; DPRINTF("\n"); @@ -2720,7 +2720,7 @@ ohci_set_hw_power(struct usb_bus *bus) return; } -struct usb_bus_methods ohci_bus_methods = +static const struct usb_bus_methods ohci_bus_methods = { .endpoint_init = ohci_ep_init, .xfer_setup = ohci_xfer_setup, diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c index fe3cf93eb6ce..de65df53f56e 100644 --- a/sys/dev/usb/controller/uhci.c +++ b/sys/dev/usb/controller/uhci.c @@ -151,11 +151,11 @@ struct uhci_std_temp { uint8_t last_frame; }; -extern struct usb_bus_methods uhci_bus_methods; -extern struct usb_pipe_methods uhci_device_bulk_methods; -extern struct usb_pipe_methods uhci_device_ctrl_methods; -extern struct usb_pipe_methods uhci_device_intr_methods; -extern struct usb_pipe_methods uhci_device_isoc_methods; +static const struct usb_bus_methods uhci_bus_methods; +static const struct usb_pipe_methods uhci_device_bulk_methods; +static const struct usb_pipe_methods uhci_device_ctrl_methods; +static const struct usb_pipe_methods uhci_device_intr_methods; +static const struct usb_pipe_methods uhci_device_isoc_methods; static uint8_t uhci_restart(uhci_softc_t *sc); static void uhci_do_poll(struct usb_bus *); @@ -1840,7 +1840,7 @@ uhci_setup_standard_chain(struct usb_xfer *xfer) static void uhci_device_done(struct usb_xfer *xfer, usb_error_t error) { - struct usb_pipe_methods *methods = xfer->endpoint->methods; + const struct usb_pipe_methods *methods = xfer->endpoint->methods; uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus); uhci_qh_t *qh; @@ -1935,7 +1935,7 @@ uhci_device_bulk_start(struct usb_xfer *xfer) uhci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods uhci_device_bulk_methods = +static const struct usb_pipe_methods uhci_device_bulk_methods = { .open = uhci_device_bulk_open, .close = uhci_device_bulk_close, @@ -1997,7 +1997,7 @@ uhci_device_ctrl_start(struct usb_xfer *xfer) uhci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods uhci_device_ctrl_methods = +static const struct usb_pipe_methods uhci_device_ctrl_methods = { .open = uhci_device_ctrl_open, .close = uhci_device_ctrl_close, @@ -2084,7 +2084,7 @@ uhci_device_intr_start(struct usb_xfer *xfer) uhci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods uhci_device_intr_methods = +static const struct usb_pipe_methods uhci_device_intr_methods = { .open = uhci_device_intr_open, .close = uhci_device_intr_close, @@ -2292,7 +2292,7 @@ uhci_device_isoc_start(struct usb_xfer *xfer) uhci_transfer_intr_enqueue(xfer); } -struct usb_pipe_methods uhci_device_isoc_methods = +static const struct usb_pipe_methods uhci_device_isoc_methods = { .open = uhci_device_isoc_open, .close = uhci_device_isoc_close, @@ -3076,7 +3076,7 @@ uhci_device_resume(struct usb_device *udev) { struct uhci_softc *sc = UHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; uhci_qh_t *qh; DPRINTF("\n"); @@ -3118,7 +3118,7 @@ uhci_device_suspend(struct usb_device *udev) { struct uhci_softc *sc = UHCI_BUS2SC(udev->bus); struct usb_xfer *xfer; - struct usb_pipe_methods *methods; + const struct usb_pipe_methods *methods; uhci_qh_t *qh; DPRINTF("\n"); @@ -3213,7 +3213,7 @@ uhci_set_hw_power(struct usb_bus *bus) } -struct usb_bus_methods uhci_bus_methods = +static const struct usb_bus_methods uhci_bus_methods = { .endpoint_init = uhci_ep_init, .xfer_setup = uhci_xfer_setup, diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c index 6750f32b06c1..1a38abe7b025 100644 --- a/sys/dev/usb/controller/uss820dci.c +++ b/sys/dev/usb/controller/uss820dci.c @@ -94,11 +94,11 @@ SYSCTL_INT(_hw_usb_uss820dci, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -struct usb_bus_methods uss820dci_bus_methods; -struct usb_pipe_methods uss820dci_device_bulk_methods; -struct usb_pipe_methods uss820dci_device_ctrl_methods; -struct usb_pipe_methods uss820dci_device_intr_methods; -struct usb_pipe_methods uss820dci_device_isoc_fs_methods; +static const struct usb_bus_methods uss820dci_bus_methods; +static const struct usb_pipe_methods uss820dci_device_bulk_methods; +static const struct usb_pipe_methods uss820dci_device_ctrl_methods; +static const struct usb_pipe_methods uss820dci_device_intr_methods; +static const struct usb_pipe_methods uss820dci_device_isoc_fs_methods; static uss820dci_cmd_t uss820dci_setup_rx; static uss820dci_cmd_t uss820dci_data_rx; @@ -1571,7 +1571,7 @@ uss820dci_device_bulk_start(struct usb_xfer *xfer) uss820dci_start_standard_chain(xfer); } -struct usb_pipe_methods uss820dci_device_bulk_methods = +static const struct usb_pipe_methods uss820dci_device_bulk_methods = { .open = uss820dci_device_bulk_open, .close = uss820dci_device_bulk_close, @@ -1608,7 +1608,7 @@ uss820dci_device_ctrl_start(struct usb_xfer *xfer) uss820dci_start_standard_chain(xfer); } -struct usb_pipe_methods uss820dci_device_ctrl_methods = +static const struct usb_pipe_methods uss820dci_device_ctrl_methods = { .open = uss820dci_device_ctrl_open, .close = uss820dci_device_ctrl_close, @@ -1645,7 +1645,7 @@ uss820dci_device_intr_start(struct usb_xfer *xfer) uss820dci_start_standard_chain(xfer); } -struct usb_pipe_methods uss820dci_device_intr_methods = +static const struct usb_pipe_methods uss820dci_device_intr_methods = { .open = uss820dci_device_intr_open, .close = uss820dci_device_intr_close, @@ -1727,7 +1727,7 @@ uss820dci_device_isoc_fs_start(struct usb_xfer *xfer) uss820dci_start_standard_chain(xfer); } -struct usb_pipe_methods uss820dci_device_isoc_fs_methods = +static const struct usb_pipe_methods uss820dci_device_isoc_fs_methods = { .open = uss820dci_device_isoc_fs_open, .close = uss820dci_device_isoc_fs_close, @@ -2376,7 +2376,7 @@ uss820dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) } } -struct usb_bus_methods uss820dci_bus_methods = +static const struct usb_bus_methods uss820dci_bus_methods = { .endpoint_init = &uss820dci_ep_init, .xfer_setup = &uss820dci_xfer_setup, diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 75f3d5efb2db..48c5edb60f6b 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -160,7 +160,7 @@ static void xhci_ctx_set_le64(struct xhci_softc *sc, volatile uint64_t *ptr, uin static uint64_t xhci_ctx_get_le64(struct xhci_softc *sc, volatile uint64_t *ptr); #endif -extern struct usb_bus_methods xhci_bus_methods; +static const struct usb_bus_methods xhci_bus_methods; #ifdef USB_DEBUG static void @@ -3069,7 +3069,7 @@ xhci_device_generic_start(struct usb_xfer *xfer) usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout); } -struct usb_pipe_methods xhci_device_generic_methods = +static const struct usb_pipe_methods xhci_device_generic_methods = { .open = xhci_device_generic_open, .close = xhci_device_generic_close, @@ -4235,7 +4235,7 @@ xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, } } -struct usb_bus_methods xhci_bus_methods = { +static const struct usb_bus_methods xhci_bus_methods = { .endpoint_init = xhci_ep_init, .endpoint_uninit = xhci_ep_uninit, .xfer_setup = xhci_xfer_setup, diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c index 73ca73b079e3..ec7e7112b4fd 100644 --- a/sys/dev/usb/template/usb_template.c +++ b/sys/dev/usb/template/usb_template.c @@ -846,7 +846,7 @@ usb_hw_ep_resolve(struct usb_device *udev, struct usb_hw_ep_scratch *ues; struct usb_hw_ep_scratch_sub *ep; const struct usb_hw_ep_profile *pf; - struct usb_bus_methods *methods; + const struct usb_bus_methods *methods; struct usb_device_descriptor *dd; uint16_t mps; diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h index 9836058d991f..064a5534ed0e 100644 --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -97,7 +97,7 @@ struct usb_bus { struct usb_dma_parent_tag dma_parent_tag[1]; struct usb_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX]; #endif - struct usb_bus_methods *methods; /* filled by HC driver */ + const struct usb_bus_methods *methods; /* filled by HC driver */ struct usb_device **devices; struct ifnet *ifp; /* only for USB Packet Filter */ diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 7e8181c06f84..0b7fb1a14db5 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -376,7 +376,7 @@ usb_init_endpoint(struct usb_device *udev, uint8_t iface_index, struct usb_endpoint_ss_comp_descriptor *ecomp, struct usb_endpoint *ep) { - struct usb_bus_methods *methods; + const struct usb_bus_methods *methods; usb_stream_t x; methods = udev->bus->methods; diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h index b5b5d13d5cd0..c1ec799cba6b 100644 --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -139,7 +139,7 @@ struct usb_hw_ep_scratch { struct usb_hw_ep_scratch_sub *ep_max; struct usb_config_descriptor *cd; struct usb_device *udev; - struct usb_bus_methods *methods; + const struct usb_bus_methods *methods; uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16]; uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16]; }; diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 3e9d1cbb6994..1a4903444ced 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -2541,7 +2541,7 @@ usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode) uint8_t usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode) { - struct usb_bus_methods *mtod; + const struct usb_bus_methods *mtod; int8_t temp; mtod = udev->bus->methods; diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index f2acf700dbc6..562ebb08ef6e 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -160,7 +160,7 @@ usbd_update_max_frame_size(struct usb_xfer *xfer) usb_timeout_t usbd_get_dma_delay(struct usb_device *udev) { - struct usb_bus_methods *mtod; + const struct usb_bus_methods *mtod; uint32_t temp; mtod = udev->bus->methods; diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 26f77694b950..099b390eebe8 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -140,7 +140,7 @@ struct usb_endpoint { struct usb_endpoint_descriptor *edesc; struct usb_endpoint_ss_comp_descriptor *ecomp; - struct usb_pipe_methods *methods; /* set by HC driver */ + const struct usb_pipe_methods *methods; /* set by HC driver */ uint16_t isoc_next; From 6e8706afba9793284052a890088b3bc025f5c9c9 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 11 Dec 2013 14:54:58 +0000 Subject: [PATCH 011/172] calendar(1): use strlcpy instead of strncpy use strlcpy instead of strncpy which avoids non-null-termination if the string is MAXPATHLEN bytes or longer. --- usr.bin/calendar/calcpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/calendar/calcpp.c b/usr.bin/calendar/calcpp.c index 413739b361f6..6a15683ecbe6 100644 --- a/usr.bin/calendar/calcpp.c +++ b/usr.bin/calendar/calcpp.c @@ -133,7 +133,7 @@ tokenscpp(char *buf, char *string) s = p; while(!isspace((unsigned char)*p)) p++; - strncpy(string, s, MAXPATHLEN); + strlcpy(string, s, MAXPATHLEN); return(T_DEFINE); } else if ((p = strstr(buf, "#ifndef")) != NULL) { p += 8; From 9336463d8696496d0b765ba36d92799209228de3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 11 Dec 2013 15:32:28 +0000 Subject: [PATCH 012/172] Loose -> Lose so this sentence makes sense. MFC after: 3 days --- sys/arm/at91/if_ate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index ce34028208e8..91b573864bff 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -1144,7 +1144,7 @@ atestart_locked(struct ifnet *ifp) /* * There's a small race between the loop in ate_intr finishing * and the check above to see if the packet was finished, as well - * as when atestart gets called via other paths. Loose the race + * as when atestart gets called via other paths. Lose the race * gracefully and free the mbuf... */ if (sc->sent_mbuf[sc->txhead] != NULL) { From 8528c7c86e6ba0447f65ad3f3006d5bcdea97691 Mon Sep 17 00:00:00 2001 From: "George V. Neville-Neil" Date: Wed, 11 Dec 2013 17:18:10 +0000 Subject: [PATCH 013/172] Fix a panic when booting with kernels that have FREEBBSD_COMPAT 4, 5, 6 or 43 by only thunking the data parameter for old ioctls compatability ioctls instead of doing it for all of them. Submitted by: jhb@ --- sys/dev/vt/vt_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 34f2b1b220e9..95bc531cf70c 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -1321,9 +1321,12 @@ vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data, case _IO('c', 110): cmd = CONS_SETKBD; break; + default: + goto skip_thunk; } ival = IOCPARM_IVAL(data); data = (caddr_t)&ival; +skip_thunk: #endif switch (cmd) { From 8adff99c8df21e13298d835d206d612aea299387 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 11 Dec 2013 17:40:35 +0000 Subject: [PATCH 014/172] Destroy mtx lock when failed to allocate memory during attach. Submitted by: Dmitry Luhtionov MFC after: 2 weeks --- sys/dev/ahci/ahciem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/dev/ahci/ahciem.c b/sys/dev/ahci/ahciem.c index d96f044d7dcd..8785a7800e40 100644 --- a/sys/dev/ahci/ahciem.c +++ b/sys/dev/ahci/ahciem.c @@ -85,8 +85,10 @@ ahci_em_attach(device_t dev) mtx_init(&enc->mtx, "AHCI enclosure lock", NULL, MTX_DEF); rid = 0; if (!(enc->r_memc = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &rid, RF_ACTIVE))) + &rid, RF_ACTIVE))) { + mtx_destroy(&enc->mtx); return (ENXIO); + } enc->capsem = ATA_INL(enc->r_memc, 0); rid = 1; if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, From b2b76a45bfba68bac25e5326f319bcc0294bb173 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 11 Dec 2013 21:19:04 +0000 Subject: [PATCH 015/172] Use fixed-width types for all fields in MP Table structures and pack all the structures. While here, move a helper struct only used in the kernel parser out of this header since it is not part of the MP specification itself. --- sys/x86/include/mptable.h | 156 +++++++++++++++++++------------------- sys/x86/x86/mptable.c | 7 ++ 2 files changed, 83 insertions(+), 80 deletions(-) diff --git a/sys/x86/include/mptable.h b/sys/x86/include/mptable.h index b8a9d791a6fe..c3ecb9725ae4 100644 --- a/sys/x86/include/mptable.h +++ b/sys/x86/include/mptable.h @@ -30,47 +30,50 @@ enum busTypes { NOBUS = 0, + CBUS = 1, + CBUSII = 2, EISA = 3, ISA = 6, MCA = 9, PCI = 13, + XPRESS = 18, MAX_BUSTYPE = 18, UNKNOWN_BUSTYPE = 0xff }; /* MP Floating Pointer Structure */ typedef struct MPFPS { - char signature[4]; - u_int32_t pap; - u_char length; - u_char spec_rev; - u_char checksum; - u_char config_type; - u_char mpfb2; - u_char mpfb3; - u_char mpfb4; - u_char mpfb5; -} *mpfps_t; + uint8_t signature[4]; + uint32_t pap; + uint8_t length; + uint8_t spec_rev; + uint8_t checksum; + uint8_t config_type; + uint8_t mpfb2; + uint8_t mpfb3; + uint8_t mpfb4; + uint8_t mpfb5; +} __packed *mpfps_t; #define MPFB2_IMCR_PRESENT 0x80 #define MPFB2_MUL_CLK_SRCS 0x40 /* MP Configuration Table Header */ typedef struct MPCTH { - char signature[4]; - u_short base_table_length; - u_char spec_rev; - u_char checksum; - u_char oem_id[8]; - u_char product_id[12]; - u_int32_t oem_table_pointer; - u_short oem_table_size; - u_short entry_count; - u_int32_t apic_address; - u_short extended_table_length; - u_char extended_table_checksum; - u_char reserved; -} *mpcth_t; + uint8_t signature[4]; + uint16_t base_table_length; + uint8_t spec_rev; + uint8_t checksum; + uint8_t oem_id[8]; + uint8_t product_id[12]; + uint32_t oem_table_pointer; + uint16_t oem_table_size; + uint16_t entry_count; + uint32_t apic_address; + uint16_t extended_table_length; + uint8_t extended_table_checksum; + uint8_t reserved; +} __packed *mpcth_t; /* Base table entries */ @@ -81,44 +84,44 @@ typedef struct MPCTH { #define MPCT_ENTRY_LOCAL_INT 4 typedef struct PROCENTRY { - u_char type; - u_char apic_id; - u_char apic_version; - u_char cpu_flags; - u_int32_t cpu_signature; - u_int32_t feature_flags; - u_int32_t reserved1; - u_int32_t reserved2; -} *proc_entry_ptr; + uint8_t type; + uint8_t apic_id; + uint8_t apic_version; + uint8_t cpu_flags; + uint32_t cpu_signature; + uint32_t feature_flags; + uint32_t reserved1; + uint32_t reserved2; +} __packed *proc_entry_ptr; #define PROCENTRY_FLAG_EN 0x01 #define PROCENTRY_FLAG_BP 0x02 typedef struct BUSENTRY { - u_char type; - u_char bus_id; - char bus_type[6]; -} *bus_entry_ptr; + uint8_t type; + uint8_t bus_id; + uint8_t bus_type[6]; +} __packed *bus_entry_ptr; typedef struct IOAPICENTRY { - u_char type; - u_char apic_id; - u_char apic_version; - u_char apic_flags; - u_int32_t apic_address; -} *io_apic_entry_ptr; + uint8_t type; + uint8_t apic_id; + uint8_t apic_version; + uint8_t apic_flags; + uint32_t apic_address; +} __packed *io_apic_entry_ptr; #define IOAPICENTRY_FLAG_EN 0x01 typedef struct INTENTRY { - u_char type; - u_char int_type; - u_short int_flags; - u_char src_bus_id; - u_char src_bus_irq; - u_char dst_apic_id; - u_char dst_apic_int; -} *int_entry_ptr; + uint8_t type; + uint8_t int_type; + uint16_t int_flags; + uint8_t src_bus_id; + uint8_t src_bus_irq; + uint8_t dst_apic_id; + uint8_t dst_apic_int; +} __packed *int_entry_ptr; #define INTENTRY_TYPE_INT 0 #define INTENTRY_TYPE_NMI 1 @@ -137,45 +140,45 @@ typedef struct INTENTRY { /* Extended table entries */ typedef struct EXTENTRY { - u_char type; - u_char length; -} *ext_entry_ptr; + uint8_t type; + uint8_t length; +} __packed *ext_entry_ptr; #define MPCT_EXTENTRY_SAS 0x80 #define MPCT_EXTENTRY_BHD 0x81 #define MPCT_EXTENTRY_CBASM 0x82 typedef struct SASENTRY { - u_char type; - u_char length; - u_char bus_id; - u_char address_type; + uint8_t type; + uint8_t length; + uint8_t bus_id; + uint8_t address_type; uint64_t address_base; uint64_t address_length; -} __attribute__((__packed__)) *sas_entry_ptr; +} __packed *sas_entry_ptr; #define SASENTRY_TYPE_IO 0 #define SASENTRY_TYPE_MEMORY 1 #define SASENTRY_TYPE_PREFETCH 2 typedef struct BHDENTRY { - u_char type; - u_char length; - u_char bus_id; - u_char bus_info; - u_char parent_bus; - u_char reserved[3]; -} *bhd_entry_ptr; + uint8_t type; + uint8_t length; + uint8_t bus_id; + uint8_t bus_info; + uint8_t parent_bus; + uint8_t reserved[3]; +} __packed *bhd_entry_ptr; #define BHDENTRY_INFO_SUBTRACTIVE_DECODE 0x1 typedef struct CBASMENTRY { - u_char type; - u_char length; - u_char bus_id; - u_char address_mod; - u_int predefined_range; -} *cbasm_entry_ptr; + uint8_t type; + uint8_t length; + uint8_t bus_id; + uint8_t address_mod; + uint32_t predefined_range; +} __packed *cbasm_entry_ptr; #define CBASMENTRY_ADDRESS_MOD_ADD 0x0 #define CBASMENTRY_ADDRESS_MOD_SUBTRACT 0x1 @@ -183,13 +186,6 @@ typedef struct CBASMENTRY { #define CBASMENTRY_RANGE_ISA_IO 0 #define CBASMENTRY_RANGE_VGA_IO 1 -/* descriptions of MP table entries */ -typedef struct BASETABLE_ENTRY { - u_char type; - u_char length; - char name[16]; -} basetable_entry; - #ifdef _KERNEL struct mptable_hostb_softc { #ifdef NEW_PCIB diff --git a/sys/x86/x86/mptable.c b/sys/x86/x86/mptable.c index f9fdbf3c0cd7..33493e0943c2 100644 --- a/sys/x86/x86/mptable.c +++ b/sys/x86/x86/mptable.c @@ -78,6 +78,13 @@ __FBSDID("$FreeBSD$"); typedef void mptable_entry_handler(u_char *entry, void *arg); typedef void mptable_extended_entry_handler(ext_entry_ptr entry, void *arg); +/* descriptions of MP table entries */ +typedef struct BASETABLE_ENTRY { + uint8_t type; + uint8_t length; + uint8_t name[16]; +} basetable_entry; + static basetable_entry basetable_entry_types[] = { {0, 20, "Processor"}, From a61a3b338fce6c01a91ad0e98e42b5ff22be98d6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 11 Dec 2013 21:21:03 +0000 Subject: [PATCH 016/172] - Use instead of duplicating its definitions. - Switch to mmaping the table from RAM instead of reading it out of /dev/mem via read(2). --- usr.sbin/mptable/mptable.c | 460 ++++++++++++------------------------- 1 file changed, 145 insertions(+), 315 deletions(-) diff --git a/usr.sbin/mptable/mptable.c b/usr.sbin/mptable/mptable.c index 01fa89774445..fcc12c020d5b 100644 --- a/usr.sbin/mptable/mptable.c +++ b/usr.sbin/mptable/mptable.c @@ -43,9 +43,12 @@ static const char rcsid[] = #define OEM_PROCESSING_READY_NOT #include +#include +#include #include #include #include +#include #include #include #include @@ -74,23 +77,8 @@ static const char rcsid[] = #define GROPE_AREA2 0x90000 #define GROPE_SIZE 0x10000 -#define PROCENTRY_FLAG_EN 0x01 -#define PROCENTRY_FLAG_BP 0x02 -#define IOAPICENTRY_FLAG_EN 0x01 - #define MAXPNSTR 132 -enum busTypes { - CBUS = 1, - CBUSII = 2, - EISA = 3, - ISA = 6, - PCI = 13, - XPRESS = 18, - MAX_BUSTYPE = 18, - UNKNOWN_BUSTYPE = 0xff -}; - typedef struct BUSTYPENAME { u_char type; char name[ 7 ]; @@ -129,140 +117,25 @@ static const char *whereStrings[] = { "GROPE AREA #2" }; -typedef struct TABLE_ENTRY { - u_char type; - u_char length; - char name[ 32 ]; -} tableEntry; - -static const tableEntry extendedtableEntryTypes[] = -{ - { 128, 20, "System Address Space" }, - { 129, 8, "Bus Hierarchy" }, - { 130, 8, "Compatibility Bus Address" } -}; - -/* MP Floating Pointer Structure */ -typedef struct MPFPS { - char signature[ 4 ]; - u_int32_t pap; - u_char length; - u_char spec_rev; - u_char checksum; - u_char mpfb1; - u_char mpfb2; - u_char mpfb3; - u_char mpfb4; - u_char mpfb5; -} mpfps_t; - -/* MP Configuration Table Header */ -typedef struct MPCTH { - char signature[ 4 ]; - u_short base_table_length; - u_char spec_rev; - u_char checksum; - u_char oem_id[ 8 ]; - u_char product_id[ 12 ]; - u_int32_t oem_table_pointer; - u_short oem_table_size; - u_short entry_count; - u_int32_t apic_address; - u_short extended_table_length; - u_char extended_table_checksum; - u_char reserved; -} mpcth_t; - - -typedef struct PROCENTRY { - u_char type; - u_char apicID; - u_char apicVersion; - u_char cpuFlags; - u_int32_t cpuSignature; - u_int32_t featureFlags; - u_int32_t reserved1; - u_int32_t reserved2; -} ProcEntry; - -typedef struct BUSENTRY { - u_char type; - u_char busID; - char busType[ 6 ]; -} BusEntry; - -typedef struct IOAPICENTRY { - u_char type; - u_char apicID; - u_char apicVersion; - u_char apicFlags; - u_int32_t apicAddress; -} IOApicEntry; - -typedef struct INTENTRY { - u_char type; - u_char intType; - u_short intFlags; - u_char srcBusID; - u_char srcBusIRQ; - u_char dstApicID; - u_char dstApicINT; -} IntEntry; - - -/* - * extended entry type structures - */ - -typedef struct SASENTRY { - u_char type; - u_char length; - u_char busID; - u_char addressType; - u_int64_t addressBase; - u_int64_t addressLength; -} __attribute__((__packed__)) SasEntry; - - -typedef struct BHDENTRY { - u_char type; - u_char length; - u_char busID; - u_char busInfo; - u_char busParent; - u_char reserved[ 3 ]; -} BhdEntry; - - -typedef struct CBASMENTRY { - u_char type; - u_char length; - u_char busID; - u_char addressMod; - u_int predefinedRange; -} CbasmEntry; - - - static void apic_probe( u_int32_t* paddr, int* where ); static void MPConfigDefault( int featureByte ); -static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps ); +static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ); static void MPConfigTableHeader( u_int32_t pap ); -static int readType( void ); static void seekEntry( u_int32_t addr ); static void readEntry( void* entry, int size ); +static void *mapEntry( u_int32_t addr, int size ); -static void processorEntry( void ); -static void busEntry( void ); -static void ioApicEntry( void ); -static void intEntry( void ); +static void processorEntry( proc_entry_ptr entry ); +static void busEntry( bus_entry_ptr entry ); +static void ioApicEntry( io_apic_entry_ptr entry ); +static void intEntry( int_entry_ptr entry ); -static void sasEntry( void ); -static void bhdEntry( void ); -static void cbasmEntry( void ); +static void sasEntry( sas_entry_ptr entry ); +static void bhdEntry( bhd_entry_ptr entry ); +static void cbasmEntry( cbasm_entry_ptr entry ); static void doDmesg( void ); static void pnstr( char* s, int c ); @@ -360,10 +233,10 @@ main( int argc, char *argv[] ) puts( SEP_LINE ); /* check whether an MP config table exists */ - if ( (defaultConfig = mpfps.mpfb1) ) + if ( (defaultConfig = mpfps->config_type) ) MPConfigDefault( defaultConfig ); else - MPConfigTableHeader( mpfps.pap ); + MPConfigTableHeader( mpfps->pap ); /* do a dmesg output */ if ( dmesg ) @@ -524,12 +397,12 @@ apic_probe( u_int32_t* paddr, int* where ) * */ static void -MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps ) +MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ) { - - /* read in mpfps structure*/ - seekEntry( paddr ); - readEntry( mpfps, sizeof( mpfps_t ) ); + mpfps_t mpfps; + + /* map in mpfps structure*/ + *mpfpsp = mpfps = mapEntry( paddr, sizeof( mpfps ) ); /* show its contents */ printf( "MP Floating Pointer Structure:\n\n" ); @@ -576,7 +449,7 @@ MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps ) } /* bit 7 is IMCRP */ - printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ? + printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) ? "PIC" : "Virtual Wire" ); /* MP feature bytes 3-5 are expected to be ZERO */ @@ -652,59 +525,53 @@ MPConfigDefault( int featureByte ) static void MPConfigTableHeader( u_int32_t pap ) { - u_int32_t paddr; mpcth_t cth; int x; int totalSize; - int count, c; - int type; + int c; int oldtype, entrytype; + u_int8_t *entry; if ( pap == 0 ) { printf( "MP Configuration Table Header MISSING!\n" ); exit( 1 ); } - /* convert physical address to virtual address */ - paddr = pap; - - /* read in cth structure */ - seekEntry( paddr ); - readEntry( &cth, sizeof( cth ) ); + /* map in cth structure */ + cth = mapEntry( pap, sizeof( *cth ) ); printf( "MP Config Table Header:\n\n" ); printf( " physical address:\t\t0x%08x\n", pap ); printf( " signature:\t\t\t'" ); - pnstr( cth.signature, 4 ); + pnstr( cth->signature, 4 ); printf( "'\n" ); - printf( " base table length:\t\t%d\n", cth.base_table_length ); + printf( " base table length:\t\t%d\n", cth->base_table_length ); - printf( " version:\t\t\t1.%1d\n", cth.spec_rev ); - printf( " checksum:\t\t\t0x%02x\n", cth.checksum ); + printf( " version:\t\t\t1.%1d\n", cth->spec_rev ); + printf( " checksum:\t\t\t0x%02x\n", cth->checksum ); printf( " OEM ID:\t\t\t'" ); - pnstr( cth.oem_id, 8 ); + pnstr( cth->oem_id, 8 ); printf( "'\n" ); printf( " Product ID:\t\t\t'" ); - pnstr( cth.product_id, 12 ); + pnstr( cth->product_id, 12 ); printf( "'\n" ); - printf( " OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer ); - printf( " OEM table size:\t\t%d\n", cth.oem_table_size ); + printf( " OEM table pointer:\t\t0x%08x\n", cth->oem_table_pointer ); + printf( " OEM table size:\t\t%d\n", cth->oem_table_size ); - printf( " entry count:\t\t\t%d\n", cth.entry_count ); + printf( " entry count:\t\t\t%d\n", cth->entry_count ); - printf( " local APIC address:\t\t0x%08x\n", cth.apic_address ); + printf( " local APIC address:\t\t0x%08x\n", cth->apic_address ); - printf( " extended table length:\t%d\n", cth.extended_table_length ); - printf( " extended table checksum:\t%d\n", cth.extended_table_checksum ); + printf( " extended table length:\t%d\n", cth->extended_table_length ); + printf( " extended table checksum:\t%d\n", cth->extended_table_checksum ); - totalSize = cth.base_table_length - sizeof( struct MPCTH ); - count = cth.entry_count; + totalSize = cth->base_table_length - sizeof( struct MPCTH ); puts( SEP_LINE ); @@ -723,101 +590,99 @@ MPConfigTableHeader( u_int32_t pap ) nintr = 0; oldtype = -1; - for (c = count; c; c--) { - entrytype = readType(); + entry = mapEntry(pap + sizeof(*cth), cth->base_table_length); + for (c = cth->entry_count; c; c--) { + entrytype = *entry; if (entrytype != oldtype) printf("--\n"); if (entrytype < oldtype) printf("MPTABLE OUT OF ORDER!\n"); switch (entrytype) { - case 0: - if (oldtype != 0) + case MPCT_ENTRY_PROCESSOR: + if (oldtype != MPCT_ENTRY_PROCESSOR) printf( "Processors:\tAPIC ID\tVersion\tState" "\t\tFamily\tModel\tStep\tFlags\n" ); - oldtype = 0; - processorEntry(); + processorEntry((proc_entry_ptr)entry); + entry += sizeof(struct PROCENTRY); break; - case 1: - if (oldtype != 1) + case MPCT_ENTRY_BUS: + if (oldtype != MPCT_ENTRY_BUS) printf( "Bus:\t\tBus ID\tType\n" ); - oldtype = 1; - busEntry(); + busEntry((bus_entry_ptr)entry); + entry += sizeof(struct BUSENTRY); break; - case 2: - if (oldtype != 2) + case MPCT_ENTRY_IOAPIC: + if (oldtype != MPCT_ENTRY_IOAPIC) printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" ); - oldtype = 2; - ioApicEntry(); + ioApicEntry((io_apic_entry_ptr)entry); + entry += sizeof(struct IOAPICENTRY); break; - case 3: - if (oldtype != 3) + case MPCT_ENTRY_INT: + if (oldtype != MPCT_ENTRY_INT) printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); - oldtype = 3; - intEntry(); + intEntry((int_entry_ptr)entry); + entry += sizeof(struct INTENTRY); break; - case 4: - if (oldtype != 4) + case MPCT_ENTRY_LOCAL_INT: + if (oldtype != MPCT_ENTRY_LOCAL_INT) printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); - oldtype = 4; - intEntry(); + intEntry((int_entry_ptr)entry); + entry += sizeof(struct INTENTRY); break; default: printf("MPTABLE HOSED! record type = %d\n", entrytype); exit(1); } + oldtype = entrytype; } #if defined( EXTENDED_PROCESSING_READY ) /* process any extended data */ - if ( (totalSize = cth.extended_table_length) ) { + if ( cth->extended_table_length ) { + ext_entry_ptr ext_entry, end; + puts( SEP_LINE ); printf( "MP Config Extended Table Entries:\n\n" ); - while ( totalSize > 0 ) { - switch ( type = readType() ) { - case 128: - sasEntry(); + ext_entry = mapEntry(pap + cth->base_table_length, + cth->extended_table_length); + end = (ext_entry_ptr)((char *)ext_entry + cth->extended_table_length); + while (ext_entry < end) { + switch (ext_entry->type) { + case MPCT_EXTENTRY_SAS: + sasEntry((sas_entry_ptr)ext_entry); break; - case 129: - bhdEntry(); + case MPCT_EXTENTRY_BHD: + bhdEntry((bhd_entry_ptr)ext_entry); break; - case 130: - cbasmEntry(); + case MPCT_EXTENTRY_CBASM: + cbasmEntry((cbasm_entry_ptr)ext_entry); break; default: printf( "Extended Table HOSED!\n" ); exit( 1 ); } - totalSize -= extendedtableEntryTypes[ type-128 ].length; + ext_entry = (ext_entry_ptr)((char *)ext_entry + ext_entry->length); } } #endif /* EXTENDED_PROCESSING_READY */ /* process any OEM data */ - if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) { + if ( cth->oem_table_pointer && (cth->oem_table_size > 0) ) { #if defined( OEM_PROCESSING_READY ) # error your on your own here! - /* convert OEM table pointer to virtual address */ - poemtp = (u_int32_t)cth.oem_table_pointer; - - /* read in oem table structure */ - if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL ) - err( 1, "oem malloc" ); - - seekEntry( poemtp ); - readEntry( oemdata, cth.oem_table_size ); + /* map in oem table structure */ + oemdata = mapEntry( cth->oem_table_pointer, cth->oem_table_size); /** process it */ - - free( oemdata ); #else printf( "\nyou need to modify the source to handle OEM data!\n\n" ); #endif /* OEM_PROCESSING_READY */ @@ -828,11 +693,11 @@ MPConfigTableHeader( u_int32_t pap ) #if defined( RAW_DUMP ) { int ofd; - u_char dumpbuf[ 4096 ]; + void *dumpbuf; ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR, 0666 ); - seekEntry( paddr ); - readEntry( dumpbuf, 1024 ); + + dumpbuf = mapEntry( paddr, 1024 ); write( ofd, dumpbuf, 1024 ); close( ofd ); } @@ -840,24 +705,6 @@ MPConfigTableHeader( u_int32_t pap ) } -/* - * - */ -static int -readType( void ) -{ - u_char type; - - if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) ) - err( 1, "type read; pfd: %d", pfd ); - - if ( lseek( pfd, -1, SEEK_CUR ) < 0 ) - err( 1, "type seek" ); - - return (int)type; -} - - /* * */ @@ -879,31 +726,37 @@ readEntry( void* entry, int size ) err( 1, "readEntry" ); } +static void * +mapEntry( u_int32_t addr, int size ) +{ + void *p; + + p = mmap( NULL, size, PROT_READ, MAP_SHARED, pfd, addr ); + if (p == MAP_FAILED) + err( 1, "mapEntry" ); + return (p); +} static void -processorEntry( void ) +processorEntry( proc_entry_ptr entry ) { - ProcEntry entry; - - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); /* count it */ ++ncpu; - printf( "\t\t%2d", entry.apicID ); - printf( "\t 0x%2x", entry.apicVersion ); + printf( "\t\t%2d", entry->apic_id ); + printf( "\t 0x%2x", entry->apic_version ); printf( "\t %s, %s", - (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", - (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); + (entry->cpu_flags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", + (entry->cpu_flags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); printf( "\t %d\t %d\t %d", - (entry.cpuSignature >> 8) & 0x0f, - (entry.cpuSignature >> 4) & 0x0f, - entry.cpuSignature & 0x0f ); + (entry->cpu_signature >> 8) & 0x0f, + (entry->cpu_signature >> 4) & 0x0f, + entry->cpu_signature & 0x0f ); - printf( "\t 0x%04x\n", entry.featureFlags ); + printf( "\t 0x%04x\n", entry->feature_flags ); } @@ -924,50 +777,42 @@ lookupBusType( char* name ) static void -busEntry( void ) +busEntry( bus_entry_ptr entry ) { int x; char name[ 8 ]; char c; - BusEntry entry; - - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); /* count it */ ++nbus; - printf( "\t\t%2d", entry.busID ); - printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" ); + printf( "\t\t%2d", entry->bus_id ); + printf( "\t " ); pnstr( entry->bus_type, 6 ); printf( "\n" ); for ( x = 0; x < 6; ++x ) { - if ( (c = entry.busType[ x ]) == ' ' ) + if ( (c = entry->bus_type[ x ]) == ' ' ) break; name[ x ] = c; } name[ x ] = '\0'; - busses[ entry.busID ] = lookupBusType( name ); + busses[ entry->bus_id ] = lookupBusType( name ); } static void -ioApicEntry( void ) +ioApicEntry( io_apic_entry_ptr entry ) { - IOApicEntry entry; - - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); /* count it */ ++napic; - printf( "\t\t%2d", entry.apicID ); - printf( "\t 0x%02x", entry.apicVersion ); + printf( "\t\t%2d", entry->apic_id ); + printf( "\t 0x%02x", entry->apic_version ); printf( "\t %s", - (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); - printf( "\t\t 0x%x\n", entry.apicAddress ); + (entry->apic_flags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); + printf( "\t\t 0x%x\n", entry->apic_address ); - apics[ entry.apicID ] = entry.apicID; + apics[ entry->apic_id ] = entry->apic_id; } @@ -983,53 +828,45 @@ static const char *triggerMode[] = { }; static void -intEntry( void ) +intEntry( int_entry_ptr entry ) { - IntEntry entry; - - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); /* count it */ - if ( (int)entry.type == 3 ) + if ( entry->type == MPCT_ENTRY_INT ) ++nintr; - printf( "\t\t%s", intTypes[ (int)entry.intType ] ); + printf( "\t\t%s", intTypes[ entry->int_type ] ); - printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] ); - printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] ); + printf( "\t%9s", polarityMode[ entry->int_flags & INTENTRY_FLAGS_POLARITY ] ); + printf( "%12s", triggerMode[ (entry->int_flags & INTENTRY_FLAGS_TRIGGER) >> 2 ] ); - printf( "\t %5d", (int)entry.srcBusID ); - if ( busses[ (int)entry.srcBusID ] == PCI ) + printf( "\t %5d", entry->src_bus_id ); + if ( busses[ entry->src_bus_id ] == PCI ) printf( "\t%2d:%c", - ((int)entry.srcBusIRQ >> 2) & 0x1f, - ((int)entry.srcBusIRQ & 0x03) + 'A' ); + (entry->src_bus_irq >> 2) & 0x1f, + (entry->src_bus_irq & 0x03) + 'A' ); else - printf( "\t %3d", (int)entry.srcBusIRQ ); - printf( "\t %6d", (int)entry.dstApicID ); - printf( "\t %3d\n", (int)entry.dstApicINT ); + printf( "\t %3d", entry->src_bus_irq ); + printf( "\t %6d", entry->dst_apic_id ); + printf( "\t %3d\n", entry->dst_apic_int ); } static void -sasEntry( void ) +sasEntry( sas_entry_ptr entry ) { - SasEntry entry; - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); - - printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); - printf( " bus ID: %d", entry.busID ); + printf( "--\nSystem Address Space\n"); + printf( " bus ID: %d", entry->bus_id ); printf( " address type: " ); - switch ( entry.addressType ) { - case 0: + switch ( entry->address_type ) { + case SASENTRY_TYPE_IO: printf( "I/O address\n" ); break; - case 1: + case SASENTRY_TYPE_MEMORY: printf( "memory address\n" ); break; - case 2: + case SASENTRY_TYPE_PREFETCH: printf( "prefetch address\n" ); break; default: @@ -1037,39 +874,32 @@ sasEntry( void ) break; } - printf( " address base: 0x%llx\n", (long long)entry.addressBase ); - printf( " address range: 0x%llx\n", (long long)entry.addressLength ); + printf( " address base: 0x%jx\n", (uintmax_t)entry->address_base ); + printf( " address range: 0x%jx\n", (uintmax_t)entry->address_length ); } static void -bhdEntry( void ) +bhdEntry( bhd_entry_ptr entry ) { - BhdEntry entry; - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); - - printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); - printf( " bus ID: %d", entry.busID ); - printf( " bus info: 0x%02x", entry.busInfo ); - printf( " parent bus ID: %d\n", entry.busParent ); + printf( "--\nBus Hierarchy\n" ); + printf( " bus ID: %d", entry->bus_id ); + printf( " bus info: 0x%02x", entry->bus_info ); + printf( " parent bus ID: %d\n", entry->parent_bus ); } static void -cbasmEntry( void ) +cbasmEntry( cbasm_entry_ptr entry ) { - CbasmEntry entry; - /* read it into local memory */ - readEntry( &entry, sizeof( entry ) ); - - printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); - printf( " bus ID: %d", entry.busID ); - printf( " address modifier: %s\n", (entry.addressMod & 0x01) ? - "subtract" : "add" ); - printf( " predefined range: 0x%08x\n", entry.predefinedRange ); + printf( "--\nCompatibility Bus Address\n" ); + printf( " bus ID: %d", entry->bus_id ); + printf( " address modifier: %s\n", + (entry->address_mod & CBASMENTRY_ADDRESS_MOD_SUBTRACT) ? + "subtract" : "add" ); + printf( " predefined range: 0x%08x\n", entry->predefined_range ); } From 1cf78c85c5be4eee2c1765a03547379752bc4e76 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 11 Dec 2013 21:48:04 +0000 Subject: [PATCH 017/172] Create own free list for each of the first 32 possible allocation sizes. In case of 4K allocation quantum that means for allocations up to 128K. With growth of memory fragmentation these lists may grow to quite a large sizes (tenths and hundreds of thousands items). Having in one list items of different sizes in worst case may require full linear list traversal, that may be very expensive. Having lists for items of single size means that unless user specify some alignment or border requirements (that are very rare cases) first item found on the list should satisfy the request. While running SPEC NFS benchmark on top of ZFS on 24-core machine with 84GB RAM this change reduces CPU time spent in vmem_xalloc() from 8% and lock congestion spinning around it from 20% to invisible levels. And that all is by the cost of just 26 more pointers per vmem instance. If at some point our kernel will start to actively use KVA allocations with odd sizes above 128K, something may need to be done to bigger lists also. --- sys/kern/subr_vmem.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sys/kern/subr_vmem.c b/sys/kern/subr_vmem.c index f3f3eecee93d..3b70738389bb 100644 --- a/sys/kern/subr_vmem.c +++ b/sys/kern/subr_vmem.c @@ -70,7 +70,10 @@ __FBSDID("$FreeBSD$"); #include #include -#define VMEM_MAXORDER (sizeof(vmem_size_t) * NBBY) +#define VMEM_OPTORDER 5 +#define VMEM_OPTVALUE (1 << VMEM_OPTORDER) +#define VMEM_MAXORDER \ + (VMEM_OPTVALUE - 1 + sizeof(vmem_size_t) * NBBY - VMEM_OPTORDER) #define VMEM_HASHSIZE_MIN 16 #define VMEM_HASHSIZE_MAX 131072 @@ -200,8 +203,10 @@ static LIST_HEAD(, vmem) vmem_list = LIST_HEAD_INITIALIZER(vmem_list); #define VMEM_CROSS_P(addr1, addr2, boundary) \ ((((addr1) ^ (addr2)) & -(boundary)) != 0) -#define ORDER2SIZE(order) ((vmem_size_t)1 << (order)) -#define SIZE2ORDER(size) ((int)flsl(size) - 1) +#define ORDER2SIZE(order) ((order) < VMEM_OPTVALUE ? ((order) + 1) : \ + (vmem_size_t)1 << ((order) - (VMEM_OPTVALUE - VMEM_OPTORDER - 1))) +#define SIZE2ORDER(size) ((size) <= VMEM_OPTVALUE ? ((size) - 1) : \ + (flsl(size) + (VMEM_OPTVALUE - VMEM_OPTORDER - 2))) /* * Maximum number of boundary tags that may be required to satisfy an @@ -334,11 +339,14 @@ bt_free(vmem_t *vm, bt_t *bt) /* * freelist[0] ... [1, 1] - * freelist[1] ... [2, 3] - * freelist[2] ... [4, 7] - * freelist[3] ... [8, 15] + * freelist[1] ... [2, 2] * : - * freelist[n] ... [(1 << n), (1 << (n + 1)) - 1] + * freelist[29] ... [30, 30] + * freelist[30] ... [31, 31] + * freelist[31] ... [32, 63] + * freelist[33] ... [64, 127] + * : + * freelist[n] ... [(1 << (n - 26)), (1 << (n - 25)) - 1] * : */ @@ -979,6 +987,7 @@ vmem_init(vmem_t *vm, const char *name, vmem_addr_t base, vmem_size_t size, int i; MPASS(quantum > 0); + MPASS((quantum & (quantum - 1)) == 0); bzero(vm, sizeof(*vm)); @@ -988,8 +997,7 @@ vmem_init(vmem_t *vm, const char *name, vmem_addr_t base, vmem_size_t size, LIST_INIT(&vm->vm_freetags); strlcpy(vm->vm_name, name, sizeof(vm->vm_name)); vm->vm_quantum_mask = quantum - 1; - vm->vm_quantum_shift = SIZE2ORDER(quantum); - MPASS(ORDER2SIZE(vm->vm_quantum_shift) == quantum); + vm->vm_quantum_shift = flsl(quantum) - 1; vm->vm_nbusytag = 0; vm->vm_size = 0; vm->vm_inuse = 0; From cd730bd6b2b1f4796d2e2e0936d265c425e449c0 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 12 Dec 2013 00:27:22 +0000 Subject: [PATCH 018/172] sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c When a da or ada device dissappears, outstanding IOs fail with ENXIO, not EIO. The check for EIO was probably copied from Illumos, where that is indeed the correct errno. Without this change, pulling a busy drive from a zpool would usually turn it into UNAVAIL, even though pulling an idle drive would turn it into REMOVED. With this change, it is REMOVED every time. Also, vdev_geom_io_intr shouldn't do zfs_post_remove, because that results in devd getting two resource.fs.zfs.removed events. The comment said that the event had to be sent directly instead of through the async removal thread because "the DE engine is using this information to discard prevoius I/O errors". However, the fact that vdev_geom_io_intr was never actually sending the events until now, and that vdev_geom_orphan never sent them at all, and that vdev_geom_orphan usually gets called about 2 seconds after the actual removal, means that FreeBSD's userland can cope with a late event just fine. Approved by: ken (mentor) Sponsored by: Spectra Logic Corporation MFC after: 4 weeks --- .../contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index e1cca48f2014..4f2d0fe3fd48 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -770,20 +770,12 @@ vdev_geom_io_intr(struct bio *bp) */ vd->vdev_notrim = B_TRUE; } - if (zio->io_error == EIO && !vd->vdev_remove_wanted) { + if (zio->io_error == ENXIO && !vd->vdev_remove_wanted) { /* * If provider's error is set we assume it is being * removed. */ if (bp->bio_to->error != 0) { - /* - * We post the resource as soon as possible, instead of - * when the async removal actually happens, because the - * DE is using this information to discard previous I/O - * errors. - */ - /* XXX: zfs_post_remove() can sleep. */ - zfs_post_remove(zio->io_spa, vd); vd->vdev_remove_wanted = B_TRUE; spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE); } else if (!vd->vdev_delayed_close) { From 6930130109f957d1602fbd76f86b54f8bfb55a8d Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 12 Dec 2013 03:04:00 +0000 Subject: [PATCH 019/172] Allow pmap_remove_pages() to be called for physical maps not associated with the current thread. Obtained from: alc@ --- sys/ia64/ia64/pmap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index 89bd82d42bf8..dbddb5fa9adf 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -2103,19 +2103,16 @@ pmap_remove_pages(pmap_t pmap) { struct pv_chunk *pc, *npc; struct ia64_lpte *pte; + pmap_t oldpmap; pv_entry_t pv; vm_offset_t va; vm_page_t m; u_long inuse, bitmask; int allfree, bit, field, idx; - if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) { - printf("warning: %s called with non-current pmap\n", - __func__); - return; - } rw_wlock(&pvh_global_lock); PMAP_LOCK(pmap); + oldpmap = pmap_switch(pmap); TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) { allfree = 1; for (field = 0; field < _NPCM; field++) { @@ -2155,8 +2152,9 @@ pmap_remove_pages(pmap_t pmap) free_pv_chunk(pc); } } - rw_wunlock(&pvh_global_lock); + pmap_switch(oldpmap); PMAP_UNLOCK(pmap); + rw_wunlock(&pvh_global_lock); } /* From 8d7b3005167c2b0941ea9d279fa7e5b2a3d2c859 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Thu, 12 Dec 2013 04:12:19 +0000 Subject: [PATCH 020/172] FBT now does work fully on PowerPC. MFC after: 2 weeks --- sys/powerpc/aim/trap.c | 2 +- sys/powerpc/aim/trap_subr32.S | 16 +++++++++++++--- sys/powerpc/aim/trap_subr64.S | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index d382ba554118..33e8cf5dac43 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -297,7 +297,7 @@ trap(struct trapframe *frame) #ifdef KDTRACE_HOOKS case EXC_PGM: if (frame->srr1 & EXC_PGM_TRAP) { - if (*(uintptr_t *)frame->srr0 == 0x7c810808) { + if (*(uint32_t *)frame->srr0 == 0x7c810808) { if (dtrace_invop_jump_addr != NULL) { dtrace_invop_jump_addr(frame); return; diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index 78accf3fc4ea..99bbff68d484 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -883,8 +883,8 @@ CNAME(dblow): mfcr %r29 /* save CR in r29 */ mfsrr1 %r1 mtcr %r1 - bf 17,1f /* branch if privileged */ - + bf 17,2f /* branch if privileged */ +1: /* Unprivileged case */ mtcr %r29 /* put the condition register back */ mfsprg2 %r29 /* ... and r29 */ @@ -893,7 +893,17 @@ CNAME(dblow): li %r1, 0 /* How to get the vector from LR */ bla generictrap /* and we look like a generic trap */ -1: +2: +#ifdef KDTRACE_HOOKS + /* Privileged, so drop to KDB */ + mfsrr0 %r1 + lwz %r4,0(%r1) + /* Check if it's a DTrace trap. */ + li %r3,0x0808 + addis %r3,%r3,0x7c81 + cmplw %cr0,%r3,%r4 + beq %cr0,1b +#endif /* Privileged, so drop to KDB */ GET_CPUINFO(%r1) stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 5911a7fc92e4..6ee4ee0b443d 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -789,8 +789,9 @@ CNAME(dblow): mfcr %r29 /* save CR in r29 */ mfsrr1 %r1 mtcr %r1 - bf 17,1f /* branch if privileged */ + bf 17,2f /* branch if privileged */ +1: /* Unprivileged case */ mtcr %r29 /* put the condition register back */ mfsprg2 %r29 /* ... and r29 */ @@ -799,8 +800,17 @@ CNAME(dblow): li %r1, 0 /* How to get the vector from LR */ bla generictrap /* and we look like a generic trap */ -1: +2: +#ifdef KDTRACE_HOOKS /* Privileged, so drop to KDB */ + mfsrr0 %r1 + lwz %r4,0(%r1) + /* Check if it's a DTrace trap. */ + li %r3,0x0808 + addis %r3,%r3,0x7c81 + cmplw %cr0,%r3,%r4 + beq %cr0,1b +#endif GET_CPUINFO(%r1) std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r1) /* free r27 */ std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ From 89df2158c5f812c8467e8410de5f88c8387c5250 Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Thu, 12 Dec 2013 05:49:27 +0000 Subject: [PATCH 021/172] Prevent release build errors found during snapshot builds where if NOPORTS=1, pkg-stage.sh cannot build the ports-mgmt/pkg port if WITH_DVD=1. MFC after: 3 days Sponsored by: The FreeBSD Foundation --- release/scripts/pkg-stage.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release/scripts/pkg-stage.sh b/release/scripts/pkg-stage.sh index 93768fffa8d9..3781f776656a 100755 --- a/release/scripts/pkg-stage.sh +++ b/release/scripts/pkg-stage.sh @@ -24,6 +24,11 @@ fi REVISION="${2}" . "${1}" || exit 1 +# If NOPORTS is set for the release, do not attempt to build pkg(8). +if [ ! -f /usr/ports/Makefile ]; then + exit 0 +fi + if [ ! -x /usr/local/sbin/pkg ]; then /usr/bin/make -C /usr/ports/ports-mgmt/pkg install clean fi From 2634da8cd5adac77dfb9756c45920472ca05cf44 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 12 Dec 2013 08:23:28 +0000 Subject: [PATCH 022/172] Fix bug introduced at r256607. We have to recalculate bp_resid here since sizes of original and completed requests may differ due to end of media. Bisected by: pho --- sys/geom/geom_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 6ec77cca25ae..2c113e63f1cd 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -487,7 +487,7 @@ g_dev_done(struct bio *bp2) bp = bp2->bio_parent; bp->bio_error = bp2->bio_error; bp->bio_completed = bp2->bio_completed; - bp->bio_resid = bp2->bio_resid; + bp->bio_resid = bp->bio_length - bp2->bio_completed; if (bp2->bio_error != 0) { g_trace(G_T_BIO, "g_dev_done(%p) had error %d", bp2, bp2->bio_error); From 27ce2fd67cfe7ecd9420eaa15fc60be881ebf8e9 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 12 Dec 2013 08:34:51 +0000 Subject: [PATCH 023/172] Set chain bit correctly. This will fix some problems sending and receiving Zero Length Packets, ZLPs. See comment in code for more information. MFC after: 1 week Reported by: Kohji Okuno --- sys/dev/usb/controller/xhci.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 48c5edb60f6b..c56e6f05ae7c 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -1892,7 +1892,16 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp) td->td_trb[x].dwTrb2 = htole32(dword); dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) | - XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT; + XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT | + /* + * CHAIN-BIT: Ensure that a multi-TRB IN-endpoint + * frame only receives a single short packet event + * by setting the CHAIN bit in the LINK field. In + * addition some XHCI controllers have problems + * sending a ZLP unless the CHAIN-BIT is set in + * the LINK TRB. + */ + XHCI_TRB_3_CHAIN_BIT; td->td_trb[x].dwTrb3 = htole32(dword); @@ -1930,7 +1939,7 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp) } /* clear TD SIZE to zero, hence this is the last TRB */ - /* remove chain bit because this is the last TRB in the chain */ + /* remove chain bit because this is the last data TRB in the chain */ td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); From ae893e1ad9359169123469adb1b840f80a5728f1 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Thu, 12 Dec 2013 08:48:45 +0000 Subject: [PATCH 024/172] Fix the version string in dts emission. Reported by: Patrick Wildt MFC after: 1 week --- usr.bin/dtc/fdt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc index 7810c0d3c7a7..b2405efab52e 100644 --- a/usr.bin/dtc/fdt.cc +++ b/usr.bin/dtc/fdt.cc @@ -1181,7 +1181,7 @@ void device_tree::write_dts(int fd) { FILE *file = fdopen(fd, "w"); - fputs("/dtc-v1/;\n\n", file); + fputs("/dts-v1/;\n\n", file); if (!reservations.empty()) { From e00bea9e62db034ada0bb2e2ab333ee206a07693 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Thu, 12 Dec 2013 08:55:24 +0000 Subject: [PATCH 025/172] Some more cleanups and bug fixes in dtc for property printing / parsing. Submitted by: Patrick Wildt --- usr.bin/dtc/fdt.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc index b2405efab52e..0599d5501a54 100644 --- a/usr.bin/dtc/fdt.cc +++ b/usr.bin/dtc/fdt.cc @@ -137,7 +137,7 @@ property_value::resolve_type() break; } } - if (is_all_printable && (bytes > nuls)) + if ((is_all_printable && (bytes > nuls)) || bytes == 0) { type = STRING; if (nuls > 0) @@ -204,7 +204,7 @@ property_value::write_as_bytes(FILE *file) putc('[', file); for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++) { - fprintf(file, "%hhx", *i); + fprintf(file, "%02hhx", *i); if (i+1 != e) { putc(' ', file); @@ -367,6 +367,11 @@ property::property(input_buffer &structs, input_buffer &strings) return; } key = string(name_buffer); + + // If we're empty, do not push anything as value. + if (!length) + return; + // Read the value uint8_t byte; property_value v; From ca187878c02aec8f447aa7245ca588a51b0c3fc7 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 12 Dec 2013 11:05:48 +0000 Subject: [PATCH 026/172] Fix long known bug with handling device aliases residing not in devfs root. Historically creation of device aliases created symbolic links using only name of target device as a link target, not considering current directory. Fix that by adding number of "../" chunks to the terget device name, required to get out of the current directory to devfs root first. MFC after: 1 month --- sys/fs/devfs/devfs_devs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index 6b6cf6e8be23..da21f97db390 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -486,9 +486,9 @@ devfs_populate_loop(struct devfs_mount *dm, int cleanup) { struct cdev_priv *cdp; struct devfs_dirent *de; - struct devfs_dirent *dd; + struct devfs_dirent *dd, *dt; struct cdev *pdev; - int de_flags, j; + int de_flags, depth, j; char *q, *s; sx_assert(&dm->dm_lock, SX_XLOCKED); @@ -589,9 +589,17 @@ devfs_populate_loop(struct devfs_mount *dm, int cleanup) de->de_mode = 0755; de->de_dirent->d_type = DT_LNK; pdev = cdp->cdp_c.si_parent; - j = strlen(pdev->si_name) + 1; + dt = dd; + depth = 0; + while (dt != dm->dm_rootdir && + (dt = devfs_parent_dirent(dt)) != NULL) + depth++; + j = depth * 3 + strlen(pdev->si_name) + 1; de->de_symlink = malloc(j, M_DEVFS, M_WAITOK); - bcopy(pdev->si_name, de->de_symlink, j); + de->de_symlink[0] = 0; + while (depth-- > 0) + strcat(de->de_symlink, "../"); + strcat(de->de_symlink, pdev->si_name); } else { de->de_uid = cdp->cdp_c.si_uid; de->de_gid = cdp->cdp_c.si_gid; From c3ebd5edbcc78d8b41873002780c56d0542ff914 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybalko Date: Thu, 12 Dec 2013 14:49:26 +0000 Subject: [PATCH 027/172] Do not try to probe/attach if attempt to add fbd child are failed. Sponsored by: The FreeBSD Foundation --- sys/dev/drm2/drm_fb_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/dev/drm2/drm_fb_helper.c b/sys/dev/drm2/drm_fb_helper.c index 90a00987a1b3..d797502a7a21 100644 --- a/sys/dev/drm2/drm_fb_helper.c +++ b/sys/dev/drm2/drm_fb_helper.c @@ -1043,7 +1043,10 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, kdev = fb_helper->dev->device; fbd = device_add_child(kdev, "fbd", device_get_unit(kdev)); - ret = device_probe_and_attach(fbd); + if (fbd != NULL) + ret = device_probe_and_attach(fbd); + else + ret = ENODEV; #ifdef DEV_VT if (ret != 0) DRM_ERROR("Failed to attach fbd device: %d\n", ret); From 369f2ddcb8339dfb73ba278660641eeb843cf040 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 12 Dec 2013 17:48:33 +0000 Subject: [PATCH 028/172] Use correct value pointing to previously selected FDT DTB. Reviewed by: brooks Sponsored by: DARPA, AFRL MFC after: 1 week --- sys/mips/beri/beri_machdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c index 7c8eea573b64..85dd15300804 100644 --- a/sys/mips/beri/beri_machdep.c +++ b/sys/mips/beri/beri_machdep.c @@ -178,7 +178,7 @@ platform_start(__register_t a0, __register_t a1, __register_t a2, if (OF_install(OFW_FDT, 0) == FALSE) while (1); - if (OF_init(&fdt_static_dtb) != 0) + if (OF_init((void *)dtbp) != 0) while (1); #endif From eb31a574742ba1fa7ca8c877a9745668a999fde8 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Thu, 12 Dec 2013 17:59:09 +0000 Subject: [PATCH 029/172] Fix multi-repository support by properly respecting 'enabled' flag. This will read the REPOS_DIR env/config setting (default is /etc/pkg and /usr/local/etc/pkg/repos) and use the last enabled repository. This can be changed in the environment using a comma-separated list, or in /usr/local/etc/pkg.conf with JSON array syntax of: REPOS_DIR: ["/etc/pkg", "/usr/local/etc/pkg/repos"] Approved by: bapt MFC after: 1 week --- usr.sbin/pkg/config.c | 188 +++++++++++++++++++++++++++++++++++++++--- usr.sbin/pkg/config.h | 2 + usr.sbin/pkg/pkg.7 | 11 ++- 3 files changed, 186 insertions(+), 15 deletions(-) diff --git a/usr.sbin/pkg/config.c b/usr.sbin/pkg/config.c index affcee999cdd..658ff0a3cc36 100644 --- a/usr.sbin/pkg/config.c +++ b/usr.sbin/pkg/config.c @@ -32,8 +32,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -51,11 +53,17 @@ __FBSDID("$FreeBSD$"); #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ +struct config_value { + char *value; + STAILQ_ENTRY(config_value) next; +}; + struct config_entry { uint8_t type; const char *key; const char *val; char *value; + STAILQ_HEAD(, config_value) *list; bool envset; }; @@ -65,6 +73,7 @@ static struct config_entry c[] = { "PACKAGESITE", URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", NULL, + NULL, false, }, [ABI] = { @@ -72,6 +81,7 @@ static struct config_entry c[] = { "ABI", NULL, NULL, + NULL, false, }, [MIRROR_TYPE] = { @@ -79,6 +89,7 @@ static struct config_entry c[] = { "MIRROR_TYPE", "SRV", NULL, + NULL, false, }, [ASSUME_ALWAYS_YES] = { @@ -86,6 +97,7 @@ static struct config_entry c[] = { "ASSUME_ALWAYS_YES", "NO", NULL, + NULL, false, }, [SIGNATURE_TYPE] = { @@ -93,6 +105,7 @@ static struct config_entry c[] = { "SIGNATURE_TYPE", NULL, NULL, + NULL, false, }, [FINGERPRINTS] = { @@ -100,6 +113,15 @@ static struct config_entry c[] = { "FINGERPRINTS", NULL, NULL, + NULL, + false, + }, + [REPOS_DIR] = { + PKG_CONFIG_LIST, + "REPOS_DIR", + NULL, + NULL, + NULL, false, }, }; @@ -474,17 +496,34 @@ subst_packagesite(const char *abi) c[PACKAGESITE].value = strdup(sbuf_data(newval)); } +static int +boolstr_to_bool(const char *str) +{ + if (str != NULL && (strcasecmp(str, "true") == 0 || + strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || + str[0] == '1')) + return (true); + + return (false); +} + static void config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) { + yaml_node_item_t *item; yaml_node_pair_t *pair; - yaml_node_t *key, *val; + yaml_node_t *key, *val, *item_val; struct sbuf *buf = sbuf_new_auto(); + struct config_entry *temp_config; + struct config_value *cv; int i; size_t j; pair = node->data.mapping.pairs.start; + /* Temporary config for configs that may be disabled. */ + temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); + while (pair < node->data.mapping.pairs.top) { key = yaml_document_get_node(doc, pair->key); val = yaml_document_get_node(doc, pair->value); @@ -530,7 +569,12 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) else if (strcasecmp(key->data.scalar.value, "fingerprints") == 0) sbuf_cpy(buf, "FINGERPRINTS"); - else { /* Skip unknown entries for future use. */ + else if (strcasecmp(key->data.scalar.value, + "enabled") == 0) { + /* Skip disabled repos. */ + if (!boolstr_to_bool(val->data.scalar.value)) + goto cleanup; + } else { /* Skip unknown entries for future use. */ ++pair; continue; } @@ -554,10 +598,58 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) continue; } - c[i].value = strdup(val->data.scalar.value); + /* Parse sequence value ["item1", "item2"] */ + switch (c[i].type) { + case PKG_CONFIG_LIST: + if (val->type != YAML_SEQUENCE_NODE) { + fprintf(stderr, "Skipping invalid array " + "value for %s.\n", c[i].key); + ++pair; + continue; + } + item = val->data.sequence.items.start; + temp_config[i].list = + malloc(sizeof(*temp_config[i].list)); + STAILQ_INIT(temp_config[i].list); + + while (item < val->data.sequence.items.top) { + item_val = yaml_document_get_node(doc, *item); + if (item_val->type != YAML_SCALAR_NODE) { + ++item; + continue; + } + cv = malloc(sizeof(struct config_value)); + cv->value = + strdup(item_val->data.scalar.value); + STAILQ_INSERT_TAIL(temp_config[i].list, cv, + next); + ++item; + } + break; + default: + /* Normal string value. */ + temp_config[i].value = strdup(val->data.scalar.value); + break; + } ++pair; } + /* Repo is enabled, copy over all settings from temp_config. */ + for (i = 0; i < CONFIG_SIZE; i++) { + if (c[i].envset) + continue; + switch (c[i].type) { + case PKG_CONFIG_LIST: + c[i].list = temp_config[i].list; + break; + default: + c[i].value = temp_config[i].value; + break; + } + } + +cleanup: + free(temp_config); sbuf_delete(buf); } @@ -632,23 +724,84 @@ read_conf_file(const char *confpath, pkg_conf_file_t conftype) return (0); } +static int +load_repositories(const char *repodir) +{ + struct dirent *ent; + DIR *d; + char *p; + size_t n; + char path[MAXPATHLEN]; + int ret; + + ret = 0; + + if ((d = opendir(repodir)) == NULL) + return (1); + + while ((ent = readdir(d))) { + /* Trim out 'repos'. */ + if ((n = strlen(ent->d_name)) <= 5) + continue; + p = &ent->d_name[n - 5]; + if (strcmp(p, ".conf") == 0) { + snprintf(path, sizeof(path), "%s%s%s", + repodir, + repodir[strlen(repodir) - 1] == '/' ? "" : "/", + ent->d_name); + if (access(path, F_OK) == 0 && + read_conf_file(path, CONFFILE_REPO)) { + ret = 1; + goto cleanup; + } + } + } + +cleanup: + closedir(d); + + return (ret); +} + int config_init(void) { - const char *val; + char *val; int i; const char *localbase; + char *env_list_item; char confpath[MAXPATHLEN]; + struct config_value *cv; char abi[BUFSIZ]; for (i = 0; i < CONFIG_SIZE; i++) { val = getenv(c[i].key); if (val != NULL) { - c[i].val = val; c[i].envset = true; + switch (c[i].type) { + case PKG_CONFIG_LIST: + /* Split up comma-separated items from env. */ + c[i].list = malloc(sizeof(*c[i].list)); + STAILQ_INIT(c[i].list); + for (env_list_item = strtok(val, ","); + env_list_item != NULL; + env_list_item = strtok(NULL, ",")) { + cv = + malloc(sizeof(struct config_value)); + cv->value = + strdup(env_list_item); + STAILQ_INSERT_TAIL(c[i].list, cv, + next); + } + break; + default: + c[i].val = val; + break; + } } } + /* Read LOCALBASE/etc/pkg.conf first. */ localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); @@ -657,10 +810,22 @@ config_init(void) CONFFILE_PKG)) goto finalize; - snprintf(confpath, sizeof(confpath), "/etc/pkg/FreeBSD.conf"); - if (access(confpath, F_OK) == 0 && read_conf_file(confpath, - CONFFILE_REPO)) - goto finalize; + /* Then read in all repos from REPOS_DIR list of directories. */ + if (c[REPOS_DIR].list == NULL) { + c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); + STAILQ_INIT(c[REPOS_DIR].list); + cv = malloc(sizeof(struct config_value)); + cv->value = strdup("/etc/pkg"); + STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); + cv = malloc(sizeof(struct config_value)); + if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) + goto finalize; + STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); + } + + STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) + if (load_repositories(cv->value)) + goto finalize; finalize: if (c[ABI].val == NULL && c[ABI].value == NULL) { @@ -704,10 +869,7 @@ config_bool(pkg_config_key k, bool *val) else value = c[k].val; - if (strcasecmp(value, "true") == 0 || - strcasecmp(value, "yes") == 0 || - strcasecmp(value, "on") == 0 || - *value == '1') + if (boolstr_to_bool(value)) *val = true; return (0); diff --git a/usr.sbin/pkg/config.h b/usr.sbin/pkg/config.h index 72d2ec0b01a0..ea0d0005d769 100644 --- a/usr.sbin/pkg/config.h +++ b/usr.sbin/pkg/config.h @@ -39,12 +39,14 @@ typedef enum { ASSUME_ALWAYS_YES, SIGNATURE_TYPE, FINGERPRINTS, + REPOS_DIR, CONFIG_SIZE } pkg_config_key; typedef enum { PKG_CONFIG_STRING=0, PKG_CONFIG_BOOL, + PKG_CONFIG_LIST, } pkg_config_t; typedef enum { diff --git a/usr.sbin/pkg/pkg.7 b/usr.sbin/pkg/pkg.7 index e46f3ddbf7fb..342c93420b6a 100644 --- a/usr.sbin/pkg/pkg.7 +++ b/usr.sbin/pkg/pkg.7 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 19, 2013 +.Dd December 12, 2013 .Dt PKG 7 .Os .Sh NAME @@ -152,6 +152,7 @@ MIRROR_TYPE: "srv", SIGNATURE_TYPE: "none", FINGERPRINTS: "/usr/share/keys/pkg", ASSUME_ALWAYS_YES: "yes" +REPOS_DIR: ["/etc/pkg", "/usr/local/etc/pkg/repos"] .Ed .Pp Reference @@ -194,14 +195,20 @@ The URL that .Xr pkg 8 and other packages will be fetched from. +.It Ev REPOS_DIR +Comma-separated list of directories that should be searched for repository +configuration files. .El .Sh FILES Configuration is read from the files in the listed order. -The first enabled repository is the one used for bootstrapping +This path can be changed by setting +.Sy REPOS_DIR . +The last enabled repository is the one used for bootstrapping .Xr pkg 8 . .Bl -tag -width "/usr/local/etc/pkg/repos/*.conf" .It Pa /usr/local/etc/pkg.conf .It Pa /etc/pkg/FreeBSD.conf +.It Pa /usr/local/etc/pkg/repos/*.conf .El .Sh EXAMPLES Some examples are listed here. From 8b8807f515993731173768308a44ecfe44bcd838 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 12 Dec 2013 18:08:31 +0000 Subject: [PATCH 030/172] Add an FDT DTS and MDROOT kernel configuration for BERI on NetFPGA. At this point we only support one CPU, the PIC, and a UART console. Reviewed by: brooks Sponsored by: DARPA, AFRL MFC after: 5 days --- sys/boot/fdt/dts/beri-netfpga.dts | 135 ++++++++++++++++++++++++++++++ sys/mips/conf/BERI_NETFPGA_MDROOT | 28 +++++++ 2 files changed, 163 insertions(+) create mode 100644 sys/boot/fdt/dts/beri-netfpga.dts create mode 100644 sys/mips/conf/BERI_NETFPGA_MDROOT diff --git a/sys/boot/fdt/dts/beri-netfpga.dts b/sys/boot/fdt/dts/beri-netfpga.dts new file mode 100644 index 000000000000..697916895056 --- /dev/null +++ b/sys/boot/fdt/dts/beri-netfpga.dts @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2012-2013 Robert N. M. Watson + * Copyright (c) 2013 SRI International + * Copyright (c) 2013 Bjoern A. Zeeb + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249) + * ("MRC2"), as part of the DARPA MRC research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/dts-v1/; + +/* + * Device names here have been largely made up on the spot, especially for the + * "compatible" strings, and might want to be revised. + */ + +/ { + model = "SRI/Cambridge Beri (NetFPGA)"; + compatible = "sri-cambridge,beri-netfpga"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <1>; + + /* + * Secondary CPUs all start disabled and use the + * spin-table enable method. cpu-release-addr must be + * specified for each cpu other than cpu@0. Values of + * cpu-release-addr grow down from 0x100000 (kernel). + */ + status = "disabled"; + enable-method = "spin-table"; + + cpu@0 { + device-type = "cpu"; + compatible = "sri-cambridge,beri"; + + reg = <0>; + status = "okay"; + }; + +/* + cpu@1 { + device-type = "cpu"; + compatible = "sri-cambridge,beri"; + + reg = <1>; + // XXX: should we need cached prefix? + cpu-release-addr = <0xffffffff 0x800fffe0>; + }; +*/ + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <1>; + + /* + * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so + * we use mips4k coprocessor 0 interrupt management directly. + */ + compatible = "simple-bus", "mips,mips4k"; + ranges = <>; + + memory { + device_type = "memory"; + reg = <0x0 0x0FFFFFFF>; // ~256M at 0x0 + }; + + beripic: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x7f804000 0x400 + 0x7f806000 0x10 + 0x7f806080 0x10 + 0x7f806100 0x10>; + interrupts = <0 1 2 3 4>; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + }; + + serial0: serial@7f002100 { + compatible = "ns16550"; + reg = <0x7f002100 0x20>; + reg-shift = <2>; + clock-frequency = <100000000>; + interrupts = <8>; + interrupt-parent = <&beripic>; + }; + }; + + aliases { + serial0 = &serial0; + }; + + chosen { + stdin = "serial0"; + stdout = "serial0"; + bootargs = "-v"; + }; +}; diff --git a/sys/mips/conf/BERI_NETFPGA_MDROOT b/sys/mips/conf/BERI_NETFPGA_MDROOT new file mode 100644 index 000000000000..f98389a53374 --- /dev/null +++ b/sys/mips/conf/BERI_NETFPGA_MDROOT @@ -0,0 +1,28 @@ +# +# BERI_NETFPGA_MDROOT -- Kernel for the SRI/Cambridge "BERI" (Bluespec Extensible +# RISC Implementation) FPGA soft core, as configured in its NetFPGA reference +# configuration. +# +# $FreeBSD$ +# + +include "BERI_TEMPLATE" + +ident BERI_NETFPGA_MDROOT + +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=beri-netfpga.dts + +device uart + +# +# This kernel configuration uses an embedded memory root file system. +# Adjust the following path and size based on local requirements. +# +options MD_ROOT # MD is a potential root device +options MD_ROOT_SIZE=26112 # 25.5MB +options ROOTDEVNAME=\"ufs:md0\" +#makeoptions MFS_IMAGE=/foo/baz/baz/mdroot.img + +# end From 9fa569a71313ee3ddcd0b22fbf75510f7fa820e0 Mon Sep 17 00:00:00 2001 From: Luiz Otavio O Souza Date: Thu, 12 Dec 2013 18:29:36 +0000 Subject: [PATCH 031/172] After r256961 ofw_iicbuc.c will be built for any kernel which includes options 'iicbus' and 'fdt'. Remove the (now) unnecessary entries. Verified on BBB (am335x), EFIKA_MX (imx51 - by ray@), DIGI-CCWMX53 (imx53 - kernel build). Approved by: adrian (mentor) --- sys/arm/freescale/imx/files.imx51 | 1 - sys/arm/freescale/imx/files.imx53 | 1 - sys/arm/freescale/imx/files.imx6 | 1 - sys/arm/ti/files.ti | 1 - 4 files changed, 4 deletions(-) diff --git a/sys/arm/freescale/imx/files.imx51 b/sys/arm/freescale/imx/files.imx51 index 756e1b047f0f..e84eb232d45f 100644 --- a/sys/arm/freescale/imx/files.imx51 +++ b/sys/arm/freescale/imx/files.imx51 @@ -46,7 +46,6 @@ arm/freescale/imx/imx_wdog.c optional imxwdt # i2c arm/freescale/imx/i2c.c optional fsliic -dev/ofw/ofw_iicbus.c optional fsliic # IPU - Image Processing Unit (frame buffer also) arm/freescale/imx/imx51_ipuv3.c optional sc diff --git a/sys/arm/freescale/imx/files.imx53 b/sys/arm/freescale/imx/files.imx53 index 56a58902ade1..f936ccc82123 100644 --- a/sys/arm/freescale/imx/files.imx53 +++ b/sys/arm/freescale/imx/files.imx53 @@ -46,7 +46,6 @@ arm/freescale/imx/imx_wdog.c optional imxwdt # i2c arm/freescale/imx/i2c.c optional fsliic -dev/ofw/ofw_iicbus.c optional fsliic # IPU - Image Processing Unit (frame buffer also) arm/freescale/imx/imx51_ipuv3.c optional sc diff --git a/sys/arm/freescale/imx/files.imx6 b/sys/arm/freescale/imx/files.imx6 index cda896786eec..8064a959bf7a 100644 --- a/sys/arm/freescale/imx/files.imx6 +++ b/sys/arm/freescale/imx/files.imx6 @@ -51,6 +51,5 @@ arm/freescale/imx/imx6_usbphy.c optional ehci #arm/freescale/imx/imx51_gpio.c optional gpio #dev/ata/chipsets/ata-fsl.c optional imxata #arm/freescale/imx/i2c.c optional fsliic -#dev/ofw/ofw_iicbus.c optional fsliic #arm/freescale/imx/imx51_ipuv3.c optional sc diff --git a/sys/arm/ti/files.ti b/sys/arm/ti/files.ti index a176305f4fb8..b2c964a4f883 100644 --- a/sys/arm/ti/files.ti +++ b/sys/arm/ti/files.ti @@ -22,7 +22,6 @@ arm/ti/ti_pruss.c standard arm/ti/ti_gpio.c optional gpio arm/ti/ti_i2c.c optional ti_i2c -dev/ofw/ofw_iicbus.c optional iicbus dev/uart/uart_dev_ti8250.c optional uart dev/uart/uart_dev_ns8250.c optional uart From e3b4f880030371ab48194de4253b4971819e25a5 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Thu, 12 Dec 2013 20:20:46 +0000 Subject: [PATCH 032/172] Mention BIND removal in release notes. Submitted by: skreuzer --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 4440bdd5a747..647d6c756d60 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -328,6 +328,13 @@ Userland Changes + BIND has been replaced by &man.unbound.8; for + local dns resolution in the base system. With this change, nslookup + and dig are no longer a part of the base system. Users should + instead use &man.host.1; and &man.drill.1; Alternatively, + nslookup and dig can be obtained by installing the + dns/bind-tools port. + The &man.adduser.8; utility now supports a option to set the mode of a new user's home directory. From eba633a62f6701470b496a4cdbe646a7b13f3750 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 12 Dec 2013 20:34:04 +0000 Subject: [PATCH 033/172] Add a command to inject an NMI on a specific vcpu. It is a simple wrapper around the existing vm_inject_nmi(). Reviewed by: grehan, neel --- usr.sbin/bhyvectl/bhyvectl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 0e9220494e38..1b68776dca2e 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -189,12 +189,14 @@ usage(void) " [--set-mem=]\n" " [--get-lowmem]\n" " [--get-highmem]\n" - " [--get-gpa-pmap]\n", + " [--get-gpa-pmap]\n" + " [--inject-nmi]\n", progname); exit(1); } static int get_stats, getcap, setcap, capval, get_gpa_pmap; +static int inject_nmi; static const char *capname; static int create, destroy, get_lowmem, get_highmem; static uint64_t memsize; @@ -557,6 +559,7 @@ main(int argc, char *argv[]) { "run", NO_ARG, &run, 1 }, { "create", NO_ARG, &create, 1 }, { "destroy", NO_ARG, &destroy, 1 }, + { "inject-nmi", NO_ARG, &inject_nmi, 1 }, { NULL, 0, NULL, 0 } }; @@ -825,6 +828,10 @@ main(int argc, char *argv[]) vmcs_entry_interruption_info); } + if (!error && inject_nmi) { + error = vm_inject_nmi(ctx, vcpu); + } + if (!error && (get_lowmem || get_all)) { gpa = 0; error = vm_get_memory_seg(ctx, gpa, &len, &wired); From 9ea4ca859598c5d1bf5a6dadf59192ebde4dfc73 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Thu, 12 Dec 2013 20:47:18 +0000 Subject: [PATCH 034/172] I caught the following snippet at the end of my /var/log/bsdinstall_log: === DEBUG: Running installation step: services local: Not in a function /usr/libexec/bsdinstall/services: cannot create : Read-only file system /usr/libexec/bsdinstall/services: /tmp/bsdinstall/etc/rc.conf.services: \ Permission denied === The `local: Not in a function' is obvious, and was introduced by myself in SVN revision 256348. The latter two are caused by the attempt to use "\" to continue the line after using the ">>" redirect. This appears to attempt to write a file with the name " " in the current directory and subsequently attempts to execute the file that was originally intended for writing (which is not executable; hence the `Permission denied'). That was introduced in SVN r228192 about 2 years ago, apparently unnoticed until I started going over the debug outputs very carefully. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/services | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services index 8ce9e7bcd6e6..3297407e1110 100755 --- a/usr.sbin/bsdinstall/scripts/services +++ b/usr.sbin/bsdinstall/scripts/services @@ -50,13 +50,12 @@ DAEMONS=$(dialog --backtitle "FreeBSD Installer" \ 2>&1 1>&3) exec 3>&- -local havedump= +havedump= for daemon in $DAEMONS; do if [ "$daemon" == "dumpdev" ]; then havedump=1 - echo \# Set dumpdev to \"AUTO\" to enable crash dumps, \ - \"NO\" to disable >> \ - $BSDINSTALL_TMPETC/rc.conf.services + echo '# Set dumpdev to "AUTO" to enable crash dumps, "NO"' \ + 'to disable' >> $BSDINSTALL_TMPETC/rc.conf.services echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services continue fi From fbb49182f063430f803dd43bf45a793769e32b66 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Thu, 12 Dec 2013 22:33:32 +0000 Subject: [PATCH 035/172] Somehow stable/10 branch contains correct version, but head doesn't. --- sbin/growfs/growfs.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8 index cff105f648d9..9d62a83b974b 100644 --- a/sbin/growfs/growfs.8 +++ b/sbin/growfs/growfs.8 @@ -116,7 +116,7 @@ The utility first appeared in .Fx 4.4 . The ability to resize mounted filesystems was added in -.Fx 9.2 . +.Fx 10.0 . .Sh AUTHORS .An Christoph Herrmann Aq chm@FreeBSD.org .An Thomas-Henning von Kamptz Aq tomsoft@FreeBSD.org From 4702d987cd8808282a4d81d1f8f81bbd55100569 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Fri, 13 Dec 2013 02:37:35 +0000 Subject: [PATCH 036/172] Add PMU-based CPU frequency scaling. This method is used on most Titanium PowerBooks. MFC after: 1 month --- sys/conf/files.powerpc | 1 + sys/powerpc/aim/mp_cpudep.c | 21 ++- sys/powerpc/cpufreq/pmufreq.c | 222 +++++++++++++++++++++++ sys/powerpc/include/cpu.h | 2 + sys/powerpc/include/dbdma.h | 3 + sys/powerpc/include/pcpu.h | 3 +- sys/powerpc/include/spr.h | 4 + sys/powerpc/powermac/platform_powermac.c | 104 +++++++++++ sys/powerpc/powermac/pmu.c | 121 +++++++++++- sys/powerpc/powermac/pmuvar.h | 5 +- sys/powerpc/powermac/uninorth.c | 69 +++++-- sys/powerpc/powermac/uninorthvar.h | 22 +++ sys/powerpc/powermac/viareg.h | 4 +- sys/powerpc/powerpc/mp_machdep.c | 17 ++ 14 files changed, 565 insertions(+), 33 deletions(-) create mode 100644 sys/powerpc/cpufreq/pmufreq.c diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index f3365ef14263..9dda37edde93 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -107,6 +107,7 @@ powerpc/booke/pmap.c optional booke powerpc/booke/trap.c optional booke powerpc/cpufreq/dfs.c optional cpufreq powerpc/cpufreq/pcr.c optional cpufreq aim +powerpc/cpufreq/pmufreq.c optional cpufreq aim pmu powerpc/fpu/fpu_add.c optional fpu_emu powerpc/fpu/fpu_compare.c optional fpu_emu powerpc/fpu/fpu_div.c optional fpu_emu diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c index 76822716c46c..98b286414b70 100644 --- a/sys/powerpc/aim/mp_cpudep.c +++ b/sys/powerpc/aim/mp_cpudep.c @@ -322,17 +322,13 @@ cpudep_ap_setup() mtspr(SPR_CELL_TSRL, bsp_state[5]); break; - case MPC7450: - case MPC7455: - case MPC7457: - /* Only MPC745x CPUs have an L3 cache. */ - reg = mpc745x_l3_enable(bsp_state[3]); - - /* Fallthrough */ case MPC7400: case MPC7410: case MPC7447A: case MPC7448: + case MPC7450: + case MPC7455: + case MPC7457: /* XXX: Program the CPU ID into PIR */ __asm __volatile("mtspr 1023,%0" :: "r"(PCPU_GET(cpuid))); @@ -342,6 +338,17 @@ cpudep_ap_setup() mtspr(SPR_HID0, bsp_state[0]); isync(); mtspr(SPR_HID1, bsp_state[1]); isync(); + /* Now enable the L3 cache. */ + switch (vers) { + case MPC7450: + case MPC7455: + case MPC7457: + /* Only MPC745x CPUs have an L3 cache. */ + reg = mpc745x_l3_enable(bsp_state[3]); + default: + break; + } + reg = mpc74xx_l2_enable(bsp_state[2]); reg = mpc74xx_l1d_enable(); reg = mpc74xx_l1i_enable(); diff --git a/sys/powerpc/cpufreq/pmufreq.c b/sys/powerpc/cpufreq/pmufreq.c new file mode 100644 index 000000000000..d22ff0b6a675 --- /dev/null +++ b/sys/powerpc/cpufreq/pmufreq.c @@ -0,0 +1,222 @@ +/*- + * Copyright (c) 2011 Justin Hibbits + * Copyright (c) 2009 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cpufreq_if.h" +#include "powerpc/powermac/pmuvar.h" + +struct pmufreq_softc { + device_t dev; + uint32_t minfreq; + uint32_t maxfreq; + uint32_t curfreq; +}; + +static void pmufreq_identify(driver_t *driver, device_t parent); +static int pmufreq_probe(device_t dev); +static int pmufreq_attach(device_t dev); +static int pmufreq_settings(device_t dev, struct cf_setting *sets, int *count); +static int pmufreq_set(device_t dev, const struct cf_setting *set); +static int pmufreq_get(device_t dev, struct cf_setting *set); +static int pmufreq_type(device_t dev, int *type); + +static device_method_t pmufreq_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, pmufreq_identify), + DEVMETHOD(device_probe, pmufreq_probe), + DEVMETHOD(device_attach, pmufreq_attach), + + /* cpufreq interface */ + DEVMETHOD(cpufreq_drv_set, pmufreq_set), + DEVMETHOD(cpufreq_drv_get, pmufreq_get), + DEVMETHOD(cpufreq_drv_type, pmufreq_type), + DEVMETHOD(cpufreq_drv_settings, pmufreq_settings), + + {0, 0} +}; + +static driver_t pmufreq_driver = { + "pmufreq", + pmufreq_methods, + sizeof(struct pmufreq_softc) +}; + +static devclass_t pmufreq_devclass; +DRIVER_MODULE(pmufreq, cpu, pmufreq_driver, pmufreq_devclass, 0, 0); + +static void +pmufreq_identify(driver_t *driver, device_t parent) +{ + phandle_t node; + uint32_t min_freq; + + node = ofw_bus_get_node(parent); + if (OF_getprop(node, "min-clock-frequency", &min_freq, sizeof(min_freq)) == -1) + return; + + /* Make sure we're not being doubly invoked. */ + if (device_find_child(parent, "pmufreq", -1) != NULL) + return; + + /* + * We attach a child for every CPU since settings need to + * be performed on every CPU in the SMP case. + */ + if (BUS_ADD_CHILD(parent, 10, "pmufreq", -1) == NULL) + device_printf(parent, "add pmufreq child failed\n"); +} + +static int +pmufreq_probe(device_t dev) +{ + uint32_t min_freq; + struct pmufreq_softc *sc; + phandle_t node; + + if (resource_disabled("pmufreq", 0)) + return (ENXIO); + + sc = device_get_softc(dev); + node = ofw_bus_get_node(device_get_parent(dev)); + /* + * A scalable MPC7455 has min-clock-frequency/max-clock-frequency as OFW + * properties of the 'cpu' node. + */ + if (OF_getprop(node, "min-clock-frequency", &min_freq, sizeof(min_freq)) == -1) + return (ENXIO); + device_set_desc(dev, "PMU-based frequency scaling"); + return (0); +} + +static int +pmufreq_attach(device_t dev) +{ + struct pmufreq_softc *sc; + phandle_t node; + + sc = device_get_softc(dev); + sc->dev = dev; + + node = ofw_bus_get_node(device_get_parent(dev)); + OF_getprop(node, "min-clock-frequency", &sc->minfreq, sizeof(sc->minfreq)); + OF_getprop(node, "max-clock-frequency", &sc->maxfreq, sizeof(sc->maxfreq)); + OF_getprop(node, "rounded-clock-frequency", &sc->curfreq, sizeof(sc->curfreq)); + sc->minfreq /= 1000000; + sc->maxfreq /= 1000000; + sc->curfreq /= 1000000; + + cpufreq_register(dev); + return (0); +} + +static int +pmufreq_settings(device_t dev, struct cf_setting *sets, int *count) +{ + struct pmufreq_softc *sc; + + sc = device_get_softc(dev); + if (sets == NULL || count == NULL) + return (EINVAL); + if (*count < 2) + return (E2BIG); + + /* Return a list of valid settings for this driver. */ + memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * 2); + + sets[0].freq = sc->maxfreq; sets[0].dev = dev; + sets[1].freq = sc->minfreq; sets[1].dev = dev; + /* Set high latency for CPU frequency changes, it's a tedious process. */ + sets[0].lat = INT_MAX; + sets[1].lat = INT_MAX; + *count = 2; + + return (0); +} + +static int +pmufreq_set(device_t dev, const struct cf_setting *set) +{ + struct pmufreq_softc *sc; + int speed_sel; + int error; + + if (set == NULL) + return (EINVAL); + + sc = device_get_softc(dev); + + if (set->freq == sc->maxfreq) + speed_sel = 0; + else + speed_sel = 1; + + error = pmu_set_speed(speed_sel); + if (error == 0) + sc->curfreq = set->freq; + + return error; +} + +static int +pmufreq_get(device_t dev, struct cf_setting *set) +{ + struct pmufreq_softc *sc; + + if (set == NULL) + return (EINVAL); + sc = device_get_softc(dev); + + set->freq = sc->curfreq; + set->dev = dev; + + return (0); +} + +static int +pmufreq_type(device_t dev, int *type) +{ + + if (type == NULL) + return (EINVAL); + + *type = CPUFREQ_TYPE_ABSOLUTE; + return (0); +} + diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h index bf4db83c7dbb..d684d68d1489 100644 --- a/sys/powerpc/include/cpu.h +++ b/sys/powerpc/include/cpu.h @@ -98,4 +98,6 @@ void cpu_reset(void); void fork_trampoline(void); void swi_vm(void *); +void flush_disable_caches(void); + #endif /* _MACHINE_CPU_H_ */ diff --git a/sys/powerpc/include/dbdma.h b/sys/powerpc/include/dbdma.h index 2095ad3cd73c..22e4b0c72f7f 100644 --- a/sys/powerpc/include/dbdma.h +++ b/sys/powerpc/include/dbdma.h @@ -147,4 +147,7 @@ void dbdma_insert_branch(dbdma_channel_t *chan, int slot, int to_slot); void dbdma_sync_commands(dbdma_channel_t *chan, bus_dmasync_op_t op); +void dbdma_save_state(dbdma_channel_t *chan); +void dbdma_restore_state(dbdma_channel_t *chan); + #endif /* _MACHINE_DBDMA_H_ */ diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index 8a55967e7d4d..79b2d96709fd 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -49,7 +49,8 @@ struct pmap; uint32_t pc_ipimask; \ register_t pc_tempsave[CPUSAVE_LEN]; \ register_t pc_disisave[CPUSAVE_LEN]; \ - register_t pc_dbsave[CPUSAVE_LEN]; + register_t pc_dbsave[CPUSAVE_LEN]; \ + void *pc_restore; #define PCPU_MD_AIM32_FIELDS \ /* char __pad[0] */ diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h index f99b67f06559..f27506991dba 100644 --- a/sys/powerpc/include/spr.h +++ b/sys/powerpc/include/spr.h @@ -519,6 +519,8 @@ #define MSSCR0_EMODE 0x00200000 /* 10: MPX bus mode (read-only) */ #define MSSCR0_ABD 0x00100000 /* 11: address bus driven (read-only) */ #define MSSCR0_MBZ 0x000fffff /* 12-31: must be zero */ +#define MSSCR0_L2PFE 0x00000003 /* 30-31: L2 prefetch enable */ +#define SPR_LDSTCR 0x3f8 /* .6. Load/Store Control Register */ #define SPR_L2PM 0x3f8 /* .6. L2 Private Memory Control Register */ #define SPR_L2CR 0x3f9 /* .6. L2 Control Register */ #define L2CR_L2E 0x80000000 /* 0: L2 enable */ @@ -543,12 +545,14 @@ Setting this bit disables instruction caching. */ #define L2CR_L2I 0x00200000 /* 10: L2 global invalidate. */ +#define L2CR_L2IO_7450 0x00010000 /* 11: L2 instruction-only (MPC745x). */ #define L2CR_L2CTL 0x00100000 /* 11: L2 RAM control (ZZ enable). Enables automatic operation of the L2ZZ (low-power mode) signal. */ #define L2CR_L2WT 0x00080000 /* 12: L2 write-through. */ #define L2CR_L2TS 0x00040000 /* 13: L2 test support. */ #define L2CR_L2OH 0x00030000 /* 14-15: L2 output hold. */ +#define L2CR_L2DO_7450 0x00010000 /* 15: L2 data-only (MPC745x). */ #define L2CR_L2SL 0x00008000 /* 16: L2 DLL slow. */ #define L2CR_L2DF 0x00004000 /* 17: L2 differential clock. */ #define L2CR_L2BYP 0x00002000 /* 18: L2 DLL bypass. */ diff --git a/sys/powerpc/powermac/platform_powermac.c b/sys/powerpc/powermac/platform_powermac.c index 49f3e1a9b2bc..fd6184683fac 100644 --- a/sys/powerpc/powermac/platform_powermac.c +++ b/sys/powerpc/powermac/platform_powermac.c @@ -376,6 +376,110 @@ powermac_smp_start_cpu(platform_t plat, struct pcpu *pc) #endif } +/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */ +void +flush_disable_caches(void) +{ + register_t msr; + register_t msscr0; + register_t cache_reg; + volatile uint32_t *memp; + uint32_t temp; + int i; + int x; + + msr = mfmsr(); + powerpc_sync(); + mtmsr(msr & ~(PSL_EE | PSL_DR)); + msscr0 = mfspr(SPR_MSSCR0); + msscr0 &= ~MSSCR0_L2PFE; + mtspr(SPR_MSSCR0, msscr0); + powerpc_sync(); + isync(); + __asm__ __volatile__("dssall; sync"); + powerpc_sync(); + isync(); + __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); + __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); + __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); + + /* Lock the L1 Data cache. */ + mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF); + powerpc_sync(); + isync(); + + mtspr(SPR_LDSTCR, 0); + + /* + * Perform this in two stages: Flush the cache starting in RAM, then do it + * from ROM. + */ + memp = (volatile uint32_t *)0x00000000; + for (i = 0; i < 128 * 1024; i++) { + temp = *memp; + __asm__ __volatile__("dcbf 0,%0" :: "r"(memp)); + memp += 32/sizeof(*memp); + } + + memp = (volatile uint32_t *)0xfff00000; + x = 0xfe; + + for (; x != 0xff;) { + mtspr(SPR_LDSTCR, x); + for (i = 0; i < 128; i++) { + temp = *memp; + __asm__ __volatile__("dcbf 0,%0" :: "r"(memp)); + memp += 32/sizeof(*memp); + } + x = ((x << 1) | 1) & 0xff; + } + mtspr(SPR_LDSTCR, 0); + + cache_reg = mfspr(SPR_L2CR); + if (cache_reg & L2CR_L2E) { + cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450); + mtspr(SPR_L2CR, cache_reg); + powerpc_sync(); + mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF); + while (mfspr(SPR_L2CR) & L2CR_L2HWF) + ; /* Busy wait for cache to flush */ + powerpc_sync(); + cache_reg &= ~L2CR_L2E; + mtspr(SPR_L2CR, cache_reg); + powerpc_sync(); + mtspr(SPR_L2CR, cache_reg | L2CR_L2I); + powerpc_sync(); + while (mfspr(SPR_L2CR) & L2CR_L2I) + ; /* Busy wait for L2 cache invalidate */ + powerpc_sync(); + } + + cache_reg = mfspr(SPR_L3CR); + if (cache_reg & L3CR_L3E) { + cache_reg &= ~(L3CR_L3IO | L3CR_L3DO); + mtspr(SPR_L3CR, cache_reg); + powerpc_sync(); + mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF); + while (mfspr(SPR_L3CR) & L3CR_L3HWF) + ; /* Busy wait for cache to flush */ + powerpc_sync(); + cache_reg &= ~L3CR_L3E; + mtspr(SPR_L3CR, cache_reg); + powerpc_sync(); + mtspr(SPR_L3CR, cache_reg | L3CR_L3I); + powerpc_sync(); + while (mfspr(SPR_L3CR) & L3CR_L3I) + ; /* Busy wait for L3 cache invalidate */ + powerpc_sync(); + } + + mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE); + powerpc_sync(); + isync(); + + mtmsr(msr); +} + static void powermac_reset(platform_t platform) { diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c index 97770047f5fc..ca979d8c9238 100644 --- a/sys/powerpc/powermac/pmu.c +++ b/sys/powerpc/powermac/pmu.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -43,11 +44,18 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include /* For save_vec() */ #include +#include +#include /* For save_fpu() */ +#include #include #include +#include #include #include +#include #include #include @@ -59,6 +67,11 @@ __FBSDID("$FreeBSD$"); #include "clock_if.h" #include "pmuvar.h" #include "viareg.h" +#include "uninorthvar.h" /* For unin_chip_sleep()/unin_chip_wake() */ + +#define PMU_DEFAULTS PMU_INT_TICK | PMU_INT_ADB | \ + PMU_INT_PCEJECT | PMU_INT_SNDBRT | \ + PMU_INT_BATTERY | PMU_INT_ENVIRONMENT /* * Bus interface @@ -93,6 +106,7 @@ static int pmu_acline_state(SYSCTL_HANDLER_ARGS); static int pmu_query_battery(struct pmu_softc *sc, int batt, struct pmu_battstate *info); static int pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS); +static void pmu_sleep_int(void); /* * List of battery-related sysctls we might ask for @@ -115,8 +129,6 @@ static device_method_t pmu_methods[] = { DEVMETHOD(device_attach, pmu_attach), DEVMETHOD(device_detach, pmu_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), /* ADB bus interface */ DEVMETHOD(adb_hb_send_raw_packet, pmu_adb_send), @@ -193,7 +205,7 @@ static signed char pm_send_cmd_type[] = { 0x02, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1, -1, 0x01, 0x01, 0x01, -1, -1, -1, -1, -1, - 0x00, 0x00, -1, -1, -1, -1, 0x04, 0x04, + 0x00, 0x00, -1, -1, -1, 0x05, 0x04, 0x04, 0x04, -1, 0x00, -1, -1, -1, -1, -1, 0x00, -1, -1, -1, -1, -1, -1, -1, 0x01, 0x02, -1, -1, -1, -1, -1, -1, @@ -229,7 +241,7 @@ static signed char pm_receive_cmd_type[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x03, 0x09, -1, -1, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - -1, -1, -1, -1, -1, -1, 0x01, 0x01, + -1, -1, -1, -1, -1, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -357,12 +369,13 @@ pmu_attach(device_t dev) /* Init PMU */ - reg = PMU_INT_TICK | PMU_INT_ADB | PMU_INT_PCEJECT | PMU_INT_SNDBRT; - reg |= PMU_INT_BATTERY; - reg |= PMU_INT_ENVIRONMENT; + pmu_write_reg(sc, vBufB, pmu_read_reg(sc, vBufB) | vPB4); + pmu_write_reg(sc, vDirB, (pmu_read_reg(sc, vDirB) | vPB4) & ~vPB3); + + reg = PMU_DEFAULTS; pmu_send(sc, PMU_SET_IMASK, 1, ®, 16, resp); - pmu_write_reg(sc, vIER, 0x90); /* make sure VIA interrupts are on */ + pmu_write_reg(sc, vIER, 0x94); /* make sure VIA interrupts are on */ pmu_send(sc, PMU_SYSTEM_READY, 1, cmd, 16, resp); pmu_send(sc, PMU_GET_VERSION, 1, cmd, 16, resp); @@ -1018,3 +1031,95 @@ pmu_settime(device_t dev, struct timespec *ts) return (0); } +static register_t sprgs[4]; +static register_t srrs[2]; +extern void *ap_pcpu; + +void pmu_sleep_int(void) +{ + static u_quad_t timebase = 0; + jmp_buf resetjb; + struct thread *fputd; + struct thread *vectd; + register_t hid0; + register_t msr; + register_t saved_msr; + + ap_pcpu = pcpup; + + PCPU_SET(restore, &resetjb); + + *(unsigned long *)0x80 = 0x100; + saved_msr = mfmsr(); + fputd = PCPU_GET(fputhread); + vectd = PCPU_GET(vecthread); + if (fputd != NULL) + save_fpu(fputd); + if (vectd != NULL) + save_vec(vectd); + if (setjmp(resetjb) == 0) { + sprgs[0] = mfspr(SPR_SPRG0); + sprgs[1] = mfspr(SPR_SPRG1); + sprgs[2] = mfspr(SPR_SPRG2); + sprgs[3] = mfspr(SPR_SPRG3); + srrs[0] = mfspr(SPR_SRR0); + srrs[1] = mfspr(SPR_SRR1); + timebase = mftb(); + powerpc_sync(); + flush_disable_caches(); + hid0 = mfspr(SPR_HID0); + hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP; + powerpc_sync(); + isync(); + msr = mfmsr() | PSL_POW; + mtspr(SPR_HID0, hid0); + powerpc_sync(); + + while (1) + mtmsr(msr); + } + mttb(timebase); + PCPU_SET(curthread, curthread); + PCPU_SET(curpcb, curthread->td_pcb); + pmap_activate(curthread); + powerpc_sync(); + mtspr(SPR_SPRG0, sprgs[0]); + mtspr(SPR_SPRG1, sprgs[1]); + mtspr(SPR_SPRG2, sprgs[2]); + mtspr(SPR_SPRG3, sprgs[3]); + mtspr(SPR_SRR0, srrs[0]); + mtspr(SPR_SRR1, srrs[1]); + mtmsr(saved_msr); + if (fputd == curthread) + enable_fpu(curthread); + if (vectd == curthread) + enable_vec(curthread); + powerpc_sync(); +} + +int +pmu_set_speed(int low_speed) +{ + struct pmu_softc *sc; + uint8_t sleepcmd[] = {'W', 'O', 'O', 'F', 0}; + uint8_t resp[16]; + + sc = device_get_softc(pmu); + pmu_write_reg(sc, vIER, 0x10); + spinlock_enter(); + mtdec(0x7fffffff); + mb(); + mtdec(0x7fffffff); + + sleepcmd[4] = low_speed; + pmu_send(sc, PMU_CPU_SPEED, 5, sleepcmd, 16, resp); + unin_chip_sleep(NULL, 1); + pmu_sleep_int(); + unin_chip_wake(NULL); + + mtdec(1); /* Force a decrementer exception */ + spinlock_exit(); + pmu_write_reg(sc, vIER, 0x90); + + return (0); +} diff --git a/sys/powerpc/powermac/pmuvar.h b/sys/powerpc/powermac/pmuvar.h index 25a85c7d77e8..98209f8912e2 100644 --- a/sys/powerpc/powermac/pmuvar.h +++ b/sys/powerpc/powermac/pmuvar.h @@ -160,7 +160,8 @@ struct pmu_softc { volatile int sc_autopoll; int sc_batteries; struct cdev *sc_leddev; - int lid_closed; + int lid_closed; + uint8_t saved_regs[9]; }; struct pmu_battstate { @@ -172,4 +173,6 @@ struct pmu_battstate { int voltage; }; +int pmu_set_speed(int low_speed); + #endif /* PMUVAR_H */ diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c index 748148e78067..ab051a5c7b3a 100644 --- a/sys/powerpc/powermac/uninorth.c +++ b/sys/powerpc/powermac/uninorth.c @@ -136,6 +136,13 @@ static driver_t unin_chip_driver = { static devclass_t unin_chip_devclass; +/* + * Assume there is only one unin chip in a PowerMac, so that pmu.c functions can + * suspend the chip after the whole rest of the device tree is suspended, not + * earlier. + */ +static device_t unin_chip; + DRIVER_MODULE(unin, nexus, unin_chip_driver, unin_chip_devclass, 0, 0); /* @@ -210,31 +217,30 @@ unin_chip_add_reg(phandle_t devnode, struct unin_chip_devinfo *dinfo) } static void -unin_enable_gmac(device_t dev) +unin_update_reg(device_t dev, uint32_t regoff, uint32_t set, uint32_t clr) { - volatile u_int *clkreg; + volatile u_int *reg; struct unin_chip_softc *sc; u_int32_t tmpl; sc = device_get_softc(dev); - clkreg = (void *)(sc->sc_addr + UNIN_CLOCKCNTL); - tmpl = inl(clkreg); - tmpl |= UNIN_CLOCKCNTL_GMAC; - outl(clkreg, tmpl); + reg = (void *)(sc->sc_addr + regoff); + tmpl = inl(reg); + tmpl &= ~clr; + tmpl |= set; + outl(reg, tmpl); +} + +static void +unin_enable_gmac(device_t dev) +{ + unin_update_reg(dev, UNIN_CLOCKCNTL, UNIN_CLOCKCNTL_GMAC, 0); } static void unin_enable_mpic(device_t dev) { - volatile u_int *toggle; - struct unin_chip_softc *sc; - u_int32_t tmpl; - - sc = device_get_softc(dev); - toggle = (void *)(sc->sc_addr + UNIN_TOGGLE_REG); - tmpl = inl(toggle); - tmpl |= UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE; - outl(toggle, tmpl); + unin_update_reg(dev, UNIN_TOGGLE_REG, UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE, 0); } static int @@ -311,6 +317,9 @@ unin_chip_attach(device_t dev) return (error); } + if (unin_chip == NULL) + unin_chip = dev; + /* * Iterate through the sub-devices */ @@ -631,3 +640,33 @@ unin_chip_get_devinfo(device_t dev, device_t child) return (&dinfo->udi_obdinfo); } +int +unin_chip_wake(device_t dev) +{ + + if (dev == NULL) + dev = unin_chip; + unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_NORMAL, UNIN_PWR_MASK); + DELAY(10); + unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_RUNNING, 0); + DELAY(100); + + return (0); +} + +int +unin_chip_sleep(device_t dev, int idle) +{ + if (dev == NULL) + dev = unin_chip; + + unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_SLEEPING, 0); + DELAY(10); + if (idle) + unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_IDLE2, UNIN_PWR_MASK); + else + unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_SLEEP, UNIN_PWR_MASK); + DELAY(10); + + return (0); +} diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h index aa834f6a1e8e..e08478d7580b 100644 --- a/sys/powerpc/powermac/uninorthvar.h +++ b/sys/powerpc/powermac/uninorthvar.h @@ -28,6 +28,8 @@ #ifndef _POWERPC_POWERMAC_UNINORTHVAR_H_ #define _POWERPC_POWERMAC_UNINORTHVAR_H_ +#include +#include #include struct uninorth_softc { @@ -75,6 +77,24 @@ struct unin_chip_devinfo { #define UNIN_CLOCKCNTL 0x20 #define UNIN_CLOCKCNTL_GMAC 0x2 +/* + * Power management register + */ +#define UNIN_PWR_MGMT 0x30 +#define UNIN_PWR_NORMAL 0x00 +#define UNIN_PWR_IDLE2 0x01 +#define UNIN_PWR_SLEEP 0x02 +#define UNIN_PWR_SAVE 0x03 +#define UNIN_PWR_MASK 0x03 + +/* + * Hardware initialization state register + */ +#define UNIN_HWINIT_STATE 0x70 +#define UNIN_SLEEPING 0x01 +#define UNIN_RUNNING 0x02 + + /* * Toggle registers */ @@ -82,4 +102,6 @@ struct unin_chip_devinfo { #define UNIN_MPIC_RESET 0x2 #define UNIN_MPIC_OUTPUT_ENABLE 0x4 +extern int unin_chip_sleep(device_t dev, int idle); +extern int unin_chip_wake(device_t dev); #endif /* _POWERPC_POWERMAC_UNINORTHVAR_H_ */ diff --git a/sys/powerpc/powermac/viareg.h b/sys/powerpc/powermac/viareg.h index 85739cd14775..2f519b2a777f 100644 --- a/sys/powerpc/powermac/viareg.h +++ b/sys/powerpc/powermac/viareg.h @@ -30,14 +30,16 @@ /* VIA interface registers */ #define vBufB 0x0000 /* register B */ -#define vBufA 0x0200 /* register A */ #define vDirB 0x0400 /* data direction register */ #define vDirA 0x0600 /* data direction register */ +#define vT1C 0x0800 /* Timer 1 counter Lo */ +#define vT1CH 0x0a00 /* Timer 1 counter Hi */ #define vSR 0x1400 /* shift register */ #define vACR 0x1600 /* aux control register */ #define vPCR 0x1800 /* peripheral control register */ #define vIFR 0x1a00 /* interrupt flag register */ #define vIER 0x1c00 /* interrupt enable register */ +#define vBufA 0x1e00 /* register A */ #define vPB 0x0000 #define vPB3 0x08 diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 6835d0c84add..28d9a081397f 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "pic_if.h" @@ -66,10 +67,21 @@ volatile static u_quad_t ap_timebase; static u_int ipi_msg_cnt[32]; static struct mtx ap_boot_mtx; struct pcb stoppcbs[MAXCPU]; +int longfault(faultbuf, int); void machdep_ap_bootstrap(void) { + jmp_buf *restore; + + /* The following is needed for restoring from sleep. */ +#ifdef __powerpc64__ + /* Writing to the time base register is hypervisor-privileged */ + if (mfmsr() & PSL_HV) + mttb(0); +#else + mttb(0); +#endif /* Set up important bits on the CPU (HID registers, etc.) */ cpudep_ap_setup(); @@ -78,6 +90,11 @@ machdep_ap_bootstrap(void) PCPU_SET(awake, 1); __asm __volatile("msync; isync"); + restore = PCPU_GET(restore); + if (restore != NULL) { + longjmp(*restore, 1); + } + while (ap_letgo == 0) ; From 0782240958117692ab9861abb5483c9e64f6bc39 Mon Sep 17 00:00:00 2001 From: Benjamin Kaduk Date: Fri, 13 Dec 2013 03:09:29 +0000 Subject: [PATCH 037/172] Apply patch from upstream Heimdal for encoding fix RFC 4402 specifies the implementation of the gss_pseudo_random() function for the krb5 mechanism (and the C bindings therein). The implementation uses a PRF+ function that concatenates the output of individual krb5 pseudo-random operations produced with a counter and seed. The original implementation of this function in Heimdal incorrectly encoded the counter as a little-endian integer, but the RFC specifies the counter encoding as big-endian. The implementation initializes the counter to zero, so the first block of output (16 octets, for the modern AES enctypes 17 and 18) is unchanged. (RFC 4402 specifies that the counter should begin at 1, but both existing implementations begin with zero and it looks like the standard will be re-issued, with test vectors, to begin at zero.) This is upstream's commit f85652af868e64811f2b32b815d4198e7f9017f6, from 13 October, 2013: % Fix krb5's gss_pseudo_random() (n is big-endian) % % The first enctype RFC3961 prf output length's bytes are correct because % the little- and big-endian representations of unsigned zero are the % same. The second block of output was wrong because the counter was not % being encoded as big-endian. % % This change could break applications. But those applications would not % have been interoperating with other implementations anyways (in % particular: MIT's). Approved by: hrs (mentor, src committer) MFC after: 3 days --- crypto/heimdal/lib/gssapi/krb5/prf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/heimdal/lib/gssapi/krb5/prf.c b/crypto/heimdal/lib/gssapi/krb5/prf.c index 162a3097099f..671ab2c6d982 100644 --- a/crypto/heimdal/lib/gssapi/krb5/prf.c +++ b/crypto/heimdal/lib/gssapi/krb5/prf.c @@ -119,7 +119,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status, while(dol > 0) { size_t tsize; - _gsskrb5_encode_om_uint32(num, input.data); + _gsskrb5_encode_be_om_uint32(num, input.data); ret = krb5_crypto_prf(context, crypto, &input, &output); if (ret) { @@ -133,7 +133,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status, tsize = min(dol, output.length); memcpy(p, output.data, tsize); - p += output.length; + p += tsize; dol -= tsize; krb5_data_free(&output); num++; From 10b31d0b541232a29582b20af135557d2c62604c Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Fri, 13 Dec 2013 05:54:25 +0000 Subject: [PATCH 038/172] Some style(9) fixes MFC after: 1 month X-MFC with: r259284 --- sys/powerpc/cpufreq/pmufreq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/powerpc/cpufreq/pmufreq.c b/sys/powerpc/cpufreq/pmufreq.c index d22ff0b6a675..2fbeef3b1ccf 100644 --- a/sys/powerpc/cpufreq/pmufreq.c +++ b/sys/powerpc/cpufreq/pmufreq.c @@ -106,9 +106,9 @@ pmufreq_identify(driver_t *driver, device_t parent) static int pmufreq_probe(device_t dev) { - uint32_t min_freq; struct pmufreq_softc *sc; phandle_t node; + uint32_t min_freq; if (resource_disabled("pmufreq", 0)) return (ENXIO); @@ -174,8 +174,7 @@ static int pmufreq_set(device_t dev, const struct cf_setting *set) { struct pmufreq_softc *sc; - int speed_sel; - int error; + int error, speed_sel; if (set == NULL) return (EINVAL); @@ -191,7 +190,7 @@ pmufreq_set(device_t dev, const struct cf_setting *set) if (error == 0) sc->curfreq = set->freq; - return error; + return (error); } static int From b13e60da569243e8c7a37edbe7600798e9a1f701 Mon Sep 17 00:00:00 2001 From: Peter Grehan Date: Fri, 13 Dec 2013 08:31:13 +0000 Subject: [PATCH 039/172] bhyve(8) man page. mdoc formatting and much input and review from Warren Block (wblock@). Reviewed by: many MFC after: 3 days --- usr.sbin/bhyve/Makefile | 3 +- usr.sbin/bhyve/bhyve.8 | 299 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 usr.sbin/bhyve/bhyve.8 diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index a08341f9d8c8..7f2973c4cacc 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -6,6 +6,7 @@ PROG= bhyve DEBUG_FLAGS= -g -O0 +MAN= bhyve.8 SRCS= acpi.c atpic.c bhyverun.c block_if.c consport.c dbgport.c elcr.c SRCS+= inout.c legacy_irq.c mem.c mevent.c mptbl.c pci_ahci.c SRCS+= pci_emul.c pci_hostbridge.c pci_lpc.c pci_passthru.c pci_virtio_block.c @@ -15,8 +16,6 @@ SRCS+= uart_emul.c virtio.c xmsr.c spinup_ap.c .PATH: ${.CURDIR}/../../sys/amd64/vmm SRCS+= vmm_instruction_emul.c -NO_MAN= - DPADD= ${LIBVMMAPI} ${LIBMD} ${LIBUTIL} ${LIBPTHREAD} LDADD= -lvmmapi -lmd -lutil -lpthread diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 new file mode 100644 index 000000000000..50403ef93414 --- /dev/null +++ b/usr.sbin/bhyve/bhyve.8 @@ -0,0 +1,299 @@ +.\" Copyright (c) 2013 Peter Grehan +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 12, 2013 +.Dt BHYVE 8 +.Os +.Sh NAME +.Nm bhyve +.Nd "run a guest operating system inside a virtual machine" +.Sh SYNOPSIS +.Nm +.Op Fl aehAHPW +.Op Fl c Ar numcpus +.Op Fl g Ar gdbport +.Op Fl p Ar pinnedcpu +.Op Fl s Ar slot,emulation Ns Op , Ns Ar conf +.Op Fl S Ar slot,emulation Ns Op , Ns Ar conf +.Op Fl l Ar lpcdev Ns Op , Ns Ar conf +.Ar vmname +.Sh DESCRIPTION +.Nm +is an experimental hypervisor that runs guest operating systems inside a +virtual machine. +.Pp +Parameters such as the number of virtual CPUs, amount of guest memory, and +I/O connectivity can be specified with command-line parameters. +.Pp +The guest operating system must be loaded with +.Xr bhyveload 4 +or a similar boot loader before running +.Nm . +.Pp +.Nm +runs until the guest operating system reboots or an unhandled hypervisor +exit is detected. +.Sh OPTIONS +.Bl -tag -width 10n +.It Fl a +Disallow use of the local APIC in X2APIC mode. +.It Fl A +Generate ACPI tables. +Required for +.Fx Ns /amd64 +guests. +.It Fl c Ar numcpus +Number of guest virtual CPUs. +The default is 1 and the maximum is 16. +.It Fl H +Yield the virtual CPU thread when a HLT instruction is detected. +If this option is not specified, virtual CPUs will use 100% of a host CPU. +.It Fl g Ar gdbport +For +.Fx Ns /amd64 kernels compiled with +.Cd "option bvmdebug" , +allow a remote kernel kgdb to be relayed to the guest kernel gdb stub +via a local IPv4 address and this port. +This option will be deprecated in a future version. +.It Fl p Ar pinnedcpu +Force guest virtual CPUs to be pinned to host CPUs. +Virtual CPU +.Em n +is pinned to host CPU +.Em pinnedcpu+n . +.It Fl P +Force the guest virtual CPU to exit when a PAUSE instruction is detected. +.It Fl W +Force virtio PCI device emulations to use MSI interrupts instead of MSI-X +interrupts. +.It Fl s Ar slot,emulation Ns Op , Ns Ar conf +Configure a virtual PCI slot and function. +.Pp +.Nm bhyve +provides PCI bus emulation and virtual devices that can be attached to +slots on the bus. +There are 32 available slots, with the option of providing up to 8 functions +per slot. +.Bl -tag -width 10n +.It Ar slot +.Ar pcislot Ns Op Ar :function +.Pp +The +.Ar pcislot +value is 0 to 31 and the optional function value is 0 to 7. +If not specified, the function value defaults to 0. +.It Ar emulation +.Bl -tag -width 10n +.It Li hostbridge | Li amd_hostbridge +.Pp +Provide a simple host bridge. +This is usually configured at slot 0, and is required by most guest +operating systems. +The +.Li amd_hostbridge +emulation is identical but uses a PCI vendor ID of +.Li AMD . +.It Li passthru +PCI pass-through device. +.It Li virtio-net +Virtio network interface. +.It Li virtio-block +Virtio block storage interface. +.It Li ahci-cd +AHCI controller attached to an ATAPI CD/DVD. +.It Li ahci-hd +AHCI controller attached to a SATA hard-drive. +.It Li uart +PCI 16550 serial device. +.It Li lpc +LPC PCI-ISA bridge with COM1 and COM2 16550 serial ports. +.El +.It Op Ar conf +This optional parameter describes the backend for device emulations. +If +.Ar conf +is not specified, the device emulation has no backend and can be +considered unconnected. +.Pp +Network devices: +.Bl -tag -width 10n +.It Ar tapN Ns Op , Ns Ar mac=xx:xx:xx:xx:xx:xx +.It Ar vmnetN Ns Op , Ns Ar mac=xx:xx:xx:xx:xx:xx +.Pp +If +.Ar mac +is not specified, the MAC address is derived from a fixed OUI and the +remaining bytes from an MD5 hash of the slot and function numbers and +the device name. +.Pp +The MAC address is an ASCII string in +.Xr ethers 5 +format. +.El +.Pp +Block storage devices: +.Bl -tag -width 10n +.It Pa /filename Ns Oo , Ns Li nocache Oc Ns Oo , Ns Li direct Oc Ns Oo , Ns Li ro Oc +.It Pa /dev/xxx Ns Oo , Ns Ar nocache Oc Ns Oo , Ns Ar direct Oc Ns Oo , Ns Ar ro Oc +.Bl -tag -width 8n +.It Li nocache +Open the file with +.Dv O_DIRECT . +.It Li direct +Open the file using +.Dv O_SYNC . +.It Li ro +Force the file to be opened read-only. +.El +.Pp +The +.Li nocache , +.Li direct , +and +.Li ro +options are not available for virtio block devices. +.El +.Pp +TTY devices: +.Bl -tag -width 10n +.It Li stdio +Connect the serial port to the standard input and output of +the bhyve process. +.It Pa /dev/xxx +Use the host TTY device for serial port I/O. +.El +.Pp +Pass-through devices: +.Bl -tag -width 10n +.It Ns Ar slot Ns / Ns Ar bus Ns / Ns Ar function +Connect to a PCI device on the host at the selector described by +.Ar slot , +.Ar bus , +and +.Ar function +numbers. +.El +.Pp +The host device must have been reserved at boot-time using the +.Va pptdev +loader variable as described in +.Xr vmm 4 . +.El +.It Fl S Ar slot , Ns Ar emulation Ns Op , Ns Ar conf +Identical to the -s option except the device is instructed to use legacy +ISA addresses if possible. +Currently this only has an effect with the +.Li uart +device emulation. +This option will be deprecated in a future version. +.It Fl l Ar lpcdev Ns Op , Ns Ar conf +Allow devices behind the LPC PCI-ISA bridge to be configured. +The only supported devices are the TTY-class devices, +.Li com1 +and +.Li com2 . +.It Fl m Ar size Ns Op Ar K|k|M|m|G|g|T|t +Guest physical memory size in bytes. +This must be the same size that was given to +.Xr bhyveload 8 . +.Pp +The size argument may be suffixed with one of K, M, G or T (either upper +or lower case) to indicate a multiple of kilobytes, megabytes, gigabytes, +or terabytes. +If no suffix is given, the value is assumed to be in megabytes. +.It Fl e +Force +.Nm +to exit when a guest issues an access to an I/O port that is not emulated. +This is intended for debug purposes. +.It Fl h +Print help message and exit. +.It Ar vmname +Alphanumeric name of the guest. +This should be the same as that created by +.Xr bhyveload 8 . +.El +.Sh EXAMPLES +The guest operating system must have been loaded with +.Xr bhyveload 4 +or a similar boot loader before +.Xr bhyve 4 +can be run. +.Pp +To run a virtual machine with 1GB of memory, two virtual CPUs, a virtio +block device backed by the +.Pa /my/image +filesystem image, and a serial port for the console: +.Bd -literal -offset indent +bhyve -c 2 -s 0,hostbridge -s 1,lpc -s 2,virtio-blk,/my/image \\ + -l com1,stdio -A -H -P -m 1G vm1 +.Ed +.Pp +Run a 24GB single-CPU virtual machine with three network ports, one of which +has a MAC address specified: +.Bd -literal -offset indent +bhyve -s 0,hostbridge -s 1,lpc -s 2:0,virtio-net,tap0 \\ + -s 2:1,virtio-net,tap1 \\ + -s 2:2,virtio-net,tap2,mac=00:be:fa:76:45:00 \\ + -s 3,virtio-blk,/my/image -l com1,stdio \\ + -A -H -P -m 24G bigvm +.Ed +.Pp +Run an 8GB quad-CPU virtual machine with 8 AHCI SATA disks, an AHCI ATAPI +CD-ROM, a single virtio network port, an AMD hostbridge, and the console +port connected to an +.Xr nmdm 4 +null-model device. +.Bd -literal -offset indent +bhyve -c 4 \e\ + -s 0,amd_hostbridge -s 1,lpc \\ + -s 1:0,ahci-hd,/images/disk.1 \\ + -s 1:1,ahci-hd,/images/disk.2 \\ + -s 1:2,ahci-hd,/images/disk.3 \\ + -s 1:3,ahci-hd,/images/disk.4 \\ + -s 1:4,ahci-hd,/images/disk.5 \\ + -s 1:5,ahci-hd,/images/disk.6 \\ + -s 1:6,ahci-hd,/images/disk.7 \\ + -s 1:7,ahci-hd,/images/disk.8 \\ + -s 2,ahci-cd,/images.install.iso \\ + -s 3,virtio-net,tap0 \\ + -l com1,/dev/nmdm0A \\ + -A -H -P -m 8G +.Ed +.Sh SEE ALSO +.Xr bhyve 4 , +.Xr nmdm 4 , +.Xr vmm 4 , +.Xr ethers 5 , +.Xr bhyveload 8 , +.Xr bhyvectl 8 +.Sh HISTORY +.Nm +first appeared in +.Fx 10.0 . +.Sh AUTHORS +.An Neel Natu Aq neel@freebsd.org +.An Peter Grehan Aq grehan@freebsd.org From 3318a9c895596306e80fc28a559ed4e96c0b4d61 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 13 Dec 2013 20:53:31 +0000 Subject: [PATCH 040/172] rlimit: add and utilize lim_shared MFC after: 2 weeks --- sys/kern/kern_resource.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 470eaedd52d7..72b90e3a69b6 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -80,6 +80,8 @@ static int donice(struct thread *td, struct proc *chgp, int n); static struct uidinfo *uilookup(uid_t uid); static void ruxagg_locked(struct rusage_ext *rux, struct thread *td); +static __inline int lim_shared(struct plimit *limp); + /* * Resource controls and accounting. */ @@ -1129,6 +1131,14 @@ lim_hold(limp) return (limp); } +static __inline int +lim_shared(limp) + struct plimit *limp; +{ + + return (limp->pl_refcnt > 1); +} + void lim_fork(struct proc *p1, struct proc *p2) { @@ -1162,7 +1172,7 @@ lim_copy(dst, src) struct plimit *dst, *src; { - KASSERT(dst->pl_refcnt == 1, ("lim_copy to shared limit")); + KASSERT(!lim_shared(dst), ("lim_copy to shared limit")); bcopy(src->pl_rlimit, dst->pl_rlimit, sizeof(src->pl_rlimit)); } From c2a48c0d1b948197f238ec893266f4facaabf616 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 13 Dec 2013 20:54:45 +0000 Subject: [PATCH 041/172] rlimit: avoid unnecessary copying of rlimits If refcount is 1 just modify rlimits in place. MFC after: 2 weeks --- sys/kern/kern_resource.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 72b90e3a69b6..f4914fa3364d 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -679,21 +679,29 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, limp->rlim_max = RLIM_INFINITY; oldssiz.rlim_cur = 0; - newlim = lim_alloc(); + newlim = NULL; PROC_LOCK(p); + if (lim_shared(p->p_limit)) { + PROC_UNLOCK(p); + newlim = lim_alloc(); + PROC_LOCK(p); + } oldlim = p->p_limit; alimp = &oldlim->pl_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) if ((error = priv_check(td, PRIV_PROC_SETRLIMIT))) { PROC_UNLOCK(p); - lim_free(newlim); + if (newlim != NULL) + lim_free(newlim); return (error); } if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; - lim_copy(newlim, oldlim); - alimp = &newlim->pl_rlimit[which]; + if (newlim != NULL) { + lim_copy(newlim, oldlim); + alimp = &newlim->pl_rlimit[which]; + } switch (which) { @@ -743,9 +751,11 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, if (p->p_sysent->sv_fixlimit != NULL) p->p_sysent->sv_fixlimit(limp, which); *alimp = *limp; - p->p_limit = newlim; + if (newlim != NULL) + p->p_limit = newlim; PROC_UNLOCK(p); - lim_free(oldlim); + if (newlim != NULL) + lim_free(oldlim); if (which == RLIMIT_STACK) { /* From b026eddfeac766240ce0a06e3ec8a741d57c8bb8 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 13 Dec 2013 21:49:41 +0000 Subject: [PATCH 042/172] sbin/devd/devd.cc Increase the size of devd's client socket's send buffer from the default (8k) to 128k. This prevents clients from getting POLLHUPped during event storms. For example, during zpool creation, the kernel emits a resource.fs.zfs.statechange event for every vdev in the pool. A 128k buffer is large enough to hold the statechange events for a pool with nearly 800 drives. Reviewed by: ian, imp Approved by: ken (mentor) Sponsored by: Spectra Logic Corp MFC after: 4 weeks --- sbin/devd/devd.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 21816e59c587..b64c459a5791 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -104,6 +104,19 @@ __FBSDID("$FreeBSD$"); #define CF "/etc/devd.conf" #define SYSCTL "hw.bus.devctl_disable" +/* + * Since the client socket is nonblocking, we must increase its send buffer to + * handle brief event storms. On FreeBSD, AF_UNIX sockets don't have a receive + * buffer, so the client can't increate the buffersize by itself. + * + * For example, when creating a ZFS pool, devd emits one 165 character + * resource.fs.zfs.statechange message for each vdev in the pool. A 64k + * buffer has enough space for almost 400 drives, which would be very large but + * not impossibly large pool. A 128k buffer has enough space for 794 drives, + * which is more than can fit in a rack with modern technology. + */ +#define CLIENT_BUFSIZE 131072 + using namespace std; extern FILE *yyin; @@ -892,6 +905,7 @@ void new_client(int fd) { int s; + int sndbuf_size; /* * First go reap any zombie clients, then accept the connection, and @@ -901,10 +915,15 @@ new_client(int fd) check_clients(); s = accept(fd, NULL, NULL); if (s != -1) { + sndbuf_size = CLIENT_BUFSIZE; + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, + sizeof(sndbuf_size))) + err(1, "setsockopt"); shutdown(s, SHUT_RD); clients.push_back(s); ++num_clients; - } + } else + err(1, "accept"); } static void From 0603b75a7afa58e162c0055fd4992c9bb8ffff6c Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Fri, 13 Dec 2013 21:50:03 +0000 Subject: [PATCH 043/172] getopt_long.3: wording quibbles - Make wording more clear: "is expect" vs "is expected" [1] - Remove extraneous trailing period.. Reported by: dim [1] --- lib/libc/stdlib/getopt_long.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libc/stdlib/getopt_long.3 b/lib/libc/stdlib/getopt_long.3 index 06eadca957da..69047162c556 100644 --- a/lib/libc/stdlib/getopt_long.3 +++ b/lib/libc/stdlib/getopt_long.3 @@ -130,11 +130,11 @@ field should be one of: .Pp .Bl -tag -width ".Dv optional_argument" -offset indent -compact .It Dv no_argument -no argument to the option is expect +no argument to the option is expected .It Dv required_argument an argument to the option is required .It Dv optional_argument -an argument to the option may be presented. +an argument to the option may be presented .El .Pp If From f0038a8e9853c03fad761ea66a6f3f10557faa19 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 13 Dec 2013 22:58:57 +0000 Subject: [PATCH 044/172] sbin/devd/devd.cc Promoting the SIGINFO handler's log message from LOG_INFO to LOG_NOTICE, and promoting the "Processing event ..." message from LOG_DEBUG to LOG_INFO. Setting the logfile to LOG_NOTICE with this change will have the same result as setting it to LOG_INFO without this change. Setting it to LOG_INFO with this change will include the useful "Processing event ..." messages that were previously at LOG_DEBUG, without including useless messages like "Pushing table". The intent of this change is that one can log "Processing event ..." without logging "Pushing table" and related messages that are sent for every event. The number of lines actually logged is reduced by about 75% by making this change and setting syslog to LOG_INFO vs setting syslog to LOG_DEBUG. etc/syslog.conf Changing the recommended loglevel to notice instead of info. Sponsored by: Spectra Logic Corp MFC after: 4 weeks --- etc/syslog.conf | 2 +- sbin/devd/devd.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/etc/syslog.conf b/etc/syslog.conf index 702bd664215d..e65db5347bc5 100644 --- a/etc/syslog.conf +++ b/etc/syslog.conf @@ -30,7 +30,7 @@ cron.* /var/log/cron # news.notice /var/log/news/news.notice # Uncomment this if you wish to see messages produced by devd # !devd -# *.>=info /var/log/devd.log +# *.>=notice /var/log/devd.log !ppp *.* /var/log/ppp.log !* diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index b64c459a5791..2bb14f11c683 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -772,7 +772,7 @@ process_event(char *buffer) char *sp; sp = buffer + 1; - devdlog(LOG_DEBUG, "Processing event '%s'\n", buffer); + devdlog(LOG_INFO, "Processing event '%s'\n", buffer); type = *buffer++; cfg.push_var_table(); // No match doesn't have a device, and the format is a little @@ -989,7 +989,7 @@ event_loop(void) } rv = select(max_fd, &fds, NULL, NULL, &tv); if (got_siginfo) { - devdlog(LOG_INFO, "Events received so far=%u\n", + devdlog(LOG_NOTICE, "Events received so far=%u\n", total_events); got_siginfo = 0; } From 93e9cae3fa2d3167f51a53ae48d92778a446944f Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Sat, 14 Dec 2013 03:08:03 +0000 Subject: [PATCH 045/172] Read card capabilities after firmware initialization, instead of setting them up as part of firmware initialization (which the driver gets to do only if it's the master driver). Read the range of tids available for the ETHOFLD functionality if it's enabled. New is_ftid() and is_etid() functions to test whether a tid falls within the range of filter tids or ETHOFLD tids respectively. MFC after: 2 weeks --- sys/dev/cxgbe/common/common.h | 25 +++++++++++++-- sys/dev/cxgbe/offload.h | 5 +++ sys/dev/cxgbe/t4_main.c | 58 +++++++++++++++++++++++++++++------ sys/dev/cxgbe/t4_sge.c | 1 - sys/dev/cxgbe/tom/t4_cpl_io.c | 9 +++--- 5 files changed, 80 insertions(+), 18 deletions(-) diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index efda04d5b897..e3883db471ff 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -267,8 +267,10 @@ struct adapter_params { unsigned short a_wnd[NCCTRL_WIN]; unsigned short b_wnd[NCCTRL_WIN]; - unsigned int mc_size; /* MC memory size */ - unsigned int nfilters; /* size of filter region */ + u_int ftid_min; + u_int ftid_max; + u_int etid_min; + u_int netids; unsigned int cim_la_size; @@ -280,8 +282,10 @@ struct adapter_params { unsigned int offload:1; /* hw is TOE capable, fw has divvied up card resources for TOE operation. */ unsigned int bypass:1; /* this is a bypass card */ + unsigned int ethoffload:1; unsigned int ofldq_wr_cred; + unsigned int eo_wr_cred; }; #define CHELSIO_T4 0x4 @@ -318,11 +322,28 @@ struct link_config { #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) +static inline int is_ftid(const struct adapter *sc, u_int tid) +{ + + return (tid >= sc->params.ftid_min && tid <= sc->params.ftid_max); +} + +static inline int is_etid(const struct adapter *sc, u_int tid) +{ + + return (tid >= sc->params.etid_min); +} + static inline int is_offload(const struct adapter *adap) { return adap->params.offload; } +static inline int is_ethoffload(const struct adapter *adap) +{ + return adap->params.ethoffload; +} + static inline int chip_id(struct adapter *adap) { return adap->params.chipid; diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h index 8d3cf66208f3..a03d114a1a28 100644 --- a/sys/dev/cxgbe/offload.h +++ b/sys/dev/cxgbe/offload.h @@ -101,6 +101,11 @@ struct tid_info { u_int nftids; u_int ftid_base; u_int ftids_in_use; + + struct mtx etid_lock __aligned(CACHE_LINE_SIZE); + struct etid_entry *etid_tab; + u_int netids; + u_int etid_base; }; struct t4_range { diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index b1cfb2a20a2a..e74c47a859f6 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -2359,7 +2359,6 @@ partition_resources(struct adapter *sc, const struct firmware *default_cfg, #define LIMIT_CAPS(x) do { \ caps.x &= htobe16(t4_##x##_allowed); \ - sc->x = htobe16(caps.x); \ } while (0) /* @@ -2461,6 +2460,8 @@ get_params__post_init(struct adapter *sc) sc->sge.eq_start = val[1]; sc->tids.ftid_base = val[2]; sc->tids.nftids = val[3] - val[2] + 1; + sc->params.ftid_min = val[2]; + sc->params.ftid_max = val[3]; sc->vres.l2t.start = val[4]; sc->vres.l2t.size = val[5] - val[4] + 1; KASSERT(sc->vres.l2t.size <= L2T_SIZE, @@ -2479,7 +2480,35 @@ get_params__post_init(struct adapter *sc) return (rc); } - if (caps.toecaps) { +#define READ_CAPS(x) do { \ + sc->x = htobe16(caps.x); \ +} while (0) + READ_CAPS(linkcaps); + READ_CAPS(niccaps); + READ_CAPS(toecaps); + READ_CAPS(rdmacaps); + READ_CAPS(iscsicaps); + READ_CAPS(fcoecaps); + + if (sc->niccaps & FW_CAPS_CONFIG_NIC_ETHOFLD) { + param[0] = FW_PARAM_PFVF(ETHOFLD_START); + param[1] = FW_PARAM_PFVF(ETHOFLD_END); + param[2] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ); + rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 3, param, val); + if (rc != 0) { + device_printf(sc->dev, + "failed to query NIC parameters: %d.\n", rc); + return (rc); + } + sc->tids.etid_base = val[0]; + sc->params.etid_min = val[0]; + sc->tids.netids = val[1] - val[0] + 1; + sc->params.netids = sc->tids.netids; + sc->params.eo_wr_cred = val[2]; + sc->params.ethoffload = 1; + } + + if (sc->toecaps) { /* query offload-related parameters */ param[0] = FW_PARAM_DEV(NTID); param[1] = FW_PARAM_PFVF(SERVER_START); @@ -2502,7 +2531,7 @@ get_params__post_init(struct adapter *sc) sc->params.ofldq_wr_cred = val[5]; sc->params.offload = 1; } - if (caps.rdmacaps) { + if (sc->rdmacaps) { param[0] = FW_PARAM_PFVF(STAG_START); param[1] = FW_PARAM_PFVF(STAG_END); param[2] = FW_PARAM_PFVF(RQ_START); @@ -2541,7 +2570,7 @@ get_params__post_init(struct adapter *sc) sc->vres.ocq.start = val[4]; sc->vres.ocq.size = val[5] - val[4] + 1; } - if (caps.iscsicaps) { + if (sc->iscsicaps) { param[0] = FW_PARAM_PFVF(ISCSI_START); param[1] = FW_PARAM_PFVF(ISCSI_END); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 2, param, val); @@ -4487,6 +4516,7 @@ cxgbe_sysctls(struct port_info *pi) struct sysctl_ctx_list *ctx; struct sysctl_oid *oid; struct sysctl_oid_list *children; + struct adapter *sc = pi->adapter; ctx = device_get_sysctl_ctx(pi->dev); @@ -4516,7 +4546,7 @@ cxgbe_sysctls(struct port_info *pi) &pi->first_txq, 0, "index of first tx queue"); #ifdef TCP_OFFLOAD - if (is_offload(pi->adapter)) { + if (is_offload(sc)) { SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nofldrxq", CTLFLAG_RD, &pi->nofldrxq, 0, "# of rx queues for offloaded TCP connections"); @@ -4555,7 +4585,7 @@ cxgbe_sysctls(struct port_info *pi) #define SYSCTL_ADD_T4_REG64(pi, name, desc, reg) \ SYSCTL_ADD_OID(ctx, children, OID_AUTO, name, \ - CTLTYPE_U64 | CTLFLAG_RD, pi->adapter, reg, \ + CTLTYPE_U64 | CTLFLAG_RD, sc, reg, \ sysctl_handle_t4_reg64, "QU", desc) SYSCTL_ADD_T4_REG64(pi, "tx_octets", "# of octets in good frames", @@ -6125,6 +6155,11 @@ sysctl_tids(SYSCTL_HANDLER_ARGS) t->ftid_base + t->nftids - 1); } + if (t->netids) { + sbuf_printf(sb, "ETID range: %u-%u\n", t->etid_base, + t->etid_base + t->netids - 1); + } + sbuf_printf(sb, "HW TID usage: %u IP users, %u IPv6 users", t4_read_reg(sc, A_LE_DB_ACT_CNT_IPV4), t4_read_reg(sc, A_LE_DB_ACT_CNT_IPV6)); @@ -7156,14 +7191,17 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) struct adapter *sc = iq->adapter; const struct cpl_set_tcb_rpl *rpl = (const void *)(rss + 1); unsigned int idx = GET_TID(rpl); + unsigned int rc; + struct filter_entry *f; KASSERT(m == NULL, ("%s: payload with opcode %02x", __func__, rss->opcode)); - if (idx >= sc->tids.ftid_base && - (idx -= sc->tids.ftid_base) < sc->tids.nftids) { - unsigned int rc = G_COOKIE(rpl->cookie); - struct filter_entry *f = &sc->tids.ftid_tab[idx]; + if (is_ftid(sc, idx)) { + + idx -= sc->tids.ftid_base; + f = &sc->tids.ftid_tab[idx]; + rc = G_COOKIE(rpl->cookie); mtx_lock(&sc->tids.ftid_lock); if (rc == FW_FILTER_WR_FLT_ADDED) { diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index fd40d3e7269b..ba88e21c407d 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -2901,7 +2901,6 @@ alloc_wrq(struct adapter *sc, struct port_info *pi, struct sge_wrq *wrq, SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "unstalled", CTLFLAG_RD, &wrq->eq.unstalled, 0, "# of times queue recovered after stall"); - return (rc); } diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c index 046482e38908..e2f5c79f0926 100644 --- a/sys/dev/cxgbe/tom/t4_cpl_io.c +++ b/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -1299,18 +1299,18 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) #define V_CPL_FW4_ACK_OPCODE(x) ((x) << S_CPL_FW4_ACK_OPCODE) #define G_CPL_FW4_ACK_OPCODE(x) \ (((x) >> S_CPL_FW4_ACK_OPCODE) & M_CPL_FW4_ACK_OPCODE) - + #define S_CPL_FW4_ACK_FLOWID 0 #define M_CPL_FW4_ACK_FLOWID 0xffffff #define V_CPL_FW4_ACK_FLOWID(x) ((x) << S_CPL_FW4_ACK_FLOWID) #define G_CPL_FW4_ACK_FLOWID(x) \ (((x) >> S_CPL_FW4_ACK_FLOWID) & M_CPL_FW4_ACK_FLOWID) - + #define S_CPL_FW4_ACK_CR 24 #define M_CPL_FW4_ACK_CR 0xff #define V_CPL_FW4_ACK_CR(x) ((x) << S_CPL_FW4_ACK_CR) #define G_CPL_FW4_ACK_CR(x) (((x) >> S_CPL_FW4_ACK_CR) & M_CPL_FW4_ACK_CR) - + #define S_CPL_FW4_ACK_SEQVAL 0 #define M_CPL_FW4_ACK_SEQVAL 0x1 #define V_CPL_FW4_ACK_SEQVAL(x) ((x) << S_CPL_FW4_ACK_SEQVAL) @@ -1437,8 +1437,7 @@ do_set_tcb_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) ("%s: unexpected opcode 0x%x", __func__, opcode)); KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__)); - if (tid >= sc->tids.ftid_base && - tid < sc->tids.ftid_base + sc->tids.nftids) + if (is_ftid(sc, tid)) return (t4_filter_rpl(iq, rss, m)); /* TCB is a filter */ CXGBE_UNIMPLEMENTED(__func__); From 4c631db3cc8c9a773840620eb70726079492a4ce Mon Sep 17 00:00:00 2001 From: Gavin Atkinson Date: Sat, 14 Dec 2013 18:49:59 +0000 Subject: [PATCH 046/172] Fix several panics when initialization of an ISA or PC-CARD device fails: o Assign sc->an_dev in an_probe() (which isn't really a probe function in the standard newbus sense) as we may need it for printing errors. o Use device_printf() rather than if_printf() in an_reset() - this is called from an_probe() long before the ifp structure is initialised in an_attach(). o Initialize the ifp structure early in an_attach() as we use if_printf() in cases where allocation of descriptors etc fails. MFC after: 3 days --- sys/dev/an/if_an.c | 9 +++++---- sys/dev/an/if_an_pccard.c | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index dbd5a7c8d453..ee9282ec14da 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -358,6 +358,7 @@ an_probe(device_t dev) CSR_WRITE_2(sc, AN_INT_EN(sc->mpi350), 0); CSR_WRITE_2(sc, AN_EVENT_ACK(sc->mpi350), 0xFFFF); + sc->an_dev = dev; mtx_init(&sc->an_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); AN_LOCK(sc); @@ -686,6 +687,9 @@ an_attach(struct an_softc *sc, int flags) device_printf(sc->an_dev, "can not if_alloc()\n"); goto fail; } + ifp->if_softc = sc; + if_initname(ifp, device_get_name(sc->an_dev), + device_get_unit(sc->an_dev)); sc->an_gone = 0; sc->an_associated = 0; @@ -759,9 +763,6 @@ an_attach(struct an_softc *sc, int flags) #endif AN_UNLOCK(sc); - ifp->if_softc = sc; - if_initname(ifp, device_get_name(sc->an_dev), - device_get_unit(sc->an_dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = an_ioctl; ifp->if_start = an_start; @@ -1388,7 +1389,7 @@ an_reset(struct an_softc *sc) an_cmd(sc, AN_CMD_NOOP2, 0); if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) - if_printf(sc->an_ifp, "reset failed\n"); + device_printf(sc->an_dev, "reset failed\n"); an_cmd(sc, AN_CMD_DISABLE, 0); diff --git a/sys/dev/an/if_an_pccard.c b/sys/dev/an/if_an_pccard.c index bdd40f3dfe59..e9485eac5830 100644 --- a/sys/dev/an/if_an_pccard.c +++ b/sys/dev/an/if_an_pccard.c @@ -141,8 +141,6 @@ an_pccard_attach(device_t dev) an_alloc_irq(dev, sc->irq_rid, 0); - sc->an_dev = dev; - error = an_attach(sc, flags); if (error) goto fail; From 46cf9b63fd0fc369b9a01fd8e9ca84bc9858cfb2 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sat, 14 Dec 2013 19:01:24 +0000 Subject: [PATCH 047/172] Rebase the PMC indices at 1, since PMC_SOFT is at 0. MFC after: 1 week --- sys/powerpc/include/pmc_mdep.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h index 678852b6233c..7e369572b9f0 100644 --- a/sys/powerpc/include/pmc_mdep.h +++ b/sys/powerpc/include/pmc_mdep.h @@ -7,8 +7,8 @@ #ifndef _MACHINE_PMC_MDEP_H_ #define _MACHINE_PMC_MDEP_H_ -#define PMC_MDEP_CLASS_INDEX_PPC7450 0 -#define PMC_MDEP_CLASS_INDEX_PPC970 0 +#define PMC_MDEP_CLASS_INDEX_PPC7450 1 +#define PMC_MDEP_CLASS_INDEX_PPC970 1 union pmc_md_op_pmcallocate { uint64_t __pad[4]; From 0587a072152140a44e5a0609e463c729ed9e9199 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sat, 14 Dec 2013 20:12:28 +0000 Subject: [PATCH 048/172] Add userland PMC backtracing, and use the PMC trapframe macros for kernel backtraces. MFC after: 1 week --- sys/dev/hwpmc/hwpmc_powerpc.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_powerpc.c b/sys/dev/hwpmc/hwpmc_powerpc.c index 25a32fa35d36..ed1f023e94e8 100644 --- a/sys/dev/hwpmc/hwpmc_powerpc.c +++ b/sys/dev/hwpmc/hwpmc_powerpc.c @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #define INKERNEL(x) (((vm_offset_t)(x)) <= VM_MAX_KERNEL_ADDRESS && \ ((vm_offset_t)(x)) >= VM_MIN_KERNEL_ADDRESS) +#define INUSER(x) (((vm_offset_t)(x)) <= VM_MAXUSER_ADDRESS && \ + ((vm_offset_t)(x)) >= VM_MIN_ADDRESS) struct powerpc_cpu **powerpc_pcpu; @@ -55,13 +57,13 @@ pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, int frames = 0; uintptr_t *sp; - cc[frames++] = tf->srr0; - sp = (uintptr_t *)tf->fixreg[1]; + cc[frames++] = PMC_TRAPFRAME_TO_PC(tf); + sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf); for (frames = 1; frames < maxsamples; frames++) { if (!INKERNEL(sp)) break; - cc[frames++] = *(sp + 1); + cc[frames++] = sp[1]; sp = (uintptr_t *)*sp; } return (frames); @@ -172,8 +174,17 @@ int pmc_save_user_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { - (void) cc; - (void) maxsamples; - (void) tf; - return (0); + uintptr_t *sp; + int frames = 0; + + cc[frames++] = PMC_TRAPFRAME_TO_PC(tf); + sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf); + + for (frames = 1; frames < maxsamples; frames++) { + if (!INUSER(sp)) + break; + cc[frames++] = fuword(sp + 1); + sp = (uintptr_t *)fuword(sp); + } + return (frames); } From 92be6c51f098779786970ceb279c710eb4b4f352 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 14 Dec 2013 22:07:40 +0000 Subject: [PATCH 049/172] Widen lun_id_t to 64 bits. This is a follow-on to r257345 to let the kernel support all valid SAM-5 LUN IDs. CAM_VERSION is bumped, as the CAM ABI (though not API) is changed. No behavior is changed relative to r257345 except that LUNs with non-zero high 32 bits will no longer be ignored during device enumeration for SIMs that have set PIM_EXTLUNS. Reviewed by: scottl --- sys/cam/cam.h | 8 +- sys/cam/cam_ccb.h | 7 +- sys/cam/cam_compat.c | 187 ++++++++++++++++++++++++++++++++++++---- sys/cam/cam_compat.h | 61 ++++++++++++- sys/cam/scsi/scsi_xpt.c | 12 +-- 5 files changed, 234 insertions(+), 41 deletions(-) diff --git a/sys/cam/cam.h b/sys/cam/cam.h index 20fd3cc0825a..302504fb4fcd 100644 --- a/sys/cam/cam.h +++ b/sys/cam/cam.h @@ -39,16 +39,12 @@ typedef u_int path_id_t; typedef u_int target_id_t; -typedef u_int lun_id_t; -typedef union { - u_int64_t lun64; - u_int8_t lun[8]; -} lun64_id_t; +typedef u_int64_t lun_id_t; #define CAM_XPT_PATH_ID ((path_id_t)~0) #define CAM_BUS_WILDCARD ((path_id_t)~0) #define CAM_TARGET_WILDCARD ((target_id_t)~0) -#define CAM_LUN_WILDCARD ((lun_id_t)~0) +#define CAM_LUN_WILDCARD (~(u_int)0) #define CAM_EXTLUN_BYTE_SWIZZLE(lun) ( \ ((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \ diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 139bd505ee50..87553c629380 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -109,10 +109,6 @@ typedef enum { CAM_UNLOCKED = 0x80000000 /* Call callback without lock. */ } ccb_flags; -typedef enum { - CAM_EXTLUN_VALID = 0x00000001,/* 64bit lun field is valid */ -} ccb_xflags; - /* XPT Opcodes for xpt_action */ typedef enum { /* Function code flags are bits greater than 0xff */ @@ -326,7 +322,6 @@ struct ccb_hdr { path_id_t path_id; /* Path ID for the request */ target_id_t target_id; /* Target device ID */ lun_id_t target_lun; /* Target LUN number */ - lun64_id_t ext_lun; /* 64bit extended/multi-level LUNs */ u_int32_t flags; /* ccb_flags */ u_int32_t xflags; /* Extended flags */ ccb_ppriv_area periph_priv; @@ -555,7 +550,7 @@ struct ccb_dev_match { /* * Definitions for the path inquiry CCB fields. */ -#define CAM_VERSION 0x18 /* Hex value for current version */ +#define CAM_VERSION 0x19 /* Hex value for current version */ typedef enum { PI_MDP_ABLE = 0x80, /* Supports MDP message */ diff --git a/sys/cam/cam_compat.c b/sys/cam/cam_compat.c index f2914794fe10..bcce814ffdf1 100644 --- a/sys/cam/cam_compat.c +++ b/sys/cam/cam_compat.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -53,6 +54,9 @@ __FBSDID("$FreeBSD$"); static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td, d_ioctl_t *cbfnp); +static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, + int flag, struct thread *td, d_ioctl_t *cbfnp); +static int cam_compat_translate_dev_match_0x18(union ccb *ccb); int cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, @@ -63,28 +67,28 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, switch (cmd) { case CAMIOCOMMAND_0x16: { - union ccb *ccb; + struct ccb_hdr_0x17 *hdr17; - ccb = (union ccb *)addr; - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS_0x16) { - ccb->ccb_h.flags &= ~CAM_SG_LIST_PHYS_0x16; - ccb->ccb_h.flags |= CAM_DATA_SG_PADDR; + hdr17 = (struct ccb_hdr_0x17 *)addr; + if (hdr17->flags & CAM_SG_LIST_PHYS_0x16) { + hdr17->flags &= ~CAM_SG_LIST_PHYS_0x16; + hdr17->flags |= CAM_DATA_SG_PADDR; } - if (ccb->ccb_h.flags & CAM_DATA_PHYS_0x16) { - ccb->ccb_h.flags &= ~CAM_DATA_PHYS_0x16; - ccb->ccb_h.flags |= CAM_DATA_PADDR; + if (hdr17->flags & CAM_DATA_PHYS_0x16) { + hdr17->flags &= ~CAM_DATA_PHYS_0x16; + hdr17->flags |= CAM_DATA_PADDR; } - if (ccb->ccb_h.flags & CAM_SCATTER_VALID_0x16) { - ccb->ccb_h.flags &= CAM_SCATTER_VALID_0x16; - ccb->ccb_h.flags |= CAM_DATA_SG; + if (hdr17->flags & CAM_SCATTER_VALID_0x16) { + hdr17->flags &= CAM_SCATTER_VALID_0x16; + hdr17->flags |= CAM_DATA_SG; } cmd = CAMIOCOMMAND; - error = (cbfnp)(dev, cmd, addr, flag, td); + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; } case CAMGETPASSTHRU_0x16: cmd = CAMGETPASSTHRU; - error = (cbfnp)(dev, cmd, addr, flag, td); + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; case CAMIOCOMMAND_0x17: cmd = CAMIOCOMMAND; @@ -94,6 +98,14 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, cmd = CAMGETPASSTHRU; error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; + case CAMIOCOMMAND_0x18: + cmd = CAMIOCOMMAND; + error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp); + break; + case CAMGETPASSTHRU_0x18: + cmd = CAMGETPASSTHRU; + error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp); + break; default: error = ENOTTY; } @@ -127,7 +139,6 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, hdr->path_id = hdr17->path_id; hdr->target_id = hdr17->target_id; hdr->target_lun = hdr17->target_lun; - hdr->ext_lun.lun64 = 0; hdr->flags = hdr17->flags; hdr->xflags = 0; hdr->periph_priv = hdr17->periph_priv; @@ -159,13 +170,11 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, hdr17->sim_priv = hdr->sim_priv; hdr17->timeout = hdr->timeout; - /* The PATH_INQ only needs special handling on the way out */ - if (ccb->ccb_h.func_code != XPT_PATH_INQ) { - bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); - } else { + if (ccb->ccb_h.func_code == XPT_PATH_INQ) { struct ccb_pathinq *cpi; struct ccb_pathinq_0x17 *cpi17; + /* The PATH_INQ only needs special handling on the way out */ cpi = &ccb->cpi; cpi17 = (struct ccb_pathinq_0x17 *)hdr17; cpi17->version_num = cpi->version_num; @@ -196,9 +205,151 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, cpi17->hba_device = cpi->hba_device; cpi17->hba_subvendor = cpi->hba_subvendor; cpi17->hba_subdevice = cpi->hba_subdevice; + } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) { + /* Copy the rest of the header over */ + bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); + + cam_compat_translate_dev_match_0x18(ccb); + } else { + bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); } xpt_free_ccb(ccb); return (error); } + +static int +cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag, + struct thread *td, d_ioctl_t *cbfnp) +{ + union ccb *ccb; + struct ccb_hdr *hdr; + struct ccb_hdr_0x18 *hdr18; + uint8_t *ccbb, *ccbb18; + u_int error; + + hdr18 = (struct ccb_hdr_0x18 *)addr; + ccb = xpt_alloc_ccb(); + hdr = &ccb->ccb_h; + + hdr->pinfo = hdr18->pinfo; + hdr->xpt_links = hdr18->xpt_links; + hdr->sim_links = hdr18->sim_links; + hdr->periph_links = hdr18->periph_links; + hdr->retry_count = hdr18->retry_count; + hdr->cbfcnp = hdr18->cbfcnp; + hdr->func_code = hdr18->func_code; + hdr->status = hdr18->status; + hdr->path = hdr18->path; + hdr->path_id = hdr18->path_id; + hdr->target_id = hdr18->target_id; + hdr->target_lun = hdr18->target_lun; + if (hdr18->xflags & CAM_EXTLUN_VALID_0x18) + hdr->target_lun = hdr18->ext_lun; + hdr->flags = hdr18->flags; + hdr->xflags = hdr18->xflags; + hdr->periph_priv = hdr18->periph_priv; + hdr->sim_priv = hdr18->sim_priv; + hdr->timeout = hdr18->timeout; + hdr->softtimeout.tv_sec = 0; + hdr->softtimeout.tv_usec = 0; + + ccbb = (uint8_t *)&hdr[1]; + ccbb18 = (uint8_t *)&hdr18[1]; + bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN); + + error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td); + + hdr18->pinfo = hdr->pinfo; + hdr18->xpt_links = hdr->xpt_links; + hdr18->sim_links = hdr->sim_links; + hdr18->periph_links = hdr->periph_links; + hdr18->retry_count = hdr->retry_count; + hdr18->cbfcnp = hdr->cbfcnp; + hdr18->func_code = hdr->func_code; + hdr18->status = hdr->status; + hdr18->path = hdr->path; + hdr18->path_id = hdr->path_id; + hdr18->target_id = hdr->target_id; + hdr18->target_lun = hdr->target_lun; + hdr18->ext_lun = hdr->target_lun; + hdr18->flags = hdr->flags; + hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18; + hdr18->periph_priv = hdr->periph_priv; + hdr18->sim_priv = hdr->sim_priv; + hdr18->timeout = hdr->timeout; + + bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN); + + if (ccb->ccb_h.func_code == XPT_DEV_MATCH) + cam_compat_translate_dev_match_0x18(ccb); + + xpt_free_ccb(ccb); + + return (error); +} + +static int +cam_compat_translate_dev_match_0x18(union ccb *ccb) +{ + struct dev_match_result *dm; + struct dev_match_result_0x18 *dm18; + struct cam_periph_map_info mapinfo; + int i; + + /* Remap the CCB into kernel address space */ + bzero(&mapinfo, sizeof(mapinfo)); + cam_periph_mapmem(ccb, &mapinfo); + + dm = ccb->cdm.matches; + /* Translate in-place: old fields are smaller */ + dm18 = (struct dev_match_result_0x18 *)(dm); + + for (i = 0; i < ccb->cdm.num_matches; i++) { + dm18[i].type = dm[i].type; + switch (dm[i].type) { + case DEV_MATCH_PERIPH: + memcpy(&dm18[i].result.periph_result.periph_name, + &dm[i].result.periph_result.periph_name, + DEV_IDLEN); + dm18[i].result.periph_result.unit_number = + dm[i].result.periph_result.unit_number; + dm18[i].result.periph_result.path_id = + dm[i].result.periph_result.path_id; + dm18[i].result.periph_result.target_id = + dm[i].result.periph_result.target_id; + dm18[i].result.periph_result.target_lun = + dm[i].result.periph_result.target_lun; + break; + case DEV_MATCH_DEVICE: + dm18[i].result.device_result.path_id = + dm[i].result.device_result.path_id; + dm18[i].result.device_result.target_id = + dm[i].result.device_result.target_id; + dm18[i].result.device_result.target_lun = + dm[i].result.device_result.target_lun; + dm18[i].result.device_result.protocol = + dm[i].result.device_result.protocol; + memcpy(&dm18[i].result.device_result.inq_data, + &dm[i].result.device_result.inq_data, + sizeof(struct scsi_inquiry_data)); + memcpy(&dm18[i].result.device_result.ident_data, + &dm[i].result.device_result.ident_data, + sizeof(struct ata_params)); + dm18[i].result.device_result.flags = + dm[i].result.device_result.flags; + break; + case DEV_MATCH_BUS: + memcpy(&dm18[i].result.bus_result, + &dm[i].result.bus_result, + sizeof(struct bus_match_result)); + break; + } + } + + cam_periph_unmapmem(ccb, &mapinfo); + + return (0); +} + diff --git a/sys/cam/cam_compat.h b/sys/cam/cam_compat.h index d5bde1ab1ed2..9a2097fb4bf9 100644 --- a/sys/cam/cam_compat.h +++ b/sys/cam/cam_compat.h @@ -65,7 +65,7 @@ struct ccb_hdr_0x17 { struct cam_path *path; /* Compiled path for this ccb */ path_id_t path_id; /* Path ID for the request */ target_id_t target_id; /* Target device ID */ - lun_id_t target_lun; /* Target LUN number */ + u_int target_lun; /* Target LUN number */ u_int32_t flags; /* ccb_flags */ ccb_ppriv_area periph_priv; ccb_spriv_area sim_priv; @@ -116,5 +116,64 @@ struct ccb_pathinq_0x17 { #define CAMIOCOMMAND_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 2, CAM_0X17_LEN) #define CAMGETPASSTHRU_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 3, CAM_0X17_LEN) +/* Version 0x18 compatibility */ +#define CAM_VERSION_0x18 0x18 + +struct ccb_hdr_0x18 { + cam_pinfo pinfo; /* Info for priority scheduling */ + camq_entry xpt_links; /* For chaining in the XPT layer */ + camq_entry sim_links; /* For chaining in the SIM layer */ + camq_entry periph_links; /* For chaining in the type driver */ + u_int32_t retry_count; + void (*cbfcnp)(struct cam_periph *, union ccb *); + xpt_opcode func_code; /* XPT function code */ + u_int32_t status; /* Status returned by CAM subsystem */ + struct cam_path *path; /* Compiled path for this ccb */ + path_id_t path_id; /* Path ID for the request */ + target_id_t target_id; /* Target device ID */ + u_int target_lun; /* Target LUN number */ + u_int64_t ext_lun; /* 64-bit LUN, more or less */ + u_int32_t flags; /* ccb_flags */ + u_int32_t xflags; /* extended ccb_flags */ + ccb_ppriv_area periph_priv; + ccb_spriv_area sim_priv; + ccb_qos_area qos; + u_int32_t timeout; /* Hard timeout value in seconds */ + struct timeval softtimeout; /* Soft timeout value in sec + usec */ +}; + +typedef enum { + CAM_EXTLUN_VALID_0x18 = 0x00000001,/* 64bit lun field is valid */ +} ccb_xflags_0x18; + +struct dev_match_result_0x18 { + dev_match_type type; + union { + struct { + char periph_name[DEV_IDLEN]; + u_int32_t unit_number; + path_id_t path_id; + target_id_t target_id; + u_int target_lun; + } periph_result; + struct { + path_id_t path_id; + target_id_t target_id; + u_int target_lun; + cam_proto protocol; + struct scsi_inquiry_data inq_data; + struct ata_params ident_data; + dev_result_flags flags; + } device_result; + struct bus_match_result bus_result; + } result; +}; + +#define CAM_0X18_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr) + sizeof(struct ccb_hdr_0x18)) +#define CAM_0X18_DATA_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr_0x18)) + +#define CAMIOCOMMAND_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 2, CAM_0X18_LEN) +#define CAMGETPASSTHRU_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 3, CAM_0X18_LEN) + #endif #endif diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 69752e1d0f7f..33fc4105d032 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -101,10 +101,8 @@ SYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0, (lval) |= (lp)->luns[(i)].lundata[1]; \ } #define CAM_GET_LUN(lp, i, lval) \ - (lval) = scsi_4btoul((lp)->luns[(i)].lundata); \ - (lval) = ((lval) >> 16) | ((lval) << 16); -#define CAM_LUN_ONLY_32BITS(lp, i) \ - (scsi_4btoul(&((lp)->luns[(i)].lundata[4])) == 0) + (lval) = scsi_8btou64((lp)->luns[(i)].lundata); \ + (lval) = CAM_EXTLUN_BYTE_SWIZZLE(lval); /* * If we're not quirked to search <= the first 8 luns @@ -1766,8 +1764,6 @@ probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new, continue; CAM_GET_SIMPLE_LUN(old, idx1, this_lun); } - if (!CAM_LUN_ONLY_32BITS(old, idx1)) - continue; if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { @@ -2038,10 +2034,6 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) break; } - /* XXX print warning? */ - if (!CAM_LUN_ONLY_32BITS(target->luns, - scan_info->lunindex[target_id])) - continue; if (CAM_CAN_GET_SIMPLE_LUN(target->luns, scan_info->lunindex[target_id])) { CAM_GET_SIMPLE_LUN(target->luns, From e14376e4dd44b744014cde85f5f52702d2e5dda6 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 14 Dec 2013 22:28:32 +0000 Subject: [PATCH 050/172] Avoid warning about insecure format with clang. --- sys/dev/ofw/ofw_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/ofw/ofw_console.c b/sys/dev/ofw/ofw_console.c index 30c10187ddf6..7e0276816898 100644 --- a/sys/dev/ofw/ofw_console.c +++ b/sys/dev/ofw/ofw_console.c @@ -100,7 +100,7 @@ cn_drvinit(void *unused) sizeof(output)) == -1) return; if (strlen(output) > 0) - tty_makealias(tp, output); + tty_makealias(tp, "%s", output); } } From b1e3e965683bdd66615e9fc3263e9e259203a6b8 Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Sat, 14 Dec 2013 22:41:17 +0000 Subject: [PATCH 051/172] Reduce disc1.iso size by 74MB by removing lib32 libraries, sendmail, and atf. MFC after: 3 days X-MFC-To-10: immediate (-RC2 requirement) Sponsored by: The FreeBSD Foundation --- release/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/Makefile b/release/Makefile index 89f9066ebbb6..f6af5dc80f21 100644 --- a/release/Makefile +++ b/release/Makefile @@ -142,7 +142,7 @@ system: packagesystem mkdir -p release cd ${WORLDDIR} && ${IMAKE} installkernel installworld distribution \ DESTDIR=${.OBJDIR}/release WITHOUT_RESCUE=1 WITHOUT_KERNEL_SYMBOLS=1 \ - WITHOUT_PROFILE=1 + WITHOUT_PROFILE=1 WITHOUT_SENDMAIL=1 WITHOUT_ATF=1 WITHOUT_LIB32=1 # Copy distfiles mkdir -p release/usr/freebsd-dist cp *.txz MANIFEST release/usr/freebsd-dist From 374ce66b66569893a7d4f9550f9c8137120f5b49 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Sun, 15 Dec 2013 04:11:43 +0000 Subject: [PATCH 052/172] proc exit: don't take PROC_LOCK while freeing rlimits Code wishing to check rlimits of some process should check whether it is exiting first, which current consumers do. MFC after: 2 weeks --- sys/kern/kern_exit.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index b2f86b15cf7e..3ac6c33d658d 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -385,10 +385,8 @@ exit1(struct thread *td, int rv) /* * Release our limits structure. */ - PROC_LOCK(p); plim = p->p_limit; p->p_limit = NULL; - PROC_UNLOCK(p); lim_free(plim); tidhash_remove(td); From 76210de388e846c264427a5c71d58cefc4af1409 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Sun, 15 Dec 2013 07:04:59 +0000 Subject: [PATCH 053/172] revise the helper functions to lookup binaries and their shared libraries. --- release/picobsd/build/picobsd | 107 ++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/release/picobsd/build/picobsd b/release/picobsd/build/picobsd index 8d5caa8d7c2e..26e1b08a898f 100755 --- a/release/picobsd/build/picobsd +++ b/release/picobsd/build/picobsd @@ -91,7 +91,7 @@ log() { # message # unconditionally log and wait for input logverbose() { # message local foo - printf "\n*** %s\n" "$*" + printf "\n*** %s\n" "$*" >&2 read -p "=== Press enter to continue" foo return 0 } @@ -570,71 +570,89 @@ do_links() { # rootdir varname # cp -p ${u_progs} ${dst}/libexec # ignore errors # } +# find programs and required libraries. Accept -L libs -P path +# if no argument default to objdir/SHLIBDIRPREFIX for both find_progs() { # programs - local pass i old_libs="" tmp o="" - if [ x"$1" = "x-L" -a -d "$2" ] ; then # set lib search path - o="-P $2"; shift; shift - fi - # Result returned in global variables - u_libs="" ; u_progs="`find_progs_helper $*`" + # logverbose "find_progs: called with $*" + local i=`realpath ${o_objdir:-${_SHLIBDIRPREFIX}/..}` + # default values for -L and -P + local dir="-P $i" + local ldir="-L $i" + + while [ "$1" != "" ] ; do + if [ x"$1" = "x-L" -a -d "$2" ] ; then # set lib search path + ldir="-L $2"; shift; shift + elif [ x"$1" = "x-P" -a -d "$2" ] ; then # set prog search path + dir="-P $2"; shift; shift + else + break + fi + done + + # Results are returned in global variables + u_libs="" + u_progs="`find_progs_helper $dir $*`" [ -z "${u_progs}" ] && return 1 # not found, error - # use objdump to find libraries. Iterate to fetch recursive - # dependencies. - tmp="${u_progs}" ; pass=1 + + # use objdump to find libraries. + # Iterate to fetch recursive dependencies. + local tmp="${u_progs}" + local old_libs="" + local pass=1 while [ $pass -lt 10 ] ; do pass=$(($pass + 1)) i="`objdump -x ${tmp} | \ - awk '$1 == "NEEDED" { print $2 }' | sort | uniq`" + awk '$1 == "NEEDED" { print $2 }' | sort | uniq | tr '\n' ' '`" if [ "$old_libs" = "$i" ] ; then - log "libraries for: $my_progs ($u_progs) are ($i) $u_libs" - log "--- done find_progs ---" + # logverbose "find_progs: have `echo ${u_libs} | wc -w`/`echo ${i} | wc -w` libraries for: $my_progs ($u_progs)" + # logverbose "they are ($i) $u_libs" return 0 else # logverbose "old--- $old_libs --- new +++ $i +++" fi - u_libs="`find_progs_helper $o $i`" + u_libs="`find_progs_helper $ldir $i`" old_libs="$i" tmp="$tmp $u_libs" done log "WARNING: Too many passes, giving up" } -find_progs_helper() { # programs - local dir=${o_objdir:-${_SHLIBDIRPREFIX}/..} - local ldir="" - if [ x"$1" = "x-P" -a -d "$2" ] ; then # set path - ldir=$2; shift; shift - fi - local progs="$*" - local subdirs=". local/bin local/sbin local/lib local/libexec \ - bin sbin usr.bin usr.sbin libexec lib \ - gnu/usr.bin gnu/lib \ - secure/usr.bin secure/usr.sbin secure/libexec secure/lib" - local names="" # files to search - local o="" +# prints to stdout files and libs in the search paths +find_progs_helper() { # first arg is either -P or -L + local ty=$1 dir=$2 ; shift; shift + local progs="`echo $* | tr ' ' '\n' | sort -u | tr '\n' ' '`" + # first, extract absolute pathnames or files in this directory + + # accumulate others in $names + local names="" local i for i in $progs ; do - # full pathnames are just listed - [ -f "$i" ] && echo $i && continue - names="${names} ${o} -name $i" - o="-o" + [ -f "$i" ] && echo `realpath $i` && continue + names="${names} $i" done + # if nothing left, we are done [ -z "${names}" ] && return 0 - local places="" # places to search - for i in $subdirs ; do - [ -d "${dir}/${i}" ] && places="${places} ${dir}/${i}" - done - if [ -n "${ldir}" ] ; then - for i in $subdirs ; do - [ -d "${ldir}/${i}" ] && places="${places} ${ldir}/${i}" - done + + local depth p + local places="" # places to search + if [ x-P = "x$ty" ] ; then # search programs + depth=2 + p=". local/bin local/sbin local/libexec \ + bin sbin usr/bin usr/sbin libexec gnu/usr.bin \ + secure/usr.bin secure/usr.sbin secure/libexec " + else + depth=3 + p="lib usr/lib gnu/lib secure/lib" fi - for i in $progs ; do - # full pathnames are just listed - [ -f "$i" ] && echo $i && continue - find ${places} -maxdepth 3 -type f -name ${i} | head -1 + for i in $p ; do + i="${dir}/${i}" + [ -d "${i}" ] && places="${places} `realpath ${i}`" + done + # logverbose "--- looking into $places" + places=`echo ${places} | tr ' ' '\n' | sort -u` + for i in $names ; do + find ${places} -maxdepth $depth -type f -name ${i} | head -1 done - # use maxdepth 3 because some libs are way down } # Populate the memory filesystem with binaries and non-variable @@ -746,6 +764,7 @@ populate_mfs_tree() { fi log "for a shared 'crunch' take libraries and dynamic loader as well" + # /stand/crunch is our main binary, we extract its libs find_progs ${dst}/stand/crunch if [ -n "${u_libs}" ] ; then mkdir -p ${dst}/lib && cp -p ${u_libs} ${dst}/lib From c3e51c9ce1ca864e37fef30547c947384cc0955a Mon Sep 17 00:00:00 2001 From: Alfred Perlstein Date: Sun, 15 Dec 2013 07:07:13 +0000 Subject: [PATCH 054/172] Defer start/stop port to workqueues. We need to do this because the Linux compat layer uses sx(9) for mutex, however the lagg code uses rmlocks and calls into the mellanox driver. This causes deadlock due to sleeping while holding a rmlock. Submitted by: Shahar Klein (shahark mellanox.com) MFC After: 3 days. --- sys/ofed/drivers/net/mlx4/en_netdev.c | 93 ++++++++++++++++++++------- sys/ofed/drivers/net/mlx4/mlx4_en.h | 7 +- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c index 99a933681531..fa77652dedce 100644 --- a/sys/ofed/drivers/net/mlx4/en_netdev.c +++ b/sys/ofed/drivers/net/mlx4/en_netdev.c @@ -153,6 +153,19 @@ static int mlx4_en_cache_mclist(struct net_device *dev, u64 **mcaddrp) return (i); } +static void mlx4_en_stop_port(struct net_device *dev) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + + queue_work(priv->mdev->workqueue, &priv->stop_port_task); +} + +static void mlx4_en_start_port(struct net_device *dev) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + + queue_work(priv->mdev->workqueue, &priv->start_port_task); +} static void mlx4_en_set_multicast(struct net_device *dev) { @@ -473,6 +486,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work) queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); } + mlx4_en_QUERY_PORT(priv->mdev, priv->port); mutex_unlock(&mdev->state_lock); } @@ -498,8 +512,31 @@ static void mlx4_en_linkstate(struct work_struct *work) mutex_unlock(&mdev->state_lock); } +static void mlx4_en_lock_and_stop_port(struct work_struct *work) +{ + struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, + stop_port_task); + struct net_device *dev = priv->dev; + struct mlx4_en_dev *mdev = priv->mdev; + + mutex_lock(&mdev->state_lock); + mlx4_en_do_stop_port(dev); + mutex_unlock(&mdev->state_lock); +} -int mlx4_en_start_port(struct net_device *dev) +static void mlx4_en_lock_and_start_port(struct work_struct *work) +{ + struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, + start_port_task); + struct net_device *dev = priv->dev; + struct mlx4_en_dev *mdev = priv->mdev; + + mutex_lock(&mdev->state_lock); + mlx4_en_do_start_port(dev); + mutex_unlock(&mdev->state_lock); +} + +int mlx4_en_do_start_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -691,7 +728,7 @@ int mlx4_en_start_port(struct net_device *dev) } -void mlx4_en_stop_port(struct net_device *dev) +void mlx4_en_do_stop_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -761,8 +798,8 @@ static void mlx4_en_restart(struct work_struct *work) mutex_lock(&mdev->state_lock); if (priv->port_up) { - mlx4_en_stop_port(dev); - if (mlx4_en_start_port(dev)) + mlx4_en_do_stop_port(dev); + if (mlx4_en_do_start_port(dev)) en_err(priv, "Failed restarting port %d\n", priv->port); } mutex_unlock(&mdev->state_lock); @@ -793,7 +830,7 @@ mlx4_en_init_locked(struct mlx4_en_priv *priv) dev = priv->dev; mdev = priv->mdev; if (dev->if_drv_flags & IFF_DRV_RUNNING) - mlx4_en_stop_port(dev); + mlx4_en_do_stop_port(dev); if (!mdev->device_up) { en_err(priv, "Cannot open - device down/disabled\n"); @@ -816,7 +853,7 @@ mlx4_en_init_locked(struct mlx4_en_priv *priv) } mlx4_en_set_default_moderation(priv); - if (mlx4_en_start_port(dev)) + if (mlx4_en_do_start_port(dev)) en_err(priv, "Failed starting port:%d\n", priv->port); } @@ -905,7 +942,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev) mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); mutex_lock(&mdev->state_lock); - mlx4_en_stop_port(dev); + mlx4_en_do_stop_port(dev); mutex_unlock(&mdev->state_lock); cancel_delayed_work(&priv->stats_task); @@ -925,7 +962,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev) mtx_destroy(&priv->stats_lock.m); mtx_destroy(&priv->vlan_lock.m); - mtx_destroy(&priv->ioctl_lock.m); kfree(priv); if_free(dev); } @@ -951,9 +987,9 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) * the port */ en_dbg(DRV, priv, "Change MTU called with card down!?\n"); } else { - mlx4_en_stop_port(dev); + mlx4_en_do_stop_port(dev); mlx4_en_set_default_moderation(priv); - err = mlx4_en_start_port(dev); + err = mlx4_en_do_start_port(dev); if (err) { en_err(priv, "Failed restarting port:%d\n", priv->port); @@ -973,8 +1009,13 @@ static int mlx4_en_calc_media(struct mlx4_en_priv *priv) active = IFM_ETHER; if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN) return (active); - if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) - return (active); + /* + * [ShaharK] mlx4_en_QUERY_PORT sleeps and cannot be called under a + * non-sleepable lock. + * I moved it to the periodic mlx4_en_do_get_stats. + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) + return (active); + */ active |= IFM_FDX; trans_type = priv->port_state.transciver; /* XXX I don't know all of the transceiver values. */ @@ -1078,7 +1119,6 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data) error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu); break; case SIOCSIFFLAGS: - mutex_lock(&mdev->state_lock); if (dev->if_flags & IFF_UP) { if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) mlx4_en_start_port(dev); @@ -1087,16 +1127,24 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data) } else { if (dev->if_drv_flags & IFF_DRV_RUNNING) { mlx4_en_stop_port(dev); - if_link_state_change(dev, LINK_STATE_DOWN); + if_link_state_change(dev, LINK_STATE_DOWN); + /* + * Since mlx4_en_stop_port is defered we + * have to wait till it's finished. + */ + for (int count=0; count<10; count++) { + if (dev->if_drv_flags & IFF_DRV_RUNNING) { + DELAY(20000); + } else { + break; + } + } } } - mutex_unlock(&mdev->state_lock); break; case SIOCADDMULTI: case SIOCDELMULTI: - spin_lock(&priv->ioctl_lock); mlx4_en_set_multicast(dev); - spin_unlock(&priv->ioctl_lock); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: @@ -1153,7 +1201,7 @@ static int mlx4_en_set_ring_size(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; - mlx4_en_stop_port(dev); + mlx4_en_do_stop_port(dev); } mlx4_en_free_resources(priv); priv->prof->tx_ring_size = tx_size; @@ -1164,7 +1212,7 @@ static int mlx4_en_set_ring_size(struct net_device *dev, goto out; } if (port_up) { - err = mlx4_en_start_port(dev); + err = mlx4_en_do_start_port(dev); if (err) en_err(priv, "Failed starting port\n"); } @@ -1256,7 +1304,7 @@ static int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS) mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; - mlx4_en_stop_port(priv->dev); + mlx4_en_do_stop_port(priv->dev); } mlx4_en_free_resources(priv); priv->tx_ring_num = tx_ring_num; @@ -1265,7 +1313,7 @@ static int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS) if (error) en_err(priv, "Failed reallocating port resources\n"); if (error == 0 && port_up) { - error = -mlx4_en_start_port(priv->dev); + error = -mlx4_en_do_start_port(priv->dev); if (error) en_err(priv, "Failed starting port\n"); } @@ -1517,8 +1565,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->msg_enable = MLX4_EN_MSG_LEVEL; priv->ip_reasm = priv->mdev->profile.ip_reasm; mtx_init(&priv->stats_lock.m, "mlx4 stats", NULL, MTX_DEF); - mtx_init(&priv->ioctl_lock.m, "mlx4 ioctl", NULL, MTX_DEF); mtx_init(&priv->vlan_lock.m, "mlx4 vlan", NULL, MTX_DEF); + INIT_WORK(&priv->start_port_task, mlx4_en_lock_and_start_port); + INIT_WORK(&priv->stop_port_task, mlx4_en_lock_and_stop_port); INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast); INIT_WORK(&priv->watchdog_task, mlx4_en_restart); INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); diff --git a/sys/ofed/drivers/net/mlx4/mlx4_en.h b/sys/ofed/drivers/net/mlx4/mlx4_en.h index 7f3c352b7bbb..0dc5fe6b3734 100644 --- a/sys/ofed/drivers/net/mlx4/mlx4_en.h +++ b/sys/ofed/drivers/net/mlx4/mlx4_en.h @@ -493,7 +493,6 @@ struct mlx4_en_priv { spinlock_t vlan_lock; struct mlx4_en_port_state port_state; spinlock_t stats_lock; - spinlock_t ioctl_lock; unsigned long last_moder_packets[MAX_RX_RINGS]; unsigned long last_moder_tx_packets; @@ -546,6 +545,8 @@ struct mlx4_en_priv { struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; struct mlx4_en_tx_hash_entry tx_hash[MLX4_EN_TX_HASH_SIZE]; struct work_struct mcast_task; + struct work_struct start_port_task; + struct work_struct stop_port_task; struct work_struct watchdog_task; struct work_struct linkstate_task; struct delayed_work stats_task; @@ -580,8 +581,8 @@ void mlx4_en_destroy_netdev(struct net_device *dev); int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, struct mlx4_en_port_profile *prof); -int mlx4_en_start_port(struct net_device *dev); -void mlx4_en_stop_port(struct net_device *dev); +int mlx4_en_do_start_port(struct net_device *dev); +void mlx4_en_do_stop_port(struct net_device *dev); void mlx4_en_free_resources(struct mlx4_en_priv *priv); int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); From f9790aeb8869bfcedf111517bace712b390e6cc5 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Sun, 15 Dec 2013 08:37:24 +0000 Subject: [PATCH 055/172] split netmap code according to functions: - netmap.c base code - netmap_freebsd.c FreeBSD-specific code - netmap_generic.c emulate netmap over standard drivers - netmap_mbq.c simple mbuf tailq - netmap_mem2.c memory management - netmap_vale.c VALE switch simplify devce-specific code --- sys/conf/files | 4 + sys/dev/netmap/if_em_netmap.h | 236 ++- sys/dev/netmap/if_igb_netmap.h | 323 ++-- sys/dev/netmap/if_lem_netmap.h | 267 ++- sys/dev/netmap/if_re_netmap.h | 299 +-- sys/dev/netmap/ixgbe_netmap.h | 461 ++--- sys/dev/netmap/netmap.c | 3229 ++++++++----------------------- sys/dev/netmap/netmap_freebsd.c | 410 ++++ sys/dev/netmap/netmap_generic.c | 818 ++++++++ sys/dev/netmap/netmap_kern.h | 598 +++++- sys/dev/netmap/netmap_mbq.c | 152 ++ sys/dev/netmap/netmap_mbq.h | 78 + sys/dev/netmap/netmap_mem2.c | 300 ++- sys/dev/netmap/netmap_mem2.h | 15 +- sys/dev/netmap/netmap_vale.c | 1983 +++++++++++++++++++ sys/modules/netmap/Makefile | 8 +- sys/net/netmap.h | 48 +- sys/net/netmap_user.h | 280 ++- 18 files changed, 5936 insertions(+), 3573 deletions(-) create mode 100644 sys/dev/netmap/netmap_freebsd.c create mode 100644 sys/dev/netmap/netmap_generic.c create mode 100644 sys/dev/netmap/netmap_mbq.c create mode 100644 sys/dev/netmap/netmap_mbq.h create mode 100644 sys/dev/netmap/netmap_vale.c diff --git a/sys/conf/files b/sys/conf/files index a73d31e0c9eb..9f8a6cd9cc44 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1880,7 +1880,11 @@ dev/nand/nfc_if.m optional nand dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/netmap/netmap.c optional netmap +dev/netmap/netmap_freebsd.c optional netmap +dev/netmap/netmap_generic.c optional netmap +dev/netmap/netmap_mbq.c optional netmap dev/netmap/netmap_mem2.c optional netmap +dev/netmap/netmap_vale.c optional netmap # compile-with "${NORMAL_C} -Wconversion -Wextra" dev/nge/if_nge.c optional nge dev/nxge/if_nxge.c optional nxge \ diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h index 1ea11238aaaf..dbbee4222407 100644 --- a/sys/dev/netmap/if_em_netmap.h +++ b/sys/dev/netmap/if_em_netmap.h @@ -26,7 +26,7 @@ /* * $FreeBSD$ * - * netmap support for em. + * netmap support for: em. * * For more details on netmap support please see ixgbe_netmap.h */ @@ -39,10 +39,6 @@ #include -static void em_netmap_block_tasks(struct adapter *); -static void em_netmap_unblock_tasks(struct adapter *); - - // XXX do we need to block/unblock the tasks ? static void em_netmap_block_tasks(struct adapter *adapter) @@ -85,45 +81,31 @@ em_netmap_unblock_tasks(struct adapter *adapter) /* - * Register/unregister routine + * Register/unregister. We are already under netmap lock. */ static int -em_netmap_reg(struct ifnet *ifp, int onoff) +em_netmap_reg(struct netmap_adapter *na, int onoff) { + struct ifnet *ifp = na->ifp; struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); - int error = 0; - - if (na == NULL) - return EINVAL; /* no netmap support here */ + EM_CORE_LOCK(adapter); em_disable_intr(adapter); /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); em_netmap_block_tasks(adapter); - + /* enable or disable flags and callbacks in na and ifp */ if (onoff) { - ifp->if_capenable |= IFCAP_NETMAP; - - na->if_transmit = ifp->if_transmit; - ifp->if_transmit = netmap_transmit; - - em_init_locked(adapter); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == 0) { - error = ENOMEM; - goto fail; - } + nm_set_native_flags(na); } else { -fail: - /* return to non-netmap mode */ - ifp->if_transmit = na->if_transmit; - ifp->if_capenable &= ~IFCAP_NETMAP; - em_init_locked(adapter); /* also enable intr */ + nm_clear_native_flags(na); } + em_init_locked(adapter); /* also enable intr */ em_netmap_unblock_tasks(adapter); - return (error); + EM_CORE_UNLOCK(adapter); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } @@ -131,93 +113,103 @@ em_netmap_reg(struct ifnet *ifp, int onoff) * Reconcile kernel and user view of the transmit ring. */ static int -em_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) +em_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct tx_ring *txr = &adapter->tx_rings[ring_nr]; - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; - + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, new_slots; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_txsync_prologue(kring, &new_slots); /* generate an interrupt approximately every half ring */ u_int report_frequency = kring->nkr_num_slots >> 1; - k = ring->cur; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct tx_ring *txr = &adapter->tx_rings[ring_nr]; + + if (cur > lim) /* error checking in nm_txsync_prologue() */ return netmap_ring_reinit(kring); bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_POSTREAD); /* - * Process new packets to send. j is the current index in the - * netmap ring, l is the corresponding index in the NIC ring. + * First part: process new packets to send. */ - j = kring->nr_hwcur; - if (j != k) { /* we have new packets to send */ - l = netmap_idx_k2n(kring, j); - for (n = 0; j != k; n++) { - /* slot is the current slot in the netmap ring */ - struct netmap_slot *slot = &ring->slot[j]; - /* curr is the current slot in the nic ring */ - struct e1000_tx_desc *curr = &txr->tx_base[l]; - struct em_buffer *txbuf = &txr->tx_buffers[l]; - int flags = ((slot->flags & NS_REPORT) || - j == 0 || j == report_frequency) ? - E1000_TXD_CMD_RS : 0; + + nm_i = kring->nr_hwcur; + if (nm_i != cur) { /* we have new packets to send */ + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; + u_int len = slot->len; uint64_t paddr; void *addr = PNMB(slot, &paddr); - u_int len = slot->len; - if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { - return netmap_ring_reinit(kring); - } + /* device-specific */ + struct e1000_tx_desc *curr = &txr->tx_base[nic_i]; + struct em_buffer *txbuf = &txr->tx_buffers[nic_i]; + int flags = (slot->flags & NS_REPORT || + nic_i == 0 || nic_i == report_frequency) ? + E1000_TXD_CMD_RS : 0; + + NM_CHECK_ADDR_LEN(addr, len); - slot->flags &= ~NS_REPORT; if (slot->flags & NS_BUF_CHANGED) { curr->buffer_addr = htole64(paddr); /* buffer has changed, reload map */ netmap_reload_map(txr->txtag, txbuf->map, addr); - slot->flags &= ~NS_BUF_CHANGED; } + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + + /* Fill the slot in the NIC ring. */ curr->upper.data = 0; curr->lower.data = htole32(adapter->txd_cmd | len | (E1000_TXD_CMD_EOP | flags) ); bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } - kring->nr_hwcur = k; /* the saved ring->cur */ - kring->nr_hwavail -= n; + kring->nr_hwcur = cur; /* the saved ring->cur */ + /* decrease avail by # of packets sent minus previous ones */ + kring->nr_hwavail -= new_slots; + /* synchronize the NIC ring */ bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), l); + /* (re)start the tx unit up to slot nic_i (excluded) */ + E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), nic_i); } - if (n == 0 || kring->nr_hwavail < 1) { + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || kring->nr_hwavail < 1) { int delta; /* record completed transmissions using TDH */ - l = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); - if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ - D("TDH wrap %d", l); - l -= kring->nkr_num_slots; + nic_i = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); + if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */ + D("TDH wrap %d", nic_i); + nic_i -= kring->nkr_num_slots; } - delta = l - txr->next_to_clean; + delta = nic_i - txr->next_to_clean; if (delta) { /* some completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; - txr->next_to_clean = l; + txr->next_to_clean = nic_i; kring->nr_hwavail += delta; } } - /* update avail to what the kernel knows */ - ring->avail = kring->nr_hwavail; + + nm_txsync_finalize(kring, cur); return 0; } @@ -227,19 +219,23 @@ em_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) * Reconcile kernel and user view of the receive ring. */ static int -em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) +em_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, resvd; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_rxsync_prologue(kring, &resvd); /* cur + res */ int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; - u_int k = ring->cur, resvd = ring->reserved; - k = ring->cur; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; + + if (cur > lim) return netmap_ring_reinit(kring); /* XXX check sync modes */ @@ -247,84 +243,85 @@ em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); /* - * Import newly received packets into the netmap ring. - * j is an index in the netmap ring, l in the NIC ring. + * First part: import newly received packets. */ - l = rxr->next_to_check; - j = netmap_idx_n2k(kring, l); if (netmap_no_pendintr || force_update) { uint16_t slot_flags = kring->nkr_slot_flags; + nic_i = rxr->next_to_check; + nm_i = netmap_idx_n2k(kring, nic_i); + for (n = 0; ; n++) { - struct e1000_rx_desc *curr = &rxr->rx_base[l]; + struct e1000_rx_desc *curr = &rxr->rx_base[nic_i]; uint32_t staterr = le32toh(curr->status); if ((staterr & E1000_RXD_STAT_DD) == 0) break; - ring->slot[j].len = le16toh(curr->length); - ring->slot[j].flags = slot_flags; - bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[l].map, + ring->slot[nm_i].len = le16toh(curr->length); + ring->slot[nm_i].flags = slot_flags; + bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[nic_i].map, BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; + nm_i = nm_next(nm_i, lim); /* make sure next_to_refresh follows next_to_check */ - rxr->next_to_refresh = l; // XXX - l = (l == lim) ? 0 : l + 1; + rxr->next_to_refresh = nic_i; // XXX + nic_i = nm_next(nic_i, lim); } if (n) { /* update the state variables */ - rxr->next_to_check = l; + rxr->next_to_check = nic_i; kring->nr_hwavail += n; } kring->nr_kflags &= ~NKR_PENDINTR; } - /* skip past packets that userspace has released */ - j = kring->nr_hwcur; /* netmap ring index */ - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - if (j != k) { /* userspace has released some packets. */ - l = netmap_idx_k2n(kring, j); /* NIC ring index */ - for (n = 0; j != k; n++) { - struct netmap_slot *slot = &ring->slot[j]; - struct e1000_rx_desc *curr = &rxr->rx_base[l]; - struct em_buffer *rxbuf = &rxr->rx_buffers[l]; + /* + * Second part: skip past packets that userspace has released. + */ + nm_i = kring->nr_hwcur; + if (nm_i != cur) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; uint64_t paddr; void *addr = PNMB(slot, &paddr); - if (addr == netmap_buffer_base) { /* bad buf */ - return netmap_ring_reinit(kring); - } + struct e1000_rx_desc *curr = &rxr->rx_base[nic_i]; + struct em_buffer *rxbuf = &rxr->rx_buffers[nic_i]; + + if (addr == netmap_buffer_base) /* bad buf */ + goto ring_reset; if (slot->flags & NS_BUF_CHANGED) { - curr->buffer_addr = htole64(paddr); /* buffer has changed, reload map */ + curr->buffer_addr = htole64(paddr); netmap_reload_map(rxr->rxtag, rxbuf->map, addr); slot->flags &= ~NS_BUF_CHANGED; } curr->status = 0; bus_dmamap_sync(rxr->rxtag, rxbuf->map, BUS_DMASYNC_PREREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } kring->nr_hwavail -= n; - kring->nr_hwcur = k; + kring->nr_hwcur = cur; + bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* * IMPORTANT: we must leave one free slot in the ring, - * so move l back by one unit + * so move nic_i back by one unit */ - l = (l == 0) ? lim : l - 1; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), l); + nic_i = (nic_i == 0) ? lim : nic_i - 1; + E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i); } - /* tell userspace that there are new packets */ + + /* tell userspace that there might be new packets */ ring->avail = kring->nr_hwavail - resvd; + return 0; + +ring_reset: + return netmap_ring_reinit(kring); } @@ -342,7 +339,8 @@ em_netmap_attach(struct adapter *adapter) na.nm_txsync = em_netmap_txsync; na.nm_rxsync = em_netmap_rxsync; na.nm_register = em_netmap_reg; - netmap_attach(&na, adapter->num_queues); + na.num_tx_rings = na.num_rx_rings = adapter->num_queues; + netmap_attach(&na); } /* end of file */ diff --git a/sys/dev/netmap/if_igb_netmap.h b/sys/dev/netmap/if_igb_netmap.h index 10d94b5faa38..b91d0baba06f 100644 --- a/sys/dev/netmap/if_igb_netmap.h +++ b/sys/dev/netmap/if_igb_netmap.h @@ -37,88 +37,10 @@ #include /* vtophys ? */ #include - /* - * register-unregister routine + * Adaptation to different versions of the driver. */ -static int -igb_netmap_reg(struct ifnet *ifp, int onoff) -{ - struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); - int error = 0; - if (na == NULL) - return EINVAL; /* no netmap support here */ - - igb_disable_intr(adapter); - - /* Tell the stack that the interface is no longer active */ - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - if (onoff) { - ifp->if_capenable |= IFCAP_NETMAP; - - na->if_transmit = ifp->if_transmit; - ifp->if_transmit = netmap_transmit; - - igb_init_locked(adapter); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == 0) { - error = ENOMEM; - goto fail; - } - } else { -fail: - /* restore if_transmit */ - ifp->if_transmit = na->if_transmit; - ifp->if_capenable &= ~IFCAP_NETMAP; - igb_init_locked(adapter); /* also enable intr */ - } - return (error); -} - - -/* - * Reconcile kernel and user view of the transmit ring. - */ -static int -igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) -{ - struct adapter *adapter = ifp->if_softc; - struct tx_ring *txr = &adapter->tx_rings[ring_nr]; - struct netmap_adapter *na = NA(ifp); - struct netmap_kring *kring = &na->tx_rings[ring_nr]; - struct netmap_ring *ring = kring->ring; - u_int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; - - /* generate an interrupt approximately every half ring */ - u_int report_frequency = kring->nkr_num_slots >> 1; - - k = ring->cur; - if (k > lim) - return netmap_ring_reinit(kring); - - bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, - BUS_DMASYNC_POSTREAD); - - /* check for new packets to send. - * j indexes the netmap ring, l indexes the nic ring, and - * j = kring->nr_hwcur, l = E1000_TDT (not tracked), - * j == (l + kring->nkr_hwofs) % ring_size - */ - j = kring->nr_hwcur; - if (j != k) { /* we have new packets to send */ - /* 82575 needs the queue index added */ - u32 olinfo_status = - (adapter->hw.mac.type == e1000_82575) ? (txr->me << 4) : 0; - - l = netmap_idx_k2n(kring, j); - for (n = 0; j != k; n++) { - /* slot is the current slot in the netmap ring */ - struct netmap_slot *slot = &ring->slot[j]; - /* curr is the current slot in the nic ring */ - union e1000_adv_tx_desc *curr = - (union e1000_adv_tx_desc *)&txr->tx_base[l]; #ifndef IGB_MEDIA_RESET /* at the same time as IGB_MEDIA_RESET was defined, the * tx buffer descriptor was renamed, so use this to revert @@ -126,24 +48,95 @@ igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) */ #define igb_tx_buf igb_tx_buffer #endif - struct igb_tx_buf *txbuf = &txr->tx_buffers[l]; - int flags = ((slot->flags & NS_REPORT) || - j == 0 || j == report_frequency) ? - E1000_ADVTXD_DCMD_RS : 0; + + +/* + * Register/unregister. We are already under netmap lock. + */ +static int +igb_netmap_reg(struct netmap_adapter *na, int onoff) +{ + struct ifnet *ifp = na->ifp; + struct adapter *adapter = ifp->if_softc; + + IGB_CORE_LOCK(adapter); + igb_disable_intr(adapter); + + /* Tell the stack that the interface is no longer active */ + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + + /* enable or disable flags and callbacks in na and ifp */ + if (onoff) { + nm_set_native_flags(na); + } else { + nm_clear_native_flags(na); + } + igb_init_locked(adapter); /* also enable intr */ + IGB_CORE_UNLOCK(adapter); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); +} + + +/* + * Reconcile kernel and user view of the transmit ring. + */ +static int +igb_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) +{ + struct ifnet *ifp = na->ifp; + struct netmap_kring *kring = &na->tx_rings[ring_nr]; + struct netmap_ring *ring = kring->ring; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, new_slots; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_txsync_prologue(kring, &new_slots); + /* generate an interrupt approximately every half ring */ + u_int report_frequency = kring->nkr_num_slots >> 1; + + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct tx_ring *txr = &adapter->tx_rings[ring_nr]; + /* 82575 needs the queue index added */ + u32 olinfo_status = + (adapter->hw.mac.type == e1000_82575) ? (txr->me << 4) : 0; + + if (cur > lim) /* error checking in nm_txsync_prologue() */ + return netmap_ring_reinit(kring); + + bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, + BUS_DMASYNC_POSTREAD); + + /* + * First part: process new packets to send. + */ + + nm_i = kring->nr_hwcur; + if (nm_i != cur) { /* we have new packets to send */ + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; + u_int len = slot->len; uint64_t paddr; void *addr = PNMB(slot, &paddr); - u_int len = slot->len; - if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { - return netmap_ring_reinit(kring); - } + /* device-specific */ + union e1000_adv_tx_desc *curr = + (union e1000_adv_tx_desc *)&txr->tx_base[nic_i]; + struct igb_tx_buf *txbuf = &txr->tx_buffers[nic_i]; + int flags = (slot->flags & NS_REPORT || + nic_i == 0 || nic_i == report_frequency) ? + E1000_ADVTXD_DCMD_RS : 0; + + NM_CHECK_ADDR_LEN(addr, len); - slot->flags &= ~NS_REPORT; if (slot->flags & NS_BUF_CHANGED) { /* buffer has changed, reload map */ netmap_reload_map(txr->txtag, txbuf->map, addr); - slot->flags &= ~NS_BUF_CHANGED; } + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + + /* Fill the slot in the NIC ring. */ curr->read.buffer_addr = htole64(paddr); // XXX check olinfo and cmd_type_len curr->read.olinfo_status = @@ -151,48 +144,56 @@ igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) (len<< E1000_ADVTXD_PAYLEN_SHIFT)); curr->read.cmd_type_len = htole32(len | E1000_ADVTXD_DTYP_DATA | - E1000_ADVTXD_DCMD_IFCS | - E1000_ADVTXD_DCMD_DEXT | - E1000_ADVTXD_DCMD_EOP | flags); + E1000_ADVTXD_DCMD_IFCS | + E1000_ADVTXD_DCMD_DEXT | + E1000_ADVTXD_DCMD_EOP | flags); + /* make sure changes to the buffer are synced */ bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } - kring->nr_hwcur = k; /* the saved ring->cur */ - kring->nr_hwavail -= n; + kring->nr_hwcur = cur; /* the saved ring->cur */ + /* decrease avail by # of packets sent minus previous ones */ + kring->nr_hwavail -= new_slots; /* Set the watchdog XXX ? */ txr->queue_status = IGB_QUEUE_WORKING; txr->watchdog_time = ticks; + /* synchronize the NIC ring */ bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), l); + /* (re)start the tx unit up to slot nic_i (excluded) */ + E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), nic_i); } - if (n == 0 || kring->nr_hwavail < 1) { + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || kring->nr_hwavail < 1) { int delta; /* record completed transmissions using TDH */ - l = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); - if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ - D("TDH wrap %d", l); - l -= kring->nkr_num_slots; + nic_i = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); + if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */ + D("TDH wrap %d", nic_i); + nic_i -= kring->nkr_num_slots; } - delta = l - txr->next_to_clean; + delta = nic_i - txr->next_to_clean; if (delta) { /* some completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; - txr->next_to_clean = l; + txr->next_to_clean = nic_i; kring->nr_hwavail += delta; } } - /* update avail to what the kernel knows */ - ring->avail = kring->nr_hwavail; + + nm_txsync_finalize(kring, cur); return 0; } @@ -202,101 +203,107 @@ igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) * Reconcile kernel and user view of the receive ring. */ static int -igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) +igb_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, resvd; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_rxsync_prologue(kring, &resvd); /* cur + res */ int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; - u_int k = ring->cur, resvd = ring->reserved; - k = ring->cur; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; + + if (cur > lim) return netmap_ring_reinit(kring); /* XXX check sync modes */ bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); /* - * import newly received packets into the netmap ring. - * j is an index in the netmap ring, l in the NIC ring. + * First part: import newly received packets. */ - l = rxr->next_to_check; - j = netmap_idx_n2k(kring, l); if (netmap_no_pendintr || force_update) { uint16_t slot_flags = kring->nkr_slot_flags; + nic_i = rxr->next_to_check; + nm_i = netmap_idx_n2k(kring, nic_i); + for (n = 0; ; n++) { - union e1000_adv_rx_desc *curr = &rxr->rx_base[l]; + union e1000_adv_rx_desc *curr = &rxr->rx_base[nic_i]; uint32_t staterr = le32toh(curr->wb.upper.status_error); if ((staterr & E1000_RXD_STAT_DD) == 0) break; - ring->slot[j].len = le16toh(curr->wb.upper.length); - ring->slot[j].flags = slot_flags; + ring->slot[nm_i].len = le16toh(curr->wb.upper.length); + ring->slot[nm_i].flags = slot_flags; bus_dmamap_sync(rxr->ptag, - rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + rxr->rx_buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } if (n) { /* update the state variables */ - rxr->next_to_check = l; + rxr->next_to_check = nic_i; kring->nr_hwavail += n; } kring->nr_kflags &= ~NKR_PENDINTR; } - /* skip past packets that userspace has released */ - j = kring->nr_hwcur; /* netmap ring index */ - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - if (j != k) { /* userspace has released some packets. */ - l = netmap_idx_k2n(kring, j); - for (n = 0; j != k; n++) { - struct netmap_slot *slot = ring->slot + j; - union e1000_adv_rx_desc *curr = &rxr->rx_base[l]; - struct igb_rx_buf *rxbuf = rxr->rx_buffers + l; + /* + * Second part: skip past packets that userspace has released. + */ + nm_i = kring->nr_hwcur; + if (nm_i != cur) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; uint64_t paddr; void *addr = PNMB(slot, &paddr); - if (addr == netmap_buffer_base) { /* bad buf */ - return netmap_ring_reinit(kring); - } + union e1000_adv_rx_desc *curr = &rxr->rx_base[nic_i]; + struct igb_rx_buf *rxbuf = &rxr->rx_buffers[nic_i]; + + if (addr == netmap_buffer_base) /* bad buf */ + goto ring_reset; if (slot->flags & NS_BUF_CHANGED) { + /* buffer has changed, reload map */ netmap_reload_map(rxr->ptag, rxbuf->pmap, addr); slot->flags &= ~NS_BUF_CHANGED; } - curr->read.pkt_addr = htole64(paddr); curr->wb.upper.status_error = 0; + curr->read.pkt_addr = htole64(paddr); bus_dmamap_sync(rxr->ptag, rxbuf->pmap, - BUS_DMASYNC_PREREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + BUS_DMASYNC_PREREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } kring->nr_hwavail -= n; - kring->nr_hwcur = k; + kring->nr_hwcur = cur; + bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* * IMPORTANT: we must leave one free slot in the ring, - * so move l back by one unit + * so move nic_i back by one unit */ - l = (l == 0) ? lim : l - 1; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), l); + nic_i = (nic_i == 0) ? lim : nic_i - 1; + E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i); } - /* tell userspace that there are new packets */ + + /* tell userspace that there might be new packets */ ring->avail = kring->nr_hwavail - resvd; + return 0; + +ring_reset: + return netmap_ring_reinit(kring); } @@ -314,6 +321,8 @@ igb_netmap_attach(struct adapter *adapter) na.nm_txsync = igb_netmap_txsync; na.nm_rxsync = igb_netmap_rxsync; na.nm_register = igb_netmap_reg; - netmap_attach(&na, adapter->num_queues); -} + na.num_tx_rings = na.num_rx_rings = adapter->num_queues; + netmap_attach(&na); +} + /* end of file */ diff --git a/sys/dev/netmap/if_lem_netmap.h b/sys/dev/netmap/if_lem_netmap.h index 25e5c7c27e3e..8ad3b7a2a352 100644 --- a/sys/dev/netmap/if_lem_netmap.h +++ b/sys/dev/netmap/if_lem_netmap.h @@ -27,11 +27,12 @@ /* * $FreeBSD$ * - * netmap support for "lem" + * netmap support for: lem * * For details on netmap support please see ixgbe_netmap.h */ + #include #include #include @@ -40,17 +41,13 @@ /* - * Register/unregister + * Register/unregister. We are already under netmap lock. */ static int -lem_netmap_reg(struct ifnet *ifp, int onoff) +lem_netmap_reg(struct netmap_adapter *na, int onoff) { + struct ifnet *ifp = na->ifp; struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); - int error = 0; - - if (na == NULL) - return EINVAL; EM_CORE_LOCK(adapter); @@ -64,24 +61,14 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) taskqueue_drain(adapter->tq, &adapter->rxtx_task); taskqueue_drain(adapter->tq, &adapter->link_task); #endif /* !EM_LEGCY_IRQ */ + + /* enable or disable flags and callbacks in na and ifp */ if (onoff) { - ifp->if_capenable |= IFCAP_NETMAP; - - na->if_transmit = ifp->if_transmit; - ifp->if_transmit = netmap_transmit; - - lem_init_locked(adapter); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == 0) { - error = ENOMEM; - goto fail; - } + nm_set_native_flags(na); } else { -fail: - /* return to non-netmap mode */ - ifp->if_transmit = na->if_transmit; - ifp->if_capenable &= ~IFCAP_NETMAP; - lem_init_locked(adapter); /* also enable intr */ + nm_clear_native_flags(na); } + lem_init_locked(adapter); /* also enable intr */ #ifndef EM_LEGACY_IRQ taskqueue_unblock(adapter->tq); // XXX do we need this ? @@ -89,7 +76,7 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) EM_CORE_UNLOCK(adapter); - return (error); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } @@ -97,108 +84,102 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) * Reconcile kernel and user view of the transmit ring. */ static int -lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) +lem_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; - + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, new_slots; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_txsync_prologue(kring, &new_slots); /* generate an interrupt approximately every half ring */ - int report_frequency = kring->nkr_num_slots >> 1; + u_int report_frequency = kring->nkr_num_slots >> 1; - ND("%s: hwofs %d, hwcur %d hwavail %d lease %d cur %d avail %d", - ifp->if_xname, - kring->nkr_hwofs, kring->nr_hwcur, kring->nr_hwavail, - kring->nkr_hwlease, - ring->cur, ring->avail); - /* take a copy of ring->cur now, and never read it again */ - k = ring->cur; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + + if (cur > lim) /* error checking in nm_txsync_prologue() */ return netmap_ring_reinit(kring); bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_POSTREAD); + /* - * Process new packets to send. j is the current index in the - * netmap ring, l is the corresponding index in the NIC ring. + * First part: process new packets to send. */ - j = kring->nr_hwcur; - if (netmap_verbose > 255) - RD(5, "device %s send %d->%d", ifp->if_xname, j, k); - if (j != k) { /* we have new packets to send */ - l = netmap_idx_k2n(kring, j); - for (n = 0; j != k; n++) { - /* slot is the current slot in the netmap ring */ - struct netmap_slot *slot = &ring->slot[j]; - /* curr is the current slot in the nic ring */ - struct e1000_tx_desc *curr = &adapter->tx_desc_base[l]; - struct em_buffer *txbuf = &adapter->tx_buffer_area[l]; - int flags = ((slot->flags & NS_REPORT) || - j == 0 || j == report_frequency) ? - E1000_TXD_CMD_RS : 0; + + nm_i = kring->nr_hwcur; + if (nm_i != cur) { /* we have new packets to send */ + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; + u_int len = slot->len; uint64_t paddr; void *addr = PNMB(slot, &paddr); - u_int len = slot->len; - if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { - return netmap_ring_reinit(kring); - } - ND("slot %d NIC %d %s", j, l, nm_dump_buf(addr, len, 128, NULL)); + /* device-specific */ + struct e1000_tx_desc *curr = &adapter->tx_desc_base[nic_i]; + struct em_buffer *txbuf = &adapter->tx_buffer_area[nic_i]; + int flags = (slot->flags & NS_REPORT || + nic_i == 0 || nic_i == report_frequency) ? + E1000_TXD_CMD_RS : 0; - slot->flags &= ~NS_REPORT; - if (1 || slot->flags & NS_BUF_CHANGED) { + NM_CHECK_ADDR_LEN(addr, len); + + if (slot->flags & NS_BUF_CHANGED) { /* buffer has changed, reload map */ - netmap_reload_map(adapter->txtag, txbuf->map, addr); curr->buffer_addr = htole64(paddr); - slot->flags &= ~NS_BUF_CHANGED; + netmap_reload_map(adapter->txtag, txbuf->map, addr); } + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + + /* Fill the slot in the NIC ring. */ curr->upper.data = 0; - curr->lower.data = - htole32( adapter->txd_cmd | len | + curr->lower.data = htole32(adapter->txd_cmd | len | (E1000_TXD_CMD_EOP | flags) ); - - ND("len %d kring %d nic %d", len, j, l); bus_dmamap_sync(adapter->txtag, txbuf->map, - BUS_DMASYNC_PREWRITE); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + BUS_DMASYNC_PREWRITE); + + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } - ND("sent %d packets from %d, TDT now %d", n, kring->nr_hwcur, l); - kring->nr_hwcur = k; /* the saved ring->cur */ - kring->nr_hwavail -= n; + kring->nr_hwcur = cur; /* the saved ring->cur */ + /* decrease avail by # of packets sent minus previous ones */ + kring->nr_hwavail -= new_slots; + /* synchronize the NIC ring */ bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), l); + /* (re)start the tx unit up to slot nic_i (excluded) */ + E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), nic_i); } - if (n == 0 || kring->nr_hwavail < 1) { + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || kring->nr_hwavail < 1) { int delta; /* record completed transmissions using TDH */ - l = E1000_READ_REG(&adapter->hw, E1000_TDH(0)); - ND("tdh is now %d", l); - if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ - D("bad TDH %d", l); - l -= kring->nkr_num_slots; + nic_i = E1000_READ_REG(&adapter->hw, E1000_TDH(0)); + if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */ + D("TDH wrap %d", nic_i); + nic_i -= kring->nkr_num_slots; } - delta = l - adapter->next_tx_to_clean; + delta = nic_i - adapter->next_tx_to_clean; if (delta) { - /* some tx completed, increment hwavail. */ + /* some completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; - if (netmap_verbose > 255) - RD(5, "%s tx recover %d bufs", - ifp->if_xname, delta); - adapter->next_tx_to_clean = l; + adapter->next_tx_to_clean = nic_i; kring->nr_hwavail += delta; } } - /* update avail to what the kernel knows */ - ring->avail = kring->nr_hwavail; + + nm_txsync_finalize(kring, cur); return 0; } @@ -208,39 +189,39 @@ lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) * Reconcile kernel and user view of the receive ring. */ static int -lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) +lem_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, resvd; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_rxsync_prologue(kring, &resvd); /* cur + res */ int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; - u_int k = ring->cur, resvd = ring->reserved; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + + if (cur > lim) return netmap_ring_reinit(kring); - /* XXX check sync modes */ bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); /* - * Import newly received packets into the netmap ring. - * j is an index in the netmap ring, l in the NIC ring. + * First part: import newly received packets. */ - l = adapter->next_rx_desc_to_check; - j = netmap_idx_n2k(kring, l); - ND("%s: next NIC %d kring %d (ofs %d), hwcur %d hwavail %d cur %d avail %d", - ifp->if_xname, - l, j, kring->nkr_hwofs, kring->nr_hwcur, kring->nr_hwavail, - ring->cur, ring->avail); if (netmap_no_pendintr || force_update) { uint16_t slot_flags = kring->nkr_slot_flags; + nic_i = adapter->next_rx_desc_to_check; + nm_i = netmap_idx_n2k(kring, nic_i); + for (n = 0; ; n++) { - struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; + struct e1000_rx_desc *curr = &adapter->rx_desc_base[nic_i]; uint32_t staterr = le32toh(curr->status); int len; @@ -248,76 +229,73 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) break; len = le16toh(curr->length) - 4; // CRC if (len < 0) { - D("bogus pkt size at %d", j); + D("bogus pkt size %d nic idx %d", len, nic_i); len = 0; } - ND("\n%s", nm_dump_buf(NMB(&ring->slot[j]), - len, 128, NULL)); - ring->slot[j].len = len; - ring->slot[j].flags = slot_flags; + ring->slot[nm_i].len = len; + ring->slot[nm_i].flags = slot_flags; bus_dmamap_sync(adapter->rxtag, - adapter->rx_buffer_area[l].map, - BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + adapter->rx_buffer_area[nic_i].map, + BUS_DMASYNC_POSTREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } if (n) { /* update the state variables */ - adapter->next_rx_desc_to_check = l; + adapter->next_rx_desc_to_check = nic_i; + // ifp->if_ipackets += n; kring->nr_hwavail += n; } kring->nr_kflags &= ~NKR_PENDINTR; } - /* skip past packets that userspace has released */ - j = kring->nr_hwcur; /* netmap ring index */ - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - if (j != k) { /* userspace has released some packets. */ - l = netmap_idx_k2n(kring, j); /* NIC ring index */ - for (n = 0; j != k; n++) { - struct netmap_slot *slot = &ring->slot[j]; - struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; - struct em_buffer *rxbuf = &adapter->rx_buffer_area[l]; + /* + * Second part: skip past packets that userspace has released. + */ + nm_i = kring->nr_hwcur; + if (nm_i != cur) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; uint64_t paddr; void *addr = PNMB(slot, &paddr); - if (addr == netmap_buffer_base) { /* bad buf */ - return netmap_ring_reinit(kring); - } + struct e1000_rx_desc *curr = &adapter->rx_desc_base[nic_i]; + struct em_buffer *rxbuf = &adapter->rx_buffer_area[nic_i]; + + if (addr == netmap_buffer_base) /* bad buf */ + goto ring_reset; if (slot->flags & NS_BUF_CHANGED) { /* buffer has changed, reload map */ - netmap_reload_map(adapter->rxtag, rxbuf->map, addr); curr->buffer_addr = htole64(paddr); + netmap_reload_map(adapter->rxtag, rxbuf->map, addr); slot->flags &= ~NS_BUF_CHANGED; } curr->status = 0; - bus_dmamap_sync(adapter->rxtag, rxbuf->map, BUS_DMASYNC_PREREAD); - - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } kring->nr_hwavail -= n; - kring->nr_hwcur = k; + kring->nr_hwcur = cur; bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* * IMPORTANT: we must leave one free slot in the ring, - * so move l back by one unit + * so move nic_i back by one unit */ - l = (l == 0) ? lim : l - 1; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), l); + nic_i = (nic_i == 0) ? lim : nic_i - 1; + E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), nic_i); } - /* tell userspace that there are new packets */ + + /* tell userspace that there might be new packets */ ring->avail = kring->nr_hwavail - resvd; + return 0; + +ring_reset: + return netmap_ring_reinit(kring); } @@ -335,7 +313,8 @@ lem_netmap_attach(struct adapter *adapter) na.nm_txsync = lem_netmap_txsync; na.nm_rxsync = lem_netmap_rxsync; na.nm_register = lem_netmap_reg; - netmap_attach(&na, 1); + na.num_tx_rings = na.num_rx_rings = 1; + netmap_attach(&na); } /* end of file */ diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h index ac781ccb572e..2c7ba060cffd 100644 --- a/sys/dev/netmap/if_re_netmap.h +++ b/sys/dev/netmap/if_re_netmap.h @@ -26,8 +26,9 @@ /* * $FreeBSD$ * - * netmap support for "re" - * For details on netmap support please see ixgbe_netmap.h + * netmap support for: re + * + * For more details on netmap support please see ixgbe_netmap.h */ @@ -39,44 +40,24 @@ /* - * support for netmap register/unregisted. We are already under core lock. - * only called on the first register or the last unregister. + * Register/unregister. We are already under netmap lock. */ static int -re_netmap_reg(struct ifnet *ifp, int onoff) +re_netmap_reg(struct netmap_adapter *na, int onoff) { + struct ifnet *ifp = na->ifp; struct rl_softc *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); - int error = 0; - - if (na == NULL) - return EINVAL; - /* Tell the stack that the interface is no longer active */ - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - re_stop(adapter); + RL_LOCK(adapter); + re_stop(adapter); /* also clears IFF_DRV_RUNNING */ if (onoff) { - ifp->if_capenable |= IFCAP_NETMAP; - - /* save if_transmit to restore it later */ - na->if_transmit = ifp->if_transmit; - ifp->if_transmit = netmap_transmit; - - re_init_locked(adapter); - - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == 0) { - error = ENOMEM; - goto fail; - } + nm_set_native_flags(na); } else { -fail: - /* restore if_transmit */ - ifp->if_transmit = na->if_transmit; - ifp->if_capenable &= ~IFCAP_NETMAP; - re_init_locked(adapter); /* also enables intr */ + nm_clear_native_flags(na); } - return (error); + re_init_locked(adapter); /* also enables intr */ + RL_UNLOCK(adapter); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } @@ -84,90 +65,107 @@ re_netmap_reg(struct ifnet *ifp, int onoff) * Reconcile kernel and user view of the transmit ring. */ static int -re_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) +re_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct rl_softc *sc = ifp->if_softc; - struct rl_txdesc *txd = sc->rl_ldata.rl_tx_desc; - struct netmap_adapter *na = NA(sc->rl_ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, k, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, new_slots; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_txsync_prologue(kring, &new_slots); - k = ring->cur; - if (k > lim) + /* device-specific */ + struct rl_softc *sc = ifp->if_softc; + struct rl_txdesc *txd = sc->rl_ldata.rl_tx_desc; + + if (cur > lim) /* error checking in nm_txsync_prologue() */ return netmap_ring_reinit(kring); - /* Sync the TX descriptor list */ bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, - sc->rl_ldata.rl_tx_list_map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + sc->rl_ldata.rl_tx_list_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); // XXX extra postwrite ? - /* XXX move after the transmissions */ - /* record completed transmissions */ - for (n = 0, l = sc->rl_ldata.rl_tx_considx; - l != sc->rl_ldata.rl_tx_prodidx; - n++, l = RL_TX_DESC_NXT(sc, l)) { - uint32_t cmdstat = - le32toh(sc->rl_ldata.rl_tx_list[l].rl_cmdstat); - if (cmdstat & RL_TDESC_STAT_OWN) - break; - } - if (n > 0) { - sc->rl_ldata.rl_tx_considx = l; - sc->rl_ldata.rl_tx_free += n; - kring->nr_hwavail += n; - } + /* + * First part: process new packets to send. + */ + nm_i = kring->nr_hwcur; + if (nm_i != cur) { /* we have new packets to send */ + nic_i = sc->rl_ldata.rl_tx_prodidx; + // XXX or netmap_idx_k2n(kring, nm_i); - /* update avail to what the kernel knows */ - ring->avail = kring->nr_hwavail; - - j = kring->nr_hwcur; - if (j != k) { /* we have new packets to send */ - l = sc->rl_ldata.rl_tx_prodidx; - for (n = 0; j != k; n++) { - struct netmap_slot *slot = &ring->slot[j]; - struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[l]; - int cmd = slot->len | RL_TDESC_CMD_EOF | - RL_TDESC_CMD_OWN | RL_TDESC_CMD_SOF ; + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; + u_int len = slot->len; uint64_t paddr; void *addr = PNMB(slot, &paddr); - int len = slot->len; - if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { - // XXX what about prodidx ? - return netmap_ring_reinit(kring); - } + /* device-specific */ + struct rl_desc *desc = &sc->rl_ldata.rl_tx_list[nic_i]; + int cmd = slot->len | RL_TDESC_CMD_EOF | + RL_TDESC_CMD_OWN | RL_TDESC_CMD_SOF ; - if (l == lim) /* mark end of ring */ + NM_CHECK_ADDR_LEN(addr, len); + + if (nic_i == lim) /* mark end of ring */ cmd |= RL_TDESC_CMD_EOR; if (slot->flags & NS_BUF_CHANGED) { + /* buffer has changed, reload map */ desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); - /* buffer has changed, unload and reload map */ netmap_reload_map(sc->rl_ldata.rl_tx_mtag, - txd[l].tx_dmamap, addr); - slot->flags &= ~NS_BUF_CHANGED; + txd[nic_i].tx_dmamap, addr); } - slot->flags &= ~NS_REPORT; - desc->rl_cmdstat = htole32(cmd); - bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag, - txd[l].tx_dmamap, BUS_DMASYNC_PREWRITE); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; - } - sc->rl_ldata.rl_tx_prodidx = l; - kring->nr_hwcur = k; /* the saved ring->cur */ - ring->avail -= n; // XXX see others - kring->nr_hwavail = ring->avail; + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + /* Fill the slot in the NIC ring. */ + desc->rl_cmdstat = htole32(cmd); + + /* make sure changes to the buffer are synced */ + bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag, + txd[nic_i].tx_dmamap, + BUS_DMASYNC_PREWRITE); + + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); + } + sc->rl_ldata.rl_tx_prodidx = nic_i; + /* decrease avail by # of packets sent minus previous ones */ + kring->nr_hwcur = cur; /* the saved ring->cur */ + kring->nr_hwavail -= new_slots; + + /* synchronize the NIC ring */ bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, - sc->rl_ldata.rl_tx_list_map, - BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + sc->rl_ldata.rl_tx_list_map, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); /* start ? */ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); } + + /* + * Second part: reclaim buffers for completed transmissions. + */ + if (flags & NAF_FORCE_RECLAIM || kring->nr_hwavail < 1) { + nic_i = sc->rl_ldata.rl_tx_considx; + for (n = 0; nic_i != sc->rl_ldata.rl_tx_prodidx; + n++, nic_i = RL_TX_DESC_NXT(sc, nic_i)) { + uint32_t cmdstat = + le32toh(sc->rl_ldata.rl_tx_list[nic_i].rl_cmdstat); + if (cmdstat & RL_TDESC_STAT_OWN) + break; + } + if (n > 0) { + sc->rl_ldata.rl_tx_considx = nic_i; + sc->rl_ldata.rl_tx_free += n; + kring->nr_hwavail += n; + } + } + + nm_txsync_finalize(kring, cur); + return 0; } @@ -176,42 +174,45 @@ re_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) * Reconcile kernel and user view of the receive ring. */ static int -re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) +re_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct rl_softc *sc = ifp->if_softc; - struct rl_rxdesc *rxd = sc->rl_ldata.rl_rx_desc; - struct netmap_adapter *na = NA(sc->rl_ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - int j, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, resvd; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_rxsync_prologue(kring, &resvd); /* cur + res */ int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; - u_int k = ring->cur, resvd = ring->reserved; - k = ring->cur; - if (k > lim) + /* device-specific */ + struct rl_softc *sc = ifp->if_softc; + struct rl_rxdesc *rxd = sc->rl_ldata.rl_rx_desc; + + if (cur > lim) return netmap_ring_reinit(kring); - /* XXX check sync modes */ bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, - sc->rl_ldata.rl_rx_list_map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + sc->rl_ldata.rl_rx_list_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); /* - * Import newly received packets into the netmap ring. - * j is an index in the netmap ring, l in the NIC ring. + * First part: import newly received packets. * - * The device uses all the buffers in the ring, so we need + * This device uses all the buffers in the ring, so we need * another termination condition in addition to RL_RDESC_STAT_OWN * cleared (all buffers could have it cleared. The easiest one * is to limit the amount of data reported up to 'lim' */ - l = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */ - j = netmap_idx_n2k(kring, l); /* the kring index */ if (netmap_no_pendintr || force_update) { uint16_t slot_flags = kring->nkr_slot_flags; + nic_i = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */ + nm_i = netmap_idx_n2k(kring, nic_i); + for (n = kring->nr_hwavail; n < lim ; n++) { - struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[l]; + struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[nic_i]; uint32_t rxstat = le32toh(cur_rx->rl_cmdstat); uint32_t total_len; @@ -220,74 +221,75 @@ re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) total_len = rxstat & sc->rl_rxlenmask; /* XXX subtract crc */ total_len = (total_len < 4) ? 0 : total_len - 4; - kring->ring->slot[j].len = total_len; - kring->ring->slot[j].flags = slot_flags; + ring->slot[nm_i].len = total_len; + ring->slot[nm_i].flags = slot_flags; /* sync was in re_newbuf() */ bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, - rxd[l].rx_dmamap, BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + rxd[nic_i].rx_dmamap, BUS_DMASYNC_POSTREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } if (n != kring->nr_hwavail) { - sc->rl_ldata.rl_rx_prodidx = l; + sc->rl_ldata.rl_rx_prodidx = nic_i; sc->rl_ifp->if_ipackets += n - kring->nr_hwavail; kring->nr_hwavail = n; } kring->nr_kflags &= ~NKR_PENDINTR; } - /* skip past packets that userspace has released */ - j = kring->nr_hwcur; - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - if (j != k) { /* userspace has released some packets. */ - l = netmap_idx_k2n(kring, j); /* the NIC index */ - for (n = 0; j != k; n++) { - struct netmap_slot *slot = ring->slot + j; - struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[l]; - int cmd = NETMAP_BUF_SIZE | RL_RDESC_CMD_OWN; + /* + * Second part: skip past packets that userspace has released. + */ + nm_i = kring->nr_hwcur; + if (nm_i != cur) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; uint64_t paddr; void *addr = PNMB(slot, &paddr); - if (addr == netmap_buffer_base) { /* bad buf */ - return netmap_ring_reinit(kring); - } + struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[nic_i]; + int cmd = NETMAP_BUF_SIZE | RL_RDESC_CMD_OWN; - if (l == lim) /* mark end of ring */ + if (addr == netmap_buffer_base) /* bad buf */ + goto ring_reset; + + if (nic_i == lim) /* mark end of ring */ cmd |= RL_RDESC_CMD_EOR; - slot->flags &= ~NS_REPORT; if (slot->flags & NS_BUF_CHANGED) { - netmap_reload_map(sc->rl_ldata.rl_rx_mtag, - rxd[l].rx_dmamap, addr); + /* buffer has changed, reload map */ desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); + netmap_reload_map(sc->rl_ldata.rl_rx_mtag, + rxd[nic_i].rx_dmamap, addr); slot->flags &= ~NS_BUF_CHANGED; } desc->rl_cmdstat = htole32(cmd); bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag, - rxd[l].rx_dmamap, BUS_DMASYNC_PREREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + rxd[nic_i].rx_dmamap, + BUS_DMASYNC_PREREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } kring->nr_hwavail -= n; - kring->nr_hwcur = k; - /* Flush the RX DMA ring */ + kring->nr_hwcur = cur; bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, sc->rl_ldata.rl_rx_list_map, - BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } - /* tell userspace that there are new packets */ + + /* tell userspace that there might be new packets */ ring->avail = kring->nr_hwavail - resvd; + return 0; + +ring_reset: + return netmap_ring_reinit(kring); } + /* * Additional routines to init the tx and rx rings. * In other drivers we do that inline in the main code. @@ -299,11 +301,16 @@ re_netmap_tx_init(struct rl_softc *sc) struct rl_desc *desc; int i, n; struct netmap_adapter *na = NA(sc->rl_ifp); - struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0); + struct netmap_slot *slot; + if (!na || !(na->na_flags & NAF_NATIVE_ON)) { + return; + } + + slot = netmap_reset(na, NR_TX, 0, 0); /* slot is NULL if we are not in netmap mode */ if (!slot) - return; + return; // XXX cannot happen /* in netmap mode, overwrite addresses and maps */ txd = sc->rl_ldata.rl_tx_desc; desc = sc->rl_ldata.rl_tx_list; @@ -377,6 +384,8 @@ re_netmap_attach(struct rl_softc *sc) na.nm_txsync = re_netmap_txsync; na.nm_rxsync = re_netmap_rxsync; na.nm_register = re_netmap_reg; - netmap_attach(&na, 1); + na.num_tx_rings = na.num_rx_rings = 1; + netmap_attach(&na); } + /* end of file */ diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h index fca1cf1e0a90..7fd67d2b57ff 100644 --- a/sys/dev/netmap/ixgbe_netmap.h +++ b/sys/dev/netmap/ixgbe_netmap.h @@ -26,16 +26,16 @@ /* * $FreeBSD$ * - * netmap modifications for ixgbe + * netmap support for: ixgbe * * This file is meant to be a reference on how to implement * netmap support for a network driver. - * This file contains code but only static or inline functions - * that are used by a single driver. To avoid replication of - * code we just #include it near the beginning of the - * standard driver. + * This file contains code but only static or inline functions used + * by a single driver. To avoid replication of code we just #include + * it near the beginning of the standard driver. */ + #include #include /* @@ -48,7 +48,10 @@ */ #include + /* + * device-specific sysctl variables: + * * ix_crcstrip: 0: keep CRC in rx frames (default), 1: strip it. * During regular operations the CRC is stripped, but on some * hardware reception of frames not multiple of 64 is slower, @@ -56,17 +59,11 @@ * * ix_rx_miss, ix_rx_miss_bufs: * count packets that might be missed due to lost interrupts. - * - * ix_use_dd - * use the dd bit for completed tx transmissions. - * This is tricky, much better to use TDH for now. */ SYSCTL_DECL(_dev_netmap); -static int ix_rx_miss, ix_rx_miss_bufs, ix_use_dd, ix_crcstrip; +static int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip, CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames"); -SYSCTL_INT(_dev_netmap, OID_AUTO, ix_use_dd, - CTLFLAG_RW, &ix_use_dd, 0, "use dd instead of tdh to detect tx frames"); SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss, CTLFLAG_RW, &ix_rx_miss, 0, "potentially missed rx intr"); SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss_bufs, @@ -110,283 +107,235 @@ set_crcstrip(struct ixgbe_hw *hw, int onoff) IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc); } + /* - * Register/unregister. We are already under core lock. + * Register/unregister. We are already under netmap lock. * Only called on the first register or the last unregister. */ static int -ixgbe_netmap_reg(struct ifnet *ifp, int onoff) +ixgbe_netmap_reg(struct netmap_adapter *na, int onoff) { + struct ifnet *ifp = na->ifp; struct adapter *adapter = ifp->if_softc; - struct netmap_adapter *na = NA(ifp); - int error = 0; - - if (na == NULL) - return EINVAL; /* no netmap support here */ IXGBE_CORE_LOCK(adapter); - ixgbe_disable_intr(adapter); + ixgbe_disable_intr(adapter); // XXX maybe ixgbe_stop ? /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); set_crcstrip(&adapter->hw, onoff); - if (onoff) { /* enable netmap mode */ - ifp->if_capenable |= IFCAP_NETMAP; - - /* save if_transmit and replace with our routine */ - na->if_transmit = ifp->if_transmit; - ifp->if_transmit = netmap_transmit; - - /* - * reinitialize the adapter, now with netmap flag set, - * so the rings will be set accordingly. - */ - ixgbe_init_locked(adapter); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == 0) { - error = ENOMEM; - goto fail; - } - } else { /* reset normal mode (explicit request or netmap failed) */ -fail: - /* restore if_transmit */ - ifp->if_transmit = na->if_transmit; - ifp->if_capenable &= ~IFCAP_NETMAP; - /* initialize the card, this time in standard mode */ - ixgbe_init_locked(adapter); /* also enables intr */ + /* enable or disable flags and callbacks in na and ifp */ + if (onoff) { + nm_set_native_flags(na); + } else { + nm_clear_native_flags(na); } - set_crcstrip(&adapter->hw, onoff); + ixgbe_init_locked(adapter); /* also enables intr */ + set_crcstrip(&adapter->hw, onoff); // XXX why twice ? IXGBE_CORE_UNLOCK(adapter); - return (error); + return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } /* * Reconcile kernel and user view of the transmit ring. - * This routine might be called frequently so it must be efficient. * - * ring->cur holds the userspace view of the current ring index. Userspace - * has filled the tx slots from the previous call's ring->cur up to but not - * including ring->cur for this call. In this function the kernel updates - * kring->nr_hwcur to ring->cur, thus slots [kring->nr_hwcur, ring->cur) are - * now ready to transmit. At the last interrupt kring->nr_hwavail slots were - * available. + * Userspace wants to send packets up to the one before ring->cur, + * kernel knows kring->nr_hwcur is the first unsent packet. * - * This function runs under lock (acquired from the caller or internally). - * It must first update ring->avail to what the kernel knows, - * subtract the newly used slots (ring->cur - kring->nr_hwcur) - * from both avail and nr_hwavail, and set ring->nr_hwcur = ring->cur - * issuing a dmamap_sync on all slots. + * Here we push packets out (as many as possible), and possibly + * reclaim buffers from previously completed transmission. * - * Since ring comes from userspace, its content must be read only once, - * and validated before being used to update the kernel's structures. - * (this is also true for every use of ring in the kernel). + * ring->avail is not used on input, but it is updated on return. * - * ring->avail is never used, only checked for bogus values. - * - * I flags & FORCE_RECLAIM, reclaim transmitted - * buffers irrespective of interrupt mitigation. + * The caller (netmap) guarantees that there is only one instance + * running at any time. Any interference with other driver + * methods should be handled by the individual drivers. */ static int -ixgbe_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) +ixgbe_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct tx_ring *txr = &adapter->tx_rings[ring_nr]; - struct netmap_adapter *na = NA(adapter->ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, l, n = 0; - u_int const k = ring->cur, lim = kring->nkr_num_slots - 1; - + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, new_slots; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_txsync_prologue(kring, &new_slots); /* - * ixgbe can generate an interrupt on every tx packet, but it - * seems very expensive, so we interrupt once every half ring, - * or when requested with NS_REPORT + * interrupts on every tx packet are expensive so request + * them every half ring, or where NS_REPORT is set */ u_int report_frequency = kring->nkr_num_slots >> 1; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct tx_ring *txr = &adapter->tx_rings[ring_nr]; + int reclaim_tx; + + if (cur > lim) /* error checking in nm_txsync_prologue() */ return netmap_ring_reinit(kring); bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_POSTREAD); /* - * Process new packets to send. j is the current index in the - * netmap ring, l is the corresponding index in the NIC ring. + * First part: process new packets to send. + * nm_i is the current index in the netmap ring, + * nic_i is the corresponding index in the NIC ring. * The two numbers differ because upon a *_init() we reset * the NIC ring but leave the netmap ring unchanged. * For the transmit ring, we have * - * j = kring->nr_hwcur - * l = IXGBE_TDT (not tracked in the driver) + * nm_i = kring->nr_hwcur + * nic_i = IXGBE_TDT (not tracked in the driver) * and - * j == (l + kring->nkr_hwofs) % ring_size + * nm_i == (nic_i + kring->nkr_hwofs) % ring_size * * In this driver kring->nkr_hwofs >= 0, but for other * drivers it might be negative as well. */ - j = kring->nr_hwcur; - if (j != k) { /* we have new packets to send */ - prefetch(&ring->slot[j]); - l = netmap_idx_k2n(kring, j); /* NIC index */ - prefetch(&txr->tx_buffers[l]); - for (n = 0; j != k; n++) { - /* - * Collect per-slot info. - * Note that txbuf and curr are indexed by l. - * - * In this driver we collect the buffer address - * (using the PNMB() macro) because we always - * need to rewrite it into the NIC ring. - * Many other drivers preserve the address, so - * we only need to access it if NS_BUF_CHANGED - * is set. - * XXX note, on this device the dmamap* calls are - * not necessary because tag is 0, however just accessing - * the per-packet tag kills 1Mpps at 900 MHz. - */ - struct netmap_slot *slot = &ring->slot[j]; - union ixgbe_adv_tx_desc *curr = &txr->tx_base[l]; - struct ixgbe_tx_buf *txbuf = &txr->tx_buffers[l]; - uint64_t paddr; - // XXX type for flags and len ? - int flags = ((slot->flags & NS_REPORT) || - j == 0 || j == report_frequency) ? - IXGBE_TXD_CMD_RS : 0; + + /* + * If we have packets to send (kring->nr_hwcur != ring->cur) + * iterate over the netmap ring, fetch length and update + * the corresponding slot in the NIC ring. Some drivers also + * need to update the buffer's physical address in the NIC slot + * even NS_BUF_CHANGED is not set (PNMB computes the addresses). + * + * The netmap_reload_map() calls is especially expensive, + * even when (as in this case) the tag is 0, so do only + * when the buffer has actually changed. + * + * If possible do not set the report/intr bit on all slots, + * but only a few times per ring or when NS_REPORT is set. + * + * Finally, on 10G and faster drivers, it might be useful + * to prefetch the next slot and txr entry. + */ + + nm_i = kring->nr_hwcur; + if (nm_i != cur) { /* we have new packets to send */ + nic_i = netmap_idx_k2n(kring, nm_i); + + prefetch(&ring->slot[nm_i]); + prefetch(&txr->tx_buffers[nic_i]); + + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; u_int len = slot->len; + uint64_t paddr; void *addr = PNMB(slot, &paddr); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; - prefetch(&ring->slot[j]); - prefetch(&txr->tx_buffers[l]); + /* device-specific */ + union ixgbe_adv_tx_desc *curr = &txr->tx_base[nic_i]; + struct ixgbe_tx_buf *txbuf = &txr->tx_buffers[nic_i]; + int flags = (slot->flags & NS_REPORT || + nic_i == 0 || nic_i == report_frequency) ? + IXGBE_TXD_CMD_RS : 0; - /* - * Quick check for valid addr and len. - * NMB() returns netmap_buffer_base for invalid - * buffer indexes (but the address is still a - * valid one to be used in a ring). slot->len is - * unsigned so no need to check for negative values. - */ - if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { -ring_reset: - return netmap_ring_reinit(kring); - } + /* prefetch for next round */ + prefetch(&ring->slot[nm_i + 1]); + prefetch(&txr->tx_buffers[nic_i + 1]); + + NM_CHECK_ADDR_LEN(addr, len); if (slot->flags & NS_BUF_CHANGED) { - /* buffer has changed, unload and reload map */ + /* buffer has changed, reload map */ netmap_reload_map(txr->txtag, txbuf->map, addr); - slot->flags &= ~NS_BUF_CHANGED; } - slot->flags &= ~NS_REPORT; - /* - * Fill the slot in the NIC ring. - * In this driver we need to rewrite the buffer - * address in the NIC ring. Other drivers do not - * need this. - * Use legacy descriptor, it is faster. - */ + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + + /* Fill the slot in the NIC ring. */ + /* Use legacy descriptor, they are faster? */ curr->read.buffer_addr = htole64(paddr); curr->read.olinfo_status = 0; curr->read.cmd_type_len = htole32(len | flags | IXGBE_ADVTXD_DCMD_IFCS | IXGBE_TXD_CMD_EOP); /* make sure changes to the buffer are synced */ - bus_dmamap_sync(txr->txtag, txbuf->map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(txr->txtag, txbuf->map, + BUS_DMASYNC_PREWRITE); + + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } - kring->nr_hwcur = k; /* the saved ring->cur */ - /* decrease avail by number of packets sent */ - kring->nr_hwavail -= n; + kring->nr_hwcur = cur; /* the saved ring->cur */ + /* decrease avail by # of packets sent minus previous ones */ + kring->nr_hwavail -= new_slots; /* synchronize the NIC ring */ bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - /* (re)start the transmitter up to slot l (excluded) */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), l); + + /* (re)start the tx unit up to slot nic_i (excluded) */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), nic_i); } /* - * Reclaim buffers for completed transmissions. + * Second part: reclaim buffers for completed transmissions. * Because this is expensive (we read a NIC register etc.) * we only do it in specific cases (see below). - * In all cases kring->nr_kflags indicates which slot will be - * checked upon a tx interrupt (nkr_num_slots means none). */ if (flags & NAF_FORCE_RECLAIM) { - j = 1; /* forced reclaim, ignore interrupts */ - kring->nr_kflags = kring->nkr_num_slots; + reclaim_tx = 1; /* forced reclaim */ } else if (kring->nr_hwavail > 0) { - j = 0; /* buffers still available: no reclaim, ignore intr. */ - kring->nr_kflags = kring->nkr_num_slots; + reclaim_tx = 0; /* have buffers, no reclaim */ } else { /* - * no buffers available, locate a slot for which we request - * ReportStatus (approximately half ring after next_to_clean) - * and record it in kring->nr_kflags. - * If the slot has DD set, do the reclaim looking at TDH, - * otherwise we go to sleep (in netmap_poll()) and will be - * woken up when slot nr_kflags will be ready. + * No buffers available. Locate previous slot with + * REPORT_STATUS set. + * If the slot has DD set, we can reclaim space, + * otherwise wait for the next interrupt. + * This enables interrupt moderation on the tx + * side though it might reduce throughput. */ struct ixgbe_legacy_tx_desc *txd = (struct ixgbe_legacy_tx_desc *)txr->tx_base; - j = txr->next_to_clean + kring->nkr_num_slots/2; - if (j >= kring->nkr_num_slots) - j -= kring->nkr_num_slots; + nic_i = txr->next_to_clean + report_frequency; + if (nic_i > lim) + nic_i -= lim + 1; // round to the closest with dd set - j= (j < kring->nkr_num_slots / 4 || j >= kring->nkr_num_slots*3/4) ? + nic_i = (nic_i < kring->nkr_num_slots / 4 || + nic_i >= kring->nkr_num_slots*3/4) ? 0 : report_frequency; - kring->nr_kflags = j; /* the slot to check */ - j = txd[j].upper.fields.status & IXGBE_TXD_STAT_DD; // XXX cpu_to_le32 ? + reclaim_tx = txd[nic_i].upper.fields.status & IXGBE_TXD_STAT_DD; // XXX cpu_to_le32 ? } - if (j) { - int delta; - + if (reclaim_tx) { /* * Record completed transmissions. * We (re)use the driver's txr->next_to_clean to keep * track of the most recently completed transmission. * - * The datasheet discourages the use of TDH to find out the - * number of sent packets. We should rather check the DD - * status bit in a packet descriptor. However, we only set - * the "report status" bit for some descriptors (a kind of - * interrupt mitigation), so we can only check on those. - * For the time being we use TDH, as we do it infrequently - * enough not to pose performance problems. + * The datasheet discourages the use of TDH to find + * out the number of sent packets, but we only set + * REPORT_STATUS in a few slots so TDH is the only + * good way. */ - if (ix_use_dd) { - struct ixgbe_legacy_tx_desc *txd = - (struct ixgbe_legacy_tx_desc *)txr->tx_base; - u_int k1 = netmap_idx_k2n(kring, kring->nr_hwcur); - l = txr->next_to_clean; - delta = 0; - while (l != k1 && - txd[l].upper.fields.status & IXGBE_TXD_STAT_DD) { - delta++; - l = (l == lim) ? 0 : l + 1; + nic_i = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(ring_nr)); + if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */ + D("TDH wrap %d", nic_i); + nic_i -= kring->nkr_num_slots; } - } else { - l = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(ring_nr)); - if (l >= kring->nkr_num_slots) { /* XXX can happen */ - D("TDH wrap %d", l); - l -= kring->nkr_num_slots; - } - delta = l - txr->next_to_clean; - } - if (delta) { + if (nic_i != txr->next_to_clean) { + n = (nic_i + lim + 1) - txr->next_to_clean; + if (n > lim) + n -= lim + 1; /* some tx completed, increment avail */ - if (delta < 0) - delta += kring->nkr_num_slots; - txr->next_to_clean = l; - kring->nr_hwavail += delta; - if (kring->nr_hwavail > lim) - goto ring_reset; + txr->next_to_clean = nic_i; + kring->nr_hwavail += n; + if (kring->nr_hwavail > lim) { + RD(5, "bad hwavail %d", + kring->nr_hwavail); + return netmap_ring_reinit(kring); + } } } - /* update avail to what the kernel knows */ - ring->avail = kring->nr_hwavail; + + nm_txsync_finalize(kring, cur); return 0; } @@ -394,11 +343,12 @@ ixgbe_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) /* * Reconcile kernel and user view of the receive ring. - * Same as for the txsync, this routine must be efficient and - * avoid races in accessing the shared regions. + * Same as for the txsync, this routine must be efficient. + * The caller guarantees a single invocations, but races against + * the rest of the driver should be handled here. * - * When called, userspace has read data from slots kring->nr_hwcur - * up to ring->cur (excluded). + * When called, userspace has released buffers up to + * ring->cur - ring->reserved (last one excluded). * * The last interrupt reported kring->nr_hwavail slots available * after kring->nr_hwcur. @@ -410,18 +360,23 @@ ixgbe_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) * of whether or not we received an interrupt. */ static int -ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) +ixgbe_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) { - struct adapter *adapter = ifp->if_softc; - struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; - struct netmap_adapter *na = NA(adapter->ifp); + struct ifnet *ifp = na->ifp; struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; - u_int j, l, n, lim = kring->nkr_num_slots - 1; + u_int nm_i; /* index into the netmap ring */ + u_int nic_i; /* index into the NIC ring */ + u_int n, resvd; + u_int const lim = kring->nkr_num_slots - 1; + u_int const cur = nm_rxsync_prologue(kring, &resvd); /* cur + res */ int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; - u_int k = ring->cur, resvd = ring->reserved; - if (k > lim) + /* device-specific */ + struct adapter *adapter = ifp->if_softc; + struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; + + if (cur > lim) return netmap_ring_reinit(kring); /* XXX check sync modes */ @@ -429,17 +384,17 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); /* - * First part, import newly received packets into the netmap ring. + * First part: import newly received packets. * - * j is the index of the next free slot in the netmap ring, - * and l is the index of the next received packet in the NIC ring, + * nm_i is the index of the next free slot in the netmap ring, + * nic_i is the index of the next received packet in the NIC ring, * and they may differ in case if_init() has been called while * in netmap mode. For the receive ring we have * - * j = (kring->nr_hwcur + kring->nr_hwavail) % ring_size - * l = rxr->next_to_check; + * nm_i = (kring->nr_hwcur + kring->nr_hwavail) % ring_size + * nic_i = rxr->next_to_check; * and - * j == (l + kring->nkr_hwofs) % ring_size + * nm_i == (nic_i + kring->nkr_hwofs) % ring_size * * rxr->next_to_check is set to 0 on a ring reinit */ @@ -447,21 +402,21 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) int crclen = ix_crcstrip ? 0 : 4; uint16_t slot_flags = kring->nkr_slot_flags; - l = rxr->next_to_check; - j = netmap_idx_n2k(kring, l); + nic_i = rxr->next_to_check; + nm_i = netmap_idx_n2k(kring, nic_i); for (n = 0; ; n++) { - union ixgbe_adv_rx_desc *curr = &rxr->rx_base[l]; + union ixgbe_adv_rx_desc *curr = &rxr->rx_base[nic_i]; uint32_t staterr = le32toh(curr->wb.upper.status_error); if ((staterr & IXGBE_RXD_STAT_DD) == 0) break; - ring->slot[j].len = le16toh(curr->wb.upper.length) - crclen; - ring->slot[j].flags = slot_flags; + ring->slot[nm_i].len = le16toh(curr->wb.upper.length) - crclen; + ring->slot[nm_i].flags = slot_flags; bus_dmamap_sync(rxr->ptag, - rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + rxr->rx_buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD); + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } if (n) { /* update the state variables */ if (netmap_no_pendintr && !force_update) { @@ -469,48 +424,36 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) ix_rx_miss ++; ix_rx_miss_bufs += n; } - rxr->next_to_check = l; + rxr->next_to_check = nic_i; kring->nr_hwavail += n; } kring->nr_kflags &= ~NKR_PENDINTR; } /* - * Skip past packets that userspace has released - * (from kring->nr_hwcur to ring->cur - ring->reserved excluded), + * Second part: skip past packets that userspace has released. + * (kring->nr_hwcur to ring->cur - ring->reserved excluded), * and make the buffers available for reception. - * As usual j is the index in the netmap ring, l is the index - * in the NIC ring, and j == (l + kring->nkr_hwofs) % ring_size + * As usual nm_i is the index in the netmap ring, + * nic_i is the index in the NIC ring, and + * nm_i == (nic_i + kring->nkr_hwofs) % ring_size */ - j = kring->nr_hwcur; - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - if (j != k) { /* userspace has released some packets. */ - l = netmap_idx_k2n(kring, j); - for (n = 0; j != k; n++) { - /* collect per-slot info, with similar validations - * and flag handling as in the txsync code. - * - * NOTE curr and rxbuf are indexed by l. - * Also, this driver needs to update the physical - * address in the NIC ring, but other drivers - * may not have this requirement. - */ - struct netmap_slot *slot = &ring->slot[j]; - union ixgbe_adv_rx_desc *curr = &rxr->rx_base[l]; - struct ixgbe_rx_buf *rxbuf = &rxr->rx_buffers[l]; + nm_i = kring->nr_hwcur; + if (nm_i != cur) { + nic_i = netmap_idx_k2n(kring, nm_i); + for (n = 0; nm_i != cur; n++) { + struct netmap_slot *slot = &ring->slot[nm_i]; uint64_t paddr; void *addr = PNMB(slot, &paddr); + union ixgbe_adv_rx_desc *curr = &rxr->rx_base[nic_i]; + struct ixgbe_rx_buf *rxbuf = &rxr->rx_buffers[nic_i]; + if (addr == netmap_buffer_base) /* bad buf */ goto ring_reset; if (slot->flags & NS_BUF_CHANGED) { + /* buffer has changed, reload map */ netmap_reload_map(rxr->ptag, rxbuf->pmap, addr); slot->flags &= ~NS_BUF_CHANGED; } @@ -518,20 +461,23 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) curr->read.pkt_addr = htole64(paddr); bus_dmamap_sync(rxr->ptag, rxbuf->pmap, BUS_DMASYNC_PREREAD); - j = (j == lim) ? 0 : j + 1; - l = (l == lim) ? 0 : l + 1; + nm_i = nm_next(nm_i, lim); + nic_i = nm_next(nic_i, lim); } kring->nr_hwavail -= n; - kring->nr_hwcur = k; + kring->nr_hwcur = cur; + bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - /* IMPORTANT: we must leave one free slot in the ring, - * so move l back by one unit + /* + * IMPORTANT: we must leave one free slot in the ring, + * so move nic_i back by one unit */ - l = (l == 0) ? lim : l - 1; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), l); + nic_i = (nic_i == 0) ? lim : nic_i - 1; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), nic_i); } - /* tell userspace that there are new packets */ + + /* tell userspace that there might be new packets */ ring->avail = kring->nr_hwavail - resvd; return 0; @@ -562,7 +508,8 @@ ixgbe_netmap_attach(struct adapter *adapter) na.nm_txsync = ixgbe_netmap_txsync; na.nm_rxsync = ixgbe_netmap_rxsync; na.nm_register = ixgbe_netmap_reg; - netmap_attach(&na, adapter->num_queues); -} + na.num_tx_rings = na.num_rx_rings = adapter->num_queues; + netmap_attach(&na); +} /* end of file */ diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c index 19be406f6dbc..033cd3059e17 100644 --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -8,7 +8,7 @@ * 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. + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -25,6 +25,8 @@ /* + * $FreeBSD$ + * * This module supports memory mapped access to network devices, * see netmap(4). * @@ -130,131 +132,36 @@ ports attached to the switch) #if defined(__FreeBSD__) #include /* prerequisite */ -__FBSDID("$FreeBSD$"); - #include -#include #include #include /* defines used in kernel.h */ -#include #include /* types used in module initialization */ -#include /* cdevsw struct */ -#include /* uio struct */ +#include /* cdevsw struct, UID, GID */ #include #include /* struct socket */ #include -#include /* PROT_EXEC */ #include -#include #include -#include /* vtophys */ -#include /* vtophys */ -#include -#include -#include -#include -#include #include /* sockaddrs */ #include #include #include #include #include /* BIOCIMMEDIATE */ -#include #include /* bus_dmamap_* */ #include #include -#define prefetch(x) __builtin_prefetch(x) -#define BDG_RWLOCK_T struct rwlock // struct rwlock +/* reduce conditional code */ +#define init_waitqueue_head(x) // only needed in linux -#define BDG_RWINIT(b) \ - rw_init_flags(&(b)->bdg_lock, "bdg lock", RW_NOWITNESS) -#define BDG_WLOCK(b) rw_wlock(&(b)->bdg_lock) -#define BDG_WUNLOCK(b) rw_wunlock(&(b)->bdg_lock) -#define BDG_RLOCK(b) rw_rlock(&(b)->bdg_lock) -#define BDG_RTRYLOCK(b) rw_try_rlock(&(b)->bdg_lock) -#define BDG_RUNLOCK(b) rw_runlock(&(b)->bdg_lock) -#define BDG_RWDESTROY(b) rw_destroy(&(b)->bdg_lock) - - -/* netmap global lock. - * normally called within the user thread (upon a system call) - * or when a file descriptor or process is terminated - * (last close or last munmap) - */ - -#define NMG_LOCK_T struct mtx -#define NMG_LOCK_INIT() mtx_init(&netmap_global_lock, "netmap global lock", NULL, MTX_DEF) -#define NMG_LOCK_DESTROY() mtx_destroy(&netmap_global_lock) -#define NMG_LOCK() mtx_lock(&netmap_global_lock) -#define NMG_UNLOCK() mtx_unlock(&netmap_global_lock) -#define NMG_LOCK_ASSERT() mtx_assert(&netmap_global_lock, MA_OWNED) - - -/* atomic operations */ -#include -#define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1)) -#define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0) #elif defined(linux) #include "bsd_glue.h" -static netdev_tx_t linux_netmap_start_xmit(struct sk_buff *, struct net_device *); - -static struct device_driver* -linux_netmap_find_driver(struct device *dev) -{ - struct device_driver *dd; - - while ( (dd = dev->driver) == NULL ) { - if ( (dev = dev->parent) == NULL ) - return NULL; - } - return dd; -} - -static struct net_device* -ifunit_ref(const char *name) -{ - struct net_device *ifp = dev_get_by_name(&init_net, name); - struct device_driver *dd; - - if (ifp == NULL) - return NULL; - - if ( (dd = linux_netmap_find_driver(&ifp->dev)) == NULL ) - goto error; - - if (!try_module_get(dd->owner)) - goto error; - - return ifp; -error: - dev_put(ifp); - return NULL; -} - -static void -if_rele(struct net_device *ifp) -{ - struct device_driver *dd; - dd = linux_netmap_find_driver(&ifp->dev); - dev_put(ifp); - if (dd) - module_put(dd->owner); -} - -// XXX a mtx would suffice here too 20130404 gl -#define NMG_LOCK_T struct semaphore -#define NMG_LOCK_INIT() sema_init(&netmap_global_lock, 1) -#define NMG_LOCK_DESTROY() -#define NMG_LOCK() down(&netmap_global_lock) -#define NMG_UNLOCK() up(&netmap_global_lock) -#define NMG_LOCK_ASSERT() // XXX to be completed #elif defined(__APPLE__) @@ -306,57 +213,46 @@ int netmap_txsync_retry = 2; SYSCTL_INT(_dev_netmap, OID_AUTO, txsync_retry, CTLFLAG_RW, &netmap_txsync_retry, 0 , "Number of txsync loops in bridge's flush."); -int netmap_drop = 0; /* debugging */ int netmap_flags = 0; /* debug flags */ int netmap_fwd = 0; /* force transparent mode */ int netmap_mmap_unreg = 0; /* allow mmap of unregistered fds */ -SYSCTL_INT(_dev_netmap, OID_AUTO, drop, CTLFLAG_RW, &netmap_drop, 0 , ""); +/* + * netmap_admode selects the netmap mode to use. + * Invalid values are reset to NETMAP_ADMODE_BEST + */ +enum { NETMAP_ADMODE_BEST = 0, /* use native, fallback to generic */ + NETMAP_ADMODE_NATIVE, /* either native or none */ + NETMAP_ADMODE_GENERIC, /* force generic */ + NETMAP_ADMODE_LAST }; +#define NETMAP_ADMODE_NATIVE 1 /* Force native netmap adapter. */ +#define NETMAP_ADMODE_GENERIC 2 /* Force generic netmap adapter. */ +#define NETMAP_ADMODE_BEST 0 /* Priority to native netmap adapter. */ +static int netmap_admode = NETMAP_ADMODE_BEST; + +int netmap_generic_mit = 100*1000; /* Generic mitigation interval in nanoseconds. */ +int netmap_generic_ringsize = 1024; /* Generic ringsize. */ + SYSCTL_INT(_dev_netmap, OID_AUTO, flags, CTLFLAG_RW, &netmap_flags, 0 , ""); SYSCTL_INT(_dev_netmap, OID_AUTO, fwd, CTLFLAG_RW, &netmap_fwd, 0 , ""); SYSCTL_INT(_dev_netmap, OID_AUTO, mmap_unreg, CTLFLAG_RW, &netmap_mmap_unreg, 0, ""); +SYSCTL_INT(_dev_netmap, OID_AUTO, admode, CTLFLAG_RW, &netmap_admode, 0 , ""); +SYSCTL_INT(_dev_netmap, OID_AUTO, generic_mit, CTLFLAG_RW, &netmap_generic_mit, 0 , ""); +SYSCTL_INT(_dev_netmap, OID_AUTO, generic_ringsize, CTLFLAG_RW, &netmap_generic_ringsize, 0 , ""); NMG_LOCK_T netmap_global_lock; -/* - * protect against multiple threads using the same ring. - * also check that the ring has not been stopped. - */ -#define NM_KR_BUSY 1 -#define NM_KR_STOPPED 2 -static void nm_kr_put(struct netmap_kring *kr); -static __inline int nm_kr_tryget(struct netmap_kring *kr) -{ - /* check a first time without taking the lock - * to avoid starvation for nm_kr_get() - */ - if (unlikely(kr->nkr_stopped)) { - ND("ring %p stopped (%d)", kr, kr->nkr_stopped); - return NM_KR_STOPPED; - } - if (unlikely(NM_ATOMIC_TEST_AND_SET(&kr->nr_busy))) - return NM_KR_BUSY; - /* check a second time with lock held */ - if (unlikely(kr->nkr_stopped)) { - ND("ring %p stopped (%d)", kr, kr->nkr_stopped); - nm_kr_put(kr); - return NM_KR_STOPPED; - } - return 0; -} -static __inline void nm_kr_put(struct netmap_kring *kr) -{ - NM_ATOMIC_CLEAR(&kr->nr_busy); -} - -static void nm_kr_get(struct netmap_kring *kr) +static void +nm_kr_get(struct netmap_kring *kr) { while (NM_ATOMIC_TEST_AND_SET(&kr->nr_busy)) tsleep(kr, 0, "NM_KR_GET", 4); } -static void nm_disable_ring(struct netmap_kring *kr) + +void +netmap_disable_ring(struct netmap_kring *kr) { kr->nkr_stopped = 1; nm_kr_get(kr); @@ -365,7 +261,9 @@ static void nm_disable_ring(struct netmap_kring *kr) nm_kr_put(kr); } -void netmap_disable_all_rings(struct ifnet *ifp) + +static void +netmap_set_all_rings(struct ifnet *ifp, int stopped) { struct netmap_adapter *na; int i; @@ -375,35 +273,37 @@ void netmap_disable_all_rings(struct ifnet *ifp) na = NA(ifp); - for (i = 0; i < na->num_tx_rings + 1; i++) { - nm_disable_ring(na->tx_rings + i); - selwakeuppri(&na->tx_rings[i].si, PI_NET); + for (i = 0; i <= na->num_tx_rings; i++) { + if (stopped) + netmap_disable_ring(na->tx_rings + i); + else + na->tx_rings[i].nkr_stopped = 0; + na->nm_notify(na, i, NR_TX, NAF_DISABLE_NOTIFY | + (i == na->num_tx_rings ? NAF_GLOBAL_NOTIFY: 0)); } - for (i = 0; i < na->num_rx_rings + 1; i++) { - nm_disable_ring(na->rx_rings + i); - selwakeuppri(&na->rx_rings[i].si, PI_NET); + + for (i = 0; i <= na->num_rx_rings; i++) { + if (stopped) + netmap_disable_ring(na->rx_rings + i); + else + na->rx_rings[i].nkr_stopped = 0; + na->nm_notify(na, i, NR_RX, NAF_DISABLE_NOTIFY | + (i == na->num_rx_rings ? NAF_GLOBAL_NOTIFY: 0)); } - selwakeuppri(&na->tx_si, PI_NET); - selwakeuppri(&na->rx_si, PI_NET); } -void netmap_enable_all_rings(struct ifnet *ifp) + +void +netmap_disable_all_rings(struct ifnet *ifp) { - struct netmap_adapter *na; - int i; + netmap_set_all_rings(ifp, 1 /* stopped */); +} - if (!(ifp->if_capenable & IFCAP_NETMAP)) - return; - na = NA(ifp); - for (i = 0; i < na->num_tx_rings + 1; i++) { - D("enabling %p", na->tx_rings + i); - na->tx_rings[i].nkr_stopped = 0; - } - for (i = 0; i < na->num_rx_rings + 1; i++) { - D("enabling %p", na->rx_rings + i); - na->rx_rings[i].nkr_stopped = 0; - } +void +netmap_enable_all_rings(struct ifnet *ifp) +{ + netmap_set_all_rings(ifp, 0 /* enabled */); } @@ -432,6 +332,7 @@ nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg) return *v; } + /* * packet-dump function, user-supplied or static buffer. * The destination buffer must be at least 30+4*len @@ -440,7 +341,7 @@ const char * nm_dump_buf(char *p, int len, int lim, char *dst) { static char _dst[8192]; - int i, j, i0; + int i, j, i0; static char hex[] ="0123456789abcdef"; char *o; /* output position */ @@ -477,358 +378,13 @@ nm_dump_buf(char *p, int len, int lim, char *dst) return dst; } -/* - * system parameters (most of them in netmap_kern.h) - * NM_NAME prefix for switch port names, default "vale" - * NM_BDG_MAXPORTS number of ports - * NM_BRIDGES max number of switches in the system. - * XXX should become a sysctl or tunable - * - * Switch ports are named valeX:Y where X is the switch name and Y - * is the port. If Y matches a physical interface name, the port is - * connected to a physical device. - * - * Unlike physical interfaces, switch ports use their own memory region - * for rings and buffers. - * The virtual interfaces use per-queue lock instead of core lock. - * In the tx loop, we aggregate traffic in batches to make all operations - * faster. The batch size is bridge_batch. - */ -#define NM_BDG_MAXRINGS 16 /* XXX unclear how many. */ -#define NM_BDG_MAXSLOTS 4096 /* XXX same as above */ -#define NM_BRIDGE_RINGSIZE 1024 /* in the device */ -#define NM_BDG_HASH 1024 /* forwarding table entries */ -#define NM_BDG_BATCH 1024 /* entries in the forwarding buffer */ -#define NM_MULTISEG 64 /* max size of a chain of bufs */ -/* actual size of the tables */ -#define NM_BDG_BATCH_MAX (NM_BDG_BATCH + NM_MULTISEG) -/* NM_FT_NULL terminates a list of slots in the ft */ -#define NM_FT_NULL NM_BDG_BATCH_MAX -#define NM_BRIDGES 8 /* number of bridges */ - - -/* - * bridge_batch is set via sysctl to the max batch size to be - * used in the bridge. The actual value may be larger as the - * last packet in the block may overflow the size. - */ -int bridge_batch = NM_BDG_BATCH; /* bridge batch size */ -SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , ""); - - -/* - * These are used to handle reference counters for bridge ports. - */ -#define ADD_BDG_REF(ifp) refcount_acquire(&NA(ifp)->na_bdg_refcount) -#define DROP_BDG_REF(ifp) refcount_release(&NA(ifp)->na_bdg_refcount) - -/* The bridge references the buffers using the device specific look up table */ -static inline void * -BDG_NMB(struct netmap_mem_d *nmd, struct netmap_slot *slot) -{ - struct lut_entry *lut = nmd->pools[NETMAP_BUF_POOL].lut; - uint32_t i = slot->buf_idx; - return (unlikely(i >= nmd->pools[NETMAP_BUF_POOL].objtotal)) ? lut[0].vaddr : lut[i].vaddr; -} - -static int bdg_netmap_attach(struct netmap_adapter *); -static int bdg_netmap_reg(struct ifnet *ifp, int onoff); -int kern_netmap_regif(struct nmreq *nmr); - -/* - * Each transmit queue accumulates a batch of packets into - * a structure before forwarding. Packets to the same - * destination are put in a list using ft_next as a link field. - * ft_frags and ft_next are valid only on the first fragment. - */ -struct nm_bdg_fwd { /* forwarding entry for a bridge */ - void *ft_buf; /* netmap or indirect buffer */ - uint8_t ft_frags; /* how many fragments (only on 1st frag) */ - uint8_t _ft_port; /* dst port (unused) */ - uint16_t ft_flags; /* flags, e.g. indirect */ - uint16_t ft_len; /* src fragment len */ - uint16_t ft_next; /* next packet to same destination */ -}; - -/* - * For each output interface, nm_bdg_q is used to construct a list. - * bq_len is the number of output buffers (we can have coalescing - * during the copy). - */ -struct nm_bdg_q { - uint16_t bq_head; - uint16_t bq_tail; - uint32_t bq_len; /* number of buffers */ -}; - -/* XXX revise this */ -struct nm_hash_ent { - uint64_t mac; /* the top 2 bytes are the epoch */ - uint64_t ports; -}; - -/* - * nm_bridge is a descriptor for a VALE switch. - * Interfaces for a bridge are all in bdg_ports[]. - * The array has fixed size, an empty entry does not terminate - * the search, but lookups only occur on attach/detach so we - * don't mind if they are slow. - * - * The bridge is non blocking on the transmit ports: excess - * packets are dropped if there is no room on the output port. - * - * bdg_lock protects accesses to the bdg_ports array. - * This is a rw lock (or equivalent). - */ -struct nm_bridge { - /* XXX what is the proper alignment/layout ? */ - BDG_RWLOCK_T bdg_lock; /* protects bdg_ports */ - int bdg_namelen; - uint32_t bdg_active_ports; /* 0 means free */ - char bdg_basename[IFNAMSIZ]; - - /* Indexes of active ports (up to active_ports) - * and all other remaining ports. - */ - uint8_t bdg_port_index[NM_BDG_MAXPORTS]; - - struct netmap_adapter *bdg_ports[NM_BDG_MAXPORTS]; - - - /* - * The function to decide the destination port. - * It returns either of an index of the destination port, - * NM_BDG_BROADCAST to broadcast this packet, or NM_BDG_NOPORT not to - * forward this packet. ring_nr is the source ring index, and the - * function may overwrite this value to forward this packet to a - * different ring index. - * This function must be set by netmap_bdgctl(). - */ - bdg_lookup_fn_t nm_bdg_lookup; - - /* the forwarding table, MAC+ports. - * XXX should be changed to an argument to be passed to - * the lookup function, and allocated on attach - */ - struct nm_hash_ent ht[NM_BDG_HASH]; -}; - - -/* - * XXX in principle nm_bridges could be created dynamically - * Right now we have a static array and deletions are protected - * by an exclusive lock. - */ -struct nm_bridge nm_bridges[NM_BRIDGES]; - - -/* - * A few function to tell which kind of port are we using. - * XXX should we hold a lock ? - * - * nma_is_vp() virtual port - * nma_is_host() port connected to the host stack - * nma_is_hw() port connected to a NIC - */ -int nma_is_vp(struct netmap_adapter *na); -int -nma_is_vp(struct netmap_adapter *na) -{ - return na->nm_register == bdg_netmap_reg; -} - -static __inline int -nma_is_host(struct netmap_adapter *na) -{ - return na->nm_register == NULL; -} - -static __inline int -nma_is_hw(struct netmap_adapter *na) -{ - /* In case of sw adapter, nm_register is NULL */ - return !nma_is_vp(na) && !nma_is_host(na); -} - - -/* - * If the NIC is owned by the kernel - * (i.e., bridge), neither another bridge nor user can use it; - * if the NIC is owned by a user, only users can share it. - * Evaluation must be done under NMG_LOCK(). - */ -#define NETMAP_OWNED_BY_KERN(ifp) (!nma_is_vp(NA(ifp)) && NA(ifp)->na_bdg) -#define NETMAP_OWNED_BY_ANY(ifp) \ - (NETMAP_OWNED_BY_KERN(ifp) || (NA(ifp)->refcount > 0)) - -/* - * NA(ifp)->bdg_port port index - */ - - -/* - * this is a slightly optimized copy routine which rounds - * to multiple of 64 bytes and is often faster than dealing - * with other odd sizes. We assume there is enough room - * in the source and destination buffers. - * - * XXX only for multiples of 64 bytes, non overlapped. - */ -static inline void -pkt_copy(void *_src, void *_dst, int l) -{ - uint64_t *src = _src; - uint64_t *dst = _dst; - if (unlikely(l >= 1024)) { - memcpy(dst, src, l); - return; - } - for (; likely(l > 0); l-=64) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - } -} - - -/* - * locate a bridge among the existing ones. - * MUST BE CALLED WITH NMG_LOCK() - * - * a ':' in the name terminates the bridge name. Otherwise, just NM_NAME. - * We assume that this is called with a name of at least NM_NAME chars. - */ -static struct nm_bridge * -nm_find_bridge(const char *name, int create) -{ - int i, l, namelen; - struct nm_bridge *b = NULL; - - NMG_LOCK_ASSERT(); - - namelen = strlen(NM_NAME); /* base length */ - l = name ? strlen(name) : 0; /* actual length */ - if (l < namelen) { - D("invalid bridge name %s", name ? name : NULL); - return NULL; - } - for (i = namelen + 1; i < l; i++) { - if (name[i] == ':') { - namelen = i; - break; - } - } - if (namelen >= IFNAMSIZ) - namelen = IFNAMSIZ; - ND("--- prefix is '%.*s' ---", namelen, name); - - /* lookup the name, remember empty slot if there is one */ - for (i = 0; i < NM_BRIDGES; i++) { - struct nm_bridge *x = nm_bridges + i; - - if (x->bdg_active_ports == 0) { - if (create && b == NULL) - b = x; /* record empty slot */ - } else if (x->bdg_namelen != namelen) { - continue; - } else if (strncmp(name, x->bdg_basename, namelen) == 0) { - ND("found '%.*s' at %d", namelen, name, i); - b = x; - break; - } - } - if (i == NM_BRIDGES && b) { /* name not found, can create entry */ - /* initialize the bridge */ - strncpy(b->bdg_basename, name, namelen); - ND("create new bridge %s with ports %d", b->bdg_basename, - b->bdg_active_ports); - b->bdg_namelen = namelen; - b->bdg_active_ports = 0; - for (i = 0; i < NM_BDG_MAXPORTS; i++) - b->bdg_port_index[i] = i; - /* set the default function */ - b->nm_bdg_lookup = netmap_bdg_learning; - /* reset the MAC address table */ - bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH); - } - return b; -} - - -/* - * Free the forwarding tables for rings attached to switch ports. - */ -static void -nm_free_bdgfwd(struct netmap_adapter *na) -{ - int nrings, i; - struct netmap_kring *kring; - - NMG_LOCK_ASSERT(); - nrings = nma_is_vp(na) ? na->num_tx_rings : na->num_rx_rings; - kring = nma_is_vp(na) ? na->tx_rings : na->rx_rings; - for (i = 0; i < nrings; i++) { - if (kring[i].nkr_ft) { - free(kring[i].nkr_ft, M_DEVBUF); - kring[i].nkr_ft = NULL; /* protect from freeing twice */ - } - } - if (nma_is_hw(na)) - nm_free_bdgfwd(SWNA(na->ifp)); -} - - -/* - * Allocate the forwarding tables for the rings attached to the bridge ports. - */ -static int -nm_alloc_bdgfwd(struct netmap_adapter *na) -{ - int nrings, l, i, num_dstq; - struct netmap_kring *kring; - - NMG_LOCK_ASSERT(); - /* all port:rings + broadcast */ - num_dstq = NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1; - l = sizeof(struct nm_bdg_fwd) * NM_BDG_BATCH_MAX; - l += sizeof(struct nm_bdg_q) * num_dstq; - l += sizeof(uint16_t) * NM_BDG_BATCH_MAX; - - nrings = nma_is_vp(na) ? na->num_tx_rings : na->num_rx_rings; - kring = nma_is_vp(na) ? na->tx_rings : na->rx_rings; - for (i = 0; i < nrings; i++) { - struct nm_bdg_fwd *ft; - struct nm_bdg_q *dstq; - int j; - - ft = malloc(l, M_DEVBUF, M_NOWAIT | M_ZERO); - if (!ft) { - nm_free_bdgfwd(na); - return ENOMEM; - } - dstq = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); - for (j = 0; j < num_dstq; j++) { - dstq[j].bq_head = dstq[j].bq_tail = NM_FT_NULL; - dstq[j].bq_len = 0; - } - kring[i].nkr_ft = ft; - } - if (nma_is_hw(na)) - nm_alloc_bdgfwd(SWNA(na->ifp)); - return 0; -} /* * Fetch configuration from the device, to cope with dynamic * reconfigurations after loading the module. */ -static int +int netmap_update_config(struct netmap_adapter *na) { struct ifnet *ifp = na->ifp; @@ -836,7 +392,7 @@ netmap_update_config(struct netmap_adapter *na) txr = txd = rxr = rxd = 0; if (na->nm_config) { - na->nm_config(ifp, &txr, &txd, &rxr, &rxd); + na->nm_config(na, &txr, &txd, &rxr, &rxd); } else { /* take whatever we had at init time */ txr = na->num_tx_rings; @@ -848,15 +404,15 @@ netmap_update_config(struct netmap_adapter *na) if (na->num_tx_rings == txr && na->num_tx_desc == txd && na->num_rx_rings == rxr && na->num_rx_desc == rxd) return 0; /* nothing changed */ - if (netmap_verbose || na->refcount > 0) { + if (netmap_verbose || na->active_fds > 0) { D("stored config %s: txring %d x %d, rxring %d x %d", - ifp->if_xname, + NM_IFPNAME(ifp), na->num_tx_rings, na->num_tx_desc, na->num_rx_rings, na->num_rx_desc); D("new config %s: txring %d x %d, rxring %d x %d", - ifp->if_xname, txr, txd, rxr, rxd); + NM_IFPNAME(ifp), txr, txd, rxr, rxd); } - if (na->refcount == 0) { + if (na->active_fds == 0) { D("configuration changed (but fine)"); na->num_tx_rings = txr; na->num_tx_desc = txd; @@ -868,53 +424,112 @@ netmap_update_config(struct netmap_adapter *na) return 1; } -static struct netmap_if * + +int +netmap_krings_create(struct netmap_adapter *na, u_int ntx, u_int nrx, u_int tailroom) +{ + u_int i, len, ndesc; + struct netmap_kring *kring; + + len = (ntx + nrx) * sizeof(struct netmap_kring) + tailroom; + + na->tx_rings = malloc((size_t)len, M_DEVBUF, M_NOWAIT | M_ZERO); + if (na->tx_rings == NULL) { + D("Cannot allocate krings"); + return ENOMEM; + } + na->rx_rings = na->tx_rings + ntx; + + ndesc = na->num_tx_desc; + for (i = 0; i < ntx; i++) { /* Transmit rings */ + kring = &na->tx_rings[i]; + bzero(kring, sizeof(*kring)); + kring->na = na; + kring->nkr_num_slots = ndesc; + /* + * IMPORTANT: + * Always keep one slot empty, so we can detect new + * transmissions comparing cur and nr_hwcur (they are + * the same only if there are no new transmissions). + */ + kring->nr_hwavail = ndesc - 1; + mtx_init(&kring->q_lock, "nm_txq_lock", NULL, MTX_DEF); + init_waitqueue_head(&kring->si); + } + + ndesc = na->num_rx_desc; + for (i = 0; i < nrx; i++) { /* Receive rings */ + kring = &na->rx_rings[i]; + bzero(kring, sizeof(*kring)); + kring->na = na; + kring->nkr_num_slots = ndesc; + mtx_init(&kring->q_lock, "nm_rxq_lock", NULL, MTX_DEF); + init_waitqueue_head(&kring->si); + } + init_waitqueue_head(&na->tx_si); + init_waitqueue_head(&na->rx_si); + + na->tailroom = na->rx_rings + nrx; + + return 0; + +} + + +void +netmap_krings_delete(struct netmap_adapter *na) +{ + int i; + + for (i = 0; i < na->num_tx_rings + 1; i++) { + mtx_destroy(&na->tx_rings[i].q_lock); + } + for (i = 0; i < na->num_rx_rings + 1; i++) { + mtx_destroy(&na->rx_rings[i].q_lock); + } + free(na->tx_rings, M_DEVBUF); + na->tx_rings = na->rx_rings = na->tailroom = NULL; +} + + +static struct netmap_if* netmap_if_new(const char *ifname, struct netmap_adapter *na) { + struct netmap_if *nifp; + if (netmap_update_config(na)) { /* configuration mismatch, report and fail */ return NULL; } - return netmap_mem_if_new(ifname, na); + + if (na->active_fds) + goto final; + + if (na->nm_krings_create(na)) + goto cleanup; + + if (netmap_mem_rings_create(na)) + goto cleanup; + +final: + + nifp = netmap_mem_if_new(ifname, na); + if (nifp == NULL) + goto cleanup; + + return (nifp); + +cleanup: + + if (na->active_fds == 0) { + netmap_mem_rings_delete(na); + na->nm_krings_delete(na); + } + + return NULL; } -/* Structure associated to each thread which registered an interface. - * - * The first 4 fields of this structure are written by NIOCREGIF and - * read by poll() and NIOC?XSYNC. - * There is low contention among writers (actually, a correct user program - * should have no contention among writers) and among writers and readers, - * so we use a single global lock to protect the structure initialization. - * Since initialization involves the allocation of memory, we reuse the memory - * allocator lock. - * Read access to the structure is lock free. Readers must check that - * np_nifp is not NULL before using the other fields. - * If np_nifp is NULL initialization has not been performed, so they should - * return an error to userlevel. - * - * The ref_done field is used to regulate access to the refcount in the - * memory allocator. The refcount must be incremented at most once for - * each open("/dev/netmap"). The increment is performed by the first - * function that calls netmap_get_memory() (currently called by - * mmap(), NIOCGINFO and NIOCREGIF). - * If the refcount is incremented, it is then decremented when the - * private structure is destroyed. - */ -struct netmap_priv_d { - struct netmap_if * volatile np_nifp; /* netmap if descriptor. */ - - struct ifnet *np_ifp; /* device for which we hold a ref. */ - int np_ringid; /* from the ioctl */ - u_int np_qfirst, np_qlast; /* range of rings to scan */ - uint16_t np_txpoll; - - struct netmap_mem_d *np_mref; /* use with NMG_LOCK held */ -#ifdef __FreeBSD__ - int np_refcount; /* use with NMG_LOCK held */ -#endif /* __FreeBSD__ */ -}; - /* grab a reference to the memory allocator, if we don't have one already. The * reference is taken from the netmap_adapter registered with the priv. * @@ -925,7 +540,7 @@ netmap_get_memory_locked(struct netmap_priv_d* p) struct netmap_mem_d *nmd; int error = 0; - if (p->np_ifp == NULL) { + if (p->np_na == NULL) { if (!netmap_mmap_unreg) return ENODEV; /* for compatibility with older versions of the API @@ -934,7 +549,7 @@ netmap_get_memory_locked(struct netmap_priv_d* p) */ nmd = &nm_mem; } else { - nmd = NA(p->np_ifp)->nm_mem; + nmd = p->np_na->nm_mem; } if (p->np_mref == NULL) { error = netmap_mem_finalize(nmd); @@ -950,7 +565,8 @@ netmap_get_memory_locked(struct netmap_priv_d* p) return error; } -static int + +int netmap_get_memory(struct netmap_priv_d* p) { int error; @@ -960,12 +576,14 @@ netmap_get_memory(struct netmap_priv_d* p) return error; } + static int netmap_have_memory_locked(struct netmap_priv_d* p) { return p->np_mref != NULL; } + static void netmap_drop_memory_locked(struct netmap_priv_d* p) { @@ -975,11 +593,12 @@ netmap_drop_memory_locked(struct netmap_priv_d* p) } } + /* * File descriptor's private data destructor. * * Call nm_register(ifp,0) to stop netmap mode on the interface and - * revert to normal operation. We expect that np_ifp has not gone. + * revert to normal operation. We expect that np_na->ifp has not gone. * The second argument is the nifp to work on. In some cases it is * not attached yet to the netmap_priv_d so we need to pass it as * a separate argument. @@ -988,16 +607,15 @@ netmap_drop_memory_locked(struct netmap_priv_d* p) static void netmap_do_unregif(struct netmap_priv_d *priv, struct netmap_if *nifp) { - struct ifnet *ifp = priv->np_ifp; - struct netmap_adapter *na = NA(ifp); + struct netmap_adapter *na = priv->np_na; + struct ifnet *ifp = na->ifp; NMG_LOCK_ASSERT(); - na->refcount--; - if (na->refcount <= 0) { /* last instance */ - u_int i; + na->active_fds--; + if (na->active_fds <= 0) { /* last instance */ if (netmap_verbose) - D("deleting last instance for %s", ifp->if_xname); + D("deleting last instance for %s", NM_IFPNAME(ifp)); /* * (TO CHECK) This function is only called * when the last reference to this file descriptor goes @@ -1012,140 +630,33 @@ netmap_do_unregif(struct netmap_priv_d *priv, struct netmap_if *nifp) * happens if the close() occurs while a concurrent * syscall is running. */ - na->nm_register(ifp, 0); /* off, clear IFCAP_NETMAP */ + if (ifp) + na->nm_register(na, 0); /* off, clear flags */ /* Wake up any sleeping threads. netmap_poll will * then return POLLERR * XXX The wake up now must happen during *_down(), when * we order all activities to stop. -gl */ - nm_free_bdgfwd(na); - for (i = 0; i < na->num_tx_rings + 1; i++) { - mtx_destroy(&na->tx_rings[i].q_lock); - } - for (i = 0; i < na->num_rx_rings + 1; i++) { - mtx_destroy(&na->rx_rings[i].q_lock); - } /* XXX kqueue(9) needed; these will mirror knlist_init. */ /* knlist_destroy(&na->tx_si.si_note); */ /* knlist_destroy(&na->rx_si.si_note); */ - if (nma_is_hw(na)) - SWNA(ifp)->tx_rings = SWNA(ifp)->rx_rings = NULL; + + /* delete rings and buffers */ + netmap_mem_rings_delete(na); + na->nm_krings_delete(na); } - /* - * netmap_mem_if_delete() deletes the nifp, and if this is - * the last instance also buffers, rings and krings. - */ + /* delete the nifp */ netmap_mem_if_delete(na, nifp); } -/* we assume netmap adapter exists - * Called with NMG_LOCK held - */ -static void -nm_if_rele(struct ifnet *ifp) -{ - int i, is_hw, hw, sw, lim; - struct nm_bridge *b; - struct netmap_adapter *na; - uint8_t tmp[NM_BDG_MAXPORTS]; - - NMG_LOCK_ASSERT(); - /* I can be called not only for get_ifp()-ed references where netmap's - * capability is guaranteed, but also for non-netmap-capable NICs. - */ - if (!NETMAP_CAPABLE(ifp) || !NA(ifp)->na_bdg) { - if_rele(ifp); - return; - } - na = NA(ifp); - b = na->na_bdg; - is_hw = nma_is_hw(na); - - ND("%s has %d references", ifp->if_xname, NA(ifp)->na_bdg_refcount); - - if (!DROP_BDG_REF(ifp)) - return; - - /* - New algorithm: - make a copy of bdg_port_index; - lookup NA(ifp)->bdg_port and SWNA(ifp)->bdg_port - in the array of bdg_port_index, replacing them with - entries from the bottom of the array; - decrement bdg_active_ports; - acquire BDG_WLOCK() and copy back the array. - */ - - hw = NA(ifp)->bdg_port; - sw = (is_hw && SWNA(ifp)->na_bdg) ? SWNA(ifp)->bdg_port : -1; - lim = b->bdg_active_ports; - - ND("detach %d and %d (lim %d)", hw, sw, lim); - /* make a copy of the list of active ports, update it, - * and then copy back within BDG_WLOCK(). - */ - memcpy(tmp, b->bdg_port_index, sizeof(tmp)); - for (i = 0; (hw >= 0 || sw >= 0) && i < lim; ) { - if (hw >= 0 && tmp[i] == hw) { - ND("detach hw %d at %d", hw, i); - lim--; /* point to last active port */ - tmp[i] = tmp[lim]; /* swap with i */ - tmp[lim] = hw; /* now this is inactive */ - hw = -1; - } else if (sw >= 0 && tmp[i] == sw) { - ND("detach sw %d at %d", sw, i); - lim--; - tmp[i] = tmp[lim]; - tmp[lim] = sw; - sw = -1; - } else { - i++; - } - } - if (hw >= 0 || sw >= 0) { - D("XXX delete failed hw %d sw %d, should panic...", hw, sw); - } - hw = NA(ifp)->bdg_port; - sw = (is_hw && SWNA(ifp)->na_bdg) ? SWNA(ifp)->bdg_port : -1; - - BDG_WLOCK(b); - b->bdg_ports[hw] = NULL; - na->na_bdg = NULL; - if (sw >= 0) { - b->bdg_ports[sw] = NULL; - SWNA(ifp)->na_bdg = NULL; - } - memcpy(b->bdg_port_index, tmp, sizeof(tmp)); - b->bdg_active_ports = lim; - BDG_WUNLOCK(b); - - ND("now %d active ports", lim); - if (lim == 0) { - ND("marking bridge %s as free", b->bdg_basename); - b->nm_bdg_lookup = NULL; - } - - if (is_hw) { - if_rele(ifp); - } else { - if (na->na_flags & NAF_MEM_OWNER) - netmap_mem_private_delete(na->nm_mem); - bzero(na, sizeof(*na)); - free(na, M_DEVBUF); - bzero(ifp, sizeof(*ifp)); - free(ifp, M_DEVBUF); - } -} - - /* * returns 1 if this is the last instance and we can free priv */ -static int +int netmap_dtor_locked(struct netmap_priv_d *priv) { - struct ifnet *ifp = priv->np_ifp; + struct netmap_adapter *na = priv->np_na; #ifdef __FreeBSD__ /* @@ -1156,17 +667,21 @@ netmap_dtor_locked(struct netmap_priv_d *priv) return 0; } #endif /* __FreeBSD__ */ - if (ifp) { - netmap_do_unregif(priv, priv->np_nifp); + if (!na) { + return 1; //XXX is it correct? } + netmap_do_unregif(priv, priv->np_nifp); + priv->np_nifp = NULL; netmap_drop_memory_locked(priv); - if (ifp) { - nm_if_rele(ifp); /* might also destroy *na */ + if (priv->np_na) { + netmap_adapter_put(na); + priv->np_na = NULL; } return 1; } -static void + +void netmap_dtor(void *data) { struct netmap_priv_d *priv = data; @@ -1182,190 +697,6 @@ netmap_dtor(void *data) } -#ifdef __FreeBSD__ - -/* - * In order to track whether pages are still mapped, we hook into - * the standard cdev_pager and intercept the constructor and - * destructor. - */ - -struct netmap_vm_handle_t { - struct cdev *dev; - struct netmap_priv_d *priv; -}; - -static int -netmap_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, - vm_ooffset_t foff, struct ucred *cred, u_short *color) -{ - struct netmap_vm_handle_t *vmh = handle; - D("handle %p size %jd prot %d foff %jd", - handle, (intmax_t)size, prot, (intmax_t)foff); - dev_ref(vmh->dev); - return 0; -} - - -static void -netmap_dev_pager_dtor(void *handle) -{ - struct netmap_vm_handle_t *vmh = handle; - struct cdev *dev = vmh->dev; - struct netmap_priv_d *priv = vmh->priv; - D("handle %p", handle); - netmap_dtor(priv); - free(vmh, M_DEVBUF); - dev_rel(dev); -} - -static int -netmap_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, - int prot, vm_page_t *mres) -{ - struct netmap_vm_handle_t *vmh = object->handle; - struct netmap_priv_d *priv = vmh->priv; - vm_paddr_t paddr; - vm_page_t page; - vm_memattr_t memattr; - vm_pindex_t pidx; - - ND("object %p offset %jd prot %d mres %p", - object, (intmax_t)offset, prot, mres); - memattr = object->memattr; - pidx = OFF_TO_IDX(offset); - paddr = netmap_mem_ofstophys(priv->np_mref, offset); - if (paddr == 0) - return VM_PAGER_FAIL; - - if (((*mres)->flags & PG_FICTITIOUS) != 0) { - /* - * If the passed in result page is a fake page, update it with - * the new physical address. - */ - page = *mres; - vm_page_updatefake(page, paddr, memattr); - } else { - /* - * Replace the passed in reqpage page with our own fake page and - * free up the all of the original pages. - */ -#ifndef VM_OBJECT_WUNLOCK /* FreeBSD < 10.x */ -#define VM_OBJECT_WUNLOCK VM_OBJECT_UNLOCK -#define VM_OBJECT_WLOCK VM_OBJECT_LOCK -#endif /* VM_OBJECT_WUNLOCK */ - - VM_OBJECT_WUNLOCK(object); - page = vm_page_getfake(paddr, memattr); - VM_OBJECT_WLOCK(object); - vm_page_lock(*mres); - vm_page_free(*mres); - vm_page_unlock(*mres); - *mres = page; - vm_page_insert(page, object, pidx); - } - page->valid = VM_PAGE_BITS_ALL; - return (VM_PAGER_OK); -} - - -static struct cdev_pager_ops netmap_cdev_pager_ops = { - .cdev_pg_ctor = netmap_dev_pager_ctor, - .cdev_pg_dtor = netmap_dev_pager_dtor, - .cdev_pg_fault = netmap_dev_pager_fault, -}; - - -static int -netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff, - vm_size_t objsize, vm_object_t *objp, int prot) -{ - int error; - struct netmap_vm_handle_t *vmh; - struct netmap_priv_d *priv; - vm_object_t obj; - - D("cdev %p foff %jd size %jd objp %p prot %d", cdev, - (intmax_t )*foff, (intmax_t )objsize, objp, prot); - - vmh = malloc(sizeof(struct netmap_vm_handle_t), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (vmh == NULL) - return ENOMEM; - vmh->dev = cdev; - - NMG_LOCK(); - error = devfs_get_cdevpriv((void**)&priv); - if (error) - goto err_unlock; - vmh->priv = priv; - priv->np_refcount++; - NMG_UNLOCK(); - - error = netmap_get_memory(priv); - if (error) - goto err_deref; - - obj = cdev_pager_allocate(vmh, OBJT_DEVICE, - &netmap_cdev_pager_ops, objsize, prot, - *foff, NULL); - if (obj == NULL) { - D("cdev_pager_allocate failed"); - error = EINVAL; - goto err_deref; - } - - *objp = obj; - return 0; - -err_deref: - NMG_LOCK(); - priv->np_refcount--; -err_unlock: - NMG_UNLOCK(); -// err: - free(vmh, M_DEVBUF); - return error; -} - - -// XXX can we remove this ? -static int -netmap_close(struct cdev *dev, int fflag, int devtype, struct thread *td) -{ - if (netmap_verbose) - D("dev %p fflag 0x%x devtype %d td %p", - dev, fflag, devtype, td); - return 0; -} - - -static int -netmap_open(struct cdev *dev, int oflags, int devtype, struct thread *td) -{ - struct netmap_priv_d *priv; - int error; - - (void)dev; - (void)oflags; - (void)devtype; - (void)td; - - // XXX wait or nowait ? - priv = malloc(sizeof(struct netmap_priv_d), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (priv == NULL) - return ENOMEM; - - error = devfs_set_cdevpriv(priv, netmap_dtor); - if (error) - return error; - - priv->np_refcount = 1; - - return 0; -} -#endif /* __FreeBSD__ */ /* @@ -1391,26 +722,19 @@ netmap_open(struct cdev *dev, int oflags, int devtype, struct thread *td) * pass a chain of buffers to the host stack as coming from 'dst' */ static void -netmap_send_up(struct ifnet *dst, struct mbuf *head) +netmap_send_up(struct ifnet *dst, struct mbq *q) { struct mbuf *m; /* send packets up, outside the lock */ - while ((m = head) != NULL) { - head = head->m_nextpkt; - m->m_nextpkt = NULL; + while ((m = mbq_dequeue(q)) != NULL) { if (netmap_verbose & NM_VERB_HOST) D("sending up pkt %p size %d", m, MBUF_LEN(m)); NM_SEND_UP(dst, m); } + mbq_destroy(q); } -struct mbq { - struct mbuf *head; - struct mbuf *tail; - int count; -}; - /* * put a copy of the buffers marked NS_FORWARD into an mbuf chain. @@ -1425,9 +749,9 @@ netmap_grab_packets(struct netmap_kring *kring, struct mbq *q, int force) * XXX handle reserved */ u_int lim = kring->nkr_num_slots - 1; - struct mbuf *m, *tail = q->tail; + struct mbuf *m; u_int k = kring->ring->cur, n = kring->ring->reserved; - struct netmap_mem_d *nmd = kring->na->nm_mem; + struct netmap_adapter *na = kring->na; /* compute the final position, ring->cur - ring->reserved */ if (n > 0) { @@ -1441,25 +765,18 @@ netmap_grab_packets(struct netmap_kring *kring, struct mbq *q, int force) n = nm_next(n, lim); if ((slot->flags & NS_FORWARD) == 0 && !force) continue; - if (slot->len < 14 || slot->len > NETMAP_BDG_BUF_SIZE(nmd)) { + if (slot->len < 14 || slot->len > NETMAP_BDG_BUF_SIZE(na->nm_mem)) { D("bad pkt at %d len %d", n, slot->len); continue; } slot->flags &= ~NS_FORWARD; // XXX needed ? /* XXX adapt to the case of a multisegment packet */ - m = m_devget(BDG_NMB(nmd, slot), slot->len, 0, kring->na->ifp, NULL); + m = m_devget(BDG_NMB(na, slot), slot->len, 0, na->ifp, NULL); if (m == NULL) break; - if (tail) - tail->m_nextpkt = m; - else - q->head = m; - tail = m; - q->count++; - m->m_nextpkt = NULL; + mbq_enqueue(q, m); } - q->tail = tail; } @@ -1536,16 +853,19 @@ netmap_sw_to_nic(struct netmap_adapter *na) * can be among multiple user threads erroneously calling * this routine concurrently. */ -static void +void netmap_txsync_to_host(struct netmap_adapter *na) { struct netmap_kring *kring = &na->tx_rings[na->num_tx_rings]; struct netmap_ring *ring = kring->ring; u_int k, lim = kring->nkr_num_slots - 1; - struct mbq q = { NULL, NULL, 0 }; + struct mbq q; + int error; - if (nm_kr_tryget(kring)) { - D("ring %p busy (user error)", kring); + error = nm_kr_tryget(kring); + if (error) { + if (error == NM_KR_BUSY) + D("ring %p busy (user error)", kring); return; } k = ring->cur; @@ -1560,29 +880,13 @@ netmap_txsync_to_host(struct netmap_adapter *na) * In case of no buffers we give up. At the end of the loop, * the queue is drained in all cases. */ + mbq_init(&q); netmap_grab_packets(kring, &q, 1); kring->nr_hwcur = k; kring->nr_hwavail = ring->avail = lim; nm_kr_put(kring); - netmap_send_up(na->ifp, q.head); -} - - -/* - * This is the 'txsync' handler to send from a software ring to the - * host stack. - */ -/* SWNA(ifp)->txrings[0] is always NA(ifp)->txrings[NA(ifp)->num_txrings] */ -static int -netmap_bdg_to_host(struct ifnet *ifp, u_int ring_nr, int flags) -{ - (void)ring_nr; - (void)flags; - if (netmap_verbose > 255) - RD(5, "sync to host %s ring %d", ifp->if_xname, ring_nr); - netmap_txsync_to_host(NA(ifp)); - return 0; + netmap_send_up(na->ifp, &q); } @@ -1610,7 +914,6 @@ netmap_rxsync_from_host(struct netmap_adapter *na, struct thread *td, void *pwai if (kring->nkr_stopped) /* check a first time without lock */ return; - /* XXX as an optimization we could reuse na->core_lock */ mtx_lock(&kring->q_lock); if (kring->nkr_stopped) /* check again with lock held */ @@ -1629,7 +932,7 @@ netmap_rxsync_from_host(struct netmap_adapter *na, struct thread *td, void *pwai ring->reserved = resvd = 0; // XXX panic... } k = (k >= resvd) ? k - resvd : k + lim - resvd; - } + } if (j != k) { n = k >= j ? k - j : k + lim - j; kring->nr_hwavail -= n; @@ -1646,6 +949,104 @@ netmap_rxsync_from_host(struct netmap_adapter *na, struct thread *td, void *pwai } +/* Get a netmap adapter for the port. + * + * If it is possible to satisfy the request, return 0 + * with *na containing the netmap adapter found. + * Otherwise return an error code, with *na containing NULL. + * + * When the port is attached to a bridge, we always return + * EBUSY. + * Otherwise, if the port is already bound to a file descriptor, + * then we unconditionally return the existing adapter into *na. + * In all the other cases, we return (into *na) either native, + * generic or NULL, according to the following table: + * + * native_support + * active_fds dev.netmap.admode YES NO + * ------------------------------------------------------- + * >0 * NA(ifp) NA(ifp) + * + * 0 NETMAP_ADMODE_BEST NATIVE GENERIC + * 0 NETMAP_ADMODE_NATIVE NATIVE NULL + * 0 NETMAP_ADMODE_GENERIC GENERIC GENERIC + * + */ + +int +netmap_get_hw_na(struct ifnet *ifp, struct netmap_adapter **na) +{ + /* generic support */ + int i = netmap_admode; /* Take a snapshot. */ + int error = 0; + struct netmap_adapter *prev_na; + struct netmap_generic_adapter *gna; + + *na = NULL; /* default */ + + /* reset in case of invalid value */ + if (i < NETMAP_ADMODE_BEST || i >= NETMAP_ADMODE_LAST) + i = netmap_admode = NETMAP_ADMODE_BEST; + + if (NETMAP_CAPABLE(ifp)) { + /* If an adapter already exists, but is + * attached to a vale port, we report that the + * port is busy. + */ + if (NETMAP_OWNED_BY_KERN(NA(ifp))) + return EBUSY; + + /* If an adapter already exists, return it if + * there are active file descriptors or if + * netmap is not forced to use generic + * adapters. + */ + if (NA(ifp)->active_fds > 0 || + i != NETMAP_ADMODE_GENERIC) { + *na = NA(ifp); + return 0; + } + } + + /* If there isn't native support and netmap is not allowed + * to use generic adapters, we cannot satisfy the request. + */ + if (!NETMAP_CAPABLE(ifp) && i == NETMAP_ADMODE_NATIVE) + return EINVAL; + + /* Otherwise, create a generic adapter and return it, + * saving the previously used netmap adapter, if any. + * + * Note that here 'prev_na', if not NULL, MUST be a + * native adapter, and CANNOT be a generic one. This is + * true because generic adapters are created on demand, and + * destroyed when not used anymore. Therefore, if the adapter + * currently attached to an interface 'ifp' is generic, it + * must be that + * (NA(ifp)->active_fds > 0 || NETMAP_OWNED_BY_KERN(NA(ifp))). + * Consequently, if NA(ifp) is generic, we will enter one of + * the branches above. This ensures that we never override + * a generic adapter with another generic adapter. + */ + prev_na = NA(ifp); + error = generic_netmap_attach(ifp); + if (error) + return error; + + *na = NA(ifp); + gna = (struct netmap_generic_adapter*)NA(ifp); + gna->prev = prev_na; /* save old na */ + if (prev_na != NULL) { + ifunit_ref(ifp->if_xname); + // XXX add a refcount ? + netmap_adapter_get(prev_na); + } + D("Created generic NA %p (prev %p)", gna, gna->prev); + + return 0; +} + + /* * MUST BE CALLED UNDER NMG_LOCK() * @@ -1666,179 +1067,191 @@ netmap_rxsync_from_host(struct netmap_adapter *na, struct thread *td, void *pwai * being detached from the bridge in error handling. But once refcount * is acquired by this function, it must be released using nm_if_rele(). */ -static int -get_ifp(struct nmreq *nmr, struct ifnet **ifp, int create) +int +netmap_get_na(struct nmreq *nmr, struct netmap_adapter **na, int create) { - const char *name = nmr->nr_name; - int namelen = strlen(name); - struct ifnet *iter = NULL; - int no_prefix = 0; + struct ifnet *ifp; + int error = 0; + struct netmap_adapter *ret; + + *na = NULL; /* default return value */ /* first try to see if this is a bridge port. */ - struct nm_bridge *b; - struct netmap_adapter *na; - int i, j, cand = -1, cand2 = -1; - int needed; - NMG_LOCK_ASSERT(); - *ifp = NULL; /* default */ - if (strncmp(name, NM_NAME, sizeof(NM_NAME) - 1)) { - no_prefix = 1; /* no VALE prefix */ - goto no_bridge_port; + + error = netmap_get_bdg_na(nmr, na, create); + if (error || *na != NULL) /* valid match in netmap_get_bdg_na() */ + return error; + + ifp = ifunit_ref(nmr->nr_name); + if (ifp == NULL) { + return ENXIO; } - b = nm_find_bridge(name, create); - if (b == NULL) { - D("no bridges available for '%s'", name); - return (ENXIO); - } + error = netmap_get_hw_na(ifp, &ret); + if (error) + goto out; - /* Now we are sure that name starts with the bridge's name, - * lookup the port in the bridge. We need to scan the entire - * list. It is not important to hold a WLOCK on the bridge - * during the search because NMG_LOCK already guarantees - * that there are no other possible writers. - */ - - /* lookup in the local list of ports */ - for (j = 0; j < b->bdg_active_ports; j++) { - i = b->bdg_port_index[j]; - na = b->bdg_ports[i]; - // KASSERT(na != NULL); - iter = na->ifp; - /* XXX make sure the name only contains one : */ - if (!strcmp(iter->if_xname, name) /* virtual port */ || - (namelen > b->bdg_namelen && !strcmp(iter->if_xname, - name + b->bdg_namelen + 1)) /* NIC */) { - ADD_BDG_REF(iter); - ND("found existing if %s refs %d", name, - NA(iter)->na_bdg_refcount); - *ifp = iter; - /* we are done, this is surely netmap capable */ - return 0; - } - } - /* not found, should we create it? */ - if (!create) - return ENXIO; - /* yes we should, see if we have space to attach entries */ - needed = 2; /* in some cases we only need 1 */ - if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) { - D("bridge full %d, cannot create new port", b->bdg_active_ports); - return EINVAL; - } - /* record the next two ports available, but do not allocate yet */ - cand = b->bdg_port_index[b->bdg_active_ports]; - cand2 = b->bdg_port_index[b->bdg_active_ports + 1]; - ND("+++ bridge %s port %s used %d avail %d %d", - b->bdg_basename, name, b->bdg_active_ports, cand, cand2); - - /* - * try see if there is a matching NIC with this name - * (after the bridge's name) - */ - iter = ifunit_ref(name + b->bdg_namelen + 1); - if (!iter) { /* this is a virtual port */ - /* Create a temporary NA with arguments, then - * bdg_netmap_attach() will allocate the real one - * and attach it to the ifp - */ - struct netmap_adapter tmp_na; - int error; - - if (nmr->nr_cmd) { - /* nr_cmd must be 0 for a virtual port */ - return EINVAL; - } - bzero(&tmp_na, sizeof(tmp_na)); - /* bound checking */ - tmp_na.num_tx_rings = nmr->nr_tx_rings; - nm_bound_var(&tmp_na.num_tx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); - nmr->nr_tx_rings = tmp_na.num_tx_rings; // write back - tmp_na.num_rx_rings = nmr->nr_rx_rings; - nm_bound_var(&tmp_na.num_rx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); - nmr->nr_rx_rings = tmp_na.num_rx_rings; // write back - nm_bound_var(&nmr->nr_tx_slots, NM_BRIDGE_RINGSIZE, - 1, NM_BDG_MAXSLOTS, NULL); - tmp_na.num_tx_desc = nmr->nr_tx_slots; - nm_bound_var(&nmr->nr_rx_slots, NM_BRIDGE_RINGSIZE, - 1, NM_BDG_MAXSLOTS, NULL); - tmp_na.num_rx_desc = nmr->nr_rx_slots; - - /* create a struct ifnet for the new port. - * need M_NOWAIT as we are under nma_lock - */ - iter = malloc(sizeof(*iter), M_DEVBUF, M_NOWAIT | M_ZERO); - if (!iter) - return ENOMEM; - - strcpy(iter->if_xname, name); - tmp_na.ifp = iter; - /* bdg_netmap_attach creates a struct netmap_adapter */ - error = bdg_netmap_attach(&tmp_na); - if (error) { - D("error %d", error); - free(iter, M_DEVBUF); - return error; - } - cand2 = -1; /* only need one port */ - } else if (NETMAP_CAPABLE(iter)) { /* this is a NIC */ - /* make sure the NIC is not already in use */ - if (NETMAP_OWNED_BY_ANY(iter)) { - D("NIC %s busy, cannot attach to bridge", - iter->if_xname); - if_rele(iter); /* don't detach from bridge */ - return EINVAL; - } - if (nmr->nr_arg1 != NETMAP_BDG_HOST) - cand2 = -1; /* only need one port */ - } else { /* not a netmap-capable NIC */ - if_rele(iter); /* don't detach from bridge */ - return EINVAL; - } - na = NA(iter); - - BDG_WLOCK(b); - na->bdg_port = cand; - ND("NIC %p to bridge port %d", NA(iter), cand); - /* bind the port to the bridge (virtual ports are not active) */ - b->bdg_ports[cand] = na; - na->na_bdg = b; - b->bdg_active_ports++; - if (cand2 >= 0) { - /* also bind the host stack to the bridge */ - b->bdg_ports[cand2] = SWNA(iter); - SWNA(iter)->bdg_port = cand2; - SWNA(iter)->na_bdg = b; - b->bdg_active_ports++; - ND("host %p to bridge port %d", SWNA(iter), cand2); - } - ADD_BDG_REF(iter); // XXX one or two ? - ND("if %s refs %d", name, NA(iter)->na_bdg_refcount); - BDG_WUNLOCK(b); - *ifp = iter; - return 0; - -no_bridge_port: - *ifp = iter; - if (! *ifp) - *ifp = ifunit_ref(name); - if (*ifp == NULL) - return (ENXIO); - - if (NETMAP_CAPABLE(*ifp)) { + if (ret != NULL) { /* Users cannot use the NIC attached to a bridge directly */ - if (no_prefix && NETMAP_OWNED_BY_KERN(*ifp)) { - if_rele(*ifp); /* don't detach from bridge */ - return EINVAL; - } else - return 0; /* valid pointer, we hold the refcount */ + if (NETMAP_OWNED_BY_KERN(ret)) { + error = EINVAL; + goto out; + } + error = 0; + *na = ret; + netmap_adapter_get(ret); } - nm_if_rele(*ifp); - return EINVAL; // not NETMAP capable +out: + if_rele(ifp); + + return error; } +/* + * validate parameters on entry for *_txsync() + * Returns ring->cur if ok, or something >= kring->nkr_num_slots + * in case of error. The extra argument is a pointer to + * 'new_bufs'. XXX this may be deprecated at some point. + * + * Below is a correct configuration on input. ring->cur + * must be in the region covered by kring->hwavail, + * and ring->avail and kring->avail should end at the same slot. + * + * +-hwcur + * | + * v<--hwres-->|<-----hwavail----> + * ------+------------------------------+-------- ring + * | + * |<---avail---> + * +--cur + * + */ +u_int +nm_txsync_prologue(struct netmap_kring *kring, u_int *new_slots) +{ + struct netmap_ring *ring = kring->ring; + u_int cur = ring->cur; /* read only once */ + u_int avail = ring->avail; /* read only once */ + u_int n = kring->nkr_num_slots; + u_int kstart, kend, a; + +#if 1 /* kernel sanity checks */ + if (kring->nr_hwcur >= n || + kring->nr_hwreserved >= n || kring->nr_hwavail >= n || + kring->nr_hwreserved + kring->nr_hwavail >= n) + goto error; +#endif /* kernel sanity checks */ + kstart = kring->nr_hwcur + kring->nr_hwreserved; + if (kstart >= n) + kstart -= n; + kend = kstart + kring->nr_hwavail; + /* user sanity checks. a is the expected avail */ + if (cur < kstart) { + /* too low, but maybe wraparound */ + if (cur + n > kend) + goto error; + *new_slots = cur + n - kstart; + a = kend - cur - n; + } else { + if (cur > kend) + goto error; + *new_slots = cur - kstart; + a = kend - cur; + } + if (a != avail) { + RD(5, "wrong but fixable avail have %d need %d", + avail, a); + ring->avail = avail = a; + } + return cur; + +error: + RD(5, "kring error: hwcur %d hwres %d hwavail %d cur %d av %d", + kring->nr_hwcur, + kring->nr_hwreserved, kring->nr_hwavail, + cur, avail); + return n; +} + + +/* + * validate parameters on entry for *_rxsync() + * Returns ring->cur - ring->reserved if ok, + * or something >= kring->nkr_num_slots + * in case of error. The extra argument is a pointer to + * 'resvd'. XXX this may be deprecated at some point. + * + * Below is a correct configuration on input. ring->cur and + * ring->reserved must be in the region covered by kring->hwavail, + * and ring->avail and kring->avail should end at the same slot. + * + * +-hwcur + * | + * v<-------hwavail----------> + * ---------+--------------------------+-------- ring + * |<--res-->| + * |<---avail---> + * +--cur + * + */ +u_int +nm_rxsync_prologue(struct netmap_kring *kring, u_int *resvd) +{ + struct netmap_ring *ring = kring->ring; + u_int cur = ring->cur; /* read only once */ + u_int avail = ring->avail; /* read only once */ + u_int res = ring->reserved; /* read only once */ + u_int n = kring->nkr_num_slots; + u_int kend = kring->nr_hwcur + kring->nr_hwavail; + u_int a; + +#if 1 /* kernel sanity checks */ + if (kring->nr_hwcur >= n || kring->nr_hwavail >= n) + goto error; +#endif /* kernel sanity checks */ + /* user sanity checks */ + if (res >= n) + goto error; + /* check that cur is valid, a is the expected value of avail */ + if (cur < kring->nr_hwcur) { + /* too low, but maybe wraparound */ + if (cur + n > kend) + goto error; + a = kend - (cur + n); + } else { + if (cur > kend) + goto error; + a = kend - cur; + } + if (a != avail) { + RD(5, "wrong but fixable avail have %d need %d", + avail, a); + ring->avail = avail = a; + } + if (res != 0) { + /* then repeat the check for cur + res */ + cur = (cur >= res) ? cur - res : n + cur - res; + if (cur < kring->nr_hwcur) { + /* too low, but maybe wraparound */ + if (cur + n > kend) + goto error; + } else if (cur > kend) { + goto error; + } + } + *resvd = res; + return cur; + +error: + RD(5, "kring error: hwcur %d hwres %d hwavail %d cur %d av %d res %d", + kring->nr_hwcur, + kring->nr_hwreserved, kring->nr_hwavail, + ring->cur, avail, res); + return n; +} + /* * Error routine called when txsync/rxsync detects an error. * Can't do much more than resetting cur = hwcur, avail = hwavail. @@ -1859,7 +1272,7 @@ netmap_ring_reinit(struct netmap_kring *kring) int errors = 0; // XXX KASSERT nm_kr_tryget - RD(10, "called for %s", kring->na->ifp->if_xname); + RD(10, "called for %s", NM_IFPNAME(kring->na->ifp)); if (ring->cur > lim) errors++; for (i = 0; i <= lim; i++) { @@ -1884,7 +1297,7 @@ netmap_ring_reinit(struct netmap_kring *kring) RD(10, "total %d errors", errors); errors++; RD(10, "%s %s[%d] reinit, cur %d -> %d avail %d -> %d", - kring->na->ifp->if_xname, + NM_IFPNAME(kring->na->ifp), pos < n ? "TX" : "RX", pos < n ? pos : pos - n, ring->cur, kring->nr_hwcur, ring->avail, kring->nr_hwavail); @@ -1902,8 +1315,8 @@ netmap_ring_reinit(struct netmap_kring *kring) static int netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid) { - struct ifnet *ifp = priv->np_ifp; - struct netmap_adapter *na = NA(ifp); + struct netmap_adapter *na = priv->np_na; + struct ifnet *ifp = na->ifp; u_int i = ringid & NETMAP_RING_MASK; /* initially (np_qfirst == np_qlast) we don't want to lock */ u_int lim = na->num_rx_rings; @@ -1928,12 +1341,12 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid) priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1; if (netmap_verbose) { if (ringid & NETMAP_SW_RING) - D("ringid %s set to SW RING", ifp->if_xname); + D("ringid %s set to SW RING", NM_IFPNAME(ifp)); else if (ringid & NETMAP_HW_RING) - D("ringid %s set to HW RING %d", ifp->if_xname, + D("ringid %s set to HW RING %d", NM_IFPNAME(ifp), priv->np_qfirst); else - D("ringid %s set to all %d HW RINGS", ifp->if_xname, lim); + D("ringid %s set to all %d HW RINGS", NM_IFPNAME(ifp), lim); } return 0; } @@ -1944,18 +1357,18 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid) * If success it returns a pointer to netmap_if, otherwise NULL. * This must be called with NMG_LOCK held. */ -static struct netmap_if * -netmap_do_regif(struct netmap_priv_d *priv, struct ifnet *ifp, +struct netmap_if * +netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na, uint16_t ringid, int *err) { - struct netmap_adapter *na = NA(ifp); + struct ifnet *ifp = na->ifp; struct netmap_if *nifp = NULL; - int error, need_mem; + int error, need_mem = 0; NMG_LOCK_ASSERT(); /* ring configuration may have changed, fetch from the card */ netmap_update_config(na); - priv->np_ifp = ifp; /* store the reference */ + priv->np_na = na; /* store the reference */ error = netmap_set_ringid(priv, ringid); if (error) goto out; @@ -1967,57 +1380,40 @@ netmap_do_regif(struct netmap_priv_d *priv, struct ifnet *ifp, if (error) goto out; } - nifp = netmap_if_new(ifp->if_xname, na); + nifp = netmap_if_new(NM_IFPNAME(ifp), na); if (nifp == NULL) { /* allocation failed */ /* we should drop the allocator, but only * if we were the ones who grabbed it */ - if (need_mem) - netmap_drop_memory_locked(priv); error = ENOMEM; goto out; } - na->refcount++; + na->active_fds++; if (ifp->if_capenable & IFCAP_NETMAP) { /* was already set */ } else { - u_int i; /* Otherwise set the card in netmap mode * and make it use the shared buffers. * - * If the interface is attached to a bridge, lock it. - */ - if (NETMAP_OWNED_BY_KERN(ifp)) - BDG_WLOCK(NA(ifp)->na_bdg); - for (i = 0 ; i < na->num_tx_rings + 1; i++) - mtx_init(&na->tx_rings[i].q_lock, "nm_txq_lock", - NULL, MTX_DEF); - for (i = 0 ; i < na->num_rx_rings + 1; i++) { - mtx_init(&na->rx_rings[i].q_lock, "nm_rxq_lock", - NULL, MTX_DEF); - } - if (nma_is_hw(na)) { - SWNA(ifp)->tx_rings = &na->tx_rings[na->num_tx_rings]; - SWNA(ifp)->rx_rings = &na->rx_rings[na->num_rx_rings]; - } - /* * do not core lock because the race is harmless here, * there cannot be any traffic to netmap_transmit() */ - error = na->nm_register(ifp, 1); /* mode on */ - // XXX do we need to nm_alloc_bdgfwd() in all cases ? - if (!error) - error = nm_alloc_bdgfwd(na); + na->na_lut = na->nm_mem->pools[NETMAP_BUF_POOL].lut; + ND("%p->na_lut == %p", na, na->na_lut); + na->na_lut_objtotal = na->nm_mem->pools[NETMAP_BUF_POOL].objtotal; + error = na->nm_register(na, 1); /* mode on */ if (error) { netmap_do_unregif(priv, nifp); nifp = NULL; } - if (NETMAP_OWNED_BY_KERN(ifp)) - BDG_WUNLOCK(NA(ifp)->na_bdg); - } out: *err = error; + if (error) { + priv->np_na = NULL; + if (need_mem) + netmap_drop_memory_locked(priv); + } if (nifp != NULL) { /* * advertise that the interface is ready bt setting ni_nifp. @@ -2030,251 +1426,6 @@ netmap_do_regif(struct netmap_priv_d *priv, struct ifnet *ifp, return nifp; } -/* Process NETMAP_BDG_ATTACH and NETMAP_BDG_DETACH */ -static int -nm_bdg_attach(struct nmreq *nmr) -{ - struct ifnet *ifp; - struct netmap_if *nifp; - struct netmap_priv_d *npriv; - int error; - - npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO); - if (npriv == NULL) - return ENOMEM; - NMG_LOCK(); - error = get_ifp(nmr, &ifp, 1 /* create if not exists */); - if (error) /* no device, or another bridge or user owns the device */ - goto unlock_exit; - /* get_ifp() sets na_bdg if this is a physical interface - * that we can attach to a switch. - */ - if (!NETMAP_OWNED_BY_KERN(ifp)) { - /* got reference to a virtual port or direct access to a NIC. - * perhaps specified no bridge prefix or wrong NIC name - */ - error = EINVAL; - goto unref_exit; - } - - if (NA(ifp)->refcount > 0) { /* already registered */ - error = EBUSY; - DROP_BDG_REF(ifp); - goto unlock_exit; - } - - nifp = netmap_do_regif(npriv, ifp, nmr->nr_ringid, &error); - if (!nifp) { - goto unref_exit; - } - - NA(ifp)->na_kpriv = npriv; - NMG_UNLOCK(); - ND("registered %s to netmap-mode", ifp->if_xname); - return 0; - -unref_exit: - nm_if_rele(ifp); -unlock_exit: - NMG_UNLOCK(); - bzero(npriv, sizeof(*npriv)); - free(npriv, M_DEVBUF); - return error; -} - -static int -nm_bdg_detach(struct nmreq *nmr) -{ - struct ifnet *ifp; - int error; - int last_instance; - - NMG_LOCK(); - error = get_ifp(nmr, &ifp, 0 /* don't create */); - if (error) { /* no device, or another bridge or user owns the device */ - goto unlock_exit; - } - /* XXX do we need to check this ? */ - if (!NETMAP_OWNED_BY_KERN(ifp)) { - /* got reference to a virtual port or direct access to a NIC. - * perhaps specified no bridge's prefix or wrong NIC's name - */ - error = EINVAL; - goto unref_exit; - } - - if (NA(ifp)->refcount == 0) { /* not registered */ - error = EINVAL; - goto unref_exit; - } - - DROP_BDG_REF(ifp); /* the one from get_ifp */ - last_instance = netmap_dtor_locked(NA(ifp)->na_kpriv); /* unregister */ - NMG_UNLOCK(); - if (!last_instance) { - D("--- error, trying to detach an entry with active mmaps"); - error = EINVAL; - } else { - struct netmap_priv_d *npriv = NA(ifp)->na_kpriv; - NA(ifp)->na_kpriv = NULL; - - bzero(npriv, sizeof(*npriv)); - free(npriv, M_DEVBUF); - } - return error; - -unref_exit: - nm_if_rele(ifp); -unlock_exit: - NMG_UNLOCK(); - return error; -} - - -/* Initialize necessary fields of sw adapter located in right after hw's - * one. sw adapter attaches a pair of sw rings of the netmap-mode NIC. - * It is always activated and deactivated at the same tie with the hw's one. - * Thus we don't need refcounting on the sw adapter. - * Regardless of NIC's feature we use separate lock so that anybody can lock - * me independently from the hw adapter. - * Make sure nm_register is NULL to be handled as FALSE in nma_is_hw - */ -static void -netmap_attach_sw(struct ifnet *ifp) -{ - struct netmap_adapter *hw_na = NA(ifp); - struct netmap_adapter *na = SWNA(ifp); - - na->ifp = ifp; - na->num_rx_rings = na->num_tx_rings = 1; - na->num_tx_desc = hw_na->num_tx_desc; - na->num_rx_desc = hw_na->num_rx_desc; - na->nm_txsync = netmap_bdg_to_host; - /* we use the same memory allocator as the - * the hw adapter */ - na->nm_mem = hw_na->nm_mem; -} - - -/* exported to kernel callers, e.g. OVS ? - * Entry point. - * Called without NMG_LOCK. - */ -int -netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func) -{ - struct nm_bridge *b; - struct netmap_adapter *na; - struct ifnet *iter; - char *name = nmr->nr_name; - int cmd = nmr->nr_cmd, namelen = strlen(name); - int error = 0, i, j; - - switch (cmd) { - case NETMAP_BDG_ATTACH: - error = nm_bdg_attach(nmr); - break; - - case NETMAP_BDG_DETACH: - error = nm_bdg_detach(nmr); - break; - - case NETMAP_BDG_LIST: - /* this is used to enumerate bridges and ports */ - if (namelen) { /* look up indexes of bridge and port */ - if (strncmp(name, NM_NAME, strlen(NM_NAME))) { - error = EINVAL; - break; - } - NMG_LOCK(); - b = nm_find_bridge(name, 0 /* don't create */); - if (!b) { - error = ENOENT; - NMG_UNLOCK(); - break; - } - - error = ENOENT; - for (j = 0; j < b->bdg_active_ports; j++) { - i = b->bdg_port_index[j]; - na = b->bdg_ports[i]; - if (na == NULL) { - D("---AAAAAAAAARGH-------"); - continue; - } - iter = na->ifp; - /* the former and the latter identify a - * virtual port and a NIC, respectively - */ - if (!strcmp(iter->if_xname, name) || - (namelen > b->bdg_namelen && - !strcmp(iter->if_xname, - name + b->bdg_namelen + 1))) { - /* bridge index */ - nmr->nr_arg1 = b - nm_bridges; - nmr->nr_arg2 = i; /* port index */ - error = 0; - break; - } - } - NMG_UNLOCK(); - } else { - /* return the first non-empty entry starting from - * bridge nr_arg1 and port nr_arg2. - * - * Users can detect the end of the same bridge by - * seeing the new and old value of nr_arg1, and can - * detect the end of all the bridge by error != 0 - */ - i = nmr->nr_arg1; - j = nmr->nr_arg2; - - NMG_LOCK(); - for (error = ENOENT; i < NM_BRIDGES; i++) { - b = nm_bridges + i; - if (j >= b->bdg_active_ports) { - j = 0; /* following bridges scan from 0 */ - continue; - } - nmr->nr_arg1 = i; - nmr->nr_arg2 = j; - j = b->bdg_port_index[j]; - na = b->bdg_ports[j]; - iter = na->ifp; - strncpy(name, iter->if_xname, (size_t)IFNAMSIZ); - error = 0; - break; - } - NMG_UNLOCK(); - } - break; - - case NETMAP_BDG_LOOKUP_REG: - /* register a lookup function to the given bridge. - * nmr->nr_name may be just bridge's name (including ':' - * if it is not just NM_NAME). - */ - if (!func) { - error = EINVAL; - break; - } - NMG_LOCK(); - b = nm_find_bridge(name, 0 /* don't create */); - if (!b) { - error = EINVAL; - } else { - b->nm_bdg_lookup = func; - } - NMG_UNLOCK(); - break; - - default: - D("invalid cmd (nmr->nr_cmd) (0x%x)", cmd); - error = EINVAL; - break; - } - return error; -} /* @@ -2290,7 +1441,7 @@ netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func) * * Return 0 on success, errno otherwise. */ -static int +int netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { @@ -2353,13 +1504,12 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, if (nmr->nr_name[0] != '\0') { /* get a refcount */ - error = get_ifp(nmr, &ifp, 1 /* create */); + error = netmap_get_na(nmr, &na, 1 /* create */); if (error) break; - na = NA(ifp); /* retrieve the netmap adapter */ - nmd = na->nm_mem; /* and its memory allocator */ + nmd = na->nm_mem; /* get memory allocator */ } - + error = netmap_mem_get_info(nmd, &nmr->nr_memsize, &memflags); if (error) break; @@ -2374,9 +1524,8 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, nmr->nr_tx_slots = na->num_tx_desc; if (memflags & NETMAP_MEM_PRIVATE) nmr->nr_ringid |= NETMAP_PRIV_MEM; + netmap_adapter_put(na); } while (0); - if (ifp) - nm_if_rele(ifp); /* return the refcount */ NMG_UNLOCK(); break; @@ -2388,7 +1537,8 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, } /* possibly attach/detach NIC and VALE switch */ i = nmr->nr_cmd; - if (i == NETMAP_BDG_ATTACH || i == NETMAP_BDG_DETACH) { + if (i == NETMAP_BDG_ATTACH || i == NETMAP_BDG_DETACH + || i == NETMAP_BDG_OFFSET) { error = netmap_bdg_ctl(nmr, NULL); break; } else if (i != 0) { @@ -2402,36 +1552,35 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, do { u_int memflags; - if (priv->np_ifp != NULL) { /* thread already registered */ + if (priv->np_na != NULL) { /* thread already registered */ error = netmap_set_ringid(priv, nmr->nr_ringid); break; } /* find the interface and a reference */ - error = get_ifp(nmr, &ifp, 1 /* create */); /* keep reference */ + error = netmap_get_na(nmr, &na, 1 /* create */); /* keep reference */ if (error) break; - if (NETMAP_OWNED_BY_KERN(ifp)) { - nm_if_rele(ifp); + ifp = na->ifp; + if (NETMAP_OWNED_BY_KERN(na)) { + netmap_adapter_put(na); error = EBUSY; break; } - nifp = netmap_do_regif(priv, ifp, nmr->nr_ringid, &error); + nifp = netmap_do_regif(priv, na, nmr->nr_ringid, &error); if (!nifp) { /* reg. failed, release priv and ref */ - nm_if_rele(ifp); /* return the refcount */ - priv->np_ifp = NULL; + netmap_adapter_put(na); priv->np_nifp = NULL; break; } /* return the offset of the netmap_if object */ - na = NA(ifp); /* retrieve netmap adapter */ nmr->nr_rx_rings = na->num_rx_rings; nmr->nr_tx_rings = na->num_tx_rings; nmr->nr_rx_slots = na->num_rx_desc; nmr->nr_tx_slots = na->num_tx_desc; error = netmap_mem_get_info(na->nm_mem, &nmr->nr_memsize, &memflags); if (error) { - nm_if_rele(ifp); + netmap_adapter_put(na); break; } if (memflags & NETMAP_MEM_PRIVATE) { @@ -2459,15 +1608,21 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, } rmb(); /* make sure following reads are not from cache */ - ifp = priv->np_ifp; /* we have a reference */ + na = priv->np_na; /* we have a reference */ - if (ifp == NULL) { - D("Internal error: nifp != NULL && ifp == NULL"); + if (na == NULL) { + D("Internal error: nifp != NULL && na == NULL"); + error = ENXIO; + break; + } + + ifp = na->ifp; + if (ifp == NULL) { + RD(1, "the ifp is gone"); error = ENXIO; break; } - na = NA(ifp); /* retrieve netmap adapter */ if (priv->np_qfirst == NETMAP_SW_RING) { /* host rings */ if (cmd == NIOCTXSYNC) netmap_txsync_to_host(na); @@ -2493,13 +1648,13 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, D("pre txsync ring %d cur %d hwcur %d", i, kring->ring->cur, kring->nr_hwcur); - na->nm_txsync(ifp, i, NAF_FORCE_RECLAIM); + na->nm_txsync(na, i, NAF_FORCE_RECLAIM); if (netmap_verbose & NM_VERB_TXSYNC) D("post txsync ring %d cur %d hwcur %d", i, kring->ring->cur, kring->nr_hwcur); } else { - na->nm_rxsync(ifp, i, NAF_FORCE_READ); + na->nm_rxsync(na, i, NAF_FORCE_READ); microtime(&na->rx_rings[i].ring->ts); } nm_kr_put(kring); @@ -2521,15 +1676,17 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, bzero(&so, sizeof(so)); NMG_LOCK(); - error = get_ifp(nmr, &ifp, 0 /* don't create */); /* keep reference */ + error = netmap_get_na(nmr, &na, 0 /* don't create */); /* keep reference */ if (error) { + netmap_adapter_put(na); NMG_UNLOCK(); break; } + ifp = na->ifp; so.so_vnet = ifp->if_vnet; // so->so_proto not null. error = ifioctl(&so, cmd, data, td); - nm_if_rele(ifp); + netmap_adapter_put(na); NMG_UNLOCK(); break; } @@ -2560,7 +1717,7 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, * The first one is remapped to pwait as selrecord() uses the name as an * hidden argument. */ -static int +int netmap_poll(struct cdev *dev, int events, struct thread *td) { struct netmap_priv_d *priv = NULL; @@ -2569,12 +1726,18 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) struct netmap_kring *kring; u_int i, check_all_tx, check_all_rx, want_tx, want_rx, revents = 0; u_int lim_tx, lim_rx, host_forwarded = 0; - struct mbq q = { NULL, NULL, 0 }; + struct mbq q; void *pwait = dev; /* linux compatibility */ - int retry_tx = 1; + /* + * In order to avoid nested locks, we need to "double check" + * txsync and rxsync if we decide to do a selrecord(). + * retry_tx (and retry_rx, later) prevent looping forever. + */ + int retry_tx = 1; (void)pwait; + mbq_init(&q); if (devfs_get_cdevpriv((void **)&priv) != 0 || priv == NULL) return POLLERR; @@ -2585,18 +1748,22 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) } rmb(); /* make sure following reads are not from cache */ - ifp = priv->np_ifp; - // XXX check for deleting() ? + na = priv->np_na; + ifp = na->ifp; + // check for deleted + if (ifp == NULL) { + RD(1, "the ifp is gone"); + return POLLERR; + } + if ( (ifp->if_capenable & IFCAP_NETMAP) == 0) return POLLERR; if (netmap_verbose & 0x8000) - D("device %s events 0x%x", ifp->if_xname, events); + D("device %s events 0x%x", NM_IFPNAME(ifp), events); want_tx = events & (POLLOUT | POLLWRNORM); want_rx = events & (POLLIN | POLLRDNORM); - na = NA(ifp); /* retrieve netmap adapter */ - lim_tx = na->num_tx_rings; lim_rx = na->num_rx_rings; @@ -2618,7 +1785,11 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) return (revents); } - /* if we are in transparent mode, check also the host rx ring */ + /* + * If we are in transparent mode, check also the host rx ring + * XXX Transparent mode at the moment requires to bind all + * rings to a single file descriptor. + */ kring = &na->rx_rings[lim_rx]; if ( (priv->np_qlast == NETMAP_HW_RING) // XXX check_all && want_rx @@ -2630,8 +1801,8 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) } /* - * check_all is set if the card has more than one queue AND - * the client is polling all of them. If true, we sleep on + * check_all_{tx|rx} are set if the card has more than one queue AND + * the file descriptor is bound to all of them. If so, we sleep on * the "global" selinfo, otherwise we sleep on individual selinfo * (FreeBSD only allows two selinfo's per file descriptor). * The interrupt routine in the driver wake one or the other @@ -2650,9 +1821,11 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) } /* - * We start with a lock free round which is good if we have - * data available. If this fails, then lock and call the sync + * We start with a lock free round which is cheap if we have + * slots available. If this fails, then lock and call the sync * routines. + * XXX rather than ring->avail >0 should check that + * ring->cur has not reached hwcur+hwavail */ for (i = priv->np_qfirst; want_rx && i < lim_rx; i++) { kring = &na->rx_rings[i]; @@ -2673,6 +1846,8 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) * If we to push packets out (priv->np_txpoll) or want_tx is * still set, we do need to run the txsync calls (on all rings, * to avoid that the tx rings stall). + * XXX should also check cur != hwcur on the tx rings. + * Fortunately, normal tx mode has np_txpoll set. */ if (priv->np_txpoll || want_tx) { /* If we really want to be woken up (want_tx), @@ -2693,18 +1868,27 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) continue; /* make sure only one user thread is doing this */ if (nm_kr_tryget(kring)) { - ND("ring %p busy is %d", kring, (int)kring->nr_busy); + ND("ring %p busy is %d", + kring, (int)kring->nr_busy); revents |= POLLERR; goto out; } if (netmap_verbose & NM_VERB_TXSYNC) D("send %d on %s %d", - kring->ring->cur, ifp->if_xname, i); - if (na->nm_txsync(ifp, i, 0)) + kring->ring->cur, NM_IFPNAME(ifp), i); + if (na->nm_txsync(na, i, 0)) revents |= POLLERR; - /* Check avail/call selrecord only if called with POLLOUT */ + /* Check avail and call selrecord only if + * called with POLLOUT and run out of bufs. + * XXX Note, we cannot trust much ring->avail + * as it is exposed to userspace (even though + * just updated by txsync). We should really + * check kring->nr_hwavail or better have + * txsync set a flag telling if we need + * to do a selrecord(). + */ if (want_tx) { if (kring->ring->avail > 0) { /* stop at the first ring. We don't risk @@ -2748,7 +1932,7 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) netmap_grab_packets(kring, &q, netmap_fwd); } - if (na->nm_rxsync(ifp, i, 0)) + if (na->nm_rxsync(na, i, 0)) revents |= POLLERR; if (netmap_no_timestamp == 0 || kring->ring->flags & NR_TIMESTAMP) { @@ -2784,7 +1968,7 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) } if (q.head) - netmap_send_up(na->ifp, q.head); + netmap_send_up(na->ifp, &q); out: @@ -2793,6 +1977,71 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) /*------- driver support routines ------*/ +static int netmap_hw_krings_create(struct netmap_adapter *); + +static int +netmap_notify(struct netmap_adapter *na, u_int n_ring, enum txrx tx, int flags) +{ + struct netmap_kring *kring; + + if (tx == NR_TX) { + kring = na->tx_rings + n_ring; + selwakeuppri(&kring->si, PI_NET); + if (flags & NAF_GLOBAL_NOTIFY) + selwakeuppri(&na->tx_si, PI_NET); + } else { + kring = na->rx_rings + n_ring; + selwakeuppri(&kring->si, PI_NET); + if (flags & NAF_GLOBAL_NOTIFY) + selwakeuppri(&na->rx_si, PI_NET); + } + return 0; +} + + +// XXX check handling of failures +int +netmap_attach_common(struct netmap_adapter *na) +{ + struct ifnet *ifp = na->ifp; + + if (na->num_tx_rings == 0 || na->num_rx_rings == 0) { + D("%s: invalid rings tx %d rx %d", + ifp->if_xname, na->num_tx_rings, na->num_rx_rings); + return EINVAL; + } + WNA(ifp) = na; + NETMAP_SET_CAPABLE(ifp); + if (na->nm_krings_create == NULL) { + na->nm_krings_create = netmap_hw_krings_create; + na->nm_krings_delete = netmap_krings_delete; + } + if (na->nm_notify == NULL) + na->nm_notify = netmap_notify; + na->active_fds = 0; + + if (na->nm_mem == NULL) + na->nm_mem = &nm_mem; + return 0; +} + + +void +netmap_detach_common(struct netmap_adapter *na) +{ + if (na->ifp) + WNA(na->ifp) = NULL; /* XXX do we need this? */ + + if (na->tx_rings) { /* XXX should not happen */ + D("freeing leftover tx_rings"); + na->nm_krings_delete(na); + } + if (na->na_flags & NAF_MEM_OWNER) + netmap_mem_private_delete(na->nm_mem); + bzero(na, sizeof(*na)); + free(na, M_DEVBUF); +} + /* * Initialize a ``netmap_adapter`` object created by driver on attach. @@ -2809,53 +2058,85 @@ netmap_poll(struct cdev *dev, int events, struct thread *td) * setups. */ int -netmap_attach(struct netmap_adapter *arg, u_int num_queues) +netmap_attach(struct netmap_adapter *arg) { - struct netmap_adapter *na = NULL; + struct netmap_hw_adapter *hwna = NULL; + // XXX when is arg == NULL ? struct ifnet *ifp = arg ? arg->ifp : NULL; - size_t len; if (arg == NULL || ifp == NULL) goto fail; - /* a VALE port uses two endpoints */ - len = nma_is_vp(arg) ? sizeof(*na) : sizeof(*na) * 2; - na = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (na == NULL) + hwna = malloc(sizeof(*hwna), M_DEVBUF, M_NOWAIT | M_ZERO); + if (hwna == NULL) goto fail; - WNA(ifp) = na; - *na = *arg; /* copy everything, trust the driver to not pass junk */ - NETMAP_SET_CAPABLE(ifp); - if (na->num_tx_rings == 0) - na->num_tx_rings = num_queues; - na->num_rx_rings = num_queues; - na->refcount = na->na_single = na->na_multi = 0; - /* Core lock initialized here, others after netmap_if_new. */ - mtx_init(&na->core_lock, "netmap core lock", MTX_NETWORK_LOCK, MTX_DEF); + hwna->up = *arg; + if (netmap_attach_common(&hwna->up)) { + free(hwna, M_DEVBUF); + goto fail; + } + netmap_adapter_get(&hwna->up); + #ifdef linux if (ifp->netdev_ops) { - ND("netdev_ops %p", ifp->netdev_ops); /* prepare a clone of the netdev ops */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) - na->nm_ndo.ndo_start_xmit = ifp->netdev_ops; + hwna->nm_ndo.ndo_start_xmit = ifp->netdev_ops; #else - na->nm_ndo = *ifp->netdev_ops; + hwna->nm_ndo = *ifp->netdev_ops; #endif } - na->nm_ndo.ndo_start_xmit = linux_netmap_start_xmit; + hwna->nm_ndo.ndo_start_xmit = linux_netmap_start_xmit; #endif /* linux */ - na->nm_mem = arg->nm_mem ? arg->nm_mem : &nm_mem; - if (!nma_is_vp(arg)) - netmap_attach_sw(ifp); - D("success for %s", ifp->if_xname); + + D("success for %s", NM_IFPNAME(ifp)); return 0; fail: - D("fail, arg %p ifp %p na %p", arg, ifp, na); + D("fail, arg %p ifp %p na %p", arg, ifp, hwna); netmap_detach(ifp); - return (na ? EINVAL : ENOMEM); + return (hwna ? EINVAL : ENOMEM); } +void +NM_DBG(netmap_adapter_get)(struct netmap_adapter *na) +{ + if (!na) { + return; + } + + refcount_acquire(&na->na_refcount); +} + + +/* returns 1 iff the netmap_adapter is destroyed */ +int +NM_DBG(netmap_adapter_put)(struct netmap_adapter *na) +{ + if (!na) + return 1; + + if (!refcount_release(&na->na_refcount)) + return 0; + + if (na->nm_dtor) + na->nm_dtor(na); + + netmap_detach_common(na); + + return 1; +} + + +int +netmap_hw_krings_create(struct netmap_adapter *na) +{ + return netmap_krings_create(na, + na->num_tx_rings + 1, na->num_rx_rings + 1, 0); +} + + + /* * Free the allocated memory linked to the given ``netmap_adapter`` * object. @@ -2868,33 +2149,22 @@ netmap_detach(struct ifnet *ifp) if (!na) return; - mtx_destroy(&na->core_lock); - - if (na->tx_rings) { /* XXX should not happen */ - D("freeing leftover tx_rings"); - free(na->tx_rings, M_DEVBUF); - } - if (na->na_flags & NAF_MEM_OWNER) - netmap_mem_private_delete(na->nm_mem); - bzero(na, sizeof(*na)); - WNA(ifp) = NULL; - free(na, M_DEVBUF); + NMG_LOCK(); + netmap_disable_all_rings(ifp); + netmap_adapter_put(na); + na->ifp = NULL; + netmap_enable_all_rings(ifp); + NMG_UNLOCK(); } -int -nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, - struct netmap_adapter *na, u_int ring_nr); - - /* * Intercept packets from the network stack and pass them * to netmap as incoming packets on the 'software' ring. * We rely on the OS to make sure that the ifp and na do not go * away (typically the caller checks for IFF_DRV_RUNNING or the like). * In nm_register() or whenever there is a reinitialization, - * we make sure to access the core lock and per-ring locks - * so that IFCAP_NETMAP is visible here. + * we make sure to make the mode change visible here. */ int netmap_transmit(struct ifnet *ifp, struct mbuf *m) @@ -2917,44 +2187,16 @@ netmap_transmit(struct ifnet *ifp, struct mbuf *m) kring = &na->rx_rings[na->num_rx_rings]; lim = kring->nkr_num_slots - 1; if (netmap_verbose & NM_VERB_HOST) - D("%s packet %d len %d from the stack", ifp->if_xname, + D("%s packet %d len %d from the stack", NM_IFPNAME(ifp), kring->nr_hwcur + kring->nr_hwavail, len); // XXX reconsider long packets if we handle fragments if (len > NETMAP_BDG_BUF_SIZE(na->nm_mem)) { /* too long for us */ - D("%s from_host, drop packet size %d > %d", ifp->if_xname, + D("%s from_host, drop packet size %d > %d", NM_IFPNAME(ifp), len, NETMAP_BDG_BUF_SIZE(na->nm_mem)); goto done; } - if (SWNA(ifp)->na_bdg) { - struct nm_bdg_fwd *ft; - char *dst; - - na = SWNA(ifp); /* we operate on the host port */ - ft = na->rx_rings[0].nkr_ft; - dst = BDG_NMB(na->nm_mem, &na->rx_rings[0].ring->slot[0]); - - /* use slot 0 in the ft, there is nothing queued here */ - /* XXX we can save the copy calling m_copydata in nm_bdg_flush, - * need a special flag for this. - */ - m_copydata(m, 0, (int)len, dst); - ft->ft_flags = 0; - ft->ft_len = len; - ft->ft_buf = dst; - ft->ft_next = NM_FT_NULL; - ft->ft_frags = 1; - if (netmap_verbose & NM_VERB_HOST) - RD(5, "pkt %p size %d to bridge port %d", - dst, len, na->bdg_port); - nm_bdg_flush(ft, 1, na, 0); - na = NA(ifp); /* back to the regular object/lock */ - error = 0; - goto done; - } - /* protect against other instances of netmap_transmit, * and userspace invocations of rxsync(). - * XXX could reuse core_lock */ // XXX [Linux] there can be no other instances of netmap_transmit // on this same ring, but we still need this lock to protect @@ -2962,18 +2204,18 @@ netmap_transmit(struct ifnet *ifp, struct mbuf *m) mtx_lock(&kring->q_lock); if (kring->nr_hwavail >= lim) { if (netmap_verbose) - D("stack ring %s full\n", ifp->if_xname); + D("stack ring %s full\n", NM_IFPNAME(ifp)); } else { /* compute the insert position */ i = nm_kr_rxpos(kring); slot = &kring->ring->slot[i]; - m_copydata(m, 0, (int)len, BDG_NMB(na->nm_mem, slot)); + m_copydata(m, 0, (int)len, BDG_NMB(na, slot)); slot->len = len; slot->flags = kring->nkr_slot_flags; kring->nr_hwavail++; if (netmap_verbose & NM_VERB_HOST) - D("wake up host ring %s %d", na->ifp->if_xname, na->num_rx_rings); - selwakeuppri(&kring->si, PI_NET); + D("wake up host ring %s %d", NM_IFPNAME(na->ifp), na->num_rx_rings); + na->nm_notify(na, na->num_rx_rings, NR_RX, 0); error = 0; } mtx_unlock(&kring->q_lock); @@ -2994,7 +2236,7 @@ netmap_transmit(struct ifnet *ifp, struct mbuf *m) /* * netmap_reset() is called by the driver routines when reinitializing * a ring. The driver is in charge of locking to protect the kring. - * If netmap mode is not set just return NULL. + * If native netmap mode is not set just return NULL. */ struct netmap_slot * netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n, @@ -3044,6 +2286,7 @@ netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n, kring->nkr_hwofs = new_hwofs; if (tx == NR_TX) kring->nr_hwavail = lim; + kring->nr_hwreserved = 0; #if 0 // def linux /* XXX check that the mappings are correct */ @@ -3060,137 +2303,60 @@ netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n, * We do the wakeup here, but the ring is not yet reconfigured. * However, we are under lock so there are no races. */ - selwakeuppri(&kring->si, PI_NET); - selwakeuppri(tx == NR_TX ? &na->tx_si : &na->rx_si, PI_NET); + na->nm_notify(na, n, tx, NAF_GLOBAL_NOTIFY); return kring->ring->slot; } /* - * Grab packets from a kring, move them into the ft structure - * associated to the tx (input) port. Max one instance per port, - * filtered on input (ioctl, poll or XXX). - * Returns the next position in the ring. - */ -static int -nm_bdg_preflush(struct netmap_adapter *na, u_int ring_nr, - struct netmap_kring *kring, u_int end) -{ - struct netmap_ring *ring = kring->ring; - struct nm_bdg_fwd *ft; - u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1; - u_int ft_i = 0; /* start from 0 */ - u_int frags = 1; /* how many frags ? */ - struct nm_bridge *b = na->na_bdg; - - /* To protect against modifications to the bridge we acquire a - * shared lock, waiting if we can sleep (if the source port is - * attached to a user process) or with a trylock otherwise (NICs). - */ - ND("wait rlock for %d packets", ((j > end ? lim+1 : 0) + end) - j); - if (na->na_flags & NAF_BDG_MAYSLEEP) - BDG_RLOCK(b); - else if (!BDG_RTRYLOCK(b)) - return 0; - ND(5, "rlock acquired for %d packets", ((j > end ? lim+1 : 0) + end) - j); - ft = kring->nkr_ft; - - for (; likely(j != end); j = nm_next(j, lim)) { - struct netmap_slot *slot = &ring->slot[j]; - char *buf; - - ft[ft_i].ft_len = slot->len; - ft[ft_i].ft_flags = slot->flags; - - ND("flags is 0x%x", slot->flags); - /* this slot goes into a list so initialize the link field */ - ft[ft_i].ft_next = NM_FT_NULL; - buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ? - (void *)(uintptr_t)slot->ptr : BDG_NMB(na->nm_mem, slot); - prefetch(buf); - ++ft_i; - if (slot->flags & NS_MOREFRAG) { - frags++; - continue; - } - if (unlikely(netmap_verbose && frags > 1)) - RD(5, "%d frags at %d", frags, ft_i - frags); - ft[ft_i - frags].ft_frags = frags; - frags = 1; - if (unlikely((int)ft_i >= bridge_batch)) - ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr); - } - if (frags > 1) { - D("truncate incomplete fragment at %d (%d frags)", ft_i, frags); - // ft_i > 0, ft[ft_i-1].flags has NS_MOREFRAG - ft[ft_i - 1].ft_frags &= ~NS_MOREFRAG; - ft[ft_i - frags].ft_frags = frags - 1; - } - if (ft_i) - ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr); - BDG_RUNLOCK(b); - return j; -} - - -/* - * Pass packets from nic to the bridge. - * XXX TODO check locking: this is called from the interrupt - * handler so we should make sure that the interface is not - * disconnected while passing down an interrupt. + * Dispatch rx/tx interrupts to the netmap rings. * - * Note, no user process can access this NIC so we can ignore - * the info in the 'ring'. - */ -static void -netmap_nic_to_bdg(struct ifnet *ifp, u_int ring_nr) -{ - struct netmap_adapter *na = NA(ifp); - struct netmap_kring *kring = &na->rx_rings[ring_nr]; - struct netmap_ring *ring = kring->ring; - u_int j, k; - - /* make sure that only one thread is ever in here, - * after which we can unlock. Probably unnecessary XXX. - */ - if (nm_kr_tryget(kring)) - return; - /* fetch packets that have arrived. - * XXX maybe do this in a loop ? - */ - if (na->nm_rxsync(ifp, ring_nr, 0)) - goto put_out; - if (kring->nr_hwavail == 0 && netmap_verbose) { - D("how strange, interrupt with no packets on %s", - ifp->if_xname); - goto put_out; - } - k = nm_kr_rxpos(kring); - - j = nm_bdg_preflush(na, ring_nr, kring, k); - - /* we consume everything, but we cannot update kring directly - * because the nic may have destroyed the info in the NIC ring. - * So we need to call rxsync again to restore it. - */ - ring->cur = j; - ring->avail = 0; - na->nm_rxsync(ifp, ring_nr, 0); - -put_out: - nm_kr_put(kring); - return; -} - - -/* - * Default functions to handle rx/tx interrupts from a physical device. * "work_done" is non-null on the RX path, NULL for the TX path. * We rely on the OS to make sure that there is only one active * instance per queue, and that there is appropriate locking. * + * The 'notify' routine depends on what the ring is attached to. + * - for a netmap file descriptor, do a selwakeup on the individual + * waitqueue, plus one on the global one if needed + * - for a switch, call the proper forwarding routine + * - XXX more ? + */ +void +netmap_common_irq(struct ifnet *ifp, u_int q, u_int *work_done) +{ + struct netmap_adapter *na = NA(ifp); + struct netmap_kring *kring; + + q &= NETMAP_RING_MASK; + + if (netmap_verbose) { + RD(5, "received %s queue %d", work_done ? "RX" : "TX" , q); + } + + if (work_done) { /* RX path */ + if (q >= na->num_rx_rings) + return; // not a physical queue + kring = na->rx_rings + q; + kring->nr_kflags |= NKR_PENDINTR; // XXX atomic ? + na->nm_notify(na, q, NR_RX, + (na->num_rx_rings > 1 ? NAF_GLOBAL_NOTIFY : 0)); + *work_done = 1; /* do not fire napi again */ + } else { /* TX path */ + if (q >= na->num_tx_rings) + return; // not a physical queue + kring = na->tx_rings + q; + na->nm_notify(na, q, NR_TX, + (na->num_tx_rings > 1 ? NAF_GLOBAL_NOTIFY : 0)); + } +} + +/* + * Default functions to handle rx/tx interrupts from a physical device. + * "work_done" is non-null on the RX path, NULL for the TX path. + * * If the card is not in netmap mode, simply return 0, * so that the caller proceeds with regular processing. + * Otherwise call netmap_common_irq() and return 1. * * If the card is connected to a netmap file descriptor, * do a selwakeup on the individual queue, plus one on the global one @@ -3203,871 +2369,64 @@ netmap_nic_to_bdg(struct ifnet *ifp, u_int ring_nr) int netmap_rx_irq(struct ifnet *ifp, u_int q, u_int *work_done) { - struct netmap_adapter *na; - struct netmap_kring *kring; - + // XXX could we check NAF_NATIVE_ON ? if (!(ifp->if_capenable & IFCAP_NETMAP)) return 0; - q &= NETMAP_RING_MASK; - - if (netmap_verbose) - RD(5, "received %s queue %d", work_done ? "RX" : "TX" , q); - na = NA(ifp); - if (na->na_flags & NAF_SKIP_INTR) { + if (NA(ifp)->na_flags & NAF_SKIP_INTR) { ND("use regular interrupt"); return 0; } - if (work_done) { /* RX path */ - if (q >= na->num_rx_rings) - return 0; // not a physical queue - kring = na->rx_rings + q; - kring->nr_kflags |= NKR_PENDINTR; // XXX atomic ? - if (na->na_bdg != NULL) { - netmap_nic_to_bdg(ifp, q); - } else { - selwakeuppri(&kring->si, PI_NET); - if (na->num_rx_rings > 1 /* or multiple listeners */ ) - selwakeuppri(&na->rx_si, PI_NET); - } - *work_done = 1; /* do not fire napi again */ - } else { /* TX path */ - if (q >= na->num_tx_rings) - return 0; // not a physical queue - kring = na->tx_rings + q; - selwakeuppri(&kring->si, PI_NET); - if (na->num_tx_rings > 1 /* or multiple listeners */ ) - selwakeuppri(&na->tx_si, PI_NET); - } + netmap_common_irq(ifp, q, work_done); return 1; } -#ifdef linux /* linux-specific routines */ - - /* - * Remap linux arguments into the FreeBSD call. - * - pwait is the poll table, passed as 'dev'; - * If pwait == NULL someone else already woke up before. We can report - * events but they are filtered upstream. - * If pwait != NULL, then pwait->key contains the list of events. - * - events is computed from pwait as above. - * - file is passed as 'td'; - */ -static u_int -linux_netmap_poll(struct file * file, struct poll_table_struct *pwait) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - int events = POLLIN | POLLOUT; /* XXX maybe... */ -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) - int events = pwait ? pwait->key : POLLIN | POLLOUT; -#else /* in 3.4.0 field 'key' was renamed to '_key' */ - int events = pwait ? pwait->_key : POLLIN | POLLOUT; -#endif - return netmap_poll((void *)pwait, events, (void *)file); -} - - -static int -linux_netmap_mmap(struct file *f, struct vm_area_struct *vma) -{ - int error = 0; - unsigned long off, va; - vm_ooffset_t pa; - struct netmap_priv_d *priv = f->private_data; - /* - * vma->vm_start: start of mapping user address space - * vma->vm_end: end of the mapping user address space - * vma->vm_pfoff: offset of first page in the device - */ - - // XXX security checks - - error = netmap_get_memory(priv); - ND("get_memory returned %d", error); - if (error) - return -error; - - if ((vma->vm_start & ~PAGE_MASK) || (vma->vm_end & ~PAGE_MASK)) { - ND("vm_start = %lx vm_end = %lx", vma->vm_start, vma->vm_end); - return -EINVAL; - } - - for (va = vma->vm_start, off = vma->vm_pgoff; - va < vma->vm_end; - va += PAGE_SIZE, off++) - { - pa = netmap_mem_ofstophys(priv->np_mref, off << PAGE_SHIFT); - if (pa == 0) - return -EINVAL; - - ND("va %lx pa %p", va, pa); - error = remap_pfn_range(vma, va, pa >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot); - if (error) - return error; - } - return 0; -} - - -/* - * This one is probably already protected by the netif lock XXX - */ -static netdev_tx_t -linux_netmap_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - netmap_transmit(dev, skb); - return (NETDEV_TX_OK); -} - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) // XXX was 37 -#define LIN_IOCTL_NAME .ioctl -int -linux_netmap_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long data /* arg */) -#else -#define LIN_IOCTL_NAME .unlocked_ioctl -long -linux_netmap_ioctl(struct file *file, u_int cmd, u_long data /* arg */) -#endif -{ - int ret; - struct nmreq nmr; - bzero(&nmr, sizeof(nmr)); - - if (cmd == NIOCTXSYNC || cmd == NIOCRXSYNC) { - data = 0; /* no argument required here */ - } - if (data && copy_from_user(&nmr, (void *)data, sizeof(nmr) ) != 0) - return -EFAULT; - ret = netmap_ioctl(NULL, cmd, (caddr_t)&nmr, 0, (void *)file); - if (data && copy_to_user((void*)data, &nmr, sizeof(nmr) ) != 0) - return -EFAULT; - return -ret; -} - - -static int -netmap_release(struct inode *inode, struct file *file) -{ - (void)inode; /* UNUSED */ - if (file->private_data) - netmap_dtor(file->private_data); - return (0); -} - - -static int -linux_netmap_open(struct inode *inode, struct file *file) -{ - struct netmap_priv_d *priv; - (void)inode; /* UNUSED */ - - priv = malloc(sizeof(struct netmap_priv_d), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (priv == NULL) - return -ENOMEM; - - file->private_data = priv; - - return (0); -} - - -static struct file_operations netmap_fops = { - .owner = THIS_MODULE, - .open = linux_netmap_open, - .mmap = linux_netmap_mmap, - LIN_IOCTL_NAME = linux_netmap_ioctl, - .poll = linux_netmap_poll, - .release = netmap_release, -}; - - -static struct miscdevice netmap_cdevsw = { /* same name as FreeBSD */ - MISC_DYNAMIC_MINOR, - "netmap", - &netmap_fops, -}; - -static int netmap_init(void); -static void netmap_fini(void); - - -/* Errors have negative values on linux */ -static int linux_netmap_init(void) -{ - return -netmap_init(); -} - -module_init(linux_netmap_init); -module_exit(netmap_fini); -/* export certain symbols to other modules */ -EXPORT_SYMBOL(netmap_attach); // driver attach routines -EXPORT_SYMBOL(netmap_detach); // driver detach routines -EXPORT_SYMBOL(netmap_ring_reinit); // ring init on error -EXPORT_SYMBOL(netmap_buffer_lut); -EXPORT_SYMBOL(netmap_total_buffers); // index check -EXPORT_SYMBOL(netmap_buffer_base); -EXPORT_SYMBOL(netmap_reset); // ring init routines -EXPORT_SYMBOL(netmap_buf_size); -EXPORT_SYMBOL(netmap_rx_irq); // default irq handler -EXPORT_SYMBOL(netmap_no_pendintr); // XXX mitigation - should go away -EXPORT_SYMBOL(netmap_bdg_ctl); // bridge configuration routine -EXPORT_SYMBOL(netmap_bdg_learning); // the default lookup function -EXPORT_SYMBOL(netmap_disable_all_rings); -EXPORT_SYMBOL(netmap_enable_all_rings); - - -MODULE_AUTHOR("http://info.iet.unipi.it/~luigi/netmap/"); -MODULE_DESCRIPTION("The netmap packet I/O framework"); -MODULE_LICENSE("Dual BSD/GPL"); /* the code here is all BSD. */ - -#else /* __FreeBSD__ */ - - -static struct cdevsw netmap_cdevsw = { - .d_version = D_VERSION, - .d_name = "netmap", - .d_open = netmap_open, - .d_mmap_single = netmap_mmap_single, - .d_ioctl = netmap_ioctl, - .d_poll = netmap_poll, - .d_close = netmap_close, -}; -#endif /* __FreeBSD__ */ - -/* - *---- support for virtual bridge ----- - */ - -/* ----- FreeBSD if_bridge hash function ------- */ - -/* - * The following hash function is adapted from "Hash Functions" by Bob Jenkins - * ("Algorithm Alley", Dr. Dobbs Journal, September 1997). + * Module loader and unloader * - * http://www.burtleburtle.net/bob/hash/spooky.html + * netmap_init() creates the /dev/netmap device and initializes + * all global variables. Returns 0 on success, errno on failure + * (but there is no chance) + * + * netmap_fini() destroys everything. */ -#define mix(a, b, c) \ -do { \ - a -= b; a -= c; a ^= (c >> 13); \ - b -= c; b -= a; b ^= (a << 8); \ - c -= a; c -= b; c ^= (b >> 13); \ - a -= b; a -= c; a ^= (c >> 12); \ - b -= c; b -= a; b ^= (a << 16); \ - c -= a; c -= b; c ^= (b >> 5); \ - a -= b; a -= c; a ^= (c >> 3); \ - b -= c; b -= a; b ^= (a << 10); \ - c -= a; c -= b; c ^= (b >> 15); \ -} while (/*CONSTCOND*/0) - -static __inline uint32_t -nm_bridge_rthash(const uint8_t *addr) -{ - uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0; // hask key - - b += addr[5] << 8; - b += addr[4]; - a += addr[3] << 24; - a += addr[2] << 16; - a += addr[1] << 8; - a += addr[0]; - - mix(a, b, c); -#define BRIDGE_RTHASH_MASK (NM_BDG_HASH-1) - return (c & BRIDGE_RTHASH_MASK); -} - -#undef mix - - -static int -bdg_netmap_reg(struct ifnet *ifp, int onoff) -{ - /* the interface is already attached to the bridge, - * so we only need to toggle IFCAP_NETMAP. - */ - if (onoff) { - ifp->if_capenable |= IFCAP_NETMAP; - } else { - ifp->if_capenable &= ~IFCAP_NETMAP; - } - return 0; -} - - -/* - * Lookup function for a learning bridge. - * Update the hash table with the source address, - * and then returns the destination port index, and the - * ring in *dst_ring (at the moment, always use ring 0) - */ -u_int -netmap_bdg_learning(char *buf, u_int buf_len, uint8_t *dst_ring, - struct netmap_adapter *na) -{ - struct nm_hash_ent *ht = na->na_bdg->ht; - uint32_t sh, dh; - u_int dst, mysrc = na->bdg_port; - uint64_t smac, dmac; - - if (buf_len < 14) { - D("invalid buf length %d", buf_len); - return NM_BDG_NOPORT; - } - dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff; - smac = le64toh(*(uint64_t *)(buf + 4)); - smac >>= 16; - - /* - * The hash is somewhat expensive, there might be some - * worthwhile optimizations here. - */ - if ((buf[6] & 1) == 0) { /* valid src */ - uint8_t *s = buf+6; - sh = nm_bridge_rthash(s); // XXX hash of source - /* update source port forwarding entry */ - ht[sh].mac = smac; /* XXX expire ? */ - ht[sh].ports = mysrc; - if (netmap_verbose) - D("src %02x:%02x:%02x:%02x:%02x:%02x on port %d", - s[0], s[1], s[2], s[3], s[4], s[5], mysrc); - } - dst = NM_BDG_BROADCAST; - if ((buf[0] & 1) == 0) { /* unicast */ - dh = nm_bridge_rthash(buf); // XXX hash of dst - if (ht[dh].mac == dmac) { /* found dst */ - dst = ht[dh].ports; - } - /* XXX otherwise return NM_BDG_UNKNOWN ? */ - } - *dst_ring = 0; - return dst; -} - - -/* - * This flush routine supports only unicast and broadcast but a large - * number of ports, and lets us replace the learn and dispatch functions. - */ -int -nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_adapter *na, - u_int ring_nr) -{ - struct nm_bdg_q *dst_ents, *brddst; - uint16_t num_dsts = 0, *dsts; - struct nm_bridge *b = na->na_bdg; - u_int i, j, me = na->bdg_port; - - /* - * The work area (pointed by ft) is followed by an array of - * pointers to queues , dst_ents; there are NM_BDG_MAXRINGS - * queues per port plus one for the broadcast traffic. - * Then we have an array of destination indexes. - */ - dst_ents = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); - dsts = (uint16_t *)(dst_ents + NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1); - - /* first pass: find a destination for each packet in the batch */ - for (i = 0; likely(i < n); i += ft[i].ft_frags) { - uint8_t dst_ring = ring_nr; /* default, same ring as origin */ - uint16_t dst_port, d_i; - struct nm_bdg_q *d; - - ND("slot %d frags %d", i, ft[i].ft_frags); - dst_port = b->nm_bdg_lookup(ft[i].ft_buf, ft[i].ft_len, - &dst_ring, na); - if (netmap_verbose > 255) - RD(5, "slot %d port %d -> %d", i, me, dst_port); - if (dst_port == NM_BDG_NOPORT) - continue; /* this packet is identified to be dropped */ - else if (unlikely(dst_port > NM_BDG_MAXPORTS)) - continue; - else if (dst_port == NM_BDG_BROADCAST) - dst_ring = 0; /* broadcasts always go to ring 0 */ - else if (unlikely(dst_port == me || - !b->bdg_ports[dst_port])) - continue; - - /* get a position in the scratch pad */ - d_i = dst_port * NM_BDG_MAXRINGS + dst_ring; - d = dst_ents + d_i; - - /* append the first fragment to the list */ - if (d->bq_head == NM_FT_NULL) { /* new destination */ - d->bq_head = d->bq_tail = i; - /* remember this position to be scanned later */ - if (dst_port != NM_BDG_BROADCAST) - dsts[num_dsts++] = d_i; - } else { - ft[d->bq_tail].ft_next = i; - d->bq_tail = i; - } - d->bq_len += ft[i].ft_frags; - } - - /* - * Broadcast traffic goes to ring 0 on all destinations. - * So we need to add these rings to the list of ports to scan. - * XXX at the moment we scan all NM_BDG_MAXPORTS ports, which is - * expensive. We should keep a compact list of active destinations - * so we could shorten this loop. - */ - brddst = dst_ents + NM_BDG_BROADCAST * NM_BDG_MAXRINGS; - if (brddst->bq_head != NM_FT_NULL) { - for (j = 0; likely(j < b->bdg_active_ports); j++) { - uint16_t d_i; - i = b->bdg_port_index[j]; - if (unlikely(i == me)) - continue; - d_i = i * NM_BDG_MAXRINGS; - if (dst_ents[d_i].bq_head == NM_FT_NULL) - dsts[num_dsts++] = d_i; - } - } - - ND(5, "pass 1 done %d pkts %d dsts", n, num_dsts); - /* second pass: scan destinations (XXX will be modular somehow) */ - for (i = 0; i < num_dsts; i++) { - struct ifnet *dst_ifp; - struct netmap_adapter *dst_na; - struct netmap_kring *kring; - struct netmap_ring *ring; - u_int dst_nr, is_vp, lim, j, sent = 0, d_i, next, brd_next; - u_int needed, howmany; - int retry = netmap_txsync_retry; - struct nm_bdg_q *d; - uint32_t my_start = 0, lease_idx = 0; - int nrings; - - d_i = dsts[i]; - ND("second pass %d port %d", i, d_i); - d = dst_ents + d_i; - // XXX fix the division - dst_na = b->bdg_ports[d_i/NM_BDG_MAXRINGS]; - /* protect from the lookup function returning an inactive - * destination port - */ - if (unlikely(dst_na == NULL)) - goto cleanup; - if (dst_na->na_flags & NAF_SW_ONLY) - goto cleanup; - dst_ifp = dst_na->ifp; - /* - * The interface may be in !netmap mode in two cases: - * - when na is attached but not activated yet; - * - when na is being deactivated but is still attached. - */ - if (unlikely(!(dst_ifp->if_capenable & IFCAP_NETMAP))) { - ND("not in netmap mode!"); - goto cleanup; - } - - /* there is at least one either unicast or broadcast packet */ - brd_next = brddst->bq_head; - next = d->bq_head; - /* we need to reserve this many slots. If fewer are - * available, some packets will be dropped. - * Packets may have multiple fragments, so we may not use - * there is a chance that we may not use all of the slots - * we have claimed, so we will need to handle the leftover - * ones when we regain the lock. - */ - needed = d->bq_len + brddst->bq_len; - - is_vp = nma_is_vp(dst_na); - ND(5, "pass 2 dst %d is %x %s", - i, d_i, is_vp ? "virtual" : "nic/host"); - dst_nr = d_i & (NM_BDG_MAXRINGS-1); - if (is_vp) { /* virtual port */ - nrings = dst_na->num_rx_rings; - } else { - nrings = dst_na->num_tx_rings; - } - if (dst_nr >= nrings) - dst_nr = dst_nr % nrings; - kring = is_vp ? &dst_na->rx_rings[dst_nr] : - &dst_na->tx_rings[dst_nr]; - ring = kring->ring; - lim = kring->nkr_num_slots - 1; - -retry: - - /* reserve the buffers in the queue and an entry - * to report completion, and drop lock. - * XXX this might become a helper function. - */ - mtx_lock(&kring->q_lock); - if (kring->nkr_stopped) { - mtx_unlock(&kring->q_lock); - goto cleanup; - } - /* on physical interfaces, do a txsync to recover - * slots for packets already transmitted. - * XXX maybe we could be optimistic and rely on a retry - * in case of failure. - */ - if (nma_is_hw(dst_na)) { - dst_na->nm_txsync(dst_ifp, dst_nr, 0); - } - my_start = j = kring->nkr_hwlease; - howmany = nm_kr_space(kring, is_vp); - if (needed < howmany) - howmany = needed; - lease_idx = nm_kr_lease(kring, howmany, is_vp); - mtx_unlock(&kring->q_lock); - - /* only retry if we need more than available slots */ - if (retry && needed <= howmany) - retry = 0; - - /* copy to the destination queue */ - while (howmany > 0) { - struct netmap_slot *slot; - struct nm_bdg_fwd *ft_p, *ft_end; - u_int cnt; - - /* find the queue from which we pick next packet. - * NM_FT_NULL is always higher than valid indexes - * so we never dereference it if the other list - * has packets (and if both are empty we never - * get here). - */ - if (next < brd_next) { - ft_p = ft + next; - next = ft_p->ft_next; - } else { /* insert broadcast */ - ft_p = ft + brd_next; - brd_next = ft_p->ft_next; - } - cnt = ft_p->ft_frags; // cnt > 0 - if (unlikely(cnt > howmany)) - break; /* no more space */ - howmany -= cnt; - if (netmap_verbose && cnt > 1) - RD(5, "rx %d frags to %d", cnt, j); - ft_end = ft_p + cnt; - do { - void *dst, *src = ft_p->ft_buf; - size_t len = (ft_p->ft_len + 63) & ~63; - - slot = &ring->slot[j]; - dst = BDG_NMB(dst_na->nm_mem, slot); - /* round to a multiple of 64 */ - - ND("send %d %d bytes at %s:%d", - i, ft_p->ft_len, dst_ifp->if_xname, j); - if (ft_p->ft_flags & NS_INDIRECT) { - if (copyin(src, dst, len)) { - // invalid user pointer, pretend len is 0 - ft_p->ft_len = 0; - } - } else { - //memcpy(dst, src, len); - pkt_copy(src, dst, (int)len); - } - slot->len = ft_p->ft_len; - slot->flags = (cnt << 8)| NS_MOREFRAG; - j = nm_next(j, lim); - ft_p++; - sent++; - } while (ft_p != ft_end); - slot->flags = (cnt << 8); /* clear flag on last entry */ - /* are we done ? */ - if (next == NM_FT_NULL && brd_next == NM_FT_NULL) - break; - } - { - /* current position */ - uint32_t *p = kring->nkr_leases; /* shorthand */ - uint32_t update_pos; - int still_locked = 1; - - mtx_lock(&kring->q_lock); - if (unlikely(howmany > 0)) { - /* not used all bufs. If i am the last one - * i can recover the slots, otherwise must - * fill them with 0 to mark empty packets. - */ - ND("leftover %d bufs", howmany); - if (nm_next(lease_idx, lim) == kring->nkr_lease_idx) { - /* yes i am the last one */ - ND("roll back nkr_hwlease to %d", j); - kring->nkr_hwlease = j; - } else { - while (howmany-- > 0) { - ring->slot[j].len = 0; - ring->slot[j].flags = 0; - j = nm_next(j, lim); - } - } - } - p[lease_idx] = j; /* report I am done */ - - update_pos = is_vp ? nm_kr_rxpos(kring) : ring->cur; - - if (my_start == update_pos) { - /* all slots before my_start have been reported, - * so scan subsequent leases to see if other ranges - * have been completed, and to a selwakeup or txsync. - */ - while (lease_idx != kring->nkr_lease_idx && - p[lease_idx] != NR_NOSLOT) { - j = p[lease_idx]; - p[lease_idx] = NR_NOSLOT; - lease_idx = nm_next(lease_idx, lim); - } - /* j is the new 'write' position. j != my_start - * means there are new buffers to report - */ - if (likely(j != my_start)) { - if (is_vp) { - uint32_t old_avail = kring->nr_hwavail; - - kring->nr_hwavail = (j >= kring->nr_hwcur) ? - j - kring->nr_hwcur : - j + lim + 1 - kring->nr_hwcur; - if (kring->nr_hwavail < old_avail) { - D("avail shrink %d -> %d", - old_avail, kring->nr_hwavail); - } - still_locked = 0; - mtx_unlock(&kring->q_lock); - selwakeuppri(&kring->si, PI_NET); - } else { - ring->cur = j; - /* XXX update avail ? */ - still_locked = 0; - dst_na->nm_txsync(dst_ifp, dst_nr, 0); - mtx_unlock(&kring->q_lock); - - /* retry to send more packets */ - if (nma_is_hw(dst_na) && retry--) - goto retry; - } - } - } - if (still_locked) - mtx_unlock(&kring->q_lock); - } -cleanup: - d->bq_head = d->bq_tail = NM_FT_NULL; /* cleanup */ - d->bq_len = 0; - } - brddst->bq_head = brddst->bq_tail = NM_FT_NULL; /* cleanup */ - brddst->bq_len = 0; - return 0; -} - - -/* - * main dispatch routine for the bridge. - * We already know that only one thread is running this. - * we must run nm_bdg_preflush without lock. - */ -static int -bdg_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int flags) -{ - struct netmap_adapter *na = NA(ifp); - struct netmap_kring *kring = &na->tx_rings[ring_nr]; - struct netmap_ring *ring = kring->ring; - u_int j, k, lim = kring->nkr_num_slots - 1; - - k = ring->cur; - if (k > lim) - return netmap_ring_reinit(kring); - - if (bridge_batch <= 0) { /* testing only */ - j = k; // used all - goto done; - } - if (bridge_batch > NM_BDG_BATCH) - bridge_batch = NM_BDG_BATCH; - - j = nm_bdg_preflush(na, ring_nr, kring, k); - if (j != k) - D("early break at %d/ %d, avail %d", j, k, kring->nr_hwavail); - /* k-j modulo ring size is the number of slots processed */ - if (k < j) - k += kring->nkr_num_slots; - kring->nr_hwavail = lim - (k - j); - -done: - kring->nr_hwcur = j; - ring->avail = kring->nr_hwavail; - if (netmap_verbose) - D("%s ring %d flags %d", ifp->if_xname, ring_nr, flags); - return 0; -} - - -/* - * user process reading from a VALE switch. - * Already protected against concurrent calls from userspace, - * but we must acquire the queue's lock to protect against - * writers on the same queue. - */ -static int -bdg_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int flags) -{ - struct netmap_adapter *na = NA(ifp); - struct netmap_kring *kring = &na->rx_rings[ring_nr]; - struct netmap_ring *ring = kring->ring; - u_int j, lim = kring->nkr_num_slots - 1; - u_int k = ring->cur, resvd = ring->reserved; - int n; - - mtx_lock(&kring->q_lock); - if (k > lim) { - D("ouch dangerous reset!!!"); - n = netmap_ring_reinit(kring); - goto done; - } - - /* skip past packets that userspace has released */ - j = kring->nr_hwcur; /* netmap ring index */ - if (resvd > 0) { - if (resvd + ring->avail >= lim + 1) { - D("XXX invalid reserve/avail %d %d", resvd, ring->avail); - ring->reserved = resvd = 0; // XXX panic... - } - k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; - } - - if (j != k) { /* userspace has released some packets. */ - n = k - j; - if (n < 0) - n += kring->nkr_num_slots; - ND("userspace releases %d packets", n); - for (n = 0; likely(j != k); n++) { - struct netmap_slot *slot = &ring->slot[j]; - void *addr = BDG_NMB(na->nm_mem, slot); - - if (addr == netmap_buffer_base) { /* bad buf */ - D("bad buffer index %d, ignore ?", - slot->buf_idx); - } - slot->flags &= ~NS_BUF_CHANGED; - j = nm_next(j, lim); - } - kring->nr_hwavail -= n; - kring->nr_hwcur = k; - } - /* tell userspace that there are new packets */ - ring->avail = kring->nr_hwavail - resvd; - n = 0; -done: - mtx_unlock(&kring->q_lock); - return n; -} - - -static int -bdg_netmap_attach(struct netmap_adapter *arg) -{ - struct netmap_adapter na; - - ND("attaching virtual bridge"); - bzero(&na, sizeof(na)); - - na.ifp = arg->ifp; - na.na_flags = NAF_BDG_MAYSLEEP | NAF_MEM_OWNER; - na.num_tx_rings = arg->num_tx_rings; - na.num_rx_rings = arg->num_rx_rings; - na.num_tx_desc = arg->num_tx_desc; - na.num_rx_desc = arg->num_rx_desc; - na.nm_txsync = bdg_netmap_txsync; - na.nm_rxsync = bdg_netmap_rxsync; - na.nm_register = bdg_netmap_reg; - na.nm_mem = netmap_mem_private_new(arg->ifp->if_xname, - na.num_tx_rings, na.num_tx_desc, - na.num_rx_rings, na.num_rx_desc); - return netmap_attach(&na, na.num_tx_rings); -} - static struct cdev *netmap_dev; /* /dev/netmap character device. */ +extern struct cdevsw netmap_cdevsw; - -/* - * Module loader. - * - * Create the /dev/netmap device and initialize all global - * variables. - * - * Return 0 on success, errno on failure. - */ -static int -netmap_init(void) -{ - int i, error; - - NMG_LOCK_INIT(); - - error = netmap_mem_init(); - if (error != 0) { - printf("netmap: unable to initialize the memory allocator.\n"); - return (error); - } - printf("netmap: loaded module\n"); - netmap_dev = make_dev(&netmap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, - "netmap"); - - bzero(nm_bridges, sizeof(struct nm_bridge) * NM_BRIDGES); /* safety */ - for (i = 0; i < NM_BRIDGES; i++) - BDG_RWINIT(&nm_bridges[i]); - return (error); -} - - -/* - * Module unloader. - * - * Free all the memory, and destroy the ``/dev/netmap`` device. - */ -static void +void netmap_fini(void) { - destroy_dev(netmap_dev); + // XXX destroy_bridges() ? + if (netmap_dev) + destroy_dev(netmap_dev); netmap_mem_fini(); NMG_LOCK_DESTROY(); printf("netmap: unloaded module.\n"); } - -#ifdef __FreeBSD__ -/* - * Kernel entry point. - * - * Initialize/finalize the module and return. - * - * Return 0 on success, errno on failure. - */ -static int -netmap_loader(__unused struct module *module, int event, __unused void *arg) +int +netmap_init(void) { - int error = 0; + int error; - switch (event) { - case MOD_LOAD: - error = netmap_init(); - break; + NMG_LOCK_INIT(); - case MOD_UNLOAD: - netmap_fini(); - break; + error = netmap_mem_init(); + if (error != 0) + goto fail; + /* XXX could use make_dev_credv() to get error number */ + netmap_dev = make_dev(&netmap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, + "netmap"); + if (!netmap_dev) + goto fail; - default: - error = EOPNOTSUPP; - break; - } - - return (error); + netmap_init_bridges(); + printf("netmap: loaded module\n"); + return (0); +fail: + netmap_fini(); + return (EINVAL); /* may be incorrect */ } - - -DEV_MODULE(netmap, netmap_loader, NULL); -#endif /* __FreeBSD__ */ diff --git a/sys/dev/netmap/netmap_freebsd.c b/sys/dev/netmap/netmap_freebsd.c new file mode 100644 index 000000000000..c2814146d2ef --- /dev/null +++ b/sys/dev/netmap/netmap_freebsd.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2013 Universita` di Pisa. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $FreeBSD$ */ + +#include +#include +#include +#include /* defines used in kernel.h */ +#include /* types used in module initialization */ +#include /* DEV_MODULE */ + +#include + +#include /* vtophys */ +#include /* vtophys */ +#include +#include +#include +#include +#include + + +#include +#include /* sockaddrs */ +#include +#include +#include +#include /* bus_dmamap_* */ + +#include +#include +#include + + +/* ======================== FREEBSD-SPECIFIC ROUTINES ================== */ + +/* + * Intercept the rx routine in the standard device driver. + * Second argument is non-zero to intercept, 0 to restore + */ +int +netmap_catch_rx(struct netmap_adapter *na, int intercept) +{ + struct netmap_generic_adapter *gna = (struct netmap_generic_adapter *)na; + struct ifnet *ifp = na->ifp; + + if (intercept) { + if (gna->save_if_input) { + D("cannot intercept again"); + return EINVAL; /* already set */ + } + gna->save_if_input = ifp->if_input; + ifp->if_input = generic_rx_handler; + } else { + if (!gna->save_if_input){ + D("cannot restore"); + return EINVAL; /* not saved */ + } + ifp->if_input = gna->save_if_input; + gna->save_if_input = NULL; + } + + return 0; +} + +/* + * Intercept the packet steering routine in the tx path, + * so that we can decide which queue is used for an mbuf. + * Second argument is non-zero to intercept, 0 to restore. + * + * XXX see if FreeBSD has such a mechanism + */ +void +netmap_catch_packet_steering(struct netmap_generic_adapter *na, int enable) +{ + if (enable) { + } else { + } +} + +/* Transmit routine used by generic_netmap_txsync(). Returns 0 on success + * and non-zero on error (which may be packet drops or other errors). + * addr and len identify the netmap buffer, m is the (preallocated) + * mbuf to use for transmissions. + * + * We should add a reference to the mbuf so the m_freem() at the end + * of the transmission does not consume resources. + * + * On FreeBSD, and on multiqueue cards, we can force the queue using + * if ((m->m_flags & M_FLOWID) != 0) + * i = m->m_pkthdr.flowid % adapter->num_queues; + * else + * i = curcpu % adapter->num_queues; + * + */ +int +generic_xmit_frame(struct ifnet *ifp, struct mbuf *m, + void *addr, u_int len, u_int ring_nr) +{ + int ret; + + m->m_len = m->m_pkthdr.len = 0; + + // copy data to the mbuf + m_copyback(m, 0, len, addr); + + // inc refcount. We are alone, so we can skip the atomic + atomic_fetchadd_int(m->m_ext.ref_cnt, 1); + m->m_flags |= M_FLOWID; + m->m_pkthdr.flowid = ring_nr; + m->m_pkthdr.rcvif = ifp; /* used for tx notification */ + ret = ifp->if_transmit(ifp, m); + return ret; +} + +/* + * The following two functions are empty until we have a generic + * way to extract the info from the ifp + */ +int +generic_find_num_desc(struct ifnet *ifp, unsigned int *tx, unsigned int *rx) +{ + D("called"); + return 0; +} + +void +generic_find_num_queues(struct ifnet *ifp, u_int *txq, u_int *rxq) +{ + D("called"); + *txq = 1; + *rxq = 1; +} + +void netmap_mitigation_init(struct netmap_generic_adapter *na) +{ + ND("called"); + na->mit_pending = 0; +} + + +void netmap_mitigation_start(struct netmap_generic_adapter *na) +{ + ND("called"); +} + +void netmap_mitigation_restart(struct netmap_generic_adapter *na) +{ + ND("called"); +} + +int netmap_mitigation_active(struct netmap_generic_adapter *na) +{ + ND("called"); + return 0; +} + +void netmap_mitigation_cleanup(struct netmap_generic_adapter *na) +{ + ND("called"); +} + +/* + * In order to track whether pages are still mapped, we hook into + * the standard cdev_pager and intercept the constructor and + * destructor. + */ + +struct netmap_vm_handle_t { + struct cdev *dev; + struct netmap_priv_d *priv; +}; + +static int +netmap_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) +{ + struct netmap_vm_handle_t *vmh = handle; + D("handle %p size %jd prot %d foff %jd", + handle, (intmax_t)size, prot, (intmax_t)foff); + dev_ref(vmh->dev); + return 0; +} + + +static void +netmap_dev_pager_dtor(void *handle) +{ + struct netmap_vm_handle_t *vmh = handle; + struct cdev *dev = vmh->dev; + struct netmap_priv_d *priv = vmh->priv; + D("handle %p", handle); + netmap_dtor(priv); + free(vmh, M_DEVBUF); + dev_rel(dev); +} + +static int +netmap_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, + int prot, vm_page_t *mres) +{ + struct netmap_vm_handle_t *vmh = object->handle; + struct netmap_priv_d *priv = vmh->priv; + vm_paddr_t paddr; + vm_page_t page; + vm_memattr_t memattr; + vm_pindex_t pidx; + + ND("object %p offset %jd prot %d mres %p", + object, (intmax_t)offset, prot, mres); + memattr = object->memattr; + pidx = OFF_TO_IDX(offset); + paddr = netmap_mem_ofstophys(priv->np_mref, offset); + if (paddr == 0) + return VM_PAGER_FAIL; + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake page, update it with + * the new physical address. + */ + page = *mres; + vm_page_updatefake(page, paddr, memattr); + } else { + /* + * Replace the passed in reqpage page with our own fake page and + * free up the all of the original pages. + */ +#ifndef VM_OBJECT_WUNLOCK /* FreeBSD < 10.x */ +#define VM_OBJECT_WUNLOCK VM_OBJECT_UNLOCK +#define VM_OBJECT_WLOCK VM_OBJECT_LOCK +#endif /* VM_OBJECT_WUNLOCK */ + + VM_OBJECT_WUNLOCK(object); + page = vm_page_getfake(paddr, memattr); + VM_OBJECT_WLOCK(object); + vm_page_lock(*mres); + vm_page_free(*mres); + vm_page_unlock(*mres); + *mres = page; + vm_page_insert(page, object, pidx); + } + page->valid = VM_PAGE_BITS_ALL; + return (VM_PAGER_OK); +} + + +static struct cdev_pager_ops netmap_cdev_pager_ops = { + .cdev_pg_ctor = netmap_dev_pager_ctor, + .cdev_pg_dtor = netmap_dev_pager_dtor, + .cdev_pg_fault = netmap_dev_pager_fault, +}; + + +static int +netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff, + vm_size_t objsize, vm_object_t *objp, int prot) +{ + int error; + struct netmap_vm_handle_t *vmh; + struct netmap_priv_d *priv; + vm_object_t obj; + + D("cdev %p foff %jd size %jd objp %p prot %d", cdev, + (intmax_t )*foff, (intmax_t )objsize, objp, prot); + + vmh = malloc(sizeof(struct netmap_vm_handle_t), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (vmh == NULL) + return ENOMEM; + vmh->dev = cdev; + + NMG_LOCK(); + error = devfs_get_cdevpriv((void**)&priv); + if (error) + goto err_unlock; + vmh->priv = priv; + priv->np_refcount++; + NMG_UNLOCK(); + + error = netmap_get_memory(priv); + if (error) + goto err_deref; + + obj = cdev_pager_allocate(vmh, OBJT_DEVICE, + &netmap_cdev_pager_ops, objsize, prot, + *foff, NULL); + if (obj == NULL) { + D("cdev_pager_allocate failed"); + error = EINVAL; + goto err_deref; + } + + *objp = obj; + return 0; + +err_deref: + NMG_LOCK(); + priv->np_refcount--; +err_unlock: + NMG_UNLOCK(); +// err: + free(vmh, M_DEVBUF); + return error; +} + + +// XXX can we remove this ? +static int +netmap_close(struct cdev *dev, int fflag, int devtype, struct thread *td) +{ + if (netmap_verbose) + D("dev %p fflag 0x%x devtype %d td %p", + dev, fflag, devtype, td); + return 0; +} + + +static int +netmap_open(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + struct netmap_priv_d *priv; + int error; + + (void)dev; + (void)oflags; + (void)devtype; + (void)td; + + // XXX wait or nowait ? + priv = malloc(sizeof(struct netmap_priv_d), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (priv == NULL) + return ENOMEM; + + error = devfs_set_cdevpriv(priv, netmap_dtor); + if (error) + return error; + + priv->np_refcount = 1; + + return 0; +} + + +struct cdevsw netmap_cdevsw = { + .d_version = D_VERSION, + .d_name = "netmap", + .d_open = netmap_open, + .d_mmap_single = netmap_mmap_single, + .d_ioctl = netmap_ioctl, + .d_poll = netmap_poll, + .d_close = netmap_close, +}; + + +/* + * Kernel entry point. + * + * Initialize/finalize the module and return. + * + * Return 0 on success, errno on failure. + */ +static int +netmap_loader(__unused struct module *module, int event, __unused void *arg) +{ + int error = 0; + + switch (event) { + case MOD_LOAD: + error = netmap_init(); + break; + + case MOD_UNLOAD: + netmap_fini(); + break; + + default: + error = EOPNOTSUPP; + break; + } + + return (error); +} + + +DEV_MODULE(netmap, netmap_loader, NULL); diff --git a/sys/dev/netmap/netmap_generic.c b/sys/dev/netmap/netmap_generic.c new file mode 100644 index 000000000000..2c42db3f8862 --- /dev/null +++ b/sys/dev/netmap/netmap_generic.c @@ -0,0 +1,818 @@ +/* + * Copyright (C) 2013 Universita` di Pisa. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This module implements netmap support on top of standard, + * unmodified device drivers. + * + * A NIOCREGIF request is handled here if the device does not + * have native support. TX and RX rings are emulated as follows: + * + * NIOCREGIF + * We preallocate a block of TX mbufs (roughly as many as + * tx descriptors; the number is not critical) to speed up + * operation during transmissions. The refcount on most of + * these buffers is artificially bumped up so we can recycle + * them more easily. Also, the destructor is intercepted + * so we use it as an interrupt notification to wake up + * processes blocked on a poll(). + * + * For each receive ring we allocate one "struct mbq" + * (an mbuf tailq plus a spinlock). We intercept packets + * (through if_input) + * on the receive path and put them in the mbq from which + * netmap receive routines can grab them. + * + * TX: + * in the generic_txsync() routine, netmap buffers are copied + * (or linked, in a future) to the preallocated mbufs + * and pushed to the transmit queue. Some of these mbufs + * (those with NS_REPORT, or otherwise every half ring) + * have the refcount=1, others have refcount=2. + * When the destructor is invoked, we take that as + * a notification that all mbufs up to that one in + * the specific ring have been completed, and generate + * the equivalent of a transmit interrupt. + * + * RX: + * + */ + +#ifdef __FreeBSD__ + +#include /* prerequisite */ +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include /* PROT_EXEC */ +#include +#include /* sockaddrs */ +#include +#include +#include +#include /* bus_dmamap_* in netmap_kern.h */ + +// XXX temporary - D() defined here +#include +#include +#include + +#define rtnl_lock() D("rtnl_lock called"); +#define rtnl_unlock() D("rtnl_lock called"); +#define MBUF_TXQ(m) ((m)->m_pkthdr.flowid) +#define smp_mb() + +/* + * mbuf wrappers + */ + +/* + * we allocate an EXT_PACKET + */ +#define netmap_get_mbuf(len) m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR|M_NOFREE) + +/* mbuf destructor, also need to change the type to EXT_EXTREF, + * add an M_NOFREE flag, and then clear the flag and + * chain into uma_zfree(zone_pack, mf) + * (or reinstall the buffer ?) + */ +#define SET_MBUF_DESTRUCTOR(m, fn) do { \ + (m)->m_ext.ext_free = (void *)fn; \ + (m)->m_ext.ext_type = EXT_EXTREF; \ + } while (0) + + +#define GET_MBUF_REFCNT(m) ((m)->m_ext.ref_cnt ? *(m)->m_ext.ref_cnt : -1) + + + +#else /* linux */ + +#include "bsd_glue.h" + +#include /* rtnl_[un]lock() */ +#include /* struct ethtool_ops, get_ringparam */ +#include + +//#define RATE /* Enables communication statistics. */ + +//#define REG_RESET + +#endif /* linux */ + + +/* Common headers. */ +#include +#include +#include + + + +/* ======================== usage stats =========================== */ + +#ifdef RATE +#define IFRATE(x) x +struct rate_stats { + unsigned long txpkt; + unsigned long txsync; + unsigned long txirq; + unsigned long rxpkt; + unsigned long rxirq; + unsigned long rxsync; +}; + +struct rate_context { + unsigned refcount; + struct timer_list timer; + struct rate_stats new; + struct rate_stats old; +}; + +#define RATE_PRINTK(_NAME_) \ + printk( #_NAME_ " = %lu Hz\n", (cur._NAME_ - ctx->old._NAME_)/RATE_PERIOD); +#define RATE_PERIOD 2 +static void rate_callback(unsigned long arg) +{ + struct rate_context * ctx = (struct rate_context *)arg; + struct rate_stats cur = ctx->new; + int r; + + RATE_PRINTK(txpkt); + RATE_PRINTK(txsync); + RATE_PRINTK(txirq); + RATE_PRINTK(rxpkt); + RATE_PRINTK(rxsync); + RATE_PRINTK(rxirq); + printk("\n"); + + ctx->old = cur; + r = mod_timer(&ctx->timer, jiffies + + msecs_to_jiffies(RATE_PERIOD * 1000)); + if (unlikely(r)) + D("[v1000] Error: mod_timer()"); +} + +static struct rate_context rate_ctx; + +#else /* !RATE */ +#define IFRATE(x) +#endif /* !RATE */ + + +/* =============== GENERIC NETMAP ADAPTER SUPPORT ================= */ +#define GENERIC_BUF_SIZE netmap_buf_size /* Size of the mbufs in the Tx pool. */ + +/* + * Wrapper used by the generic adapter layer to notify + * the poller threads. Differently from netmap_rx_irq(), we check + * only IFCAP_NETMAP instead of NAF_NATIVE_ON to enable the irq. + */ +static void +netmap_generic_irq(struct ifnet *ifp, u_int q, u_int *work_done) +{ + if (unlikely(!(ifp->if_capenable & IFCAP_NETMAP))) + return; + + netmap_common_irq(ifp, q, work_done); +} + + +/* Enable/disable netmap mode for a generic network interface. */ +int generic_netmap_register(struct netmap_adapter *na, int enable) +{ + struct ifnet *ifp = na->ifp; + struct netmap_generic_adapter *gna = (struct netmap_generic_adapter *)na; + struct mbuf *m; + int error; + int i, r; + + if (!na) + return EINVAL; + +#ifdef REG_RESET + error = ifp->netdev_ops->ndo_stop(ifp); + if (error) { + return error; + } +#endif /* REG_RESET */ + + if (enable) { /* Enable netmap mode. */ + /* Initialize the rx queue, as generic_rx_handler() can + * be called as soon as netmap_catch_rx() returns. + */ + for (r=0; rnum_rx_rings; r++) { + mbq_safe_init(&na->rx_rings[r].rx_queue); + na->rx_rings[r].nr_ntc = 0; + } + + /* Init the mitigation timer. */ + netmap_mitigation_init(gna); + + /* + * Preallocate packet buffers for the tx rings. + */ + for (r=0; rnum_tx_rings; r++) { + na->tx_rings[r].nr_ntc = 0; + na->tx_rings[r].tx_pool = malloc(na->num_tx_desc * sizeof(struct mbuf *), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!na->tx_rings[r].tx_pool) { + D("tx_pool allocation failed"); + error = ENOMEM; + goto free_tx_pool; + } + for (i=0; inum_tx_desc; i++) { + m = netmap_get_mbuf(GENERIC_BUF_SIZE); + if (!m) { + D("tx_pool[%d] allocation failed", i); + error = ENOMEM; + goto free_mbufs; + } + na->tx_rings[r].tx_pool[i] = m; + } + } + rtnl_lock(); + /* Prepare to intercept incoming traffic. */ + error = netmap_catch_rx(na, 1); + if (error) { + D("netdev_rx_handler_register() failed"); + goto register_handler; + } + ifp->if_capenable |= IFCAP_NETMAP; + + /* Make netmap control the packet steering. */ + netmap_catch_packet_steering(gna, 1); + + rtnl_unlock(); + +#ifdef RATE + if (rate_ctx.refcount == 0) { + D("setup_timer()"); + memset(&rate_ctx, 0, sizeof(rate_ctx)); + setup_timer(&rate_ctx.timer, &rate_callback, (unsigned long)&rate_ctx); + if (mod_timer(&rate_ctx.timer, jiffies + msecs_to_jiffies(1500))) { + D("Error: mod_timer()"); + } + } + rate_ctx.refcount++; +#endif /* RATE */ + + } else { /* Disable netmap mode. */ + rtnl_lock(); + + ifp->if_capenable &= ~IFCAP_NETMAP; + + /* Release packet steering control. */ + netmap_catch_packet_steering(gna, 0); + + /* Do not intercept packets on the rx path. */ + netmap_catch_rx(na, 0); + + rtnl_unlock(); + + /* Free the mbufs going to the netmap rings */ + for (r=0; rnum_rx_rings; r++) { + mbq_safe_purge(&na->rx_rings[r].rx_queue); + mbq_safe_destroy(&na->rx_rings[r].rx_queue); + } + + netmap_mitigation_cleanup(gna); + + for (r=0; rnum_tx_rings; r++) { + for (i=0; inum_tx_desc; i++) { + m_freem(na->tx_rings[r].tx_pool[i]); + } + free(na->tx_rings[r].tx_pool, M_DEVBUF); + } + +#ifdef RATE + if (--rate_ctx.refcount == 0) { + D("del_timer()"); + del_timer(&rate_ctx.timer); + } +#endif + } + +#ifdef REG_RESET + error = ifp->netdev_ops->ndo_open(ifp); + if (error) { + goto alloc_tx_pool; + } +#endif + + return 0; + +register_handler: + rtnl_unlock(); +free_tx_pool: + r--; + i = na->num_tx_desc; /* Useless, but just to stay safe. */ +free_mbufs: + i--; + for (; r>=0; r--) { + for (; i>=0; i--) { + m_freem(na->tx_rings[r].tx_pool[i]); + } + free(na->tx_rings[r].tx_pool, M_DEVBUF); + i = na->num_tx_desc - 1; + } + + return error; +} + +/* + * Callback invoked when the device driver frees an mbuf used + * by netmap to transmit a packet. This usually happens when + * the NIC notifies the driver that transmission is completed. + */ +static void +generic_mbuf_destructor(struct mbuf *m) +{ + if (netmap_verbose) + D("Tx irq (%p) queue %d", m, MBUF_TXQ(m)); + netmap_generic_irq(MBUF_IFP(m), MBUF_TXQ(m), NULL); +#ifdef __FreeBSD__ + m->m_ext.ext_type = EXT_PACKET; + m->m_ext.ext_free = NULL; + if (*(m->m_ext.ref_cnt) == 0) + *(m->m_ext.ref_cnt) = 1; + uma_zfree(zone_pack, m); +#endif /* __FreeBSD__ */ + IFRATE(rate_ctx.new.txirq++); +} + +/* Record completed transmissions and update hwavail. + * + * nr_ntc is the oldest tx buffer not yet completed + * (same as nr_hwavail + nr_hwcur + 1), + * nr_hwcur is the first unsent buffer. + * When cleaning, we try to recover buffers between nr_ntc and nr_hwcur. + */ +static int +generic_netmap_tx_clean(struct netmap_kring *kring) +{ + u_int num_slots = kring->nkr_num_slots; + u_int ntc = kring->nr_ntc; + u_int hwcur = kring->nr_hwcur; + u_int n = 0; + struct mbuf **tx_pool = kring->tx_pool; + + while (ntc != hwcur) { /* buffers not completed */ + struct mbuf *m = tx_pool[ntc]; + + if (unlikely(m == NULL)) { + /* try to replenish the entry */ + tx_pool[ntc] = m = netmap_get_mbuf(GENERIC_BUF_SIZE); + if (unlikely(m == NULL)) { + D("mbuf allocation failed, XXX error"); + // XXX how do we proceed ? break ? + return -ENOMEM; + } + } else if (GET_MBUF_REFCNT(m) != 1) { + break; /* This mbuf is still busy: its refcnt is 2. */ + } + if (unlikely(++ntc == num_slots)) { + ntc = 0; + } + n++; + } + kring->nr_ntc = ntc; + kring->nr_hwavail += n; + ND("tx completed [%d] -> hwavail %d", n, kring->nr_hwavail); + + return n; +} + + +/* + * We have pending packets in the driver between nr_ntc and j. + * Compute a position in the middle, to be used to generate + * a notification. + */ +static inline u_int +generic_tx_event_middle(struct netmap_kring *kring, u_int hwcur) +{ + u_int n = kring->nkr_num_slots; + u_int ntc = kring->nr_ntc; + u_int e; + + if (hwcur >= ntc) { + e = (hwcur + ntc) / 2; + } else { /* wrap around */ + e = (hwcur + n + ntc) / 2; + if (e >= n) { + e -= n; + } + } + + if (unlikely(e >= n)) { + D("This cannot happen"); + e = 0; + } + + return e; +} + +/* + * We have pending packets in the driver between nr_ntc and hwcur. + * Schedule a notification approximately in the middle of the two. + * There is a race but this is only called within txsync which does + * a double check. + */ +static void +generic_set_tx_event(struct netmap_kring *kring, u_int hwcur) +{ + struct mbuf *m; + u_int e; + + if (kring->nr_ntc == hwcur) { + return; + } + e = generic_tx_event_middle(kring, hwcur); + + m = kring->tx_pool[e]; + if (m == NULL) { + /* This can happen if there is already an event on the netmap + slot 'e': There is nothing to do. */ + return; + } + ND("Event at %d mbuf %p refcnt %d", e, m, GET_MBUF_REFCNT(m)); + kring->tx_pool[e] = NULL; + SET_MBUF_DESTRUCTOR(m, generic_mbuf_destructor); + + // XXX wmb() ? + /* Decrement the refcount an free it if we have the last one. */ + m_freem(m); + smp_mb(); +} + + +/* + * generic_netmap_txsync() transforms netmap buffers into mbufs + * and passes them to the standard device driver + * (ndo_start_xmit() or ifp->if_transmit() ). + * On linux this is not done directly, but using dev_queue_xmit(), + * since it implements the TX flow control (and takes some locks). + */ +static int +generic_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) +{ + struct ifnet *ifp = na->ifp; + struct netmap_kring *kring = &na->tx_rings[ring_nr]; + struct netmap_ring *ring = kring->ring; + u_int j, k, num_slots = kring->nkr_num_slots; + int new_slots, ntx; + + IFRATE(rate_ctx.new.txsync++); + + // TODO: handle the case of mbuf allocation failure + /* first, reclaim completed buffers */ + generic_netmap_tx_clean(kring); + + /* Take a copy of ring->cur now, and never read it again. */ + k = ring->cur; + if (unlikely(k >= num_slots)) { + return netmap_ring_reinit(kring); + } + + rmb(); + j = kring->nr_hwcur; + /* + * 'new_slots' counts how many new slots have been added: + * everything from hwcur to cur, excluding reserved ones, if any. + * nr_hwreserved start from hwcur and counts how many slots were + * not sent to the NIC from the previous round. + */ + new_slots = k - j - kring->nr_hwreserved; + if (new_slots < 0) { + new_slots += num_slots; + } + ntx = 0; + if (j != k) { + /* Process new packets to send: + * j is the current index in the netmap ring. + */ + while (j != k) { + struct netmap_slot *slot = &ring->slot[j]; /* Current slot in the netmap ring */ + void *addr = NMB(slot); + u_int len = slot->len; + struct mbuf *m; + int tx_ret; + + if (unlikely(addr == netmap_buffer_base || len > NETMAP_BUF_SIZE)) { + return netmap_ring_reinit(kring); + } + /* Tale a mbuf from the tx pool and copy in the user packet. */ + m = kring->tx_pool[j]; + if (unlikely(!m)) { + RD(5, "This should never happen"); + kring->tx_pool[j] = m = netmap_get_mbuf(GENERIC_BUF_SIZE); + if (unlikely(m == NULL)) { + D("mbuf allocation failed"); + break; + } + } + /* XXX we should ask notifications when NS_REPORT is set, + * or roughly every half frame. We can optimize this + * by lazily requesting notifications only when a + * transmission fails. Probably the best way is to + * break on failures and set notifications when + * ring->avail == 0 || j != k + */ + tx_ret = generic_xmit_frame(ifp, m, addr, len, ring_nr); + if (unlikely(tx_ret)) { + RD(5, "start_xmit failed: err %d [%u,%u,%u,%u]", + tx_ret, kring->nr_ntc, j, k, kring->nr_hwavail); + /* + * No room for this mbuf in the device driver. + * Request a notification FOR A PREVIOUS MBUF, + * then call generic_netmap_tx_clean(kring) to do the + * double check and see if we can free more buffers. + * If there is space continue, else break; + * NOTE: the double check is necessary if the problem + * occurs in the txsync call after selrecord(). + * Also, we need some way to tell the caller that not + * all buffers were queued onto the device (this was + * not a problem with native netmap driver where space + * is preallocated). The bridge has a similar problem + * and we solve it there by dropping the excess packets. + */ + generic_set_tx_event(kring, j); + if (generic_netmap_tx_clean(kring)) { /* space now available */ + continue; + } else { + break; + } + } + slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED); + if (unlikely(++j == num_slots)) + j = 0; + ntx++; + } + + /* Update hwcur to the next slot to transmit. */ + kring->nr_hwcur = j; + + /* + * Report all new slots as unavailable, even those not sent. + * We account for them with with hwreserved, so that + * nr_hwreserved =:= cur - nr_hwcur + */ + kring->nr_hwavail -= new_slots; + kring->nr_hwreserved = k - j; + if (kring->nr_hwreserved < 0) { + kring->nr_hwreserved += num_slots; + } + + IFRATE(rate_ctx.new.txpkt += ntx); + + if (!kring->nr_hwavail) { + /* No more available slots? Set a notification event + * on a netmap slot that will be cleaned in the future. + * No doublecheck is performed, since txsync() will be + * called twice by netmap_poll(). + */ + generic_set_tx_event(kring, j); + } + ND("tx #%d, hwavail = %d", n, kring->nr_hwavail); + } + + /* Synchronize the user's view to the kernel view. */ + ring->avail = kring->nr_hwavail; + ring->reserved = kring->nr_hwreserved; + + return 0; +} + +/* + * This handler is registered (through netmap_catch_rx()) + * within the attached network interface + * in the RX subsystem, so that every mbuf passed up by + * the driver can be stolen to the network stack. + * Stolen packets are put in a queue where the + * generic_netmap_rxsync() callback can extract them. + */ +void generic_rx_handler(struct ifnet *ifp, struct mbuf *m) +{ + struct netmap_adapter *na = NA(ifp); + struct netmap_generic_adapter *gna = (struct netmap_generic_adapter *)na; + u_int work_done; + u_int rr = 0; // receive ring number + + ND("called"); + /* limit the size of the queue */ + if (unlikely(mbq_len(&na->rx_rings[rr].rx_queue) > 1024)) { + m_freem(m); + } else { + mbq_safe_enqueue(&na->rx_rings[rr].rx_queue, m); + } + + if (netmap_generic_mit < 32768) { + /* no rx mitigation, pass notification up */ + netmap_generic_irq(na->ifp, rr, &work_done); + IFRATE(rate_ctx.new.rxirq++); + } else { + /* same as send combining, filter notification if there is a + * pending timer, otherwise pass it up and start a timer. + */ + if (likely(netmap_mitigation_active(gna))) { + /* Record that there is some pending work. */ + gna->mit_pending = 1; + } else { + netmap_generic_irq(na->ifp, rr, &work_done); + IFRATE(rate_ctx.new.rxirq++); + netmap_mitigation_start(gna); + } + } +} + +/* + * generic_netmap_rxsync() extracts mbufs from the queue filled by + * generic_netmap_rx_handler() and puts their content in the netmap + * receive ring. + * Access must be protected because the rx handler is asynchronous, + */ +static int +generic_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) +{ + struct netmap_kring *kring = &na->rx_rings[ring_nr]; + struct netmap_ring *ring = kring->ring; + u_int j, n, lim = kring->nkr_num_slots - 1; + int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR; + u_int k, resvd = ring->reserved; + + if (ring->cur > lim) + return netmap_ring_reinit(kring); + + /* Import newly received packets into the netmap ring. */ + if (netmap_no_pendintr || force_update) { + uint16_t slot_flags = kring->nkr_slot_flags; + struct mbuf *m; + + n = 0; + j = kring->nr_ntc; /* first empty slot in the receive ring */ + /* extract buffers from the rx queue, stop at most one + * slot before nr_hwcur (index k) + */ + k = (kring->nr_hwcur) ? kring->nr_hwcur-1 : lim; + while (j != k) { + int len; + void *addr = NMB(&ring->slot[j]); + + if (addr == netmap_buffer_base) { /* Bad buffer */ + return netmap_ring_reinit(kring); + } + /* + * Call the locked version of the function. + * XXX Ideally we could grab a batch of mbufs at once, + * by changing rx_queue into a ring. + */ + m = mbq_safe_dequeue(&kring->rx_queue); + if (!m) + break; + len = MBUF_LEN(m); + m_copydata(m, 0, len, addr); + ring->slot[j].len = len; + ring->slot[j].flags = slot_flags; + m_freem(m); + if (unlikely(j++ == lim)) + j = 0; + n++; + } + if (n) { + kring->nr_ntc = j; + kring->nr_hwavail += n; + IFRATE(rate_ctx.new.rxpkt += n); + } + kring->nr_kflags &= ~NKR_PENDINTR; + } + + // XXX should we invert the order ? + /* Skip past packets that userspace has released */ + j = kring->nr_hwcur; + k = ring->cur; + if (resvd > 0) { + if (resvd + ring->avail >= lim + 1) { + D("XXX invalid reserve/avail %d %d", resvd, ring->avail); + ring->reserved = resvd = 0; // XXX panic... + } + k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; + } + if (j != k) { + /* Userspace has released some packets. */ + for (n = 0; j != k; n++) { + struct netmap_slot *slot = &ring->slot[j]; + + slot->flags &= ~NS_BUF_CHANGED; + if (unlikely(j++ == lim)) + j = 0; + } + kring->nr_hwavail -= n; + kring->nr_hwcur = k; + } + /* Tell userspace that there are new packets. */ + ring->avail = kring->nr_hwavail - resvd; + IFRATE(rate_ctx.new.rxsync++); + + return 0; +} + +static void +generic_netmap_dtor(struct netmap_adapter *na) +{ + struct ifnet *ifp = na->ifp; + struct netmap_generic_adapter *gna = (struct netmap_generic_adapter*)na; + struct netmap_adapter *prev_na = gna->prev; + + if (prev_na != NULL) { + D("Released generic NA %p", gna); + if_rele(na->ifp); + netmap_adapter_put(prev_na); + } + if (ifp != NULL) { + WNA(ifp) = prev_na; + D("Restored native NA %p", prev_na); + na->ifp = NULL; + } +} + +/* + * generic_netmap_attach() makes it possible to use netmap on + * a device without native netmap support. + * This is less performant than native support but potentially + * faster than raw sockets or similar schemes. + * + * In this "emulated" mode, netmap rings do not necessarily + * have the same size as those in the NIC. We use a default + * value and possibly override it if the OS has ways to fetch the + * actual configuration. + */ +int +generic_netmap_attach(struct ifnet *ifp) +{ + struct netmap_adapter *na; + struct netmap_generic_adapter *gna; + int retval; + u_int num_tx_desc, num_rx_desc; + + num_tx_desc = num_rx_desc = netmap_generic_ringsize; /* starting point */ + + generic_find_num_desc(ifp, &num_tx_desc, &num_rx_desc); + ND("Netmap ring size: TX = %d, RX = %d", num_tx_desc, num_rx_desc); + + gna = malloc(sizeof(*gna), M_DEVBUF, M_NOWAIT | M_ZERO); + if (gna == NULL) { + D("no memory on attach, give up"); + return ENOMEM; + } + na = (struct netmap_adapter *)gna; + na->ifp = ifp; + na->num_tx_desc = num_tx_desc; + na->num_rx_desc = num_rx_desc; + na->nm_register = &generic_netmap_register; + na->nm_txsync = &generic_netmap_txsync; + na->nm_rxsync = &generic_netmap_rxsync; + na->nm_dtor = &generic_netmap_dtor; + /* when using generic, IFCAP_NETMAP is set so we force + * NAF_SKIP_INTR to use the regular interrupt handler + */ + na->na_flags = NAF_SKIP_INTR; + + ND("[GNA] num_tx_queues(%d), real_num_tx_queues(%d), len(%lu)", + ifp->num_tx_queues, ifp->real_num_tx_queues, + ifp->tx_queue_len); + ND("[GNA] num_rx_queues(%d), real_num_rx_queues(%d)", + ifp->num_rx_queues, ifp->real_num_rx_queues); + + generic_find_num_queues(ifp, &na->num_tx_rings, &na->num_rx_rings); + + retval = netmap_attach_common(na); + if (retval) { + free(gna, M_DEVBUF); + } + + return retval; +} diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h index 12bd882521b3..c009f5e62684 100644 --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011-2013 Matteo Landi, Luigi Rizzo. All rights reserved. + * Copyright (C) 2013 Universita` di Pisa. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,27 +34,61 @@ #ifndef _NET_NETMAP_KERN_H_ #define _NET_NETMAP_KERN_H_ +#define WITH_VALE // comment out to disable VALE support + #if defined(__FreeBSD__) #define likely(x) __builtin_expect((long)!!(x), 1L) #define unlikely(x) __builtin_expect((long)!!(x), 0L) #define NM_LOCK_T struct mtx +#define NMG_LOCK_T struct mtx +#define NMG_LOCK_INIT() mtx_init(&netmap_global_lock, \ + "netmap global lock", NULL, MTX_DEF) +#define NMG_LOCK_DESTROY() mtx_destroy(&netmap_global_lock) +#define NMG_LOCK() mtx_lock(&netmap_global_lock) +#define NMG_UNLOCK() mtx_unlock(&netmap_global_lock) +#define NMG_LOCK_ASSERT() mtx_assert(&netmap_global_lock, MA_OWNED) + #define NM_SELINFO_T struct selinfo #define MBUF_LEN(m) ((m)->m_pkthdr.len) +#define MBUF_IFP(m) ((m)->m_pkthdr.rcvif) #define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) -#define NM_ATOMIC_T volatile int +#define NM_ATOMIC_T volatile int // XXX ? +/* atomic operations */ +#include +#define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1)) +#define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0) + +#define prefetch(x) __builtin_prefetch(x) + +MALLOC_DECLARE(M_NETMAP); + +// XXX linux struct, not used in FreeBSD +struct net_device_ops { +}; +struct hrtimer { +}; #elif defined (linux) #define NM_LOCK_T safe_spinlock_t // see bsd_glue.h #define NM_SELINFO_T wait_queue_head_t #define MBUF_LEN(m) ((m)->len) +#define MBUF_IFP(m) ((m)->dev) #define NM_SEND_UP(ifp, m) netif_rx(m) #define NM_ATOMIC_T volatile long unsigned int +// XXX a mtx would suffice here too 20130404 gl +#define NMG_LOCK_T struct semaphore +#define NMG_LOCK_INIT() sema_init(&netmap_global_lock, 1) +#define NMG_LOCK_DESTROY() +#define NMG_LOCK() down(&netmap_global_lock) +#define NMG_UNLOCK() up(&netmap_global_lock) +#define NMG_LOCK_ASSERT() // XXX to be completed + #ifndef DEV_NETMAP #define DEV_NETMAP #endif /* DEV_NETMAP */ @@ -115,6 +150,10 @@ struct netmap_priv_d; const char *nm_dump_buf(char *p, int len, int lim, char *dst); +#include "netmap_mbq.h" + +extern NMG_LOCK_T netmap_global_lock; + /* * private, kernel view of a ring. Keeps track of the status of * a ring across system calls. @@ -152,7 +191,7 @@ const char *nm_dump_buf(char *p, int len, int lim, char *dst); * nkr_leases array of nkr_num_slots where writers can report * completion of their block. NR_NOSLOT (~0) indicates * that the writer has not finished yet - * nkr_lease_idx index of next free slot in nr_leases, to be assigned + * nkr_lease_idx index of next free slot in nr_leases, to be assigned * * The kring is manipulated by txsync/rxsync and generic netmap function. * q_lock is used to arbitrate access to the kring from within the netmap @@ -166,6 +205,7 @@ struct netmap_kring { uint32_t nr_hwcur; uint32_t nr_hwavail; uint32_t nr_kflags; /* private driver flags */ + int32_t nr_hwreserved; #define NKR_PENDINTR 0x1 // Pending interrupt. uint32_t nkr_num_slots; int32_t nkr_hwofs; /* offset between NIC and netmap ring */ @@ -183,6 +223,17 @@ struct netmap_kring { NM_ATOMIC_T nr_busy; /* prevent concurrent syscalls */ volatile int nkr_stopped; + + /* support for adapters without native netmap support. + * On tx rings we preallocate an array of tx buffers + * (same size as the netmap ring), on rx rings we + * store incoming packets in a queue. + * XXX who writes to the rx queue ? + */ + struct mbuf **tx_pool; + u_int nr_ntc; /* Emulation of a next-to-clean RX ring pointer. */ + struct mbq rx_queue; /* A queue for intercepted rx mbufs. */ + } __attribute__((__aligned__(64))); @@ -245,22 +296,26 @@ nm_next(uint32_t i, uint32_t lim) +enum txrx { NR_RX = 0, NR_TX = 1 }; /* - * This struct extends the 'struct adapter' (or - * equivalent) device descriptor. It contains all fields needed to - * support netmap operation. + * The "struct netmap_adapter" extends the "struct adapter" + * (or equivalent) device descriptor. + * It contains all base fields needed to support netmap operation. + * There are in fact different types of netmap adapters + * (native, generic, VALE switch...) so a netmap_adapter is + * just the first field in the derived type. */ struct netmap_adapter { /* * On linux we do not have a good way to tell if an interface - * is netmap-capable. So we use the following trick: + * is netmap-capable. So we always use the following trick: * NA(ifp) points here, and the first entry (which hopefully * always exists and is at least 32 bits) contains a magic * value which we can use to detect that the interface is good. */ uint32_t magic; - uint32_t na_flags; /* future place for IFCAP_NETMAP */ + uint32_t na_flags; /* enabled, and other flags */ #define NAF_SKIP_INTR 1 /* use the regular interrupt handler. * useful during initialization */ @@ -272,17 +327,16 @@ struct netmap_adapter { #define NAF_MEM_OWNER 8 /* the adapter is responsible for the * deallocation of the memory allocator */ - int refcount; /* number of user-space descriptors using this +#define NAF_NATIVE_ON 16 /* the adapter is native and the attached + * interface is in netmap mode + */ +#define NAF_NETMAP_ON 32 /* netmap is active (either native or + * emulated. Where possible (e.g. FreeBSD) + * IFCAP_NETMAP also mirrors this flag. + */ + int active_fds; /* number of user-space descriptors using this interface, which is equal to the number of struct netmap_if objs in the mapped region. */ - /* - * The selwakeup in the interrupt thread can use per-ring - * and/or global wait queues. We track how many clients - * of each type we have so we can optimize the drivers, - * and especially avoid huge contention on the locks. - */ - int na_single; /* threads attached to a single hw queue */ - int na_multi; /* threads attached to multiple hw queues */ u_int num_rx_rings; /* number of adapter receive rings */ u_int num_tx_rings; /* number of adapter transmit rings */ @@ -296,6 +350,9 @@ struct netmap_adapter { */ struct netmap_kring *tx_rings; /* array of TX rings. */ struct netmap_kring *rx_rings; /* array of RX rings. */ + void *tailroom; /* space below the rings array */ + /* (used for leases) */ + NM_SELINFO_T tx_si, rx_si; /* global wait queues */ @@ -309,47 +366,157 @@ struct netmap_adapter { */ struct ifnet *ifp; /* adapter is ifp->if_softc */ - NM_LOCK_T core_lock; /* used if no device lock available */ + /* private cleanup */ + void (*nm_dtor)(struct netmap_adapter *); - int (*nm_register)(struct ifnet *, int onoff); + int (*nm_register)(struct netmap_adapter *, int onoff); - int (*nm_txsync)(struct ifnet *, u_int ring, int flags); - int (*nm_rxsync)(struct ifnet *, u_int ring, int flags); + int (*nm_txsync)(struct netmap_adapter *, u_int ring, int flags); + int (*nm_rxsync)(struct netmap_adapter *, u_int ring, int flags); #define NAF_FORCE_READ 1 #define NAF_FORCE_RECLAIM 2 /* return configuration information */ - int (*nm_config)(struct ifnet *, u_int *txr, u_int *txd, - u_int *rxr, u_int *rxd); + int (*nm_config)(struct netmap_adapter *, + u_int *txr, u_int *txd, u_int *rxr, u_int *rxd); + int (*nm_krings_create)(struct netmap_adapter *); + void (*nm_krings_delete)(struct netmap_adapter *); + int (*nm_notify)(struct netmap_adapter *, + u_int ring, enum txrx, int flags); +#define NAF_GLOBAL_NOTIFY 4 +#define NAF_DISABLE_NOTIFY 8 + + /* standard refcount to control the lifetime of the adapter + * (it should be equal to the lifetime of the corresponding ifp) + */ + int na_refcount; + + /* memory allocator (opaque) + * We also cache a pointer to the lut_entry for translating + * buffer addresses, and the total number of buffers. + */ + struct netmap_mem_d *nm_mem; + struct lut_entry *na_lut; + uint32_t na_lut_objtotal; /* max buffer index */ + + /* used internally. If non-null, the interface cannot be bound + * from userspace + */ + void *na_private; +}; + +/* + * If the NIC is owned by the kernel + * (i.e., bridge), neither another bridge nor user can use it; + * if the NIC is owned by a user, only users can share it. + * Evaluation must be done under NMG_LOCK(). + */ +#define NETMAP_OWNED_BY_KERN(na) (na->na_private) +#define NETMAP_OWNED_BY_ANY(na) \ + (NETMAP_OWNED_BY_KERN(na) || (na->active_fds > 0)) + + +/* + * derived netmap adapters for various types of ports + */ +struct netmap_vp_adapter { /* VALE software port */ + struct netmap_adapter up; /* * Bridge support: * * bdg_port is the port number used in the bridge; - * na_bdg_refcount is a refcount used for bridge ports, - * when it goes to 0 we can detach+free this port - * (a bridge port is always attached if it exists; - * it is not always registered) * na_bdg points to the bridge this NA is attached to. */ int bdg_port; - int na_bdg_refcount; struct nm_bridge *na_bdg; + int retry; + + u_int offset; /* Offset of ethernet header for each packet. */ +}; + +struct netmap_hw_adapter { /* physical device */ + struct netmap_adapter up; + + struct net_device_ops nm_ndo; // XXX linux only +}; + +struct netmap_generic_adapter { /* non-native device */ + struct netmap_hw_adapter up; + + /* Pointer to a previously used netmap adapter. */ + struct netmap_adapter *prev; + + /* generic netmap adapters support: + * a net_device_ops struct overrides ndo_select_queue(), + * save_if_input saves the if_input hook (FreeBSD), + * mit_timer and mit_pending implement rx interrupt mitigation, + */ + struct net_device_ops generic_ndo; + void (*save_if_input)(struct ifnet *, struct mbuf *); + + struct hrtimer mit_timer; + int mit_pending; +}; + +#ifdef WITH_VALE + +/* bridge wrapper for non VALE ports. It is used to connect real devices to the bridge. + * + * The real device must already have its own netmap adapter (hwna). The + * bridge wrapper and the hwna adapter share the same set of netmap rings and + * buffers, but they have two separate sets of krings descriptors, with tx/rx + * meanings swapped: + * + * netmap + * bwrap krings rings krings hwna + * +------+ +------+ +-----+ +------+ +------+ + * |tx_rings->| |\ /| |----| |<-tx_rings| + * | | +------+ \ / +-----+ +------+ | | + * | | X | | + * | | / \ | | + * | | +------+/ \+-----+ +------+ | | + * |rx_rings->| | | |----| |<-rx_rings| + * | | +------+ +-----+ +------+ | | + * +------+ +------+ + * + * - packets coming from the bridge go to the brwap rx rings, which are also the + * hwna tx rings. The bwrap notify callback will then complete the hwna tx + * (see netmap_bwrap_notify). + * - packets coming from the outside go to the hwna rx rings, which are also the + * bwrap tx rings. The (overwritten) hwna notify method will then complete + * the bridge tx (see netmap_bwrap_intr_notify). + * + * The bridge wrapper may optionally connect the hwna 'host' rings to the + * bridge. This is done by using a second port in the bridge and connecting it + * to the 'host' netmap_vp_adapter contained in the netmap_bwrap_adapter. + * The brwap host adapter cross-links the hwna host rings in the same way as shown above. + * + * - packets coming from the bridge and directed to host stack are handled by the + * bwrap host notify callback (see netmap_bwrap_host_notify) + * - packets coming from the host stack are still handled by the overwritten + * hwna notify callback (netmap_bwrap_intr_notify), but are diverted to the + * host adapter depending on the ring number. + * + */ +struct netmap_bwrap_adapter { + struct netmap_vp_adapter up; + struct netmap_vp_adapter host; /* for host rings */ + struct netmap_adapter *hwna; /* the underlying device */ + + /* backup of the hwna notify callback */ + int (*save_notify)(struct netmap_adapter *, + u_int ring, enum txrx, int flags); /* When we attach a physical interface to the bridge, we * allow the controlling process to terminate, so we need * a place to store the netmap_priv_d data structure. * This is only done when physical interfaces are attached to a bridge. */ struct netmap_priv_d *na_kpriv; - - /* memory allocator */ - struct netmap_mem_d *nm_mem; -#ifdef linux - struct net_device_ops nm_ndo; -#endif /* linux */ }; + /* - * Available space in the ring. + * Available space in the ring. Only used in VALE code */ static inline uint32_t nm_kr_space(struct netmap_kring *k, int is_rx) @@ -357,7 +524,7 @@ nm_kr_space(struct netmap_kring *k, int is_rx) int space; if (is_rx) { - int busy = k->nkr_hwlease - k->nr_hwcur; + int busy = k->nkr_hwlease - k->nr_hwcur + k->nr_hwreserved; if (busy < 0) busy += k->nkr_num_slots; space = k->nkr_num_slots - 1 - busy; @@ -381,25 +548,6 @@ nm_kr_space(struct netmap_kring *k, int is_rx) } -/* return update position */ -static inline uint32_t -nm_kr_rxpos(struct netmap_kring *k) -{ - uint32_t pos = k->nr_hwcur + k->nr_hwavail; - if (pos >= k->nkr_num_slots) - pos -= k->nkr_num_slots; -#if 0 - if (pos >= k->nkr_num_slots || - k->nkr_hwlease >= k->nkr_num_slots || - k->nr_hwcur >= k->nkr_num_slots || - k->nr_hwavail >= k->nkr_num_slots || - k->nkr_lease_idx >= k->nkr_num_slots) { - D("invalid kring, cur %d avail %d lease %d lease_idx %d lim %d", k->nr_hwcur, k->nr_hwavail, k->nkr_hwlease, - k->nkr_lease_idx, k->nkr_num_slots); - } -#endif - return pos; -} /* make a lease on the kring for N positions. return the @@ -435,23 +583,61 @@ nm_kr_lease(struct netmap_kring *k, u_int n, int is_rx) return lease_idx; } +#endif /* WITH_VALE */ + +/* return update position */ +static inline uint32_t +nm_kr_rxpos(struct netmap_kring *k) +{ + uint32_t pos = k->nr_hwcur + k->nr_hwavail; + if (pos >= k->nkr_num_slots) + pos -= k->nkr_num_slots; +#if 0 + if (pos >= k->nkr_num_slots || + k->nkr_hwlease >= k->nkr_num_slots || + k->nr_hwcur >= k->nkr_num_slots || + k->nr_hwavail >= k->nkr_num_slots || + k->nkr_lease_idx >= k->nkr_num_slots) { + D("invalid kring, cur %d avail %d lease %d lease_idx %d lim %d", k->nr_hwcur, k->nr_hwavail, k->nkr_hwlease, + k->nkr_lease_idx, k->nkr_num_slots); + } +#endif + return pos; +} + /* - * XXX NETMAP_DELETING() is unused - * - * The combination of "enable" (ifp->if_capenable & IFCAP_NETMAP) - * and refcount gives the status of the interface, namely: - * - * enable refcount Status - * - * FALSE 0 normal operation - * FALSE != 0 -- (impossible) - * TRUE 1 netmap mode - * TRUE 0 being deleted. + * protect against multiple threads using the same ring. + * also check that the ring has not been stopped. + * We only care for 0 or !=0 as a return code. */ +#define NM_KR_BUSY 1 +#define NM_KR_STOPPED 2 -#define NETMAP_DELETING(_na) ( ((_na)->refcount == 0) && \ - ( (_na)->ifp->if_capenable & IFCAP_NETMAP) ) +static __inline void nm_kr_put(struct netmap_kring *kr) +{ + NM_ATOMIC_CLEAR(&kr->nr_busy); +} + +static __inline int nm_kr_tryget(struct netmap_kring *kr) +{ + /* check a first time without taking the lock + * to avoid starvation for nm_kr_get() + */ + if (unlikely(kr->nkr_stopped)) { + ND("ring %p stopped (%d)", kr, kr->nkr_stopped); + return NM_KR_STOPPED; + } + if (unlikely(NM_ATOMIC_TEST_AND_SET(&kr->nr_busy))) + return NM_KR_BUSY; + /* check a second time with lock held */ + if (unlikely(kr->nkr_stopped)) { + ND("ring %p stopped (%d)", kr, kr->nkr_stopped); + nm_kr_put(kr); + return NM_KR_STOPPED; + } + return 0; +} /* @@ -472,16 +658,116 @@ nm_kr_lease(struct netmap_kring *k, u_int n, int is_rx) * netmap_reset() is a helper routine to be called in the driver * when reinitializing a ring. */ -int netmap_attach(struct netmap_adapter *, u_int); +int netmap_attach(struct netmap_adapter *); +int netmap_attach_common(struct netmap_adapter *); +void netmap_detach_common(struct netmap_adapter *na); void netmap_detach(struct ifnet *); int netmap_transmit(struct ifnet *, struct mbuf *); -enum txrx { NR_RX = 0, NR_TX = 1 }; struct netmap_slot *netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n, u_int new_cur); int netmap_ring_reinit(struct netmap_kring *); -u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); +/* set/clear native flags. XXX maybe also if_transmit ? */ +static inline void +nm_set_native_flags(struct netmap_adapter *na) +{ + struct ifnet *ifp = na->ifp; + na->na_flags |= (NAF_NATIVE_ON | NAF_NETMAP_ON); +#ifdef IFCAP_NETMAP /* or FreeBSD ? */ + ifp->if_capenable |= IFCAP_NETMAP; +#endif +#ifdef __FreeBSD__ + na->if_transmit = ifp->if_transmit; + ifp->if_transmit = netmap_transmit; +#else + na->if_transmit = (void *)ifp->netdev_ops; + ifp->netdev_ops = &((struct netmap_hw_adapter *)na)->nm_ndo; +#endif +} + +static inline void +nm_clear_native_flags(struct netmap_adapter *na) +{ + struct ifnet *ifp = na->ifp; + +#ifdef __FreeBSD__ + ifp->if_transmit = na->if_transmit; +#else + ifp->netdev_ops = (void *)na->if_transmit; +#endif + na->na_flags &= ~(NAF_NATIVE_ON | NAF_NETMAP_ON); +#ifdef IFCAP_NETMAP /* or FreeBSD ? */ + ifp->if_capenable &= ~IFCAP_NETMAP; +#endif +} + +/* + * validates parameters in the ring/kring, returns a value for cur, + * and the 'new_slots' value in the argument. + * If any error, returns cur > lim to force a reinit. + */ +u_int nm_txsync_prologue(struct netmap_kring *, u_int *); + +/* + * validates parameters in the ring/kring, returns a value for cur, + * and the 'reserved' value in the argument. + * If any error, returns cur > lim to force a reinit. + */ +u_int nm_rxsync_prologue(struct netmap_kring *, u_int *); + +/* + * update kring and ring at the end of txsync + */ +static inline void +nm_txsync_finalize(struct netmap_kring *kring, u_int cur) +{ + /* recompute hwreserved */ + kring->nr_hwreserved = cur - kring->nr_hwcur; + if (kring->nr_hwreserved < 0) + kring->nr_hwreserved += kring->nkr_num_slots; + + /* update avail and reserved to what the kernel knows */ + kring->ring->avail = kring->nr_hwavail; + kring->ring->reserved = kring->nr_hwreserved; +} + +/* check/fix address and len in tx rings */ +#if 1 /* debug version */ +#define NM_CHECK_ADDR_LEN(_a, _l) do { \ + if (_a == netmap_buffer_base || _l > NETMAP_BUF_SIZE) { \ + RD(5, "bad addr/len ring %d slot %d idx %d len %d", \ + ring_nr, nm_i, slot->buf_idx, len); \ + if (_l > NETMAP_BUF_SIZE) \ + _l = NETMAP_BUF_SIZE; \ + } } while (0) +#else /* no debug version */ +#define NM_CHECK_ADDR_LEN(_a, _l) do { \ + if (_l > NETMAP_BUF_SIZE) \ + _l = NETMAP_BUF_SIZE; \ + } while (0) +#endif + + +/*---------------------------------------------------------------*/ +/* + * Support routines to be used with the VALE switch + */ +int netmap_update_config(struct netmap_adapter *na); +int netmap_krings_create(struct netmap_adapter *na, u_int ntx, u_int nrx, u_int tailroom); +void netmap_krings_delete(struct netmap_adapter *na); + +struct netmap_if * +netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na, + uint16_t ringid, int *err); + + + +u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); +int netmap_get_na(struct nmreq *nmr, struct netmap_adapter **na, int create); +int netmap_get_hw_na(struct ifnet *ifp, struct netmap_adapter **na); + +#ifdef WITH_VALE /* * The following bridge-related interfaces are used by other kernel modules * In the version that only supports unicast or broadcast, the lookup @@ -489,15 +775,76 @@ u_int nm_bound_var(u_int *v, u_int dflt, u_int lo, u_int hi, const char *msg); * NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 for unknown. * XXX in practice "unknown" might be handled same as broadcast. */ -typedef u_int (*bdg_lookup_fn_t)(char *buf, u_int len, uint8_t *ring_nr, - struct netmap_adapter *); -int netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func); -u_int netmap_bdg_learning(char *, u_int, uint8_t *, struct netmap_adapter *); -#define NM_NAME "vale" /* prefix for the bridge port name */ -#define NM_BDG_MAXPORTS 254 /* up to 32 for bitmap, 254 ok otherwise */ +typedef u_int (*bdg_lookup_fn_t)(char *buf, u_int len, + uint8_t *ring_nr, struct netmap_vp_adapter *); +u_int netmap_bdg_learning(char *, u_int, uint8_t *, + struct netmap_vp_adapter *); + +#define NM_BDG_MAXPORTS 254 /* up to 254 */ #define NM_BDG_BROADCAST NM_BDG_MAXPORTS #define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) +#define NM_NAME "vale" /* prefix for bridge port name */ + + +/* these are redefined in case of no VALE support */ +int netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create); +void netmap_init_bridges(void); +int netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func); + +#else /* !WITH_VALE */ +#define netmap_get_bdg_na(_1, _2, _3) 0 +#define netmap_init_bridges(_1) +#define netmap_bdg_ctl(_1, _2) EINVAL +#endif /* !WITH_VALE */ + +/* Various prototypes */ +int netmap_poll(struct cdev *dev, int events, struct thread *td); + + +int netmap_init(void); +void netmap_fini(void); +int netmap_get_memory(struct netmap_priv_d* p); +void netmap_dtor(void *data); +int netmap_dtor_locked(struct netmap_priv_d *priv); + +int netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td); + +/* netmap_adapter creation/destruction */ +#define NM_IFPNAME(ifp) ((ifp) ? (ifp)->if_xname : "zombie") +#define NM_DEBUG_PUTGET 1 + +#ifdef NM_DEBUG_PUTGET + +#define NM_DBG(f) __##f + +void __netmap_adapter_get(struct netmap_adapter *na); + +#define netmap_adapter_get(na) \ + do { \ + struct netmap_adapter *__na = na; \ + D("getting %p:%s (%d)", __na, NM_IFPNAME(__na->ifp), __na->na_refcount); \ + __netmap_adapter_get(__na); \ + } while (0) + +int __netmap_adapter_put(struct netmap_adapter *na); + +#define netmap_adapter_put(na) \ + do { \ + struct netmap_adapter *__na = na; \ + D("putting %p:%s (%d)", __na, NM_IFPNAME(__na->ifp), __na->na_refcount); \ + __netmap_adapter_put(__na); \ + } while (0) + +#else /* !NM_DEBUG_PUTGET */ + +#define NM_DBG(f) f +void netmap_adapter_get(struct netmap_adapter *na); +int netmap_adapter_put(struct netmap_adapter *na); + +#endif /* !NM_DEBUG_PUTGET */ + + extern u_int netmap_buf_size; #define NETMAP_BUF_SIZE netmap_buf_size // XXX remove extern int netmap_mitigate; @@ -516,18 +863,18 @@ enum { /* verbose flags */ NM_VERB_NIC_TXSYNC = 0x2000, }; +extern int netmap_txsync_retry; +extern int netmap_generic_mit; +extern int netmap_generic_ringsize; + /* * NA returns a pointer to the struct netmap adapter from the ifp, * WNA is used to write it. - * SWNA() is used for the "host stack" endpoint associated - * to an interface. It is allocated together with the main NA(), - * as an array of two objects. */ #ifndef WNA #define WNA(_ifp) (_ifp)->if_pspare[0] #endif #define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp)) -#define SWNA(_ifp) (NA(_ifp) + 1) /* * Macros to determine if an interface is netmap capable or netmap enabled. @@ -561,6 +908,7 @@ enum { /* verbose flags */ #endif /* linux */ #ifdef __FreeBSD__ + /* Callback invoked by the dma machinery after a successfull dmamap_load */ static void netmap_dmamap_cb(__unused void *arg, __unused bus_dma_segment_t * segs, __unused int nseg, __unused int error) @@ -588,6 +936,7 @@ netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) netmap_dmamap_cb, NULL, BUS_DMA_NOWAIT); } } + #else /* linux */ /* @@ -695,16 +1044,97 @@ PNMB(struct netmap_slot *slot, uint64_t *pp) return ret; } +/* Generic version of NMB, which uses device-specific memory. */ +static inline void * +BDG_NMB(struct netmap_adapter *na, struct netmap_slot *slot) +{ + struct lut_entry *lut = na->na_lut; + uint32_t i = slot->buf_idx; + return (unlikely(i >= na->na_lut_objtotal)) ? + lut[0].vaddr : lut[i].vaddr; +} + /* default functions to handle rx/tx interrupts */ int netmap_rx_irq(struct ifnet *, u_int, u_int *); #define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) - -#ifdef __FreeBSD__ -MALLOC_DECLARE(M_NETMAP); -#endif /* __FreeBSD__ */ +void netmap_common_irq(struct ifnet *, u_int, u_int *work_done); +void netmap_txsync_to_host(struct netmap_adapter *na); void netmap_disable_all_rings(struct ifnet *); void netmap_enable_all_rings(struct ifnet *); +void netmap_disable_ring(struct netmap_kring *kr); + + +/* Structure associated to each thread which registered an interface. + * + * The first 4 fields of this structure are written by NIOCREGIF and + * read by poll() and NIOC?XSYNC. + * There is low contention among writers (actually, a correct user program + * should have no contention among writers) and among writers and readers, + * so we use a single global lock to protect the structure initialization. + * Since initialization involves the allocation of memory, we reuse the memory + * allocator lock. + * Read access to the structure is lock free. Readers must check that + * np_nifp is not NULL before using the other fields. + * If np_nifp is NULL initialization has not been performed, so they should + * return an error to userlevel. + * + * The ref_done field is used to regulate access to the refcount in the + * memory allocator. The refcount must be incremented at most once for + * each open("/dev/netmap"). The increment is performed by the first + * function that calls netmap_get_memory() (currently called by + * mmap(), NIOCGINFO and NIOCREGIF). + * If the refcount is incremented, it is then decremented when the + * private structure is destroyed. + */ +struct netmap_priv_d { + struct netmap_if * volatile np_nifp; /* netmap if descriptor. */ + + struct netmap_adapter *np_na; + int np_ringid; /* from the ioctl */ + u_int np_qfirst, np_qlast; /* range of rings to scan */ + uint16_t np_txpoll; + + struct netmap_mem_d *np_mref; /* use with NMG_LOCK held */ + /* np_refcount is only used on FreeBSD */ + int np_refcount; /* use with NMG_LOCK held */ +}; + + +/* + * generic netmap emulation for devices that do not have + * native netmap support. + * XXX generic_netmap_register() is only exported to implement + * nma_is_generic(). + */ +int generic_netmap_register(struct netmap_adapter *na, int enable); +int generic_netmap_attach(struct ifnet *ifp); + +int netmap_catch_rx(struct netmap_adapter *na, int intercept); +void generic_rx_handler(struct ifnet *ifp, struct mbuf *m);; +void netmap_catch_packet_steering(struct netmap_generic_adapter *na, int enable); +int generic_xmit_frame(struct ifnet *ifp, struct mbuf *m, void *addr, u_int len, u_int ring_nr); +int generic_find_num_desc(struct ifnet *ifp, u_int *tx, u_int *rx); +void generic_find_num_queues(struct ifnet *ifp, u_int *txq, u_int *rxq); + +static __inline int +nma_is_generic(struct netmap_adapter *na) +{ + return na->nm_register == generic_netmap_register; +} + +/* + * netmap_mitigation API. This is used by the generic adapter + * to reduce the number of interrupt requests/selwakeup + * to clients on incoming packets. + */ +void netmap_mitigation_init(struct netmap_generic_adapter *na); +void netmap_mitigation_start(struct netmap_generic_adapter *na); +void netmap_mitigation_restart(struct netmap_generic_adapter *na); +int netmap_mitigation_active(struct netmap_generic_adapter *na); +void netmap_mitigation_cleanup(struct netmap_generic_adapter *na); + +// int generic_timer_handler(struct hrtimer *t); #endif /* _NET_NETMAP_KERN_H_ */ diff --git a/sys/dev/netmap/netmap_mbq.c b/sys/dev/netmap/netmap_mbq.c new file mode 100644 index 000000000000..c8e581b69fe5 --- /dev/null +++ b/sys/dev/netmap/netmap_mbq.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2013 Vincenzo Maffione. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $FreeBSD$ + */ + + +#ifdef linux +#include "bsd_glue.h" +#else /* __FreeBSD__ */ +#include +#include +#include +#include +#include +#endif /* __FreeBSD__ */ + +#include "netmap_mbq.h" + + +static inline void __mbq_init(struct mbq *q) +{ + q->head = q->tail = NULL; + q->count = 0; +} + +void mbq_safe_init(struct mbq *q) +{ + mtx_init(&q->lock, "mbq", NULL, MTX_SPIN); + __mbq_init(q); +} + +void mbq_init(struct mbq *q) +{ + __mbq_init(q); +} + +static inline void __mbq_enqueue(struct mbq *q, struct mbuf *m) +{ + m->m_nextpkt = NULL; + if (q->tail) { + q->tail->m_nextpkt = m; + q->tail = m; + } else { + q->head = q->tail = m; + } + q->count++; +} + +void mbq_safe_enqueue(struct mbq *q, struct mbuf *m) +{ + mtx_lock(&q->lock); + __mbq_enqueue(q, m); + mtx_unlock(&q->lock); +} + +void mbq_enqueue(struct mbq *q, struct mbuf *m) +{ + __mbq_enqueue(q, m); +} + +static inline struct mbuf *__mbq_dequeue(struct mbq *q) +{ + struct mbuf *ret = NULL; + + if (q->head) { + ret = q->head; + q->head = ret->m_nextpkt; + if (q->head == NULL) { + q->tail = NULL; + } + q->count--; + ret->m_nextpkt = NULL; + } + + return ret; +} + +struct mbuf *mbq_safe_dequeue(struct mbq *q) +{ + struct mbuf *ret; + + mtx_lock(&q->lock); + ret = __mbq_dequeue(q); + mtx_unlock(&q->lock); + + return ret; +} + +struct mbuf *mbq_dequeue(struct mbq *q) +{ + return __mbq_dequeue(q); +} + +/* XXX seems pointless to have a generic purge */ +static void __mbq_purge(struct mbq *q, int safe) +{ + struct mbuf *m; + + for (;;) { + m = safe ? mbq_safe_dequeue(q) : mbq_dequeue(q); + if (m) { + m_freem(m); + } else { + break; + } + } +} + +void mbq_purge(struct mbq *q) +{ + __mbq_purge(q, 0); +} + +void mbq_safe_purge(struct mbq *q) +{ + __mbq_purge(q, 1); +} + +void mbq_safe_destroy(struct mbq *q) +{ + mtx_destroy(&q->lock); +} + + +void mbq_destroy(struct mbq *q) +{ +} + diff --git a/sys/dev/netmap/netmap_mbq.h b/sys/dev/netmap/netmap_mbq.h new file mode 100644 index 000000000000..ad023b617a5d --- /dev/null +++ b/sys/dev/netmap/netmap_mbq.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Vincenzo Maffione. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $FreeBSD$ + */ + + +#ifndef __NETMAP_MBQ_H__ +#define __NETMAP_MBQ_H__ + +/* + * These function implement an mbuf tailq with an optional lock. + * The base functions act ONLY ON THE QUEUE, whereas the "safe" + * variants (mbq_safe_*) also handle the lock. + */ + +/* XXX probably rely on a previous definition of SPINLOCK_T */ +#ifdef linux +#define SPINLOCK_T safe_spinlock_t +#else +#define SPINLOCK_T struct mtx +#endif + +/* A FIFO queue of mbufs with an optional lock. */ +struct mbq { + struct mbuf *head; + struct mbuf *tail; + int count; + SPINLOCK_T lock; +}; + +/* XXX "destroy" does not match "init" as a name. + * We should also clarify whether init can be used while + * holding a lock, and whether mbq_safe_destroy() is a NOP. + */ +void mbq_init(struct mbq *q); +void mbq_destroy(struct mbq *q); +void mbq_enqueue(struct mbq *q, struct mbuf *m); +struct mbuf *mbq_dequeue(struct mbq *q); +void mbq_purge(struct mbq *q); + +/* XXX missing mbq_lock() and mbq_unlock */ + +void mbq_safe_init(struct mbq *q); +void mbq_safe_destroy(struct mbq *q); +void mbq_safe_enqueue(struct mbq *q, struct mbuf *m); +struct mbuf *mbq_safe_dequeue(struct mbq *q); +void mbq_safe_purge(struct mbq *q); + +static inline unsigned int mbq_len(struct mbq *q) +{ + return q->count; +} + +#endif /* __NETMAP_MBQ_H_ */ diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c index a78904216057..f28f2c04751a 100644 --- a/sys/dev/netmap/netmap_mem2.c +++ b/sys/dev/netmap/netmap_mem2.c @@ -8,7 +8,7 @@ * 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. + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -167,12 +167,12 @@ const struct netmap_mem_d nm_blueprint = { #define DECLARE_SYSCTLS(id, name) \ SYSCTL_INT(_dev_netmap, OID_AUTO, name##_size, \ CTLFLAG_RW, &netmap_params[id].size, 0, "Requested size of netmap " STRINGIFY(name) "s"); \ - SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_size, \ - CTLFLAG_RD, &nm_mem.pools[id]._objsize, 0, "Current size of netmap " STRINGIFY(name) "s"); \ - SYSCTL_INT(_dev_netmap, OID_AUTO, name##_num, \ - CTLFLAG_RW, &netmap_params[id].num, 0, "Requested number of netmap " STRINGIFY(name) "s"); \ - SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_num, \ - CTLFLAG_RD, &nm_mem.pools[id].objtotal, 0, "Current number of netmap " STRINGIFY(name) "s") + SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_size, \ + CTLFLAG_RD, &nm_mem.pools[id]._objsize, 0, "Current size of netmap " STRINGIFY(name) "s"); \ + SYSCTL_INT(_dev_netmap, OID_AUTO, name##_num, \ + CTLFLAG_RW, &netmap_params[id].num, 0, "Requested number of netmap " STRINGIFY(name) "s"); \ + SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_num, \ + CTLFLAG_RD, &nm_mem.pools[id].objtotal, 0, "Current number of netmap " STRINGIFY(name) "s") SYSCTL_DECL(_dev_netmap); DECLARE_SYSCTLS(NETMAP_IF_POOL, if); @@ -310,7 +310,7 @@ netmap_obj_malloc(struct netmap_obj_pool *p, u_int len, uint32_t *start, uint32_ } if (p->objfree == 0) { - D("%s allocator: run out of memory", p->name); + D("no more %s objects", p->name); return NULL; } if (start) @@ -395,28 +395,22 @@ netmap_obj_free_va(struct netmap_obj_pool *p, void *vaddr) /* Return nonzero on error */ static int -netmap_new_bufs(struct netmap_mem_d *nmd, struct netmap_if *nifp, - struct netmap_slot *slot, u_int n) +netmap_new_bufs(struct netmap_mem_d *nmd, struct netmap_slot *slot, u_int n) { struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL]; u_int i = 0; /* slot counter */ uint32_t pos = 0; /* slot in p->bitmap */ uint32_t index = 0; /* buffer index */ - (void)nifp; /* UNUSED */ for (i = 0; i < n; i++) { void *vaddr = netmap_buf_malloc(nmd, &pos, &index); if (vaddr == NULL) { - D("unable to locate empty packet buffer"); + D("no more buffers after %d of %d", i, n); goto cleanup; } slot[i].buf_idx = index; slot[i].len = p->_objsize; - /* XXX setting flags=NS_BUF_CHANGED forces a pointer reload - * in the NIC ring. This is a hack that hides missing - * initializations in the drivers, and should go away. - */ - // slot[i].flags = NS_BUF_CHANGED; + slot[i].flags = 0; } ND("allocated %d buffers, %d available, first at %d", n, p->objfree, pos); @@ -433,11 +427,10 @@ netmap_new_bufs(struct netmap_mem_d *nmd, struct netmap_if *nifp, static void -netmap_free_buf(struct netmap_mem_d *nmd, struct netmap_if *nifp, uint32_t i) +netmap_free_buf(struct netmap_mem_d *nmd, uint32_t i) { struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL]; - (void)nifp; if (i < 2 || i >= p->objtotal) { D("Cannot free buf#%d: should be in [2, %d[", i, p->objtotal); return; @@ -760,7 +753,8 @@ netmap_mem_private_finalize(struct netmap_mem_d *nmd) } -static void netmap_mem_private_deref(struct netmap_mem_d *nmd) +static void +netmap_mem_private_deref(struct netmap_mem_d *nmd) { NMA_LOCK(nmd); if (--nmd->refcount <= 0) @@ -845,7 +839,7 @@ netmap_mem_global_config(struct netmap_mem_d *nmd) netmap_reset_obj_allocator(&nmd->pools[i]); } nmd->flags &= ~NETMAP_MEM_FINALIZED; - } + } for (i = 0; i < NETMAP_POOLS_NR; i++) { nmd->lasterr = netmap_config_obj_allocator(&nmd->pools[i], @@ -938,31 +932,129 @@ netmap_free_rings(struct netmap_adapter *na) na->rx_rings[i].ring = NULL; } } - free(na->tx_rings, M_DEVBUF); - na->tx_rings = na->rx_rings = NULL; } +/* call with NMA_LOCK held * + * + * Allocate netmap rings and buffers for this card + * The rings are contiguous, but have variable size. + */ +int +netmap_mem_rings_create(struct netmap_adapter *na) +{ + struct netmap_ring *ring; + u_int len, ndesc; + struct netmap_kring *kring; + + NMA_LOCK(na->nm_mem); + + for (kring = na->tx_rings; kring != na->rx_rings; kring++) { /* Transmit rings */ + ndesc = kring->nkr_num_slots; + len = sizeof(struct netmap_ring) + + ndesc * sizeof(struct netmap_slot); + ring = netmap_ring_malloc(na->nm_mem, len); + if (ring == NULL) { + D("Cannot allocate tx_ring"); + goto cleanup; + } + ND("txring[%d] at %p ofs %d", i, ring); + kring->ring = ring; + *(uint32_t *)(uintptr_t)&ring->num_slots = ndesc; + *(ssize_t *)(uintptr_t)&ring->buf_ofs = + (na->nm_mem->pools[NETMAP_IF_POOL].memtotal + + na->nm_mem->pools[NETMAP_RING_POOL].memtotal) - + netmap_ring_offset(na->nm_mem, ring); + + ring->avail = kring->nr_hwavail; + ring->cur = kring->nr_hwcur; + *(uint16_t *)(uintptr_t)&ring->nr_buf_size = + NETMAP_BDG_BUF_SIZE(na->nm_mem); + ND("initializing slots for txring"); + if (netmap_new_bufs(na->nm_mem, ring->slot, ndesc)) { + D("Cannot allocate buffers for tx_ring"); + goto cleanup; + } + } + + for ( ; kring != na->tailroom; kring++) { /* Receive rings */ + ndesc = kring->nkr_num_slots; + len = sizeof(struct netmap_ring) + + ndesc * sizeof(struct netmap_slot); + ring = netmap_ring_malloc(na->nm_mem, len); + if (ring == NULL) { + D("Cannot allocate rx_ring"); + goto cleanup; + } + ND("rxring at %p ofs %d", ring); + + kring->ring = ring; + *(uint32_t *)(uintptr_t)&ring->num_slots = ndesc; + *(ssize_t *)(uintptr_t)&ring->buf_ofs = + (na->nm_mem->pools[NETMAP_IF_POOL].memtotal + + na->nm_mem->pools[NETMAP_RING_POOL].memtotal) - + netmap_ring_offset(na->nm_mem, ring); + + ring->cur = kring->nr_hwcur; + ring->avail = kring->nr_hwavail; + *(int *)(uintptr_t)&ring->nr_buf_size = + NETMAP_BDG_BUF_SIZE(na->nm_mem); + ND("initializing slots for rxring[%d]", i); + if (netmap_new_bufs(na->nm_mem, ring->slot, ndesc)) { + D("Cannot allocate buffers for rx_ring"); + goto cleanup; + } + } + + NMA_UNLOCK(na->nm_mem); + + return 0; + +cleanup: + netmap_free_rings(na); + + NMA_UNLOCK(na->nm_mem); + + return ENOMEM; +} + +void +netmap_mem_rings_delete(struct netmap_adapter *na) +{ + /* last instance, release bufs and rings */ + u_int i, lim; + struct netmap_kring *kring; + struct netmap_ring *ring; + + NMA_LOCK(na->nm_mem); + + for (kring = na->tx_rings; kring != na->tailroom; kring++) { + ring = kring->ring; + if (ring == NULL) + continue; + lim = kring->nkr_num_slots; + for (i = 0; i < lim; i++) + netmap_free_buf(na->nm_mem, ring->slot[i].buf_idx); + } + netmap_free_rings(na); + + NMA_UNLOCK(na->nm_mem); +} /* call with NMA_LOCK held */ /* * Allocate the per-fd structure netmap_if. - * If this is the first instance, also allocate the krings, rings etc. * * We assume that the configuration stored in na * (number of tx/rx rings and descs) does not change while * the interface is in netmap mode. */ -extern int nma_is_vp(struct netmap_adapter *na); struct netmap_if * netmap_mem_if_new(const char *ifname, struct netmap_adapter *na) { struct netmap_if *nifp; - struct netmap_ring *ring; ssize_t base; /* handy for relative offsets between rings and nifp */ - u_int i, len, ndesc, ntx, nrx; - struct netmap_kring *kring; - uint32_t *tx_leases = NULL, *rx_leases = NULL; + u_int i, len, ntx, nrx; /* * verify whether virtual port need the stack ring @@ -990,124 +1082,6 @@ netmap_mem_if_new(const char *ifname, struct netmap_adapter *na) *(u_int *)(uintptr_t)&nifp->ni_rx_rings = na->num_rx_rings; strncpy(nifp->ni_name, ifname, (size_t)IFNAMSIZ); - if (na->refcount) { /* already setup, we are done */ - goto final; - } - - len = (ntx + nrx) * sizeof(struct netmap_kring); - /* - * Leases are attached to TX rings on NIC/host ports, - * and to RX rings on VALE ports. - */ - if (nma_is_vp(na)) { - len += sizeof(uint32_t) * na->num_rx_desc * na->num_rx_rings; - } else { - len += sizeof(uint32_t) * na->num_tx_desc * ntx; - } - - na->tx_rings = malloc((size_t)len, M_DEVBUF, M_NOWAIT | M_ZERO); - if (na->tx_rings == NULL) { - D("Cannot allocate krings for %s", ifname); - goto cleanup; - } - na->rx_rings = na->tx_rings + ntx; - - if (nma_is_vp(na)) { - rx_leases = (uint32_t *)(na->rx_rings + nrx); - } else { - tx_leases = (uint32_t *)(na->rx_rings + nrx); - } - - /* - * First instance, allocate netmap rings and buffers for this card - * The rings are contiguous, but have variable size. - */ - for (i = 0; i < ntx; i++) { /* Transmit rings */ - kring = &na->tx_rings[i]; - ndesc = na->num_tx_desc; - bzero(kring, sizeof(*kring)); - len = sizeof(struct netmap_ring) + - ndesc * sizeof(struct netmap_slot); - ring = netmap_ring_malloc(na->nm_mem, len); - if (ring == NULL) { - D("Cannot allocate tx_ring[%d] for %s", i, ifname); - goto cleanup; - } - ND("txring[%d] at %p ofs %d", i, ring); - kring->na = na; - kring->ring = ring; - if (tx_leases) { - kring->nkr_leases = tx_leases; - tx_leases += ndesc; - } - *(uint32_t *)(uintptr_t)&ring->num_slots = kring->nkr_num_slots = ndesc; - *(ssize_t *)(uintptr_t)&ring->buf_ofs = - (na->nm_mem->pools[NETMAP_IF_POOL].memtotal + - na->nm_mem->pools[NETMAP_RING_POOL].memtotal) - - netmap_ring_offset(na->nm_mem, ring); - - /* - * IMPORTANT: - * Always keep one slot empty, so we can detect new - * transmissions comparing cur and nr_hwcur (they are - * the same only if there are no new transmissions). - */ - ring->avail = kring->nr_hwavail = ndesc - 1; - ring->cur = kring->nr_hwcur = 0; - *(uint16_t *)(uintptr_t)&ring->nr_buf_size = - NETMAP_BDG_BUF_SIZE(na->nm_mem); - ND("initializing slots for txring[%d]", i); - if (netmap_new_bufs(na->nm_mem, nifp, ring->slot, ndesc)) { - D("Cannot allocate buffers for tx_ring[%d] for %s", i, ifname); - goto cleanup; - } - } - - for (i = 0; i < nrx; i++) { /* Receive rings */ - kring = &na->rx_rings[i]; - ndesc = na->num_rx_desc; - bzero(kring, sizeof(*kring)); - len = sizeof(struct netmap_ring) + - ndesc * sizeof(struct netmap_slot); - ring = netmap_ring_malloc(na->nm_mem, len); - if (ring == NULL) { - D("Cannot allocate rx_ring[%d] for %s", i, ifname); - goto cleanup; - } - ND("rxring[%d] at %p ofs %d", i, ring); - - kring->na = na; - kring->ring = ring; - if (rx_leases && i < na->num_rx_rings) { - kring->nkr_leases = rx_leases; - rx_leases += ndesc; - } - *(uint32_t *)(uintptr_t)&ring->num_slots = kring->nkr_num_slots = ndesc; - *(ssize_t *)(uintptr_t)&ring->buf_ofs = - (na->nm_mem->pools[NETMAP_IF_POOL].memtotal + - na->nm_mem->pools[NETMAP_RING_POOL].memtotal) - - netmap_ring_offset(na->nm_mem, ring); - - ring->cur = kring->nr_hwcur = 0; - ring->avail = kring->nr_hwavail = 0; /* empty */ - *(int *)(uintptr_t)&ring->nr_buf_size = - NETMAP_BDG_BUF_SIZE(na->nm_mem); - ND("initializing slots for rxring[%d]", i); - if (netmap_new_bufs(na->nm_mem, nifp, ring->slot, ndesc)) { - D("Cannot allocate buffers for rx_ring[%d] for %s", i, ifname); - goto cleanup; - } - } -#ifdef linux - // XXX initialize the selrecord structs. - for (i = 0; i < ntx; i++) - init_waitqueue_head(&na->tx_rings[i].si); - for (i = 0; i < nrx; i++) - init_waitqueue_head(&na->rx_rings[i].si); - init_waitqueue_head(&na->tx_si); - init_waitqueue_head(&na->rx_si); -#endif -final: /* * fill the slots for the rx and tx rings. They contain the offset * between the ring and nifp, so the information is usable in @@ -1126,13 +1100,6 @@ netmap_mem_if_new(const char *ifname, struct netmap_adapter *na) NMA_UNLOCK(na->nm_mem); return (nifp); -cleanup: - netmap_free_rings(na); - netmap_if_free(na->nm_mem, nifp); - - NMA_UNLOCK(na->nm_mem); - - return NULL; } void @@ -1143,25 +1110,6 @@ netmap_mem_if_delete(struct netmap_adapter *na, struct netmap_if *nifp) return; NMA_LOCK(na->nm_mem); - if (na->refcount <= 0) { - /* last instance, release bufs and rings */ - u_int i, j, lim; - struct netmap_ring *ring; - - for (i = 0; i < na->num_tx_rings + 1; i++) { - ring = na->tx_rings[i].ring; - lim = na->tx_rings[i].nkr_num_slots; - for (j = 0; j < lim; j++) - netmap_free_buf(na->nm_mem, nifp, ring->slot[j].buf_idx); - } - for (i = 0; i < na->num_rx_rings + 1; i++) { - ring = na->rx_rings[i].ring; - lim = na->rx_rings[i].nkr_num_slots; - for (j = 0; j < lim; j++) - netmap_free_buf(na->nm_mem, nifp, ring->slot[j].buf_idx); - } - netmap_free_rings(na); - } netmap_if_free(na->nm_mem, nifp); NMA_UNLOCK(na->nm_mem); @@ -1179,12 +1127,14 @@ netmap_mem_global_deref(struct netmap_mem_d *nmd) NMA_UNLOCK(nmd); } -int netmap_mem_finalize(struct netmap_mem_d *nmd) +int +netmap_mem_finalize(struct netmap_mem_d *nmd) { return nmd->finalize(nmd); } -void netmap_mem_deref(struct netmap_mem_d *nmd) +void +netmap_mem_deref(struct netmap_mem_d *nmd) { return nmd->deref(nmd); } diff --git a/sys/dev/netmap/netmap_mem2.h b/sys/dev/netmap/netmap_mem2.h index 83f31d011c45..f492f9814b79 100644 --- a/sys/dev/netmap/netmap_mem2.h +++ b/sys/dev/netmap/netmap_mem2.h @@ -189,7 +189,7 @@ struct netmap_mem_d { /* the three allocators */ struct netmap_obj_pool pools[NETMAP_POOLS_NR]; - netmap_mem_config_t config; + netmap_mem_config_t config; netmap_mem_finalize_t finalize; netmap_mem_deref_t deref; }; @@ -200,14 +200,17 @@ vm_paddr_t netmap_mem_ofstophys(struct netmap_mem_d *, vm_ooffset_t); int netmap_mem_finalize(struct netmap_mem_d *); int netmap_mem_init(void); void netmap_mem_fini(void); -struct netmap_if * netmap_mem_if_new(const char *, struct netmap_adapter *); -void netmap_mem_if_delete(struct netmap_adapter *na, struct netmap_if *nifp); +struct netmap_if * + netmap_mem_if_new(const char *, struct netmap_adapter *); +void netmap_mem_if_delete(struct netmap_adapter *, struct netmap_if *); +int netmap_mem_rings_create(struct netmap_adapter *); +void netmap_mem_rings_delete(struct netmap_adapter *); void netmap_mem_deref(struct netmap_mem_d *); -int netmap_mem_get_info(struct netmap_mem_d *nm_mem, u_int *size, u_int *memflags); -ssize_t netmap_mem_if_offset(struct netmap_mem_d *nm_mem, const void *vaddr); +int netmap_mem_get_info(struct netmap_mem_d *, u_int *size, u_int *memflags); +ssize_t netmap_mem_if_offset(struct netmap_mem_d *, const void *vaddr); struct netmap_mem_d* netmap_mem_private_new(const char *name, u_int txr, u_int txd, u_int rxr, u_int rxd); -void netmap_mem_private_delete(struct netmap_mem_d *nm_mem); +void netmap_mem_private_delete(struct netmap_mem_d *); #define NETMAP_BDG_BUF_SIZE(n) ((n)->pools[NETMAP_BUF_POOL]._objsize) diff --git a/sys/dev/netmap/netmap_vale.c b/sys/dev/netmap/netmap_vale.c new file mode 100644 index 000000000000..e0ce94cccb7d --- /dev/null +++ b/sys/dev/netmap/netmap_vale.c @@ -0,0 +1,1983 @@ +/* + * Copyright (C) 2013 Universita` di Pisa. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * This module implements the VALE switch for netmap + +--- VALE SWITCH --- + +NMG_LOCK() serializes all modifications to switches and ports. +A switch cannot be deleted until all ports are gone. + +For each switch, an SX lock (RWlock on linux) protects +deletion of ports. When configuring or deleting a new port, the +lock is acquired in exclusive mode (after holding NMG_LOCK). +When forwarding, the lock is acquired in shared mode (without NMG_LOCK). +The lock is held throughout the entire forwarding cycle, +during which the thread may incur in a page fault. +Hence it is important that sleepable shared locks are used. + +On the rx ring, the per-port lock is grabbed initially to reserve +a number of slot in the ring, then the lock is released, +packets are copied from source to destination, and then +the lock is acquired again and the receive ring is updated. +(A similar thing is done on the tx ring for NIC and host stack +ports attached to the switch) + + */ + +/* + * OS-specific code that is used only within this file. + * Other OS-specific code that must be accessed by drivers + * is present in netmap_kern.h + */ + +#if defined(__FreeBSD__) +#include /* prerequisite */ +__FBSDID("$FreeBSD$"); + +#include +#include +#include /* defines used in kernel.h */ +#include /* types used in module initialization */ +#include /* cdevsw struct, UID, GID */ +#include +#include /* struct socket */ +#include +#include +#include +#include /* sockaddrs */ +#include +#include +#include +#include +#include /* BIOCIMMEDIATE */ +#include /* bus_dmamap_* */ +#include +#include + +// #define prefetch(x) __builtin_prefetch(x) + + +#define BDG_RWLOCK_T struct rwlock // struct rwlock + +#define BDG_RWINIT(b) \ + rw_init_flags(&(b)->bdg_lock, "bdg lock", RW_NOWITNESS) +#define BDG_WLOCK(b) rw_wlock(&(b)->bdg_lock) +#define BDG_WUNLOCK(b) rw_wunlock(&(b)->bdg_lock) +#define BDG_RLOCK(b) rw_rlock(&(b)->bdg_lock) +#define BDG_RTRYLOCK(b) rw_try_rlock(&(b)->bdg_lock) +#define BDG_RUNLOCK(b) rw_runlock(&(b)->bdg_lock) +#define BDG_RWDESTROY(b) rw_destroy(&(b)->bdg_lock) + + +#elif defined(linux) + +#include "bsd_glue.h" + +#elif defined(__APPLE__) + +#warning OSX support is only partial +#include "osx_glue.h" + +#else + +#error Unsupported platform + +#endif /* unsupported */ + +/* + * common headers + */ + +#include +#include +#include + +#ifdef WITH_VALE + +/* + * system parameters (most of them in netmap_kern.h) + * NM_NAME prefix for switch port names, default "vale" + * NM_BDG_MAXPORTS number of ports + * NM_BRIDGES max number of switches in the system. + * XXX should become a sysctl or tunable + * + * Switch ports are named valeX:Y where X is the switch name and Y + * is the port. If Y matches a physical interface name, the port is + * connected to a physical device. + * + * Unlike physical interfaces, switch ports use their own memory region + * for rings and buffers. + * The virtual interfaces use per-queue lock instead of core lock. + * In the tx loop, we aggregate traffic in batches to make all operations + * faster. The batch size is bridge_batch. + */ +#define NM_BDG_MAXRINGS 16 /* XXX unclear how many. */ +#define NM_BDG_MAXSLOTS 4096 /* XXX same as above */ +#define NM_BRIDGE_RINGSIZE 1024 /* in the device */ +#define NM_BDG_HASH 1024 /* forwarding table entries */ +#define NM_BDG_BATCH 1024 /* entries in the forwarding buffer */ +#define NM_MULTISEG 64 /* max size of a chain of bufs */ +/* actual size of the tables */ +#define NM_BDG_BATCH_MAX (NM_BDG_BATCH + NM_MULTISEG) +/* NM_FT_NULL terminates a list of slots in the ft */ +#define NM_FT_NULL NM_BDG_BATCH_MAX +#define NM_BRIDGES 8 /* number of bridges */ + + +/* + * bridge_batch is set via sysctl to the max batch size to be + * used in the bridge. The actual value may be larger as the + * last packet in the block may overflow the size. + */ +int bridge_batch = NM_BDG_BATCH; /* bridge batch size */ +SYSCTL_DECL(_dev_netmap); +SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , ""); + + +static int bdg_netmap_attach(struct nmreq *nmr, struct ifnet *ifp); +static int bdg_netmap_reg(struct netmap_adapter *na, int onoff); +static int netmap_bwrap_attach(struct ifnet *, struct ifnet *); +static int netmap_bwrap_register(struct netmap_adapter *, int onoff); +int kern_netmap_regif(struct nmreq *nmr); + +/* + * Each transmit queue accumulates a batch of packets into + * a structure before forwarding. Packets to the same + * destination are put in a list using ft_next as a link field. + * ft_frags and ft_next are valid only on the first fragment. + */ +struct nm_bdg_fwd { /* forwarding entry for a bridge */ + void *ft_buf; /* netmap or indirect buffer */ + uint8_t ft_frags; /* how many fragments (only on 1st frag) */ + uint8_t _ft_port; /* dst port (unused) */ + uint16_t ft_flags; /* flags, e.g. indirect */ + uint16_t ft_len; /* src fragment len */ + uint16_t ft_next; /* next packet to same destination */ +}; + +/* + * For each output interface, nm_bdg_q is used to construct a list. + * bq_len is the number of output buffers (we can have coalescing + * during the copy). + */ +struct nm_bdg_q { + uint16_t bq_head; + uint16_t bq_tail; + uint32_t bq_len; /* number of buffers */ +}; + +/* XXX revise this */ +struct nm_hash_ent { + uint64_t mac; /* the top 2 bytes are the epoch */ + uint64_t ports; +}; + +/* + * nm_bridge is a descriptor for a VALE switch. + * Interfaces for a bridge are all in bdg_ports[]. + * The array has fixed size, an empty entry does not terminate + * the search, but lookups only occur on attach/detach so we + * don't mind if they are slow. + * + * The bridge is non blocking on the transmit ports: excess + * packets are dropped if there is no room on the output port. + * + * bdg_lock protects accesses to the bdg_ports array. + * This is a rw lock (or equivalent). + */ +struct nm_bridge { + /* XXX what is the proper alignment/layout ? */ + BDG_RWLOCK_T bdg_lock; /* protects bdg_ports */ + int bdg_namelen; + uint32_t bdg_active_ports; /* 0 means free */ + char bdg_basename[IFNAMSIZ]; + + /* Indexes of active ports (up to active_ports) + * and all other remaining ports. + */ + uint8_t bdg_port_index[NM_BDG_MAXPORTS]; + + struct netmap_vp_adapter *bdg_ports[NM_BDG_MAXPORTS]; + + + /* + * The function to decide the destination port. + * It returns either of an index of the destination port, + * NM_BDG_BROADCAST to broadcast this packet, or NM_BDG_NOPORT not to + * forward this packet. ring_nr is the source ring index, and the + * function may overwrite this value to forward this packet to a + * different ring index. + * This function must be set by netmap_bdgctl(). + */ + bdg_lookup_fn_t nm_bdg_lookup; + + /* the forwarding table, MAC+ports. + * XXX should be changed to an argument to be passed to + * the lookup function, and allocated on attach + */ + struct nm_hash_ent ht[NM_BDG_HASH]; +}; + + +/* + * XXX in principle nm_bridges could be created dynamically + * Right now we have a static array and deletions are protected + * by an exclusive lock. + */ +struct nm_bridge nm_bridges[NM_BRIDGES]; + + +/* + * A few function to tell which kind of port are we using. + * XXX should we hold a lock ? + * + * nma_is_vp() virtual port + * nma_is_host() port connected to the host stack + * nma_is_hw() port connected to a NIC + * nma_is_generic() generic netmap adapter XXX stop this madness + */ +static __inline int +nma_is_vp(struct netmap_adapter *na) +{ + return na->nm_register == bdg_netmap_reg; +} + + +static __inline int +nma_is_host(struct netmap_adapter *na) +{ + return na->nm_register == NULL; +} + + +static __inline int +nma_is_hw(struct netmap_adapter *na) +{ + /* In case of sw adapter, nm_register is NULL */ + return !nma_is_vp(na) && !nma_is_host(na) && !nma_is_generic(na); +} + +static __inline int +nma_is_bwrap(struct netmap_adapter *na) +{ + return na->nm_register == netmap_bwrap_register; +} + + + +/* + * this is a slightly optimized copy routine which rounds + * to multiple of 64 bytes and is often faster than dealing + * with other odd sizes. We assume there is enough room + * in the source and destination buffers. + * + * XXX only for multiples of 64 bytes, non overlapped. + */ +static inline void +pkt_copy(void *_src, void *_dst, int l) +{ + uint64_t *src = _src; + uint64_t *dst = _dst; + if (unlikely(l >= 1024)) { + memcpy(dst, src, l); + return; + } + for (; likely(l > 0); l-=64) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + } +} + + + +/* + * locate a bridge among the existing ones. + * MUST BE CALLED WITH NMG_LOCK() + * + * a ':' in the name terminates the bridge name. Otherwise, just NM_NAME. + * We assume that this is called with a name of at least NM_NAME chars. + */ +static struct nm_bridge * +nm_find_bridge(const char *name, int create) +{ + int i, l, namelen; + struct nm_bridge *b = NULL; + + NMG_LOCK_ASSERT(); + + namelen = strlen(NM_NAME); /* base length */ + l = name ? strlen(name) : 0; /* actual length */ + if (l < namelen) { + D("invalid bridge name %s", name ? name : NULL); + return NULL; + } + for (i = namelen + 1; i < l; i++) { + if (name[i] == ':') { + namelen = i; + break; + } + } + if (namelen >= IFNAMSIZ) + namelen = IFNAMSIZ; + ND("--- prefix is '%.*s' ---", namelen, name); + + /* lookup the name, remember empty slot if there is one */ + for (i = 0; i < NM_BRIDGES; i++) { + struct nm_bridge *x = nm_bridges + i; + + if (x->bdg_active_ports == 0) { + if (create && b == NULL) + b = x; /* record empty slot */ + } else if (x->bdg_namelen != namelen) { + continue; + } else if (strncmp(name, x->bdg_basename, namelen) == 0) { + ND("found '%.*s' at %d", namelen, name, i); + b = x; + break; + } + } + if (i == NM_BRIDGES && b) { /* name not found, can create entry */ + /* initialize the bridge */ + strncpy(b->bdg_basename, name, namelen); + ND("create new bridge %s with ports %d", b->bdg_basename, + b->bdg_active_ports); + b->bdg_namelen = namelen; + b->bdg_active_ports = 0; + for (i = 0; i < NM_BDG_MAXPORTS; i++) + b->bdg_port_index[i] = i; + /* set the default function */ + b->nm_bdg_lookup = netmap_bdg_learning; + /* reset the MAC address table */ + bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH); + } + return b; +} + + +/* + * Free the forwarding tables for rings attached to switch ports. + */ +static void +nm_free_bdgfwd(struct netmap_adapter *na) +{ + int nrings, i; + struct netmap_kring *kring; + + NMG_LOCK_ASSERT(); + nrings = nma_is_vp(na) ? na->num_tx_rings : na->num_rx_rings; + kring = nma_is_vp(na) ? na->tx_rings : na->rx_rings; + for (i = 0; i < nrings; i++) { + if (kring[i].nkr_ft) { + free(kring[i].nkr_ft, M_DEVBUF); + kring[i].nkr_ft = NULL; /* protect from freeing twice */ + } + } +} + + +/* + * Allocate the forwarding tables for the rings attached to the bridge ports. + */ +static int +nm_alloc_bdgfwd(struct netmap_adapter *na) +{ + int nrings, l, i, num_dstq; + struct netmap_kring *kring; + + NMG_LOCK_ASSERT(); + /* all port:rings + broadcast */ + num_dstq = NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1; + l = sizeof(struct nm_bdg_fwd) * NM_BDG_BATCH_MAX; + l += sizeof(struct nm_bdg_q) * num_dstq; + l += sizeof(uint16_t) * NM_BDG_BATCH_MAX; + + nrings = na->num_tx_rings + 1; + kring = na->tx_rings; + for (i = 0; i < nrings; i++) { + struct nm_bdg_fwd *ft; + struct nm_bdg_q *dstq; + int j; + + ft = malloc(l, M_DEVBUF, M_NOWAIT | M_ZERO); + if (!ft) { + nm_free_bdgfwd(na); + return ENOMEM; + } + dstq = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); + for (j = 0; j < num_dstq; j++) { + dstq[j].bq_head = dstq[j].bq_tail = NM_FT_NULL; + dstq[j].bq_len = 0; + } + kring[i].nkr_ft = ft; + } + return 0; +} + + +static void +netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw) +{ + int s_hw = hw, s_sw = sw; + int i, lim =b->bdg_active_ports; + uint8_t tmp[NM_BDG_MAXPORTS]; + + /* + New algorithm: + make a copy of bdg_port_index; + lookup NA(ifp)->bdg_port and SWNA(ifp)->bdg_port + in the array of bdg_port_index, replacing them with + entries from the bottom of the array; + decrement bdg_active_ports; + acquire BDG_WLOCK() and copy back the array. + */ + + D("detach %d and %d (lim %d)", hw, sw, lim); + /* make a copy of the list of active ports, update it, + * and then copy back within BDG_WLOCK(). + */ + memcpy(tmp, b->bdg_port_index, sizeof(tmp)); + for (i = 0; (hw >= 0 || sw >= 0) && i < lim; ) { + if (hw >= 0 && tmp[i] == hw) { + ND("detach hw %d at %d", hw, i); + lim--; /* point to last active port */ + tmp[i] = tmp[lim]; /* swap with i */ + tmp[lim] = hw; /* now this is inactive */ + hw = -1; + } else if (sw >= 0 && tmp[i] == sw) { + ND("detach sw %d at %d", sw, i); + lim--; + tmp[i] = tmp[lim]; + tmp[lim] = sw; + sw = -1; + } else { + i++; + } + } + if (hw >= 0 || sw >= 0) { + D("XXX delete failed hw %d sw %d, should panic...", hw, sw); + } + + BDG_WLOCK(b); + b->bdg_ports[s_hw] = NULL; + if (s_sw >= 0) { + b->bdg_ports[s_sw] = NULL; + } + memcpy(b->bdg_port_index, tmp, sizeof(tmp)); + b->bdg_active_ports = lim; + BDG_WUNLOCK(b); + + ND("now %d active ports", lim); + if (lim == 0) { + ND("marking bridge %s as free", b->bdg_basename); + b->nm_bdg_lookup = NULL; + } +} + +static void +netmap_adapter_vp_dtor(struct netmap_adapter *na) +{ + struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na; + struct nm_bridge *b = vpna->na_bdg; + struct ifnet *ifp = na->ifp; + + ND("%s has %d references", NM_IFPNAME(ifp), na->na_refcount); + + if (b) { + netmap_bdg_detach_common(b, vpna->bdg_port, -1); + } + + bzero(ifp, sizeof(*ifp)); + free(ifp, M_DEVBUF); + na->ifp = NULL; +} + +int +netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create) +{ + const char *name = nmr->nr_name; + struct ifnet *ifp; + int error = 0; + struct netmap_adapter *ret; + struct netmap_vp_adapter *vpna; + struct nm_bridge *b; + int i, j, cand = -1, cand2 = -1; + int needed; + + *na = NULL; /* default return value */ + + /* first try to see if this is a bridge port. */ + NMG_LOCK_ASSERT(); + if (strncmp(name, NM_NAME, sizeof(NM_NAME) - 1)) { + return 0; /* no error, but no VALE prefix */ + } + + b = nm_find_bridge(name, create); + if (b == NULL) { + D("no bridges available for '%s'", name); + return (ENXIO); + } + + /* Now we are sure that name starts with the bridge's name, + * lookup the port in the bridge. We need to scan the entire + * list. It is not important to hold a WLOCK on the bridge + * during the search because NMG_LOCK already guarantees + * that there are no other possible writers. + */ + + /* lookup in the local list of ports */ + for (j = 0; j < b->bdg_active_ports; j++) { + i = b->bdg_port_index[j]; + vpna = b->bdg_ports[i]; + // KASSERT(na != NULL); + ifp = vpna->up.ifp; + /* XXX make sure the name only contains one : */ + if (!strcmp(NM_IFPNAME(ifp), name)) { + netmap_adapter_get(&vpna->up); + ND("found existing if %s refs %d", name, + vpna->na_bdg_refcount); + *na = (struct netmap_adapter *)vpna; + return 0; + } + } + /* not found, should we create it? */ + if (!create) + return ENXIO; + /* yes we should, see if we have space to attach entries */ + needed = 2; /* in some cases we only need 1 */ + if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) { + D("bridge full %d, cannot create new port", b->bdg_active_ports); + return EINVAL; + } + /* record the next two ports available, but do not allocate yet */ + cand = b->bdg_port_index[b->bdg_active_ports]; + cand2 = b->bdg_port_index[b->bdg_active_ports + 1]; + ND("+++ bridge %s port %s used %d avail %d %d", + b->bdg_basename, name, b->bdg_active_ports, cand, cand2); + + /* + * try see if there is a matching NIC with this name + * (after the bridge's name) + */ + ifp = ifunit_ref(name + b->bdg_namelen + 1); + if (!ifp) { /* this is a virtual port */ + if (nmr->nr_cmd) { + /* nr_cmd must be 0 for a virtual port */ + return EINVAL; + } + + /* create a struct ifnet for the new port. + * need M_NOWAIT as we are under nma_lock + */ + ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!ifp) + return ENOMEM; + + strcpy(ifp->if_xname, name); + /* bdg_netmap_attach creates a struct netmap_adapter */ + error = bdg_netmap_attach(nmr, ifp); + if (error) { + D("error %d", error); + free(ifp, M_DEVBUF); + return error; + } + ret = NA(ifp); + cand2 = -1; /* only need one port */ + } else { /* this is a NIC */ + struct ifnet *fake_ifp; + + error = netmap_get_hw_na(ifp, &ret); + if (error || ret == NULL) + goto out; + + /* make sure the NIC is not already in use */ + if (NETMAP_OWNED_BY_ANY(ret)) { + D("NIC %s busy, cannot attach to bridge", + NM_IFPNAME(ifp)); + error = EINVAL; + goto out; + } + /* create a fake interface */ + fake_ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!fake_ifp) { + error = ENOMEM; + goto out; + } + strcpy(fake_ifp->if_xname, name); + error = netmap_bwrap_attach(fake_ifp, ifp); + if (error) { + free(fake_ifp, M_DEVBUF); + goto out; + } + ret = NA(fake_ifp); + if (nmr->nr_arg1 != NETMAP_BDG_HOST) + cand2 = -1; /* only need one port */ + if_rele(ifp); + } + vpna = (struct netmap_vp_adapter *)ret; + + BDG_WLOCK(b); + vpna->bdg_port = cand; + ND("NIC %p to bridge port %d", vpna, cand); + /* bind the port to the bridge (virtual ports are not active) */ + b->bdg_ports[cand] = vpna; + vpna->na_bdg = b; + b->bdg_active_ports++; + if (cand2 >= 0) { + struct netmap_vp_adapter *hostna = vpna + 1; + /* also bind the host stack to the bridge */ + b->bdg_ports[cand2] = hostna; + hostna->bdg_port = cand2; + hostna->na_bdg = b; + b->bdg_active_ports++; + ND("host %p to bridge port %d", hostna, cand2); + } + ND("if %s refs %d", name, vpna->up.na_refcount); + BDG_WUNLOCK(b); + *na = ret; + netmap_adapter_get(ret); + return 0; + +out: + if_rele(ifp); + + return error; +} + + +/* Process NETMAP_BDG_ATTACH and NETMAP_BDG_DETACH */ +static int +nm_bdg_attach(struct nmreq *nmr) +{ + struct netmap_adapter *na; + struct netmap_if *nifp; + struct netmap_priv_d *npriv; + struct netmap_bwrap_adapter *bna; + int error; + + npriv = malloc(sizeof(*npriv), M_DEVBUF, M_NOWAIT|M_ZERO); + if (npriv == NULL) + return ENOMEM; + NMG_LOCK(); + /* XXX probably netmap_get_bdg_na() */ + error = netmap_get_na(nmr, &na, 1 /* create if not exists */); + if (error) /* no device, or another bridge or user owns the device */ + goto unlock_exit; + /* netmap_get_na() sets na_bdg if this is a physical interface + * that we can attach to a switch. + */ + if (!nma_is_bwrap(na)) { + /* got reference to a virtual port or direct access to a NIC. + * perhaps specified no bridge prefix or wrong NIC name + */ + error = EINVAL; + goto unref_exit; + } + + if (na->active_fds > 0) { /* already registered */ + error = EBUSY; + goto unref_exit; + } + + nifp = netmap_do_regif(npriv, na, nmr->nr_ringid, &error); + if (!nifp) { + goto unref_exit; + } + + bna = (struct netmap_bwrap_adapter*)na; + bna->na_kpriv = npriv; + NMG_UNLOCK(); + ND("registered %s to netmap-mode", NM_IFPNAME(na->ifp)); + return 0; + +unref_exit: + netmap_adapter_put(na); +unlock_exit: + NMG_UNLOCK(); + bzero(npriv, sizeof(*npriv)); + free(npriv, M_DEVBUF); + return error; +} + +static int +nm_bdg_detach(struct nmreq *nmr) +{ + struct netmap_adapter *na; + int error; + struct netmap_bwrap_adapter *bna; + int last_instance; + + NMG_LOCK(); + error = netmap_get_na(nmr, &na, 0 /* don't create */); + if (error) { /* no device, or another bridge or user owns the device */ + goto unlock_exit; + } + if (!nma_is_bwrap(na)) { + /* got reference to a virtual port or direct access to a NIC. + * perhaps specified no bridge's prefix or wrong NIC's name + */ + error = EINVAL; + goto unref_exit; + } + bna = (struct netmap_bwrap_adapter *)na; + + if (na->active_fds == 0) { /* not registered */ + error = EINVAL; + goto unref_exit; + } + + last_instance = netmap_dtor_locked(bna->na_kpriv); /* unregister */ + if (!last_instance) { + D("--- error, trying to detach an entry with active mmaps"); + error = EINVAL; + } else { + struct netmap_priv_d *npriv = bna->na_kpriv; + + bna->na_kpriv = NULL; + D("deleting priv"); + + bzero(npriv, sizeof(*npriv)); + free(npriv, M_DEVBUF); + } + +unref_exit: + netmap_adapter_put(na); +unlock_exit: + NMG_UNLOCK(); + return error; + +} + + +/* exported to kernel callers, e.g. OVS ? + * Entry point. + * Called without NMG_LOCK. + */ +int +netmap_bdg_ctl(struct nmreq *nmr, bdg_lookup_fn_t func) +{ + struct nm_bridge *b; + struct netmap_adapter *na; + struct netmap_vp_adapter *vpna; + struct ifnet *iter; + char *name = nmr->nr_name; + int cmd = nmr->nr_cmd, namelen = strlen(name); + int error = 0, i, j; + + switch (cmd) { + case NETMAP_BDG_ATTACH: + error = nm_bdg_attach(nmr); + break; + + case NETMAP_BDG_DETACH: + error = nm_bdg_detach(nmr); + break; + + case NETMAP_BDG_LIST: + /* this is used to enumerate bridges and ports */ + if (namelen) { /* look up indexes of bridge and port */ + if (strncmp(name, NM_NAME, strlen(NM_NAME))) { + error = EINVAL; + break; + } + NMG_LOCK(); + b = nm_find_bridge(name, 0 /* don't create */); + if (!b) { + error = ENOENT; + NMG_UNLOCK(); + break; + } + + error = ENOENT; + for (j = 0; j < b->bdg_active_ports; j++) { + i = b->bdg_port_index[j]; + vpna = b->bdg_ports[i]; + if (vpna == NULL) { + D("---AAAAAAAAARGH-------"); + continue; + } + iter = vpna->up.ifp; + /* the former and the latter identify a + * virtual port and a NIC, respectively + */ + if (!strcmp(iter->if_xname, name)) { + /* bridge index */ + nmr->nr_arg1 = b - nm_bridges; + nmr->nr_arg2 = i; /* port index */ + error = 0; + break; + } + } + NMG_UNLOCK(); + } else { + /* return the first non-empty entry starting from + * bridge nr_arg1 and port nr_arg2. + * + * Users can detect the end of the same bridge by + * seeing the new and old value of nr_arg1, and can + * detect the end of all the bridge by error != 0 + */ + i = nmr->nr_arg1; + j = nmr->nr_arg2; + + NMG_LOCK(); + for (error = ENOENT; i < NM_BRIDGES; i++) { + b = nm_bridges + i; + if (j >= b->bdg_active_ports) { + j = 0; /* following bridges scan from 0 */ + continue; + } + nmr->nr_arg1 = i; + nmr->nr_arg2 = j; + j = b->bdg_port_index[j]; + vpna = b->bdg_ports[j]; + iter = vpna->up.ifp; + strncpy(name, iter->if_xname, (size_t)IFNAMSIZ); + error = 0; + break; + } + NMG_UNLOCK(); + } + break; + + case NETMAP_BDG_LOOKUP_REG: + /* register a lookup function to the given bridge. + * nmr->nr_name may be just bridge's name (including ':' + * if it is not just NM_NAME). + */ + if (!func) { + error = EINVAL; + break; + } + NMG_LOCK(); + b = nm_find_bridge(name, 0 /* don't create */); + if (!b) { + error = EINVAL; + } else { + b->nm_bdg_lookup = func; + } + NMG_UNLOCK(); + break; + + case NETMAP_BDG_OFFSET: + NMG_LOCK(); + error = netmap_get_bdg_na(nmr, &na, 0); + if (!error) { + vpna = (struct netmap_vp_adapter *)na; + if (nmr->nr_arg1 > NETMAP_BDG_MAX_OFFSET) + nmr->nr_arg1 = NETMAP_BDG_MAX_OFFSET; + vpna->offset = nmr->nr_arg1; + D("Using offset %d for %p", vpna->offset, vpna); + } + NMG_UNLOCK(); + break; + + default: + D("invalid cmd (nmr->nr_cmd) (0x%x)", cmd); + error = EINVAL; + break; + } + return error; +} + + +static int +netmap_vp_krings_create(struct netmap_adapter *na) +{ + u_int ntx, nrx, tailroom; + int error, i; + uint32_t *leases; + + /* XXX vps do not need host rings, + * but we crash if we don't have one + */ + ntx = na->num_tx_rings + 1; + nrx = na->num_rx_rings + 1; + + /* + * Leases are attached to RX rings on vale ports + */ + tailroom = sizeof(uint32_t) * na->num_rx_desc * nrx; + + error = netmap_krings_create(na, ntx, nrx, tailroom); + if (error) + return error; + + leases = na->tailroom; + + for (i = 0; i < nrx; i++) { /* Receive rings */ + na->rx_rings[i].nkr_leases = leases; + leases += na->num_rx_desc; + } + + error = nm_alloc_bdgfwd(na); + if (error) { + netmap_krings_delete(na); + return error; + } + + return 0; +} + +static void +netmap_vp_krings_delete(struct netmap_adapter *na) +{ + nm_free_bdgfwd(na); + netmap_krings_delete(na); +} + + +static int +nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, + struct netmap_vp_adapter *na, u_int ring_nr); + + +/* + * Grab packets from a kring, move them into the ft structure + * associated to the tx (input) port. Max one instance per port, + * filtered on input (ioctl, poll or XXX). + * Returns the next position in the ring. + */ +static int +nm_bdg_preflush(struct netmap_vp_adapter *na, u_int ring_nr, + struct netmap_kring *kring, u_int end) +{ + struct netmap_ring *ring = kring->ring; + struct nm_bdg_fwd *ft; + u_int j = kring->nr_hwcur, lim = kring->nkr_num_slots - 1; + u_int ft_i = 0; /* start from 0 */ + u_int frags = 1; /* how many frags ? */ + struct nm_bridge *b = na->na_bdg; + + /* To protect against modifications to the bridge we acquire a + * shared lock, waiting if we can sleep (if the source port is + * attached to a user process) or with a trylock otherwise (NICs). + */ + ND("wait rlock for %d packets", ((j > end ? lim+1 : 0) + end) - j); + if (na->up.na_flags & NAF_BDG_MAYSLEEP) + BDG_RLOCK(b); + else if (!BDG_RTRYLOCK(b)) + return 0; + ND(5, "rlock acquired for %d packets", ((j > end ? lim+1 : 0) + end) - j); + ft = kring->nkr_ft; + + for (; likely(j != end); j = nm_next(j, lim)) { + struct netmap_slot *slot = &ring->slot[j]; + char *buf; + + ft[ft_i].ft_len = slot->len; + ft[ft_i].ft_flags = slot->flags; + + ND("flags is 0x%x", slot->flags); + /* this slot goes into a list so initialize the link field */ + ft[ft_i].ft_next = NM_FT_NULL; + buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ? + (void *)(uintptr_t)slot->ptr : BDG_NMB(&na->up, slot); + prefetch(buf); + ++ft_i; + if (slot->flags & NS_MOREFRAG) { + frags++; + continue; + } + if (unlikely(netmap_verbose && frags > 1)) + RD(5, "%d frags at %d", frags, ft_i - frags); + ft[ft_i - frags].ft_frags = frags; + frags = 1; + if (unlikely((int)ft_i >= bridge_batch)) + ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr); + } + if (frags > 1) { + D("truncate incomplete fragment at %d (%d frags)", ft_i, frags); + // ft_i > 0, ft[ft_i-1].flags has NS_MOREFRAG + ft[ft_i - 1].ft_frags &= ~NS_MOREFRAG; + ft[ft_i - frags].ft_frags = frags - 1; + } + if (ft_i) + ft_i = nm_bdg_flush(ft, ft_i, na, ring_nr); + BDG_RUNLOCK(b); + return j; +} + + +/* + *---- support for virtual bridge ----- + */ + +/* ----- FreeBSD if_bridge hash function ------- */ + +/* + * The following hash function is adapted from "Hash Functions" by Bob Jenkins + * ("Algorithm Alley", Dr. Dobbs Journal, September 1997). + * + * http://www.burtleburtle.net/bob/hash/spooky.html + */ +#define mix(a, b, c) \ +do { \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ +} while (/*CONSTCOND*/0) + +static __inline uint32_t +nm_bridge_rthash(const uint8_t *addr) +{ + uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0; // hask key + + b += addr[5] << 8; + b += addr[4]; + a += addr[3] << 24; + a += addr[2] << 16; + a += addr[1] << 8; + a += addr[0]; + + mix(a, b, c); +#define BRIDGE_RTHASH_MASK (NM_BDG_HASH-1) + return (c & BRIDGE_RTHASH_MASK); +} + +#undef mix + + +static int +bdg_netmap_reg(struct netmap_adapter *na, int onoff) +{ + struct netmap_vp_adapter *vpna = + (struct netmap_vp_adapter*)na; + struct ifnet *ifp = na->ifp; + + /* the interface is already attached to the bridge, + * so we only need to toggle IFCAP_NETMAP. + */ + BDG_WLOCK(vpna->na_bdg); + if (onoff) { + ifp->if_capenable |= IFCAP_NETMAP; + } else { + ifp->if_capenable &= ~IFCAP_NETMAP; + } + BDG_WUNLOCK(vpna->na_bdg); + return 0; +} + + +/* + * Lookup function for a learning bridge. + * Update the hash table with the source address, + * and then returns the destination port index, and the + * ring in *dst_ring (at the moment, always use ring 0) + */ +u_int +netmap_bdg_learning(char *buf, u_int buf_len, uint8_t *dst_ring, + struct netmap_vp_adapter *na) +{ + struct nm_hash_ent *ht = na->na_bdg->ht; + uint32_t sh, dh; + u_int dst, mysrc = na->bdg_port; + uint64_t smac, dmac; + + if (buf_len < 14) { + D("invalid buf length %d", buf_len); + return NM_BDG_NOPORT; + } + dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff; + smac = le64toh(*(uint64_t *)(buf + 4)); + smac >>= 16; + + /* + * The hash is somewhat expensive, there might be some + * worthwhile optimizations here. + */ + if ((buf[6] & 1) == 0) { /* valid src */ + uint8_t *s = buf+6; + sh = nm_bridge_rthash(s); // XXX hash of source + /* update source port forwarding entry */ + ht[sh].mac = smac; /* XXX expire ? */ + ht[sh].ports = mysrc; + if (netmap_verbose) + D("src %02x:%02x:%02x:%02x:%02x:%02x on port %d", + s[0], s[1], s[2], s[3], s[4], s[5], mysrc); + } + dst = NM_BDG_BROADCAST; + if ((buf[0] & 1) == 0) { /* unicast */ + dh = nm_bridge_rthash(buf); // XXX hash of dst + if (ht[dh].mac == dmac) { /* found dst */ + dst = ht[dh].ports; + } + /* XXX otherwise return NM_BDG_UNKNOWN ? */ + } + *dst_ring = 0; + return dst; +} + + +/* + * This flush routine supports only unicast and broadcast but a large + * number of ports, and lets us replace the learn and dispatch functions. + */ +int +nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_vp_adapter *na, + u_int ring_nr) +{ + struct nm_bdg_q *dst_ents, *brddst; + uint16_t num_dsts = 0, *dsts; + struct nm_bridge *b = na->na_bdg; + u_int i, j, me = na->bdg_port; + + /* + * The work area (pointed by ft) is followed by an array of + * pointers to queues , dst_ents; there are NM_BDG_MAXRINGS + * queues per port plus one for the broadcast traffic. + * Then we have an array of destination indexes. + */ + dst_ents = (struct nm_bdg_q *)(ft + NM_BDG_BATCH_MAX); + dsts = (uint16_t *)(dst_ents + NM_BDG_MAXPORTS * NM_BDG_MAXRINGS + 1); + + /* first pass: find a destination for each packet in the batch */ + for (i = 0; likely(i < n); i += ft[i].ft_frags) { + uint8_t dst_ring = ring_nr; /* default, same ring as origin */ + uint16_t dst_port, d_i; + struct nm_bdg_q *d; + uint8_t *buf = ft[i].ft_buf; + u_int len = ft[i].ft_len; + + ND("slot %d frags %d", i, ft[i].ft_frags); + /* Drop the packet if the offset is not into the first + fragment nor at the very beginning of the second. */ + if (unlikely(na->offset > len)) + continue; + if (len == na->offset) { + buf = ft[i+1].ft_buf; + len = ft[i+1].ft_len; + } else { + buf += na->offset; + len -= na->offset; + } + dst_port = b->nm_bdg_lookup(buf, len, &dst_ring, na); + if (netmap_verbose > 255) + RD(5, "slot %d port %d -> %d", i, me, dst_port); + if (dst_port == NM_BDG_NOPORT) + continue; /* this packet is identified to be dropped */ + else if (unlikely(dst_port > NM_BDG_MAXPORTS)) + continue; + else if (dst_port == NM_BDG_BROADCAST) + dst_ring = 0; /* broadcasts always go to ring 0 */ + else if (unlikely(dst_port == me || + !b->bdg_ports[dst_port])) + continue; + + /* get a position in the scratch pad */ + d_i = dst_port * NM_BDG_MAXRINGS + dst_ring; + d = dst_ents + d_i; + + /* append the first fragment to the list */ + if (d->bq_head == NM_FT_NULL) { /* new destination */ + d->bq_head = d->bq_tail = i; + /* remember this position to be scanned later */ + if (dst_port != NM_BDG_BROADCAST) + dsts[num_dsts++] = d_i; + } else { + ft[d->bq_tail].ft_next = i; + d->bq_tail = i; + } + d->bq_len += ft[i].ft_frags; + } + + /* + * Broadcast traffic goes to ring 0 on all destinations. + * So we need to add these rings to the list of ports to scan. + * XXX at the moment we scan all NM_BDG_MAXPORTS ports, which is + * expensive. We should keep a compact list of active destinations + * so we could shorten this loop. + */ + brddst = dst_ents + NM_BDG_BROADCAST * NM_BDG_MAXRINGS; + if (brddst->bq_head != NM_FT_NULL) { + for (j = 0; likely(j < b->bdg_active_ports); j++) { + uint16_t d_i; + i = b->bdg_port_index[j]; + if (unlikely(i == me)) + continue; + d_i = i * NM_BDG_MAXRINGS; + if (dst_ents[d_i].bq_head == NM_FT_NULL) + dsts[num_dsts++] = d_i; + } + } + + ND(5, "pass 1 done %d pkts %d dsts", n, num_dsts); + /* second pass: scan destinations (XXX will be modular somehow) */ + for (i = 0; i < num_dsts; i++) { + struct ifnet *dst_ifp; + struct netmap_vp_adapter *dst_na; + struct netmap_kring *kring; + struct netmap_ring *ring; + u_int dst_nr, lim, j, sent = 0, d_i, next, brd_next; + u_int needed, howmany; + int retry = netmap_txsync_retry; + struct nm_bdg_q *d; + uint32_t my_start = 0, lease_idx = 0; + int nrings; + int offset_mismatch; + + d_i = dsts[i]; + ND("second pass %d port %d", i, d_i); + d = dst_ents + d_i; + // XXX fix the division + dst_na = b->bdg_ports[d_i/NM_BDG_MAXRINGS]; + /* protect from the lookup function returning an inactive + * destination port + */ + if (unlikely(dst_na == NULL)) + goto cleanup; + if (dst_na->up.na_flags & NAF_SW_ONLY) + goto cleanup; + dst_ifp = dst_na->up.ifp; + /* + * The interface may be in !netmap mode in two cases: + * - when na is attached but not activated yet; + * - when na is being deactivated but is still attached. + */ + if (unlikely(!(dst_ifp->if_capenable & IFCAP_NETMAP))) { + ND("not in netmap mode!"); + goto cleanup; + } + + offset_mismatch = (dst_na->offset != na->offset); + + /* there is at least one either unicast or broadcast packet */ + brd_next = brddst->bq_head; + next = d->bq_head; + /* we need to reserve this many slots. If fewer are + * available, some packets will be dropped. + * Packets may have multiple fragments, so we may not use + * there is a chance that we may not use all of the slots + * we have claimed, so we will need to handle the leftover + * ones when we regain the lock. + */ + needed = d->bq_len + brddst->bq_len; + + ND(5, "pass 2 dst %d is %x %s", + i, d_i, is_vp ? "virtual" : "nic/host"); + dst_nr = d_i & (NM_BDG_MAXRINGS-1); + nrings = dst_na->up.num_rx_rings; + if (dst_nr >= nrings) + dst_nr = dst_nr % nrings; + kring = &dst_na->up.rx_rings[dst_nr]; + ring = kring->ring; + lim = kring->nkr_num_slots - 1; + +retry: + + /* reserve the buffers in the queue and an entry + * to report completion, and drop lock. + * XXX this might become a helper function. + */ + mtx_lock(&kring->q_lock); + if (kring->nkr_stopped) { + mtx_unlock(&kring->q_lock); + goto cleanup; + } + if (dst_na->retry) { + dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); + } + my_start = j = kring->nkr_hwlease; + howmany = nm_kr_space(kring, 1); + if (needed < howmany) + howmany = needed; + lease_idx = nm_kr_lease(kring, howmany, 1); + mtx_unlock(&kring->q_lock); + + /* only retry if we need more than available slots */ + if (retry && needed <= howmany) + retry = 0; + + /* copy to the destination queue */ + while (howmany > 0) { + struct netmap_slot *slot; + struct nm_bdg_fwd *ft_p, *ft_end; + u_int cnt; + int fix_mismatch = offset_mismatch; + + /* find the queue from which we pick next packet. + * NM_FT_NULL is always higher than valid indexes + * so we never dereference it if the other list + * has packets (and if both are empty we never + * get here). + */ + if (next < brd_next) { + ft_p = ft + next; + next = ft_p->ft_next; + } else { /* insert broadcast */ + ft_p = ft + brd_next; + brd_next = ft_p->ft_next; + } + cnt = ft_p->ft_frags; // cnt > 0 + if (unlikely(cnt > howmany)) + break; /* no more space */ + howmany -= cnt; + if (netmap_verbose && cnt > 1) + RD(5, "rx %d frags to %d", cnt, j); + ft_end = ft_p + cnt; + do { + char *dst, *src = ft_p->ft_buf; + size_t copy_len = ft_p->ft_len, dst_len = copy_len; + + slot = &ring->slot[j]; + dst = BDG_NMB(&dst_na->up, slot); + + if (unlikely(fix_mismatch)) { + if (na->offset > dst_na->offset) { + src += na->offset - dst_na->offset; + copy_len -= na->offset - dst_na->offset; + dst_len = copy_len; + } else { + bzero(dst, dst_na->offset - na->offset); + dst_len += dst_na->offset - na->offset; + dst += dst_na->offset - na->offset; + } + /* fix the first fragment only */ + fix_mismatch = 0; + /* completely skip an header only fragment */ + if (copy_len == 0) { + ft_p++; + continue; + } + } + /* round to a multiple of 64 */ + copy_len = (copy_len + 63) & ~63; + + ND("send %d %d bytes at %s:%d", + i, ft_p->ft_len, NM_IFPNAME(dst_ifp), j); + if (ft_p->ft_flags & NS_INDIRECT) { + if (copyin(src, dst, copy_len)) { + // invalid user pointer, pretend len is 0 + dst_len = 0; + } + } else { + //memcpy(dst, src, copy_len); + pkt_copy(src, dst, (int)copy_len); + } + slot->len = dst_len; + slot->flags = (cnt << 8)| NS_MOREFRAG; + j = nm_next(j, lim); + ft_p++; + sent++; + } while (ft_p != ft_end); + slot->flags = (cnt << 8); /* clear flag on last entry */ + /* are we done ? */ + if (next == NM_FT_NULL && brd_next == NM_FT_NULL) + break; + } + { + /* current position */ + uint32_t *p = kring->nkr_leases; /* shorthand */ + uint32_t update_pos; + int still_locked = 1; + + mtx_lock(&kring->q_lock); + if (unlikely(howmany > 0)) { + /* not used all bufs. If i am the last one + * i can recover the slots, otherwise must + * fill them with 0 to mark empty packets. + */ + ND("leftover %d bufs", howmany); + if (nm_next(lease_idx, lim) == kring->nkr_lease_idx) { + /* yes i am the last one */ + ND("roll back nkr_hwlease to %d", j); + kring->nkr_hwlease = j; + } else { + while (howmany-- > 0) { + ring->slot[j].len = 0; + ring->slot[j].flags = 0; + j = nm_next(j, lim); + } + } + } + p[lease_idx] = j; /* report I am done */ + + update_pos = nm_kr_rxpos(kring); + + if (my_start == update_pos) { + /* all slots before my_start have been reported, + * so scan subsequent leases to see if other ranges + * have been completed, and to a selwakeup or txsync. + */ + while (lease_idx != kring->nkr_lease_idx && + p[lease_idx] != NR_NOSLOT) { + j = p[lease_idx]; + p[lease_idx] = NR_NOSLOT; + lease_idx = nm_next(lease_idx, lim); + } + /* j is the new 'write' position. j != my_start + * means there are new buffers to report + */ + if (likely(j != my_start)) { + uint32_t old_avail = kring->nr_hwavail; + + kring->nr_hwavail = (j >= kring->nr_hwcur) ? + j - kring->nr_hwcur : + j + lim + 1 - kring->nr_hwcur; + if (kring->nr_hwavail < old_avail) { + D("avail shrink %d -> %d", + old_avail, kring->nr_hwavail); + } + dst_na->up.nm_notify(&dst_na->up, dst_nr, NR_RX, 0); + still_locked = 0; + mtx_unlock(&kring->q_lock); + if (dst_na->retry && retry--) + goto retry; + } + } + if (still_locked) + mtx_unlock(&kring->q_lock); + } +cleanup: + d->bq_head = d->bq_tail = NM_FT_NULL; /* cleanup */ + d->bq_len = 0; + } + brddst->bq_head = brddst->bq_tail = NM_FT_NULL; /* cleanup */ + brddst->bq_len = 0; + return 0; +} + +static int +netmap_vp_txsync(struct netmap_vp_adapter *na, u_int ring_nr, int flags) +{ + struct netmap_kring *kring = &na->up.tx_rings[ring_nr]; + struct netmap_ring *ring = kring->ring; + u_int j, k, lim = kring->nkr_num_slots - 1; + + k = ring->cur; + if (k > lim) + return netmap_ring_reinit(kring); + + if (bridge_batch <= 0) { /* testing only */ + j = k; // used all + goto done; + } + if (bridge_batch > NM_BDG_BATCH) + bridge_batch = NM_BDG_BATCH; + + j = nm_bdg_preflush(na, ring_nr, kring, k); + if (j != k) + D("early break at %d/ %d, avail %d", j, k, kring->nr_hwavail); + /* k-j modulo ring size is the number of slots processed */ + if (k < j) + k += kring->nkr_num_slots; + kring->nr_hwavail = lim - (k - j); + +done: + kring->nr_hwcur = j; + ring->avail = kring->nr_hwavail; + if (netmap_verbose) + D("%s ring %d flags %d", NM_IFPNAME(na->up.ifp), ring_nr, flags); + return 0; +} + + +/* + * main dispatch routine for the bridge. + * We already know that only one thread is running this. + * we must run nm_bdg_preflush without lock. + */ +static int +bdg_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) +{ + struct netmap_vp_adapter *vpna = (struct netmap_vp_adapter*)na; + return netmap_vp_txsync(vpna, ring_nr, flags); +} + + +/* + * user process reading from a VALE switch. + * Already protected against concurrent calls from userspace, + * but we must acquire the queue's lock to protect against + * writers on the same queue. + */ +static int +bdg_netmap_rxsync(struct netmap_adapter *na, u_int ring_nr, int flags) +{ + struct netmap_kring *kring = &na->rx_rings[ring_nr]; + struct netmap_ring *ring = kring->ring; + u_int j, lim = kring->nkr_num_slots - 1; + u_int k = ring->cur, resvd = ring->reserved; + int n; + + mtx_lock(&kring->q_lock); + if (k > lim) { + D("ouch dangerous reset!!!"); + n = netmap_ring_reinit(kring); + goto done; + } + + /* skip past packets that userspace has released */ + j = kring->nr_hwcur; /* netmap ring index */ + if (resvd > 0) { + if (resvd + ring->avail >= lim + 1) { + D("XXX invalid reserve/avail %d %d", resvd, ring->avail); + ring->reserved = resvd = 0; // XXX panic... + } + k = (k >= resvd) ? k - resvd : k + lim + 1 - resvd; + } + + if (j != k) { /* userspace has released some packets. */ + n = k - j; + if (n < 0) + n += kring->nkr_num_slots; + ND("userspace releases %d packets", n); + for (n = 0; likely(j != k); n++) { + struct netmap_slot *slot = &ring->slot[j]; + void *addr = BDG_NMB(na, slot); + + if (addr == netmap_buffer_base) { /* bad buf */ + D("bad buffer index %d, ignore ?", + slot->buf_idx); + } + slot->flags &= ~NS_BUF_CHANGED; + j = nm_next(j, lim); + } + kring->nr_hwavail -= n; + kring->nr_hwcur = k; + } + /* tell userspace that there are new packets */ + ring->avail = kring->nr_hwavail - resvd; + n = 0; +done: + mtx_unlock(&kring->q_lock); + return n; +} + +static int +bdg_netmap_attach(struct nmreq *nmr, struct ifnet *ifp) +{ + struct netmap_vp_adapter *vpna; + struct netmap_adapter *na; + int error; + + vpna = malloc(sizeof(*vpna), M_DEVBUF, M_NOWAIT | M_ZERO); + if (vpna == NULL) + return ENOMEM; + + na = &vpna->up; + + na->ifp = ifp; + + /* bound checking */ + na->num_tx_rings = nmr->nr_tx_rings; + nm_bound_var(&na->num_tx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); + nmr->nr_tx_rings = na->num_tx_rings; // write back + na->num_rx_rings = nmr->nr_rx_rings; + nm_bound_var(&na->num_rx_rings, 1, 1, NM_BDG_MAXRINGS, NULL); + nmr->nr_rx_rings = na->num_rx_rings; // write back + nm_bound_var(&nmr->nr_tx_slots, NM_BRIDGE_RINGSIZE, + 1, NM_BDG_MAXSLOTS, NULL); + na->num_tx_desc = nmr->nr_tx_slots; + nm_bound_var(&nmr->nr_rx_slots, NM_BRIDGE_RINGSIZE, + 1, NM_BDG_MAXSLOTS, NULL); + na->num_rx_desc = nmr->nr_rx_slots; + vpna->offset = 0; + + na->na_flags |= NAF_BDG_MAYSLEEP | NAF_MEM_OWNER; + na->nm_txsync = bdg_netmap_txsync; + na->nm_rxsync = bdg_netmap_rxsync; + na->nm_register = bdg_netmap_reg; + na->nm_dtor = netmap_adapter_vp_dtor; + na->nm_krings_create = netmap_vp_krings_create; + na->nm_krings_delete = netmap_vp_krings_delete; + na->nm_mem = netmap_mem_private_new(NM_IFPNAME(na->ifp), + na->num_tx_rings, na->num_tx_desc, + na->num_rx_rings, na->num_rx_desc); + /* other nmd fields are set in the common routine */ + error = netmap_attach_common(na); + if (error) { + free(vpna, M_DEVBUF); + return error; + } + return 0; +} + +static void +netmap_bwrap_dtor(struct netmap_adapter *na) +{ + struct netmap_bwrap_adapter *bna = (struct netmap_bwrap_adapter*)na; + struct netmap_adapter *hwna = bna->hwna; + struct nm_bridge *b = bna->up.na_bdg, + *bh = bna->host.na_bdg; + struct ifnet *ifp = na->ifp; + + ND("na %p", na); + + if (b) { + netmap_bdg_detach_common(b, bna->up.bdg_port, + (bh ? bna->host.bdg_port : -1)); + } + + hwna->na_private = NULL; + netmap_adapter_put(hwna); + + bzero(ifp, sizeof(*ifp)); + free(ifp, M_DEVBUF); + na->ifp = NULL; + +} + +/* + * Pass packets from nic to the bridge. + * XXX TODO check locking: this is called from the interrupt + * handler so we should make sure that the interface is not + * disconnected while passing down an interrupt. + * + * Note, no user process can access this NIC so we can ignore + * the info in the 'ring'. + */ +/* callback that overwrites the hwna notify callback. + * Packets come from the outside or from the host stack and are put on an hwna rx ring. + * The bridge wrapper then sends the packets through the bridge. + */ +static int +netmap_bwrap_intr_notify(struct netmap_adapter *na, u_int ring_nr, enum txrx tx, int flags) +{ + struct ifnet *ifp = na->ifp; + struct netmap_bwrap_adapter *bna = na->na_private; + struct netmap_vp_adapter *hostna = &bna->host; + struct netmap_kring *kring, *bkring; + struct netmap_ring *ring; + int is_host_ring = ring_nr == na->num_rx_rings; + struct netmap_vp_adapter *vpna = &bna->up; + int error = 0; + + ND("%s[%d] %s %x", NM_IFPNAME(ifp), ring_nr, (tx == NR_TX ? "TX" : "RX"), flags); + + if (flags & NAF_DISABLE_NOTIFY) { + kring = tx == NR_TX ? na->tx_rings : na->rx_rings; + bkring = tx == NR_TX ? vpna->up.rx_rings : vpna->up.tx_rings; + if (kring->nkr_stopped) + netmap_disable_ring(bkring); + else + bkring->nkr_stopped = 0; + return 0; + } + + if (ifp == NULL || !(ifp->if_capenable & IFCAP_NETMAP)) + return 0; + + if (tx == NR_TX) + return 0; + + kring = &na->rx_rings[ring_nr]; + ring = kring->ring; + + /* make sure the ring is not disabled */ + if (nm_kr_tryget(kring)) + return 0; + + if (is_host_ring && hostna->na_bdg == NULL) { + error = bna->save_notify(na, ring_nr, tx, flags); + goto put_out; + } + + if (is_host_ring) { + vpna = hostna; + ring_nr = 0; + } else { + /* fetch packets that have arrived. + * XXX maybe do this in a loop ? + */ + error = na->nm_rxsync(na, ring_nr, 0); + if (error) + goto put_out; + } + if (kring->nr_hwavail == 0 && netmap_verbose) { + D("how strange, interrupt with no packets on %s", + NM_IFPNAME(ifp)); + goto put_out; + } + /* XXX avail ? */ + ring->cur = nm_kr_rxpos(kring); + netmap_vp_txsync(vpna, ring_nr, flags); + + if (!is_host_ring) + error = na->nm_rxsync(na, ring_nr, 0); + +put_out: + nm_kr_put(kring); + return error; +} + +static int +netmap_bwrap_register(struct netmap_adapter *na, int onoff) +{ + struct netmap_bwrap_adapter *bna = + (struct netmap_bwrap_adapter *)na; + struct netmap_adapter *hwna = bna->hwna; + struct netmap_vp_adapter *hostna = &bna->host; + int error; + + ND("%s %d", NM_IFPNAME(ifp), onoff); + + if (onoff) { + int i; + + hwna->na_lut = na->na_lut; + hwna->na_lut_objtotal = na->na_lut_objtotal; + + if (hostna->na_bdg) { + hostna->up.na_lut = na->na_lut; + hostna->up.na_lut_objtotal = na->na_lut_objtotal; + } + + /* cross-link the netmap rings */ + for (i = 0; i <= na->num_tx_rings; i++) { + hwna->tx_rings[i].nkr_num_slots = na->rx_rings[i].nkr_num_slots; + hwna->tx_rings[i].ring = na->rx_rings[i].ring; + } + for (i = 0; i <= na->num_rx_rings; i++) { + hwna->rx_rings[i].nkr_num_slots = na->tx_rings[i].nkr_num_slots; + hwna->rx_rings[i].ring = na->tx_rings[i].ring; + } + } + + if (hwna->ifp) { + error = hwna->nm_register(hwna, onoff); + if (error) + return error; + } + + bdg_netmap_reg(na, onoff); + + if (onoff) { + bna->save_notify = hwna->nm_notify; + hwna->nm_notify = netmap_bwrap_intr_notify; + } else { + hwna->nm_notify = bna->save_notify; + hwna->na_lut = NULL; + hwna->na_lut_objtotal = 0; + } + + return 0; +} + +static int +netmap_bwrap_config(struct netmap_adapter *na, u_int *txr, u_int *txd, + u_int *rxr, u_int *rxd) +{ + struct netmap_bwrap_adapter *bna = + (struct netmap_bwrap_adapter *)na; + struct netmap_adapter *hwna = bna->hwna; + + /* forward the request */ + netmap_update_config(hwna); + /* swap the results */ + *txr = hwna->num_rx_rings; + *txd = hwna->num_rx_desc; + *rxr = hwna->num_tx_rings; + *rxd = hwna->num_rx_desc; + + return 0; +} + +static int +netmap_bwrap_krings_create(struct netmap_adapter *na) +{ + struct netmap_bwrap_adapter *bna = + (struct netmap_bwrap_adapter *)na; + struct netmap_adapter *hwna = bna->hwna; + struct netmap_adapter *hostna = &bna->host.up; + int error; + + ND("%s", NM_IFPNAME(na->ifp)); + + error = netmap_vp_krings_create(na); + if (error) + return error; + + error = hwna->nm_krings_create(hwna); + if (error) { + netmap_vp_krings_delete(na); + return error; + } + + hostna->tx_rings = na->tx_rings + na->num_tx_rings; + hostna->rx_rings = na->rx_rings + na->num_rx_rings; + + return 0; +} + +static void +netmap_bwrap_krings_delete(struct netmap_adapter *na) +{ + struct netmap_bwrap_adapter *bna = + (struct netmap_bwrap_adapter *)na; + struct netmap_adapter *hwna = bna->hwna; + + ND("%s", NM_IFPNAME(na->ifp)); + + hwna->nm_krings_delete(hwna); + netmap_vp_krings_delete(na); +} + +/* notify method for the bridge-->hwna direction */ +static int +netmap_bwrap_notify(struct netmap_adapter *na, u_int ring_n, enum txrx tx, int flags) +{ + struct netmap_bwrap_adapter *bna = + (struct netmap_bwrap_adapter *)na; + struct netmap_adapter *hwna = bna->hwna; + struct netmap_kring *kring, *hw_kring; + struct netmap_ring *ring; + u_int lim, k; + int error = 0; + + if (tx == NR_TX) + return ENXIO; + + kring = &na->rx_rings[ring_n]; + hw_kring = &hwna->tx_rings[ring_n]; + ring = kring->ring; + + lim = kring->nkr_num_slots - 1; + k = nm_kr_rxpos(kring); + + if (hwna->ifp == NULL || !(hwna->ifp->if_capenable & IFCAP_NETMAP)) + return 0; + ring->cur = k; + ND("%s[%d] PRE rx(%d, %d, %d, %d) ring(%d, %d, %d) tx(%d, %d)", + NM_IFPNAME(na->ifp), ring_n, + kring->nr_hwcur, kring->nr_hwavail, kring->nkr_hwlease, kring->nr_hwreserved, + ring->cur, ring->avail, ring->reserved, + hw_kring->nr_hwcur, hw_kring->nr_hwavail); + if (ring_n == na->num_rx_rings) { + netmap_txsync_to_host(hwna); + } else { + error = hwna->nm_txsync(hwna, ring_n, flags); + } + kring->nr_hwcur = ring->cur; + kring->nr_hwavail = 0; + kring->nr_hwreserved = lim - ring->avail; + ND("%s[%d] PST rx(%d, %d, %d, %d) ring(%d, %d, %d) tx(%d, %d)", + NM_IFPNAME(na->ifp), ring_n, + kring->nr_hwcur, kring->nr_hwavail, kring->nkr_hwlease, kring->nr_hwreserved, + ring->cur, ring->avail, ring->reserved, + hw_kring->nr_hwcur, hw_kring->nr_hwavail); + + return error; +} + +static int +netmap_bwrap_host_notify(struct netmap_adapter *na, u_int ring_n, enum txrx tx, int flags) +{ + struct netmap_bwrap_adapter *bna = na->na_private; + struct netmap_adapter *port_na = &bna->up.up; + if (tx == NR_TX || ring_n != 0) + return ENXIO; + return netmap_bwrap_notify(port_na, port_na->num_rx_rings, NR_RX, flags); +} + +/* attach a bridge wrapper to the 'real' device */ +static int +netmap_bwrap_attach(struct ifnet *fake, struct ifnet *real) +{ + struct netmap_bwrap_adapter *bna; + struct netmap_adapter *na; + struct netmap_adapter *hwna = NA(real); + struct netmap_adapter *hostna; + int error; + + + bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO); + if (bna == NULL) + return ENOMEM; + + na = &bna->up.up; + na->ifp = fake; + /* fill the ring data for the bwrap adapter with rx/tx meanings + * swapped. The real cross-linking will be done during register, + * when all the krings will have been created. + */ + na->num_rx_rings = hwna->num_tx_rings; + na->num_tx_rings = hwna->num_rx_rings; + na->num_tx_desc = hwna->num_rx_desc; + na->num_rx_desc = hwna->num_tx_desc; + na->nm_dtor = netmap_bwrap_dtor; + na->nm_register = netmap_bwrap_register; + // na->nm_txsync = netmap_bwrap_txsync; + // na->nm_rxsync = netmap_bwrap_rxsync; + na->nm_config = netmap_bwrap_config; + na->nm_krings_create = netmap_bwrap_krings_create; + na->nm_krings_delete = netmap_bwrap_krings_delete; + na->nm_notify = netmap_bwrap_notify; + na->nm_mem = hwna->nm_mem; + na->na_private = na; /* prevent NIOCREGIF */ + bna->up.retry = 1; /* XXX maybe this should depend on the hwna */ + + bna->hwna = hwna; + netmap_adapter_get(hwna); + hwna->na_private = bna; /* weak reference */ + + hostna = &bna->host.up; + hostna->ifp = hwna->ifp; + hostna->num_tx_rings = 1; + hostna->num_tx_desc = hwna->num_rx_desc; + hostna->num_rx_rings = 1; + hostna->num_rx_desc = hwna->num_tx_desc; + // hostna->nm_txsync = netmap_bwrap_host_txsync; + // hostna->nm_rxsync = netmap_bwrap_host_rxsync; + hostna->nm_notify = netmap_bwrap_host_notify; + hostna->nm_mem = na->nm_mem; + hostna->na_private = bna; + + D("%s<->%s txr %d txd %d rxr %d rxd %d", fake->if_xname, real->if_xname, + na->num_tx_rings, na->num_tx_desc, + na->num_rx_rings, na->num_rx_desc); + + error = netmap_attach_common(na); + if (error) { + netmap_adapter_put(hwna); + free(bna, M_DEVBUF); + return error; + } + return 0; +} + +void +netmap_init_bridges(void) +{ + int i; + bzero(nm_bridges, sizeof(struct nm_bridge) * NM_BRIDGES); /* safety */ + for (i = 0; i < NM_BRIDGES; i++) + BDG_RWINIT(&nm_bridges[i]); +} +#endif /* WITH_VALE */ diff --git a/sys/modules/netmap/Makefile b/sys/modules/netmap/Makefile index b58bfdb2517c..aea844bde1ce 100644 --- a/sys/modules/netmap/Makefile +++ b/sys/modules/netmap/Makefile @@ -5,10 +5,14 @@ .PATH: ${.CURDIR}/../../dev/netmap .PATH.h: ${.CURDIR}/../../net +CFLAGS += -I${.CURDIR}/../../ KMOD = netmap SRCS = device_if.h bus_if.h opt_netmap.h SRCS += netmap.c netmap.h netmap_kern.h - -netmap.o: netmap_mem2.c +SRCS += netmap_mem2.c netmap_mem2.h +SRCS += netmap_generic.c +SRCS += netmap_mbq.c netmap_mbq.h +SRCS += netmap_vale.c +SRCS += netmap_freebsd.c .include diff --git a/sys/net/netmap.h b/sys/net/netmap.h index 0f2baebe15fc..50e230934dd0 100644 --- a/sys/net/netmap.h +++ b/sys/net/netmap.h @@ -1,33 +1,27 @@ /* * Copyright (C) 2011-2013 Matteo Landi, Luigi Rizzo. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * + * modification, are permitted provided that the following conditions + * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * 3. Neither the name of the authors nor the names of their contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI AND CONTRIBUTORS "AS IS" AND + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``S 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 MATTEO LANDI OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ /* @@ -36,7 +30,7 @@ * Definitions of constants and the structures used by the netmap * framework, for the part visible to both kernel and userspace. * Detailed info on netmap is available with "man netmap" or at - * + * * http://info.iet.unipi.it/~luigi/netmap/ * * This API is also used to communicate with the VALE software switch @@ -271,7 +265,7 @@ struct netmap_if { const ssize_t ring_ofs[0]; }; -#ifndef NIOCREGIF +#ifndef NIOCREGIF /* * ioctl names and related fields * @@ -306,10 +300,10 @@ struct netmap_if { * NETMAP_PRIV_MEM is a return value used to indicate that * this ring is in a private memory region hence buffer * swapping cannot be used - * + * * nr_cmd is used to configure NICs attached to a VALE switch, * or to dump the configuration of a VALE switch. - * + * * nr_cmd = NETMAP_BDG_ATTACH and nr_name = vale*:ifname * attaches the NIC to the switch, with nr_ringid specifying * which rings to use @@ -350,8 +344,10 @@ struct nmreq { #define NETMAP_BDG_DETACH 2 /* detach the NIC */ #define NETMAP_BDG_LOOKUP_REG 3 /* register lookup function */ #define NETMAP_BDG_LIST 4 /* get bridge's info */ +#define NETMAP_BDG_OFFSET 5 /* set the port offset */ uint16_t nr_arg1; #define NETMAP_BDG_HOST 1 /* attach the host stack on ATTACH */ +#define NETMAP_BDG_MAX_OFFSET 12 uint16_t nr_arg2; uint32_t spare2[3]; }; diff --git a/sys/net/netmap_user.h b/sys/net/netmap_user.h index fcb5cb3ea1c1..3f2858304caf 100644 --- a/sys/net/netmap_user.h +++ b/sys/net/netmap_user.h @@ -1,33 +1,28 @@ /* * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. - * + * Copyright (C) 2013 Universita` di Pisa + * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * + * modification, are permitted provided that the following conditions + * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * 3. Neither the name of the authors nor the names of their contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI AND CONTRIBUTORS "AS IS" AND + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTEO LANDI OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ /* @@ -56,11 +51,22 @@ * * Since rings are circular, we have macros to compute the next index * i = NETMAP_RING_NEXT(ring, i); + * + * To ease porting apps from pcap to netmap we supply a few fuctions + * that can be called to open, close and read from netmap in a way + * similar to libpcap. + * + * In order to use these, include #define NETMAP_WITH_LIBS + * in the source file that invokes these functions. */ #ifndef _NET_NETMAP_USER_H_ #define _NET_NETMAP_USER_H_ +#include +#include /* IFNAMSIZ */ +#include + #define _NETMAP_OFFSET(type, ptr, offset) \ ((type)(void *)((char *)(ptr) + (offset))) @@ -77,7 +83,7 @@ #define NETMAP_BUF_IDX(ring, buf) \ ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \ - (ring)->nr_buf_size ) + (ring)->nr_buf_size ) #define NETMAP_RING_NEXT(r, i) \ ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) @@ -92,4 +98,232 @@ */ #define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1) +#ifdef NETMAP_WITH_LIBS +/* + * Support for simple I/O libraries. + * Include other system headers required for compiling this. + */ + +#ifndef HAVE_NETMAP_WITH_LIBS +#define HAVE_NETMAP_WITH_LIBS + +#include +#include +#include /* memset */ +#include +#include /* EINVAL */ +#include /* O_RDWR */ +#include + +struct nm_hdr_t { /* same as pcap_pkthdr */ + struct timeval ts; + uint32_t caplen; + uint32_t len; +}; + +struct nm_desc_t { + struct nm_desc_t *self; + int fd; + void *mem; + int memsize; + struct netmap_if *nifp; + uint16_t first_ring, last_ring, cur_ring; + struct nmreq req; + struct nm_hdr_t hdr; +}; + +/* + * when the descriptor is open correctly, d->self == d + */ +#define P2NMD(p) ((struct nm_desc_t *)(p)) +#define IS_NETMAP_DESC(d) (P2NMD(d)->self == P2NMD(d)) +#define NETMAP_FD(d) (P2NMD(d)->fd) + +/* + * The callback, invoked on each received packet. Same as libpcap + */ +typedef void (*nm_cb_t)(u_char *, const struct nm_hdr_t *, const u_char *d); + +/* + * The open routine accepts an ifname (netmap:foo or vale:foo) and + * optionally a second (string) argument indicating the ring number + * to open. If successful, t opens the fd and maps the memory. + */ +static struct nm_desc_t *nm_open(const char *ifname, + const char *ring_no, int flags, int ring_flags); + +/* + * nm_dispatch() is the same as pcap_dispatch() + * nm_next() is the same as pcap_next() + */ +static int nm_dispatch(struct nm_desc_t *, int, nm_cb_t, u_char *); +static u_char *nm_next(struct nm_desc_t *, struct nm_hdr_t *); + +/* + * unmap memory, close file descriptor and free the descriptor. + */ +static int nm_close(struct nm_desc_t *); + + +/* + * Try to open, return descriptor if successful, NULL otherwise. + * An invalid netmap name will return errno = 0; + */ +static struct nm_desc_t * +nm_open(const char *ifname, const char *ring_name, int flags, int ring_flags) +{ + struct nm_desc_t *d; + u_int n; + + if (strncmp(ifname, "netmap:", 7) && strncmp(ifname, "vale", 4)) { + errno = 0; /* name not recognised */ + return NULL; + } + if (ifname[0] == 'n') + ifname += 7; + d = (struct nm_desc_t *)calloc(1, sizeof(*d)); + if (d == NULL) { + errno = ENOMEM; + return NULL; + } + d->self = d; /* set this early so nm_close() works */ + d->fd = open("/dev/netmap", O_RDWR); + if (d->fd < 0) + goto fail; + + if (flags & NETMAP_SW_RING) { + d->req.nr_ringid = NETMAP_SW_RING; + } else { + u_int r; + if (flags & NETMAP_HW_RING) /* interpret ring as int */ + r = (uintptr_t)ring_name; + else /* interpret ring as numeric string */ + r = ring_name ? atoi(ring_name) : ~0; + r = (r < NETMAP_RING_MASK) ? (r | NETMAP_HW_RING) : 0; + d->req.nr_ringid = r; /* set the ring */ + } + d->req.nr_ringid |= (flags & ~NETMAP_RING_MASK); + d->req.nr_version = NETMAP_API; + strncpy(d->req.nr_name, ifname, sizeof(d->req.nr_name)); + if (ioctl(d->fd, NIOCREGIF, &d->req)) + goto fail; + + d->memsize = d->req.nr_memsize; + d->mem = mmap(0, d->memsize, PROT_WRITE | PROT_READ, MAP_SHARED, + d->fd, 0); + if (d->mem == NULL) + goto fail; + d->nifp = NETMAP_IF(d->mem, d->req.nr_offset); + if (d->req.nr_ringid & NETMAP_SW_RING) { + d->first_ring = d->last_ring = d->req.nr_rx_rings; + } else if (d->req.nr_ringid & NETMAP_HW_RING) { + d->first_ring = d->last_ring = + d->req.nr_ringid & NETMAP_RING_MASK; + } else { + d->first_ring = 0; + d->last_ring = d->req.nr_rx_rings - 1; + } + d->cur_ring = d->first_ring; + for (n = d->first_ring; n <= d->last_ring; n++) { + struct netmap_ring *ring = NETMAP_RXRING(d->nifp, n); + ring->flags |= ring_flags; + } + return d; + +fail: + nm_close(d); + errno = EINVAL; + return NULL; +} + + +static int +nm_close(struct nm_desc_t *d) +{ + if (d == NULL || d->self != d) + return EINVAL; + if (d->mem) + munmap(d->mem, d->memsize); + if (d->fd != -1) + close(d->fd); + bzero(d, sizeof(*d)); + free(d); + return 0; +} + + +/* + * Same prototype as pcap_dispatch(), only need to cast. + */ +inline /* not really, but disable unused warnings */ +static int +nm_dispatch(struct nm_desc_t *d, int cnt, nm_cb_t cb, u_char *arg) +{ + int n = d->last_ring - d->first_ring + 1; + int c, got = 0, ri = d->cur_ring; + + if (cnt == 0) + cnt = -1; + /* cnt == -1 means infinite, but rings have a finite amount + * of buffers and the int is large enough that we never wrap, + * so we can omit checking for -1 + */ + for (c=0; c < n && cnt != got; c++) { + /* compute current ring to use */ + struct netmap_ring *ring; + + ri = d->cur_ring + c; + if (ri > d->last_ring) + ri = d->first_ring; + ring = NETMAP_RXRING(d->nifp, ri); + for ( ; ring->avail > 0 && cnt != got; got++) { + u_int i = ring->cur; + u_int idx = ring->slot[i].buf_idx; + u_char *buf = (u_char *)NETMAP_BUF(ring, idx); + // XXX should check valid buf + // prefetch(buf); + d->hdr.len = d->hdr.caplen = ring->slot[i].len; + d->hdr.ts = ring->ts; + cb(arg, &d->hdr, buf); + ring->cur = NETMAP_RING_NEXT(ring, i); + ring->avail--; + } + } + d->cur_ring = ri; + return got; +} + +inline /* not really, but disable unused warnings */ +static u_char * +nm_next(struct nm_desc_t *d, struct nm_hdr_t *hdr) +{ + int ri = d->cur_ring; + + do { + /* compute current ring to use */ + struct netmap_ring *ring = NETMAP_RXRING(d->nifp, ri); + if (ring->avail > 0) { + u_int i = ring->cur; + u_int idx = ring->slot[i].buf_idx; + u_char *buf = (u_char *)NETMAP_BUF(ring, idx); + // XXX should check valid buf + // prefetch(buf); + hdr->ts = ring->ts; + hdr->len = hdr->caplen = ring->slot[i].len; + ring->cur = NETMAP_RING_NEXT(ring, i); + ring->avail--; + d->cur_ring = ri; + return buf; + } + ri++; + if (ri > d->last_ring) + ri = d->first_ring; + } while (ri != d->cur_ring); + return NULL; /* nothing found */ +} + +#endif /* !HAVE_NETMAP_WITH_LIBS */ + +#endif /* NETMAP_WITH_LIBS */ + #endif /* _NET_NETMAP_USER_H_ */ From 05f7cd8bce27465437e9393f366ad113ee12ffbf Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Sun, 15 Dec 2013 08:52:16 +0000 Subject: [PATCH 056/172] mdoc: sort SEE ALSO. --- usr.sbin/bhyve/bhyve.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index 50403ef93414..b83211a67f27 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -288,8 +288,8 @@ bhyve -c 4 \e\ .Xr nmdm 4 , .Xr vmm 4 , .Xr ethers 5 , -.Xr bhyveload 8 , -.Xr bhyvectl 8 +.Xr bhyvectl 8 , +.Xr bhyveload 8 .Sh HISTORY .Nm first appeared in From 021c5b6dd0ffa699b1831199f340896857bcd085 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sun, 15 Dec 2013 15:51:05 +0000 Subject: [PATCH 057/172] Bump libcam shared library version forgotten in r259397. Submitted by: kib --- ObsoleteFiles.inc | 2 ++ lib/libcam/Makefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 41801c107d8d..07c35e17575e 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20131215: libcam version bumped +OLD_LIBS+=lib/libcam.so.6 usr/lib32/libcam.so.6 # 20131202: libcapsicum and libcasper moved to /lib/ OLD_LIBS+=usr/lib/libcapsicum.so.0 OLD_LIBS+=usr/lib/libcasper.so.0 diff --git a/lib/libcam/Makefile b/lib/libcam/Makefile index 9a21dde65b38..1621fe62cf16 100644 --- a/lib/libcam/Makefile +++ b/lib/libcam/Makefile @@ -42,6 +42,6 @@ MLINKS+= cam.3 cam_open_device.3 \ SDIR= ${.CURDIR}/../../sys CFLAGS+= -I${.CURDIR} -I${SDIR} -SHLIB_MAJOR= 6 +SHLIB_MAJOR= 7 .include From 6a67774f178babf17356490c79213aa452355124 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sun, 15 Dec 2013 16:17:00 +0000 Subject: [PATCH 058/172] Replace Sun RPC license for TI-RPC library with a 3-clause BSD license, with the explicit permission of Sun Microsystems in 2009. The code in question in this file was copied from lib/libc/rpc/pmap_getport.c. --- usr.sbin/ypbind/yp_ping.c | 52 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/usr.sbin/ypbind/yp_ping.c b/usr.sbin/ypbind/yp_ping.c index 14531269e6e4..4e445ead673e 100644 --- a/usr.sbin/ypbind/yp_ping.c +++ b/usr.sbin/ypbind/yp_ping.c @@ -30,35 +30,33 @@ * SUCH DAMAGE. */ -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. +/*- + * Copyright (c) 2009, Sun Microsystems, Inc. + * All rights reserved. * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - 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. + * - Neither the name of Sun Microsystems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ - #if 0 #ifndef lint static char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; From d2a94a776469ae43aa5a091f37e73552e4d1e858 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sun, 15 Dec 2013 16:58:23 +0000 Subject: [PATCH 059/172] Set max_lun to zero. This field is ignored unless we are manually probing LUNs anyway, and we certainly don't want to probe 2^32 values by hand in that case. MFC after: 2 weeks --- sys/powerpc/pseries/phyp_vscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/powerpc/pseries/phyp_vscsi.c b/sys/powerpc/pseries/phyp_vscsi.c index fab7743c4950..ed2bf083ff56 100644 --- a/sys/powerpc/pseries/phyp_vscsi.c +++ b/sys/powerpc/pseries/phyp_vscsi.c @@ -426,7 +426,7 @@ vscsi_cam_action(struct cam_sim *sim, union ccb *ccb) cpi->target_sprt = 0; cpi->hba_eng_cnt = 0; cpi->max_target = 0; - cpi->max_lun = ~(lun_id_t)(0); + cpi->max_lun = 0; cpi->initiator_id = ~0; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "IBM", HBA_IDLEN); From ac01bc33c9d328376062f069fcabd642b0ecc806 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sun, 15 Dec 2013 18:07:25 +0000 Subject: [PATCH 060/172] Save r3 before using it for the trap check, else we end up saving the new r3, containing the trap instruction encoding (0x7c810808), and restoring it back with the frame on return. This caused it to panic on my ppc32 machine, but somehow my ppc64 machine overlooked it, because I was using such a simple dtrace probe. X-MFC-with: r259245 MFC after: 2 weeks --- sys/powerpc/aim/trap_subr32.S | 6 ++++-- sys/powerpc/aim/trap_subr64.S | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index 99bbff68d484..fca80fb73a81 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -897,11 +897,13 @@ CNAME(dblow): #ifdef KDTRACE_HOOKS /* Privileged, so drop to KDB */ mfsrr0 %r1 - lwz %r4,0(%r1) + mtsprg3 %r3 + lwz %r1,0(%r1) /* Check if it's a DTrace trap. */ li %r3,0x0808 addis %r3,%r3,0x7c81 - cmplw %cr0,%r3,%r4 + cmplw %cr0,%r3,%r1 + mfsprg3 %r3 beq %cr0,1b #endif /* Privileged, so drop to KDB */ diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 6ee4ee0b443d..82c555fde724 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -804,11 +804,13 @@ CNAME(dblow): #ifdef KDTRACE_HOOKS /* Privileged, so drop to KDB */ mfsrr0 %r1 - lwz %r4,0(%r1) + mtsprg3 %r3 + lwz %r1,0(%r1) /* Check if it's a DTrace trap. */ li %r3,0x0808 addis %r3,%r3,0x7c81 - cmplw %cr0,%r3,%r4 + cmplw %cr0,%r3,%r1 + mfsprg3 %r3 beq %cr0,1b #endif GET_CPUINFO(%r1) From 337a0242ce2cdbcd6911a0934a38949ba33bc3ea Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 15 Dec 2013 18:13:42 +0000 Subject: [PATCH 061/172] Revert r259045. It seems that clang miscompiles code related to UDP with -fno-strict-overflow. --- sys/conf/kern.mk | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk index 6e6ba92c4db5..2939a59cb0b4 100644 --- a/sys/conf/kern.mk +++ b/sys/conf/kern.mk @@ -147,12 +147,6 @@ INLINE_LIMIT?= 8000 # CFLAGS+= -ffreestanding -# -# Do not allow a compiler to optimize out overflow checks for signed -# types. -# -CFLAGS+= -fno-strict-overflow - # # GCC SSP support # From dcd1a208e54ad73562c6b0ccf0cf4ef7d3b61bc2 Mon Sep 17 00:00:00 2001 From: Benjamin Kaduk Date: Sun, 15 Dec 2013 18:26:31 +0000 Subject: [PATCH 062/172] Increment __FreeBSD_version for the behavior change of gss_pseudo_random introduced in r259286. Approved by: hrs (mentor, src committer) --- sys/sys/param.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/param.h b/sys/sys/param.h index fd1403715e5f..51b62d942a8b 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100003 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100004 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, From 2773bfa99a0f4abd8403871e689a7612aabea9de Mon Sep 17 00:00:00 2001 From: Benjamin Kaduk Date: Sun, 15 Dec 2013 19:18:18 +0000 Subject: [PATCH 063/172] Add an UPDATING entry for the gss_pseudo_random behavior change Approved by: hrs (mentor, src committer) --- UPDATING | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/UPDATING b/UPDATING index c734d065636a..040492d64d5b 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,17 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20131213: + The behavior of gss_pseudo_random() for the krb5 mechanism + has changed, for applications requesting a longer random string + than produced by the underlying enctype's pseudo-random() function. + In particular, the random string produced from a session key of + enctype aes256-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96 will + be different at the 17th octet and later, after this change. + The counter used in the PRF+ construction is now encoded as a + big-endian integer in accordance with RFC 4402. + __FreeBSD_version is bumped to 1100004. + 20131108: The WITHOUT_ATF build knob has been removed and its functionality has been subsumed into the more generic WITHOUT_TESTS. If you were From 0d0e89b794030dab6be40975fd848e51f55261bb Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Sun, 15 Dec 2013 20:38:07 +0000 Subject: [PATCH 064/172] Add a pkg(8) repository configuration file for cdrom-based package installation. As part of the 'pkg-stage' target, copy the configuration file to the 'packages/repos/' directory on the DVD filesystem. MFC after: 3 days X-MFC-Before: -RC3 Sponsored by: The FreeBSD Foundation --- release/Makefile | 4 ++++ release/scripts/FreeBSD_install_cdrom.conf | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 release/scripts/FreeBSD_install_cdrom.conf diff --git a/release/Makefile b/release/Makefile index f6af5dc80f21..69e0fab08c0a 100644 --- a/release/Makefile +++ b/release/Makefile @@ -225,7 +225,11 @@ pkg-stage: .if !defined(NOPKG) && exists(${.CURDIR}/${TARGET}/pkg-stage.conf) sh ${.CURDIR}/scripts/pkg-stage.sh ${.CURDIR}/${TARGET}/pkg-stage.conf \ ${REVISION} + mkdir -p ${.OBJDIR}/dvd/packages/repos/ + cp ${.CURDIR}/scripts/FreeBSD_install_cdrom.conf \ + ${.OBJDIR}/dvd/packages/repos/ .endif + touch ${.TARGET} cdrom: disc1.iso bootonly.iso dvdrom: dvd1.iso diff --git a/release/scripts/FreeBSD_install_cdrom.conf b/release/scripts/FreeBSD_install_cdrom.conf new file mode 100644 index 000000000000..44554b1141ce --- /dev/null +++ b/release/scripts/FreeBSD_install_cdrom.conf @@ -0,0 +1,12 @@ +# +# $FreeBSD$ +# +# The pkg(8) repository configuration file for the installation DVD. +# + +FreeBSD_install_cdrom: { + url: "file:///dist/packages/${ABI}", + mirror_type: "none", + enabled: yes +} + From 547c099adb5b33682b88557e685c4cc4d54da685 Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Sun, 15 Dec 2013 20:47:27 +0000 Subject: [PATCH 065/172] Export 'REPOS_DIR' when the selected source medium for package installation is cdrom. This enables bsdconfig(8) to make use of the on-disc pkg(8) repository configuration, which fixes package selection and installation from the dvd installer. MFC after: 3 days M-MFC-With: r259426 X-MFC-Before: -RC3 Sponsored by: The FreeBSD Foundation --- usr.sbin/bsdconfig/share/packages/index.subr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usr.sbin/bsdconfig/share/packages/index.subr b/usr.sbin/bsdconfig/share/packages/index.subr index 5f4f523b626e..f0c1725c5b7f 100755 --- a/usr.sbin/bsdconfig/share/packages/index.subr +++ b/usr.sbin/bsdconfig/share/packages/index.subr @@ -119,6 +119,9 @@ f_index_initialize() $DEVICE_TYPE_HTTP_PROXY) f_getvar $VAR_HTTP_PROXY_PATH __site __site="$__site/packages/$PKG_ABI" ;; + $DEVICE_TYPE_CDROM) + __site="file://$MOUNTPOINT/packages/$PKG_ABI" + export REPOS_DIR="$MOUNTPOINT/packages/repos" ;; *) # UFS, DISK, CDROM, USB, DOS, NFS, etc. __site="file://$MOUNTPOINT/packages/$PKG_ABI" esac From 2a3237c84f8a7abda021c8e4b7fd37e1358a4af6 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 22:51:26 +0000 Subject: [PATCH 066/172] Clear content of keyfiles loaded by the loader after processing them. Pointed out by: rwatson MFC after: 1 week --- sys/geom/eli/g_eli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 2d21ab3b7512..e0d0074d4e97 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -990,6 +990,7 @@ g_eli_keyfiles_load(struct hmac_ctx *ctx, const char *provider) G_ELI_DEBUG(1, "Loaded keyfile %s for %s (type: %s).", file, provider, name); g_eli_crypto_hmac_update(ctx, data, size); + bzero(data, size); } } From 396b29c74e54981f16df7b5f069c4833779c4461 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 22:52:18 +0000 Subject: [PATCH 067/172] Clear some more places with potentially sensitive data. MFC after: 1 week --- sys/geom/eli/g_eli_crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/geom/eli/g_eli_crypto.c b/sys/geom/eli/g_eli_crypto.c index 8cf9ec10c508..e7217a1342a8 100644 --- a/sys/geom/eli/g_eli_crypto.c +++ b/sys/geom/eli/g_eli_crypto.c @@ -288,10 +288,12 @@ g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize) bzero(ctx, sizeof(*ctx)); SHA512_Update(&lctx, digest, sizeof(digest)); SHA512_Final(digest, &lctx); + bzero(&lctx, sizeof(lctx)); /* mdsize == 0 means "Give me the whole hash!" */ if (mdsize == 0) mdsize = SHA512_MDLEN; bcopy(digest, md, mdsize); + bzero(digest, sizeof(digest)); } void From 518eeaeeca43dd69fd4e9cd2ca10dc5788535a6c Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 22:58:09 +0000 Subject: [PATCH 068/172] MFp4 @1189139: Get rid of the msg_peek() function, which has a problem. If there was less data in the socket buffer than requested by the caller, the function would busy loop, as select(2) will always return immediately. We can just receive nvlhdr now, because some time ago we splitted receive of data from the receive of descriptors. MFC after: 1 week --- lib/libnv/msgio.c | 24 ------------------------ lib/libnv/msgio.h | 2 -- lib/libnv/nvlist.c | 8 +++++--- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/lib/libnv/msgio.c b/lib/libnv/msgio.c index a37d1cd0bcf5..0a0bd7ff4d88 100644 --- a/lib/libnv/msgio.c +++ b/lib/libnv/msgio.c @@ -113,30 +113,6 @@ fd_wait(int fd, bool doread) NULL, NULL); } -int -msg_peek(int sock, void *buf, size_t size) -{ - ssize_t done; - - PJDLOG_ASSERT(sock >= 0); - PJDLOG_ASSERT(size > 0); - - do { - fd_wait(sock, true); - done = recv(sock, buf, size, MSG_PEEK | MSG_WAITALL); - if (done == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - return (-1); - } else if (done == 0) { - errno = ENOTCONN; - return (-1); - } - } while (done != (ssize_t)size); - - return (0); -} - static int msg_recv(int sock, struct msghdr *msg) { diff --git a/lib/libnv/msgio.h b/lib/libnv/msgio.h index c6de92de10d7..fd5e462af0d0 100644 --- a/lib/libnv/msgio.h +++ b/lib/libnv/msgio.h @@ -38,8 +38,6 @@ struct cmsgcred; struct iovec; struct msghdr; -int msg_peek(int sock, void *buf, size_t size); - int cred_send(int sock); int cred_recv(int sock, struct cmsgcred *cred); diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c index 323b2c8d6307..299d60e8a0f2 100644 --- a/lib/libnv/nvlist.c +++ b/lib/libnv/nvlist.c @@ -724,11 +724,11 @@ nvlist_recv(int sock) { struct nvlist_header nvlhdr; nvlist_t *nvl, *ret; + unsigned char *buf; size_t nfds, size; - void *buf; int serrno, *fds; - if (msg_peek(sock, &nvlhdr, sizeof(nvlhdr)) == -1) + if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) return (NULL); if (!nvlist_check_header(&nvlhdr)) @@ -741,10 +741,12 @@ nvlist_recv(int sock) if (buf == NULL) return (NULL); + memcpy(buf, &nvlhdr, sizeof(nvlhdr)); + ret = NULL; fds = NULL; - if (buf_recv(sock, buf, size) == -1) + if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) goto out; if (nfds > 0) { From 36492dd3f5bb6532aa8f81c939fb551d39b4aed2 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 22:59:34 +0000 Subject: [PATCH 069/172] MFp4 @1189141: Change casperd's zygote process title. MFC after: 1 week --- sbin/casperd/zygote.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbin/casperd/zygote.c b/sbin/casperd/zygote.c index 70594ced1c68..9591a90a713f 100644 --- a/sbin/casperd/zygote.c +++ b/sbin/casperd/zygote.c @@ -122,6 +122,8 @@ zygote_main(int sock) assert(sock > STDERR_FILENO); + setproctitle("zygote"); + if (pjdlog_mode_get() != PJDLOG_MODE_STD) stdnull(); for (fd = STDERR_FILENO + 1; fd < sock; fd++) From 197731f68f5f6a240eb15db44670a811fd8828df Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:02:36 +0000 Subject: [PATCH 070/172] Make use of casperd's system.dns service when running without the -n option. Now tcpdump(8) is sandboxed even if DNS resolution is required. Sponsored by: The FreeBSD Foundation --- contrib/tcpdump/addrtoname.c | 23 +++++++++++-- contrib/tcpdump/tcpdump.c | 62 +++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/contrib/tcpdump/addrtoname.c b/contrib/tcpdump/addrtoname.c index 10ec7db267b3..3b0d65c11a15 100644 --- a/contrib/tcpdump/addrtoname.c +++ b/contrib/tcpdump/addrtoname.c @@ -32,6 +32,10 @@ static const char rcsid[] _U_ = #include "config.h" #endif +#ifdef __FreeBSD__ +#include +#include +#endif #include #ifdef USE_ETHER_NTOHOST @@ -203,6 +207,9 @@ intoa(u_int32_t addr) static u_int32_t f_netmask; static u_int32_t f_localnet; +#ifdef HAVE_LIBCAPSICUM +extern cap_channel_t *capdns; +#endif /* * Return a name for the IP address pointed to by ap. This address @@ -248,7 +255,13 @@ getname(const u_char *ap) */ if (!nflag && (addr & f_netmask) == f_localnet) { - hp = gethostbyaddr((char *)&addr, 4, AF_INET); +#ifdef HAVE_LIBCAPSICUM + if (capdns != NULL) { + hp = cap_gethostbyaddr(capdns, (char *)&addr, 4, + AF_INET); + } else +#endif + hp = gethostbyaddr((char *)&addr, 4, AF_INET); if (hp) { char *dotp; @@ -293,7 +306,13 @@ getname6(const u_char *ap) * Do not print names if -n was given. */ if (!nflag) { - hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6); +#ifdef HAVE_LIBCAPSICUM + if (capdns != NULL) { + hp = cap_gethostbyaddr(capdns, (char *)&addr, + sizeof(addr), AF_INET6); + } else +#endif + hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6); if (hp) { char *dotp; diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c index afcc152142dd..e1a34f4ea934 100644 --- a/contrib/tcpdump/tcpdump.c +++ b/contrib/tcpdump/tcpdump.c @@ -76,6 +76,12 @@ extern int SIZE_BUF; #include #include #include +#ifdef HAVE_LIBCAPSICUM +#include +#include +#include +#include +#endif /* HAVE_LIBCAPSICUM */ #endif /* __FreeBSD__ */ #ifndef WIN32 #include @@ -123,6 +129,10 @@ static int infoprint; char *program_name; +#ifdef HAVE_LIBCAPSICUM +cap_channel_t *capdns; +#endif + int32_t thiszone; /* seconds offset from gmt to local time */ /* Forwards */ @@ -684,6 +694,45 @@ get_next_file(FILE *VFile, char *ptr) return ret; } +#ifdef HAVE_LIBCAPSICUM +static cap_channel_t * +capdns_setup(void) +{ + cap_channel_t *capcas, *capdnsloc; + const char *types[1]; + int families[2]; + + capcas = cap_init(); + if (capcas == NULL) { + warning("unable to contact casperd"); + return (NULL); + } + capdnsloc = cap_service_open(capcas, "system.dns"); + /* Casper capability no longer needed. */ + cap_close(capcas); + if (capdnsloc == NULL) { + warning("unable to open system.dns service"); + return (NULL); + } + /* Limit system.dns to reverse DNS lookups. */ + types[0] = "ADDR"; + if (cap_dns_type_limit(capdnsloc, types, 1) < 0) { + warning("unable to limit access to system.dns service"); + cap_close(capdnsloc); + return (NULL); + } + families[0] = AF_INET; + families[1] = AF_INET6; + if (cap_dns_family_limit(capdnsloc, families, 2) < 0) { + warning("unable to limit access to system.dns service"); + cap_close(capdnsloc); + return (NULL); + } + + return (capdnsloc); +} +#endif /* HAVE_LIBCAPSICUM */ + int main(int argc, char **argv) { @@ -1417,6 +1466,12 @@ main(int argc, char **argv) free(cmdbuf); exit(0); } + +#ifdef HAVE_LIBCAPSICUM + if (!nflag) + capdns = capdns_setup(); +#endif /* HAVE_LIBCAPSICUM */ + init_addrtoname(localnet, netmask); init_checksum(); @@ -1615,7 +1670,12 @@ main(int argc, char **argv) #endif /* WIN32 */ #ifdef __FreeBSD__ - cansandbox = (nflag && VFileName == NULL && zflag == NULL); + cansandbox = (VFileName == NULL && zflag == NULL); +#ifdef HAVE_LIBCAPSICUM + cansandbox = (cansandbox && (nflag || capdns != NULL)); +#else + cansandbox = (cansandbox && nflag); +#endif if (cansandbox && cap_enter() < 0 && errno != ENOSYS) error("unable to enter the capability mode"); if (cap_sandboxed()) From 252e5045486da26695c83f80e5a8f46d9d013780 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:05:19 +0000 Subject: [PATCH 071/172] Add Casper support. Sponsored by: The FreeBSD Foundation --- usr.sbin/tcpdump/tcpdump/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile index 3ec7efd6024d..ac7636acb164 100644 --- a/usr.sbin/tcpdump/tcpdump/Makefile +++ b/usr.sbin/tcpdump/tcpdump/Makefile @@ -162,6 +162,11 @@ CFLAGS+= -DLBL_ALIGN DPADD= ${LIBL} ${LIBPCAP} LDADD= -ll -lpcap +.if ${MK_CASPER} != "no" +DPADD+= ${LIBCAPSICUM} ${LIBNV} +LDADD+= -lcapsicum -lnv +CFLAGS+=-DHAVE_LIBCAPSICUM +.endif .if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH) DPADD+= ${LIBCRYPTO} LDADD+= -lcrypto From 4622f0e183f29c48b53d4df19a750267841b7552 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:09:05 +0000 Subject: [PATCH 072/172] Make use of Casper's system.pwd and system.grp services when the -r option is given to convert uids and gids to user names and group names even when running in capability mode sandbox. While here log on stderr when we successfully enter the sandbox. Sponsored by: The FreeBSD Foundation --- usr.bin/kdump/Makefile | 6 +++ usr.bin/kdump/kdump.c | 111 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile index f19bd16b6595..9d2450465aa1 100644 --- a/usr.bin/kdump/Makefile +++ b/usr.bin/kdump/Makefile @@ -12,6 +12,12 @@ SRCS= kdump_subr.c kdump.c ioctl.c subr.c DPSRCS= kdump_subr.h CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I. +.if ${MK_CASPER} != "no" +DPADD+= ${LIBCAPSICUM} ${LIBNV} +LDADD+= -lcapsicum -lnv +CFLAGS+=-DHAVE_LIBCAPSICUM +.endif + .if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" SRCS+= linux_syscalls.c .endif diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 24bb0fd34e03..238f8fc16a13 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -74,9 +74,18 @@ extern int errno; #include #include #include +#ifdef HAVE_LIBCAPSICUM +#include +#include +#include +#include +#endif #include #include #include +#ifdef HAVE_LIBCAPSICUM +#include +#endif #include #include #include @@ -167,6 +176,10 @@ struct proc_info TAILQ_HEAD(trace_procs, proc_info) trace_procs; +#ifdef HAVE_LIBCAPSICUM +static cap_channel_t *cappwd, *capgrp; +#endif + static void strerror_init(void) { @@ -192,6 +205,64 @@ localtime_init(void) (void)localtime(<ime); } +#ifdef HAVE_LIBCAPSICUM +static int +cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) +{ + cap_channel_t *capcas, *cappwdloc, *capgrploc; + const char *cmds[1], *fields[1]; + + capcas = cap_init(); + if (capcas == NULL) { + warn("unable to contact casperd"); + return (NULL); + } + cappwdloc = cap_service_open(capcas, "system.pwd"); + capgrploc = cap_service_open(capcas, "system.grp"); + /* Casper capability no longer needed. */ + cap_close(capcas); + if (cappwdloc == NULL || capgrploc == NULL) { + if (cappwdloc == NULL) + warn("unable to open system.pwd service"); + if (capgrploc == NULL) + warn("unable to open system.grp service"); + goto fail; + } + /* Limit system.pwd to only getpwuid() function and pw_name field. */ + cmds[0] = "getpwuid"; + if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0) { + warn("unable to limit access to system.pwd service"); + goto fail; + } + fields[0] = "pw_name"; + if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0) { + warn("unable to limit access to system.pwd service"); + goto fail; + } + /* Limit system.grp to only getgrgid() function and gr_name field. */ + cmds[0] = "getgrgid"; + if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0) { + warn("unable to limit access to system.grp service"); + goto fail; + } + fields[0] = "gr_name"; + if (cap_grp_limit_fields(capgrploc, fields, 1) < 0) { + warn("unable to limit access to system.grp service"); + goto fail; + } + + *cappwdp = cappwdloc; + *capgrpp = capgrploc; + return (0); +fail: + if (capgrploc == NULL) + cap_close(cappwdloc); + if (capgrploc == NULL) + cap_close(capgrploc); + return (-1); +} +#endif /* HAVE_LIBCAPSICUM */ + int main(int argc, char *argv[]) { @@ -265,14 +336,28 @@ main(int argc, char *argv[]) strerror_init(); localtime_init(); - +#ifdef HAVE_LIBCAPSICUM + if (resolv != 0) { + if (cappwdgrp_setup(&cappwd, &capgrp) < 0) { + cappwd = NULL; + capgrp = NULL; + } + } + if (resolv == 0 || (cappwd != NULL && capgrp != NULL)) { + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + } +#else if (resolv == 0) { if (cap_enter() < 0 && errno != ENOSYS) err(1, "unable to enter capability mode"); } +#endif limitfd(STDIN_FILENO); limitfd(STDOUT_FILENO); limitfd(STDERR_FILENO); + if (cap_sandboxed()) + fprintf(stderr, "capability mode sandbox enabled\n"); TAILQ_INIT(&trace_procs); drop_logged = 0; @@ -1664,11 +1749,31 @@ ktrstat(struct stat *statp) printf("mode=%s, ", mode); } printf("nlink=%ju, ", (uintmax_t)statp->st_nlink); - if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL) + if (resolv == 0) { + pwd = NULL; + } else { +#ifdef HAVE_LIBCAPSICUM + if (cappwd != NULL) + pwd = cap_getpwuid(cappwd, statp->st_uid); + else +#endif + pwd = getpwuid(statp->st_uid); + } + if (pwd == NULL) printf("uid=%ju, ", (uintmax_t)statp->st_uid); else printf("uid=\"%s\", ", pwd->pw_name); - if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL) + if (resolv == 0) { + grp = NULL; + } else { +#ifdef HAVE_LIBCAPSICUM + if (capgrp != NULL) + grp = cap_getgrgid(capgrp, statp->st_gid); + else +#endif + grp = getgrgid(statp->st_gid); + } + if (grp == NULL) printf("gid=%ju, ", (uintmax_t)statp->st_gid); else printf("gid=\"%s\", ", grp->gr_name); From 73a4fbbb39c90286d5703cc2830053aecb46f978 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:12:42 +0000 Subject: [PATCH 073/172] Forgot to regenerate after r257736. --- sys/kern/init_sysent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 14292e72b2dc..55cd354e7060 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -368,7 +368,7 @@ struct sysent sysent[] = { { 0, (sy_call_t *)sys_sched_yield, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 331 = sched_yield */ { AS(sched_get_priority_max_args), (sy_call_t *)sys_sched_get_priority_max, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 332 = sched_get_priority_max */ { AS(sched_get_priority_min_args), (sy_call_t *)sys_sched_get_priority_min, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 333 = sched_get_priority_min */ - { AS(sched_rr_get_interval_args), (sy_call_t *)sys_sched_rr_get_interval, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 334 = sched_rr_get_interval */ + { AS(sched_rr_get_interval_args), (sy_call_t *)sys_sched_rr_get_interval, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 334 = sched_rr_get_interval */ { AS(utrace_args), (sy_call_t *)sys_utrace, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 335 = utrace */ { compat4(AS(freebsd4_sendfile_args),sendfile), AUE_SENDFILE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 336 = freebsd4 sendfile */ { AS(kldsym_args), (sy_call_t *)sys_kldsym, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 337 = kldsym */ From e1e16d2419a1d63304e2bb179247068a895befa7 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:14:27 +0000 Subject: [PATCH 074/172] Allow for pselect(2) in capability mode. Noticed by: David Drysdale --- sys/kern/capabilities.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf index 746a04cd9f12..8d33472f5b34 100644 --- a/sys/kern/capabilities.conf +++ b/sys/kern/capabilities.conf @@ -559,10 +559,11 @@ sctp_generic_sendmsg_iov sctp_peeloff ## -## Allow select(2), which will be scoped by capability rights. +## Allow pselect(2) and select(2), which will be scoped by capability rights. ## ## XXXRW: But is it? ## +pselect select ## From 61a9fc8fe25399c0958fdbaea8414895f6cc67b9 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:15:12 +0000 Subject: [PATCH 075/172] Regenerate after r259436. --- sys/kern/init_sysent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 55cd354e7060..f8e5fff53305 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -556,7 +556,7 @@ struct sysent sysent[] = { { AS(pdkill_args), (sy_call_t *)sys_pdkill, AUE_PDKILL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 519 = pdkill */ { AS(pdgetpid_args), (sy_call_t *)sys_pdgetpid, AUE_PDGETPID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 520 = pdgetpid */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 521 = pdwait4 */ - { AS(pselect_args), (sy_call_t *)sys_pselect, AUE_SELECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 522 = pselect */ + { AS(pselect_args), (sy_call_t *)sys_pselect, AUE_SELECT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 522 = pselect */ { AS(getloginclass_args), (sy_call_t *)sys_getloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 523 = getloginclass */ { AS(setloginclass_args), (sy_call_t *)sys_setloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 524 = setloginclass */ { AS(rctl_get_racct_args), (sy_call_t *)sys_rctl_get_racct, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 525 = rctl_get_racct */ From 82845da3fa3f1f962ba8c821e0ee10657db442c6 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:19:42 +0000 Subject: [PATCH 076/172] Fix syscalls that can be loaded as kernel modules - they were not given the flag allowing to call them from capability mode sandbox. Noticed by: David Drysdale --- sys/kern/makesyscalls.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 87263bf97eb8..0c3adff8f92a 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -460,7 +460,7 @@ s/\$//g printf("\t{ %s, (sy_call_t *)", argssize) > sysent column = 8 + 2 + length(argssize) + 15 if (flag("NOSTD")) { - printf("%s },", "lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT") > sysent + printf("lkmressys, AUE_NULL, NULL, 0, 0, %s, SY_THR_ABSENT },", flags) > sysent column = column + length("lkmressys") + length("AUE_NULL") + 3 } else { if (funcname == "nosys" || funcname == "sysarch" || From 007e4f41a768cf2a0df00076c50a49079a4db019 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:20:26 +0000 Subject: [PATCH 077/172] Regenerate after r259438. --- sys/kern/init_sysent.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index f8e5fff53305..6c94f3d3f578 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -289,9 +289,9 @@ struct sysent sysent[] = { { AS(openbsd_poll_args), (sy_call_t *)sys_openbsd_poll, AUE_POLL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 252 = openbsd_poll */ { 0, (sy_call_t *)sys_issetugid, AUE_ISSETUGID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 253 = issetugid */ { AS(lchown_args), (sy_call_t *)sys_lchown, AUE_LCHOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 254 = lchown */ - { AS(aio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 255 = aio_read */ - { AS(aio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 256 = aio_write */ - { AS(lio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 257 = lio_listio */ + { AS(aio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 255 = aio_read */ + { AS(aio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 256 = aio_write */ + { AS(lio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 257 = lio_listio */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 258 = nosys */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 259 = nosys */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 260 = nosys */ @@ -348,13 +348,13 @@ struct sysent sysent[] = { { AS(setresuid_args), (sy_call_t *)sys_setresuid, AUE_SETRESUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 311 = setresuid */ { AS(setresgid_args), (sy_call_t *)sys_setresgid, AUE_SETRESGID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 312 = setresgid */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 313 = obsolete signanosleep */ - { AS(aio_return_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 314 = aio_return */ - { AS(aio_suspend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 315 = aio_suspend */ - { AS(aio_cancel_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 316 = aio_cancel */ - { AS(aio_error_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 317 = aio_error */ - { AS(oaio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 318 = oaio_read */ - { AS(oaio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 319 = oaio_write */ - { AS(olio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 320 = olio_listio */ + { AS(aio_return_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 314 = aio_return */ + { AS(aio_suspend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 315 = aio_suspend */ + { AS(aio_cancel_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 316 = aio_cancel */ + { AS(aio_error_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 317 = aio_error */ + { AS(oaio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 318 = oaio_read */ + { AS(oaio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 319 = oaio_write */ + { AS(olio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 320 = olio_listio */ { 0, (sy_call_t *)sys_yield, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 321 = yield */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 322 = obsolete thr_sleep */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 323 = obsolete thr_wakeup */ @@ -393,7 +393,7 @@ struct sysent sysent[] = { { AS(extattr_set_file_args), (sy_call_t *)sys_extattr_set_file, AUE_EXTATTR_SET_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 356 = extattr_set_file */ { AS(extattr_get_file_args), (sy_call_t *)sys_extattr_get_file, AUE_EXTATTR_GET_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 357 = extattr_get_file */ { AS(extattr_delete_file_args), (sy_call_t *)sys_extattr_delete_file, AUE_EXTATTR_DELETE_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 358 = extattr_delete_file */ - { AS(aio_waitcomplete_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 359 = aio_waitcomplete */ + { AS(aio_waitcomplete_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 359 = aio_waitcomplete */ { AS(getresuid_args), (sy_call_t *)sys_getresuid, AUE_GETRESUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 360 = getresuid */ { AS(getresgid_args), (sy_call_t *)sys_getresgid, AUE_GETRESGID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 361 = getresgid */ { 0, (sy_call_t *)sys_kqueue, AUE_KQUEUE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 362 = kqueue */ @@ -492,14 +492,14 @@ struct sysent sysent[] = { { AS(thr_new_args), (sy_call_t *)sys_thr_new, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 455 = thr_new */ { AS(sigqueue_args), (sy_call_t *)sys_sigqueue, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 456 = sigqueue */ { AS(kmq_open_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 457 = kmq_open */ - { AS(kmq_setattr_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 458 = kmq_setattr */ - { AS(kmq_timedreceive_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 459 = kmq_timedreceive */ - { AS(kmq_timedsend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 460 = kmq_timedsend */ - { AS(kmq_notify_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 461 = kmq_notify */ + { AS(kmq_setattr_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 458 = kmq_setattr */ + { AS(kmq_timedreceive_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 459 = kmq_timedreceive */ + { AS(kmq_timedsend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 460 = kmq_timedsend */ + { AS(kmq_notify_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 461 = kmq_notify */ { AS(kmq_unlink_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 462 = kmq_unlink */ { AS(abort2_args), (sy_call_t *)sys_abort2, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 463 = abort2 */ { AS(thr_set_name_args), (sy_call_t *)sys_thr_set_name, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 464 = thr_set_name */ - { AS(aio_fsync_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 465 = aio_fsync */ + { AS(aio_fsync_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 465 = aio_fsync */ { AS(rtprio_thread_args), (sy_call_t *)sys_rtprio_thread, AUE_RTPRIO, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 466 = rtprio_thread */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 467 = nosys */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 468 = nosys */ From 68cfe72642a2cec63e47fcc7c9706018f9876be6 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 15 Dec 2013 23:49:42 +0000 Subject: [PATCH 078/172] Include bsd.own.mk for MK_CASPER to work. Reported by: nwhitehorn --- usr.bin/kdump/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile index 9d2450465aa1..d65779e16a59 100644 --- a/usr.bin/kdump/Makefile +++ b/usr.bin/kdump/Makefile @@ -1,6 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + .if (${MACHINE_ARCH} == "amd64") SFX= 32 .endif From 15773775f7000311e8484edbd7381ce40527336a Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Mon, 16 Dec 2013 00:50:14 +0000 Subject: [PATCH 079/172] Properly drain the TTY when both revoke(2) and close(2) end up closing the TTY. In such a case, ttydev_close() is called multiple times and each time, t_revokecnt is incremented and cv_broadcast() is called for both the t_outwait and t_inwait condition variables. Let's say revoke(2) comes in first and gets to call tty_drain() from ttydev_leave(). Let's say that the revoke comes from init(8) as the result of running "shutdown -r now". Since shutdown prints various messages to the console before announing that the machine will reboot immediately, let's also say that the output queue is not empty and that tty_drain() has something to do. Let's assume this all happens on a 9600 baud serial console, so it takes a time to drain. The shutdown command will exit(2) and as such will end up closing stdout. Let's say this close will come in second, bump t_revokecnt and call tty_wakeup(). This has tty_wait() return prematurely and the next thing that will happen is that the thread doing revoke(2) will flush the TTY. Since the drain wasn't complete, the flush will effectively drop whatever is left in t_outq. This change takes into account that tty_drain() will return ERESTART due to the fact that t_revokecnt was bumped and in that case simply call tty_drain() again. The thread in question is already performing the close so it can safely finish draining the TTY before destroying the TTY structure. Now all messages from shutdown will be printed on the serial console. Obtained from: Juniper Networks, Inc. --- sys/kern/tty.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 4fce6072d652..e181d1e62e46 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -191,8 +191,10 @@ ttydev_leave(struct tty *tp) /* Drain any output. */ MPASS((tp->t_flags & TF_STOPPED) == 0); - if (!tty_gone(tp)) - tty_drain(tp); + if (!tty_gone(tp)) { + while (tty_drain(tp) == ERESTART) + ; + } ttydisc_close(tp); From 1871769f1ffcdd19c29ab2ec33b0428332fb1736 Mon Sep 17 00:00:00 2001 From: Benjamin Kaduk Date: Mon, 16 Dec 2013 01:58:12 +0000 Subject: [PATCH 080/172] tzfile.5: catch up to r204333 The stdtime sources were moved from lib/libc to contrib/tzcode, and tzfile.h is not an installed header, so the man page refers to its location in the source tree. The documentation could be more clear about the internal nature of the header, but those changes should go through upstream tzcode. PR: docs/176864 Approved by: hrs (mentor) --- contrib/tzcode/stdtime/tzfile.5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/tzcode/stdtime/tzfile.5 b/contrib/tzcode/stdtime/tzfile.5 index 1606b5ae8c45..5e911a5ee5c1 100644 --- a/contrib/tzcode/stdtime/tzfile.5 +++ b/contrib/tzcode/stdtime/tzfile.5 @@ -6,7 +6,7 @@ .Nm tzfile .Nd timezone information .Sh SYNOPSIS -.Fd #include \&"/usr/src/lib/libc/stdtime/tzfile.h\&" +.Fd #include \&"/usr/src/contrib/tzcode/stdtime/tzfile.h\&" .Sh DESCRIPTION The time zone information files used by .Xr tzset 3 From 6f0468df7ad910ba6951f33d26920ed3590f49a2 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Mon, 16 Dec 2013 10:50:13 +0000 Subject: [PATCH 081/172] Fix regression issue after r259248: Some Intel XHCI controlles timeout processing so-called "TRBs" when the final LINK TRB of a so-called "TD" has the CHAIN-BIT set. MFC after: 1 week Tested by: glebius @ --- sys/dev/usb/controller/xhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index c56e6f05ae7c..7ce437621837 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -1942,6 +1942,8 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp) /* remove chain bit because this is the last data TRB in the chain */ td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); + /* remove CHAIN-BIT from last LINK TRB */ + td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); usb_pc_cpu_flush(td->page_cache); From 49a6d80306b6f452540beab186628dcd24b874f5 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 16 Dec 2013 11:03:59 +0000 Subject: [PATCH 082/172] Start-up script for casperd daemon. Sponsored by: The FreeBSD Foundation --- etc/defaults/rc.conf | 1 + etc/rc.d/Makefile | 1 + etc/rc.d/casperd | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 etc/rc.d/casperd diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index aa8a010549df..f217f420bcab 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -658,6 +658,7 @@ newsyslog_enable="YES" # Run newsyslog at startup. newsyslog_flags="-CN" # Newsyslog flags to create marked files mixer_enable="YES" # Run the sound mixer. opensm_enable="NO" # Opensm(8) for infiniband devices defaults to off +casperd_enable="NO" # casperd(8) daemon ############################################################## ### Jail Configuration (see rc.conf(5) manual page) ########## diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 375da6d131cb..7cb649975cf7 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -26,6 +26,7 @@ FILES= DAEMON \ bridge \ bsnmpd \ ${_bthidd} \ + casperd \ ccd \ cleanvar \ cleartmp \ diff --git a/etc/rc.d/casperd b/etc/rc.d/casperd new file mode 100644 index 000000000000..0b80169a0262 --- /dev/null +++ b/etc/rc.d/casperd @@ -0,0 +1,19 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: casperd +# REQUIRE: NETWORKING syslogd +# BEFORE: DAEMON +# KEYWORD: shutdown + +. /etc/rc.subr + +name="casperd" +rcvar="casperd_enable" +pidfile="/var/run/${name}.pid" +command="/sbin/${name}" + +load_rc_config $name +run_rc_command "$1" From e37e08c7bf077975919c9634069a7d6a85925df7 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Mon, 16 Dec 2013 13:52:18 +0000 Subject: [PATCH 083/172] Fix periodic per-CPU timers startup on boot. Reported by: neel MFC after: 2 weeks --- sys/kern/kern_clocksource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c index 0aa71bd73726..88552933826f 100644 --- a/sys/kern/kern_clocksource.c +++ b/sys/kern/kern_clocksource.c @@ -233,7 +233,8 @@ handleevents(sbintime_t now, int fake) if (!busy) { state->idle = 0; state->nextevent = t; - loadtimer(now, 0); + loadtimer(now, (fake == 2) && + (timer->et_flags & ET_FLAGS_PERCPU)); } ET_HW_UNLOCK(state); return (done); From d25257776a4d26570d930d1d054e975462cf666d Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 15:50:59 +0000 Subject: [PATCH 084/172] Add a fix for Long-standing problem with VMware. Described in below links: https://communities.vmware.com/thread/107230 https://communities.vmware.com/docs/DOC-11677 Basically, ignore the ``function 62'' and ``function 63'' interpretations of the left/right command key when we're in the lengthiest portion of the installation (initiated by the `auto' module). The net effect is that you can now (once you've started the installer from the media) escape the VM without prematurely terminating the current action due to spurious escape sequence. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/auto | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index dce4fe560de5..34a6918a6f36 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -49,6 +49,10 @@ error() { ############################################################ MAIN +# Don't send ESC on function-key 62/63 (left/right command key) +f_quietly kbdcontrol -f 62 '' +f_quietly kbdcontrol -f 63 '' + f_dprintf "Began Installation at %s" "$( date )" rm -rf $BSDINSTALL_TMPETC From a7fb3c62e7a632ec1a0463260056b808260b4faf Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 15:52:44 +0000 Subject: [PATCH 085/172] Mask error from newaliases(1) when the hostname is not fully qualified. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/config b/usr.sbin/bsdinstall/scripts/config index 3ddcadaa895f..98baade77535 100755 --- a/usr.sbin/bsdinstall/scripts/config +++ b/usr.sbin/bsdinstall/scripts/config @@ -42,7 +42,7 @@ cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot [ "${debugFile#+}" ] && cp "${debugFile#+}" $BSDINSTALL_CHROOT/var/log/ # Set up other things from installed config -chroot $BSDINSTALL_CHROOT /usr/bin/newaliases +chroot $BSDINSTALL_CHROOT /usr/bin/newaliases > /dev/null 2>&1 ################################################################################ # END From a6c8532c17900cb5568ea0c732014385ed62c50c Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 17:03:44 +0000 Subject: [PATCH 086/172] As per discussions on -current, re-add /var/mail (removed in r257842) but this time with atime=on in support of various software that requires it. Discussed on: -current MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 1 + 1 file changed, 1 insertion(+) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 78eb43c6ad8d..af0a7e681472 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -132,6 +132,7 @@ f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS=" /var mountpoint=/var /var/crash compression=lz4,exec=off,setuid=off /var/log compression=lz4,exec=off,setuid=off + /var/mail compression=lz4,atime=on /var/tmp compression=lz4,exec=on,setuid=off " # END-QUOTE From 77cf51096ff8dbb4cbc260a3828299ad04deb79e Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 16 Dec 2013 17:05:03 +0000 Subject: [PATCH 087/172] Add myself to the src-committers list Approved by: bapt (mentor) --- share/misc/committers-src.dot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index e352a9c24a03..8084ddd76e65 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -114,6 +114,7 @@ art [label="Artem Belevich\nart@FreeBSD.org\n2011/03/29"] asomers [label="Alan Somers\nasomers@FreeBSD.org\n2013/04/24"] avg [label="Andriy Gapon\navg@FreeBSD.org\n2009/02/18"] bapt [label="Baptiste Daroussin\nbapt@FreeBSD.org\n2011/12/23"] +bdrewery [label="Bryan Drewery\nbdrewery@FreeBSD.org\n2013/12/14"] benl [label="Ben Laurie\nbenl@FreeBSD.org\n2011/05/18"] benno [label="Benno Rice\nbenno@FreeBSD.org\n2000/11/02"] bms [label="Bruce M Simpson\nbms@FreeBSD.org\n2003/08/06"] @@ -331,6 +332,8 @@ avg -> art avg -> pluknet avg -> smh +bapt -> bdrewery + benno -> grehan billf -> dougb From 30c8ebe9b7bd0fac098adb73612ca17442f3ba6c Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 17:11:09 +0000 Subject: [PATCH 088/172] Accept NULL input as also meaning zero swap. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index af0a7e681472..7c19c7de84f9 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -1387,7 +1387,7 @@ while :; do f_dialog_input input \ "$msg_please_enter_amount_of_swap_space" \ "$ZFSBOOT_SWAP_SIZE" && - ZFSBOOT_SWAP_SIZE="$input" + ZFSBOOT_SWAP_SIZE="${input:-0}" ;; esac done From 840f097103fe30f98ff42c2c9f98dbeb80b7feb3 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 16 Dec 2013 18:45:21 +0000 Subject: [PATCH 089/172] Enable llvm's integrated assembler for PowerPC, since it should now be good enough for typical usage. Requested by: rdivacky MFC after: 1 week --- lib/clang/Makefile | 1 + lib/clang/include/PPCGenAsmMatcher.inc | 2 ++ lib/clang/include/llvm/Config/AsmParsers.def | 1 + lib/clang/libllvmpowerpcasmparser/Makefile | 16 ++++++++++++++++ usr.bin/clang/clang/Makefile | 3 ++- usr.bin/clang/llc/Makefile | 3 ++- usr.bin/clang/lldb/Makefile | 1 + usr.bin/clang/llvm-mc/Makefile | 3 ++- usr.bin/clang/llvm-objdump/Makefile | 3 ++- usr.bin/clang/llvm-rtdyld/Makefile | 3 ++- usr.bin/clang/opt/Makefile | 3 ++- 11 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 lib/clang/include/PPCGenAsmMatcher.inc create mode 100644 lib/clang/libllvmpowerpcasmparser/Makefile diff --git a/lib/clang/Makefile b/lib/clang/Makefile index 3f30c963e21c..2310ab9c6da7 100644 --- a/lib/clang/Makefile +++ b/lib/clang/Makefile @@ -74,6 +74,7 @@ SUBDIR= libclanganalysis \ libllvmmipsdisassembler \ libllvmmipsinfo \ libllvmmipsinstprinter \ + libllvmpowerpcasmparser \ libllvmpowerpccodegen \ libllvmpowerpcdesc \ libllvmpowerpcinfo \ diff --git a/lib/clang/include/PPCGenAsmMatcher.inc b/lib/clang/include/PPCGenAsmMatcher.inc new file mode 100644 index 000000000000..0538126d2773 --- /dev/null +++ b/lib/clang/include/PPCGenAsmMatcher.inc @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +#include "PPCGenAsmMatcher.inc.h" diff --git a/lib/clang/include/llvm/Config/AsmParsers.def b/lib/clang/include/llvm/Config/AsmParsers.def index 024462efbd1f..a2c0f7889ae9 100644 --- a/lib/clang/include/llvm/Config/AsmParsers.def +++ b/lib/clang/include/llvm/Config/AsmParsers.def @@ -2,6 +2,7 @@ LLVM_ASM_PARSER(ARM) LLVM_ASM_PARSER(Mips) +LLVM_ASM_PARSER(PowerPC) LLVM_ASM_PARSER(X86) #undef LLVM_ASM_PARSER diff --git a/lib/clang/libllvmpowerpcasmparser/Makefile b/lib/clang/libllvmpowerpcasmparser/Makefile new file mode 100644 index 000000000000..ff1f533a6446 --- /dev/null +++ b/lib/clang/libllvmpowerpcasmparser/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +.include + +LIB= llvmpowerpcasmparser + +SRCDIR= lib/Target/PowerPC/AsmParser +INCDIR= lib/Target/PowerPC +SRCS= PPCAsmParser.cpp + +TGHDRS= PPCGenAsmMatcher \ + PPCGenInstrInfo \ + PPCGenRegisterInfo \ + PPCGenSubtargetInfo + +.include "../clang.lib.mk" diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile index 27c2cf197639..cea9382e8324 100644 --- a/usr.bin/clang/clang/Makefile +++ b/usr.bin/clang/clang/Makefile @@ -85,8 +85,9 @@ LIBDEPS=clangfrontendtool \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ diff --git a/usr.bin/clang/llc/Makefile b/usr.bin/clang/llc/Makefile index e75dd816e886..75873a3cf9fb 100644 --- a/usr.bin/clang/llc/Makefile +++ b/usr.bin/clang/llc/Makefile @@ -24,8 +24,9 @@ LIBDEPS=llvmirreader \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ diff --git a/usr.bin/clang/lldb/Makefile b/usr.bin/clang/lldb/Makefile index 6869b8da9f88..5b7335c26239 100644 --- a/usr.bin/clang/lldb/Makefile +++ b/usr.bin/clang/lldb/Makefile @@ -106,6 +106,7 @@ LIBDEPS=\ llvmmipsinstprinter \ llvmpowerpcdesc \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ llvmruntimedyld \ llvmvectorize \ llvmx86desc \ diff --git a/usr.bin/clang/llvm-mc/Makefile b/usr.bin/clang/llvm-mc/Makefile index 55a702b2850e..442185c1a22b 100644 --- a/usr.bin/clang/llvm-mc/Makefile +++ b/usr.bin/clang/llvm-mc/Makefile @@ -24,8 +24,9 @@ LIBDEPS=llvmmcdisassembler \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile index 9e215a1ea528..4a0a23587bd2 100644 --- a/usr.bin/clang/llvm-objdump/Makefile +++ b/usr.bin/clang/llvm-objdump/Makefile @@ -30,8 +30,9 @@ LIBDEPS=llvmmcdisassembler \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ diff --git a/usr.bin/clang/llvm-rtdyld/Makefile b/usr.bin/clang/llvm-rtdyld/Makefile index aae366a9baa7..f0043261cc62 100644 --- a/usr.bin/clang/llvm-rtdyld/Makefile +++ b/usr.bin/clang/llvm-rtdyld/Makefile @@ -28,8 +28,9 @@ LIBDEPS=llvmdebuginfo \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ diff --git a/usr.bin/clang/opt/Makefile b/usr.bin/clang/opt/Makefile index e881329538d5..2364c70b8fbc 100644 --- a/usr.bin/clang/opt/Makefile +++ b/usr.bin/clang/opt/Makefile @@ -25,8 +25,9 @@ LIBDEPS=llvmarmdisassembler \ llvmmipsinstprinter \ llvmpowerpccodegen \ llvmpowerpcdesc \ - llvmpowerpcinfo \ llvmpowerpcinstprinter \ + llvmpowerpcasmparser \ + llvmpowerpcinfo \ llvmx86disassembler \ llvmx86asmparser \ llvmx86codegen \ From a622223f0188fe34a767c6049d9c06877e98ae0b Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 18:53:09 +0000 Subject: [PATCH 090/172] Bug-fixes and debugging improvments: + De-obfuscate debugging to show actual values + Change graid(8) syntax; s/destroy/delete/ [destroy is not invalid syntax] + Log commands that were previously quiet + Added some new comemnts and updated some existing ones + Add missing local for `disk' used in zfs_create_boot() + Use $disks instead of multiply-expanding $* in zfs_create_boot() + Pedantically unset variable holding geli(8) passphrase after use + Pedantically add double-quotes around zpool names and zfs datasets + Fix quotation expansion for zpool_cache entries of loader.conf(5) + Some limited whitespace changes MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 287 ++++++++++++++-------------- 1 file changed, 142 insertions(+), 145 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 7c19c7de84f9..1503d6cb58c9 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -156,8 +156,10 @@ CHMOD_MODE='chmod %s "%s"' DD_WITH_OPTIONS='dd if="%s" of="%s" %s' ECHO_APPEND='echo "%s" >> "%s"' GELI_ATTACH='geli attach -j - -k "%s" "%s"' +GELI_DETACH_F='geli detach -f "%s"' GELI_PASSWORD_INIT='geli init -b -B "%s" -e %s -J - -K "%s" -l 256 -s 4096 "%s"' GNOP_CREATE='gnop create -S 4096 "%s"' +GNOP_DESTROY='gnop destroy "%s"' GPART_ADD='gpart add -t %s "%s"' GPART_ADD_INDEX='gpart add -i %s -t %s "%s"' GPART_ADD_INDEX_WITH_SIZE='gpart add -i %s -t %s -s %s "%s"' @@ -166,19 +168,23 @@ GPART_ADD_LABEL_WITH_SIZE='gpart add -l %s -t %s -s %s "%s"' GPART_BOOTCODE='gpart bootcode -b "%s" "%s"' GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"' GPART_CREATE='gpart create -s %s "%s"' +GPART_DESTROY_F='gpart destroy -F "%s"' GPART_SET_ACTIVE='gpart set -a active -i %s "%s"' +GRAID_DELETE='graid delete "%s"' LN_SF='ln -sf "%s" "%s"' MKDIR_P='mkdir -p "%s"' MOUNT_TYPE='mount -t %s "%s" "%s"' PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\"" PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"' SHELL_TRUNCATE=':> "%s"' +UMOUNT='umount "%s"' ZFS_CREATE_WITH_OPTIONS='zfs create %s "%s"' ZFS_SET='zfs set "%s" "%s"' ZFS_UNMOUNT='zfs unmount "%s"' ZPOOL_CREATE_WITH_OPTIONS='zpool create %s "%s" %s %s' ZPOOL_EXPORT='zpool export "%s"' ZPOOL_IMPORT_WITH_OPTIONS='zpool import %s "%s"' +ZPOOL_LABELCLEAR_F='zpool labelclear -f "%s"' ZPOOL_SET='zpool set %s "%s"' # @@ -612,6 +618,8 @@ dialog_menu_layout() # replacement drivers do not have the exact same sector counts. # # NOTE: The MBR layout is more complicated (GPT is preferred). +# NOTE: $swapsize and $gelisize should be defined by the calling function. +# NOTE: Sets $bootpart and $targetpart for the calling function. # zfs_create_diskpart() { @@ -664,13 +672,13 @@ zfs_create_diskpart() # NOTE: Failure is ok here, blank disk will have nothing to destroy. # f_dprintf "$funcname: Destroying all data/layouts on \`%s'..." "$disk" - f_quietly gpart destroy -F $disk - f_quietly graid destroy $disk - f_quietly zpool labelclear -f /dev/$disk # Kill it with fire + f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk + f_eval_catch -d $funcname graid "$GRAID_DELETE" $disk + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" /dev/$disk # Make doubly-sure backup GPT is destroyed - f_quietly gpart create -s gpt $disk - f_quietly gpart destroy -F $disk + f_eval_catch -d $funcname gpart "$GPART_CREATE" gpt $disk + f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk # Calculate partition size given desired amount of swap f_dprintf "$funcname: Getting disk capactiy for \`%s'" "$disk" @@ -694,36 +702,35 @@ zfs_create_diskpart() # # 1. Create GPT layout using labels # - f_eval_catch $funcname gpart "$GPART_CREATE" gpt \$disk || + f_eval_catch $funcname gpart "$GPART_CREATE" gpt $disk || return $FAILURE # # 2. Add small freebsd-boot partition labeled `boot#' # f_eval_catch $funcname gpart "$GPART_ADD_LABEL_WITH_SIZE" \ - gptboot\$index freebsd-boot 512k \$disk || + gptboot$index freebsd-boot 512k $disk || return $FAILURE f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \ - /boot/pmbr /boot/gptzfsboot 1 \$disk || + /boot/pmbr /boot/gptzfsboot 1 $disk || return $FAILURE - # zpool will use the `zfs#' GPT labels + # NB: zpool will use the `zfs#' GPT labels bootpart=p2 targetpart=p2 # Change things around if we are using geli(8) if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then bootpart=p2 targetpart=p3 partsize=$(( $partsize - $gelisize )) - f_dprintf "$funcname: gelisize=[%s]" \ - "gelisize=[$gelisize]" f_eval_catch $funcname gpart \ - "$GPART_ADD_LABEL_WITH_SIZE" boot\$index \ - freebsd-zfs \${gelisize}b \$disk || + "$GPART_ADD_LABEL_WITH_SIZE" boot$index \ + freebsd-zfs ${gelisize}b $disk || return $FAILURE - # Pedantically nuke any old labels, stop geli - f_quietly zpool labelclear -f "/dev/$disk$bootpart" - f_quietly geli detach -f "/dev/$disk$targetpart" + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$bootpart + f_eval_catch -d $funcname geli "$GELI_DETACH_F" \ + /dev/$disk$targetpart fi # @@ -731,30 +738,29 @@ zfs_create_diskpart() # NOTE: Using above calculated partsize to leave room for swap. # if [ ${swapsize:-0} -gt 0 ]; then - f_dprintf "$funcname: partsize=[%s]" \ - "partsize=[$partsize]" f_eval_catch $funcname gpart \ - "$GPART_ADD_LABEL_WITH_SIZE" zfs\$index \ - freebsd-zfs \${partsize}b \$disk || + "$GPART_ADD_LABEL_WITH_SIZE" zfs$index \ + freebsd-zfs ${partsize}b $disk || return $FAILURE else f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ - zfs\$index freebsd-zfs \$disk || + zfs$index freebsd-zfs $disk || return $FAILURE fi - f_quietly zpool labelclear -f "/dev/$disk$targetpart" + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$targetpart # # 4. Add freebsd-swap partition labeled `swap#' # if [ $swapsize -gt 0 ]; then f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ - swap\$index freebsd-swap \$disk || + swap$index freebsd-swap $disk || return $FAILURE # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ - /dev/gpt/swap\$index none swap sw 0 0 \ - \$BSDINSTALL_TMPETC/fstab || + /dev/gpt/swap$index none swap sw 0 0 \ + $BSDINSTALL_TMPETC/fstab || return $FAILURE fi ;; @@ -763,25 +769,28 @@ zfs_create_diskpart() # # 1. Create MBR layout (no labels) # - f_eval_catch $funcname gpart "$GPART_CREATE" mbr \$disk || + f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk || return $FAILURE f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \ - \$disk || return $FAILURE + $disk || return $FAILURE # # 2. Add freebsd slice with all available space # - f_eval_catch $funcname gpart "$GPART_ADD" freebsd \$disk || + f_eval_catch $funcname gpart "$GPART_ADD" freebsd $disk || return $FAILURE - f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 \$disk || + f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 $disk || return $FAILURE - f_quietly zpool labelclear -f /dev/${disk}s1 # Pedantic - f_quietly gpart destroy -F ${disk}s1 # Pedantic + # Pedantically nuke any old labels + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/${disk}s1 + # Pedantically nuke any old scheme + f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" ${disk}s1 # # 3. Write BSD scheme to the freebsd slice # - f_eval_catch $funcname gpart "$GPART_CREATE" BSD \${disk}s1 || + f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 || return $FAILURE # zpool will use s1a (no labels) @@ -792,15 +801,17 @@ zfs_create_diskpart() bootpart=s1a targetpart=s1d partsize=$(( $partsize - $gelisize )) mbrindex=4 # If this is s1a then make the zpool s1d - f_dprintf "$funcname: mbrindex=[%s] gelisize=[%s]" \ - "$mbrindex" "$gelisize" f_eval_catch $funcname gpart \ "$GPART_ADD_INDEX_WITH_SIZE" \ - 1 freebsd-zfs \${gelisize}b \${disk}s1 || + 1 freebsd-zfs ${gelisize}b ${disk}s1 || return $FAILURE - # Pedantically nuke any old labels, stop geli - f_quietly zpool labelclear -f "/dev/$disk$bootpart" - f_quietly geli detach -f "/dev/$disk$targetpart" + # Pedantically nuke any old labels + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$bootpart + # Pedantically detach targetpart for later + f_eval_catch -d $funcname geli \ + "$GELI_DETACH_F" \ + /dev/$disk$targetpart fi # @@ -808,19 +819,17 @@ zfs_create_diskpart() # NOTE: Using above calculated partsize to leave room for swap. # if [ ${swapsize:-0} -gt 0 ]; then - f_dprintf "$funcname: mbrindex=[%s] partsize=[%s]" \ - "$mbrindex" "$partsize" f_eval_catch $funcname gpart \ "$GPART_ADD_INDEX_WITH_SIZE" \ - \$mbrindex freebsd-zfs \${partsize}b \ - \${disk}s1 || return $FAILURE + $mbrindex freebsd-zfs ${partsize}b \ + ${disk}s1 || return $FAILURE else - f_dprintf "$funcname: mbrindex=[%s]" "$mbrindex" f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ - \$mbrindex freebsd-zfs \${disk}s1 || + $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE fi - f_quietly zpool labelclear -f /dev/$disk$targetpart # Pedantic + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$targetpart # Pedantic # # 5. Add freebsd-swap partition @@ -831,8 +840,8 @@ zfs_create_diskpart() return $FAILURE # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ - /dev/\${disk}s1b none swap sw 0 0 \ - \$BSDINSTALL_TMPETC/fstab || + /dev/${disk}s1b none swap sw 0 0 \ + $BSDINSTALL_TMPETC/fstab || return $FAILURE fi ;; @@ -852,13 +861,13 @@ zfs_create_boot() local funcname=zfs_create_boot local poolname="$1" vdev_type="$2" local bootpart targetpart + shift 2 # poolname vdev_type + local disks="$*" disk + local bootpart targetpart # Set by zfs_create_diskpart() below - shift 2 # name vdev_type - - # We may need this later - local disks="$*" - + # # Pedantic checks; should never be seen + # if [ ! "$poolname" ]; then f_dprintf "$funcname: NULL poolname" msg_error="$msg_error: $funcname" \ @@ -874,16 +883,19 @@ zfs_create_boot() f_dprintf "$funcname: poolname=[%s] vdev_type=[%s]" \ "$poolname" "$vdev_type" + # # Initialize fstab(5) + # f_dprintf "$funcname: Initializing temporary fstab(5) file..." - f_eval_catch $funcname sh \ - "$SHELL_TRUNCATE" \$BSDINSTALL_TMPETC/fstab || + f_eval_catch $funcname sh "$SHELL_TRUNCATE" $BSDINSTALL_TMPETC/fstab || return $FAILURE f_eval_catch $funcname printf "$PRINTF_FSTAB" \ "# Device" Mountpoint FStype Options Dump "Pass#" \ - \$BSDINSTALL_TMPETC/fstab || return $FAILURE + $BSDINSTALL_TMPETC/fstab || return $FAILURE + # # Expand SI units in desired sizes + # f_dprintf "$funcname: Expanding supplied swapsize/gelisize values..." local swapsize gelisize if ! f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize; then @@ -904,23 +916,24 @@ zfs_create_boot() f_dprintf "$funcname: ZFSBOOT_GELI_BOOT_SIZE=[%s] gelisize=[%s]" \ "$ZFSBOOT_GELI_BOOT_SIZE" "$gelisize" + # # Prepare the disks + # f_dprintf "$funcname: Preparing disk partitions for ZFS pool..." local n=0 - for disk in $*; do + for disk in $disks; do zfs_create_diskpart $disk $n || return $FAILURE n=$(( $n + 1 )) done + # Now $bootpart and $targetpart are set (suffix for $disk) # MBR boot loader hack part 1 # We have to do this early because geli gets in the way later if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then f_dprintf "$funcname: Copying MBR boot loader to disks..." - f_dprintf "$funcname: disks=[%s]" "$disks" for disk in $disks; do - f_dprintf "$funcname: disk=[%s]" "$disk" f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /boot/zfsboot /dev/\${disk}s1 count=1 || + /boot/zfsboot /dev/${disk}s1 count=1 || return $FAILURE done fi @@ -935,12 +948,9 @@ zfs_create_boot() [ "$ZFSBOOT_GELI_ENCRYPTION" ] && part="$bootpart" f_dprintf "$funcname: Applying 4k alignment with gnop(8)..." - f_dprintf "$funcname: *=[%s]" "$*" - for disk in $*; do - f_dprintf "$funcname: disk=[%s] part=[%s]" \ - "$disk" "$part" + for disk in $disks; do f_eval_catch $funcname gnop "$GNOP_CREATE" \ - \$disk\$part || return $FAILURE + $disk$part || return $FAILURE if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then unenc_list="$unenc_list $disk$part.nop" else @@ -950,7 +960,7 @@ zfs_create_boot() set -- $new_list else local new_list= - for disk in $*; do + for disk in $disks; do new_list="$new_list $disk$targetpart" [ "$ZFSBOOT_GELI_ENCRYPTION" ] && unenc_list="$unenc_list $disk$bootpart" @@ -969,34 +979,30 @@ zfs_create_boot() f_dprintf "$funcname: Setting up disk encryption..." # Create the parent directories for our unencrypted pool - f_quietly umount /mnt + f_eval_catch -d $funcname umount "$UMOUNT" /mnt f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \ - \$BSDINSTALL_CHROOT || return $FAILURE + $BSDINSTALL_CHROOT || return $FAILURE # Create mirror across the unencrypted partition on all disks [ $( set -- $unenc_list; echo $# ) -gt 1 ] && bootvdev=mirror - f_dprintf "$funcname: %s %s %s" \ - "ZFSBOOT_GELI_POOL_NAME=[$ZFSBOOT_GELI_POOL_NAME]" \ - "bootvdev=[$bootvdev]" "unenc_list=[$unenc_list]" - options="-o altroot=\"\$BSDINSTALL_CHROOT\"" - options="$options -m \"/\$ZFSBOOT_GELI_POOL_NAME\"" - options="$options -f" + options="-o altroot=$BSDINSTALL_CHROOT" + options="$options -m \"/$ZFSBOOT_GELI_POOL_NAME\" -f" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ - "$options" \$ZFSBOOT_GELI_POOL_NAME \$bootvdev \ + "$options" "$ZFSBOOT_GELI_POOL_NAME" $bootvdev \ \$unenc_list || return $FAILURE - f_dprintf "$funcname: geli_pool=[%s]" "$geli_pool" - f_eval_catch $funcname mkdir "$MKDIR_P" \$geli_pool/boot || + f_eval_catch $funcname mkdir "$MKDIR_P" $geli_pool/boot || return $FAILURE # Generate an encryption key using random(4) - f_dprintf "$funcname: key=[%s]" "$key" f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /dev/random \$geli_pool/\$key "bs=4096 count=1" || + /dev/random $geli_pool/$key "bs=4096 count=1" || return $FAILURE + # # Create the geli(8) GEOMS + # local geli_list if ! msg_enter_new_password="$msg_geli_password" \ f_dialog_input_password @@ -1005,53 +1011,55 @@ zfs_create_boot() f_show_err "$msg_user_cancelled" return $FAILURE fi - f_dprintf "$funcname: disks=[%s]" "$disks" + + # Initialize geli(8) on each of the target partitions for disk in $disks; do - f_dprintf "$funcname: disk=[%s] targetpart=[%s]" \ - "$disk" "$targetpart" f_dialog_info "$msg_geli_setup" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD - if ! echo "$pw_password" | f_eval_catch $funcname \ - geli "$GELI_PASSWORD_INIT" \ - \$geli_pool/boot/\$disk\$targetpart.eli \ - AES-XTS \$geli_pool/\$key \$disk\$targetpart + if ! echo "$pw_password" | f_eval_catch \ + $funcname geli "$GELI_PASSWORD_INIT" \ + "$geli_pool/boot/$disk$targetpart.eli" \ + AES-XTS "$geli_pool/$key" \ + $disk$targetpart then f_interactive || f_die + unset pw_password # Sensitive info return $FAILURE fi - if ! echo "$pw_password" | f_eval_catch $funcname \ - geli "$GELI_ATTACH" \$geli_pool/\$key \ - \$disk\$targetpart + if ! echo "$pw_password" | f_eval_catch \ + $funcname geli "$GELI_ATTACH" \ + "$geli_pool/\$key" $disk$targetpart then f_interactive || f_die + unset pw_password # Sensitive info return $FAILURE fi geli_list="$geli_list $disk$targetpart.eli" done + unset pw_password # Sensitive info set -- $geli_list + + # Clean up f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \ - \$ZFSBOOT_GELI_POOL_NAME || return $FAILURE - f_quietly umount /mnt # done with tmpfs + "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE + f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs fi # - # Create the ZFS pool with desired type and disk devices + # Create the ZFS root pool with desired type and disk devices # local vdevs="$*" f_dprintf "$funcname: Creating boot pool..." - f_dprintf "poolname=[%s] vdev_type=[%s] vdevs=[%s]" \ - "$poolname" "$vdev_type" "$vdevs" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ - "-o altroot=\"\$BSDINSTALL_CHROOT\" -m none -f" \ - \$poolname \$vdev_type \$vdevs + "-o altroot=$BSDINSTALL_CHROOT -m none -f" \ + $poolname $vdev_type $vdevs # Customize the zpool a bit... local option f_dprintf "$funcname: Setting miscellaneous options on boot pool..." for option in checksum=fletcher4 atime=off; do - f_dprintf "$funcname: option=[%s]" "$option" - f_eval_catch $funcname zfs "$ZFS_SET" \$option \$poolname || - return $FAILURE + f_eval_catch $funcname zfs "$ZFS_SET" $option "$poolname" || + return $FAILURE done # @@ -1074,10 +1082,8 @@ zfs_create_boot() # Replace both commas and spaces with ` -o ' f_replaceall "$options" "[ ,]" " -o " options # Create the dataset with desired options - f_dprintf "$funcname: dataset=[%s] options=[%s]" \ - "$dataset" "$options" f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \ - "\${options:+-o \$options}" \$poolname\$dataset || + "${options:+-o $options}" "$poolname$dataset" || return $FAILURE done @@ -1085,57 +1091,52 @@ zfs_create_boot() f_dprintf "$funcname: Modifying directory permissions..." local dir for dir in /tmp /var/tmp; do - f_dprintf "$funcname: dir=[%s]" "$dir" f_eval_catch $funcname chmod "$CHMOD_MODE" 1777 \ - \$BSDINSTALL_CHROOTDIR\$dir || return $FAILURE + $BSDINSTALL_CHROOTDIR$dir || return $FAILURE done # Create symlink(s) if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then f_dprintf "$funcname: Creating /boot symlink for GELI..." f_eval_catch $funcname ln "$LN_SF" \ - \$ZFSBOOT_GELI_POOL_NAME/boot \ - \$BSDINSTALL_CHROOT/boot || return $FAILURE + "$ZFSBOOT_GELI_POOL_NAME/boot" \ + $BSDINSTALL_CHROOT/boot || return $FAILURE fi # Set bootfs property f_dprintf "$funcname: Setting bootfs property..." - f_dprintf "$funcname: %s %s" \ - "ZFSBOOT_BEROOT_NAME=[$ZFSBOOT_BEROOT_NAME]" \ - "ZFSBOOT_BOOTFS_NAME=[$ZFSBOOT_BOOTFS_NAME]" f_eval_catch $funcname zpool "$ZPOOL_SET" \ - bootfs=\"\$poolname/\$ZFSBOOT_BEROOT_NAME/\$ZFSBOOT_BOOTFS_NAME\" \ - \$poolname || return $FAILURE + "bootfs=\"$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME\"" \ + "$poolname" || return $FAILURE # Export the pool(s) f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..." - f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \$poolname || + f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$poolname" || return $FAILURE if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \ - \$ZFSBOOT_GELI_POOL_NAME || return $FAILURE + "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE fi # Destroy the gnop devices (if enabled) for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$disks}; do if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - f_quietly gnop destroy $disk$bootpart.nop + f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \ + $disk$bootpart.nop else - f_quietly gnop destroy $disk$targetpart.nop + f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \ + $disk$targetpart.nop fi done # MBR boot loader hack part 2 if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then f_dprintf "$funcname: Updating MBR boot loader on disks..." - f_dprintf "$funcname: disks=[%s]" # Stick the ZFS boot loader in the "convienient hole" after # the ZFS internal metadata for disk in $disks; do - f_dprintf "$funcname: disk=[%s] bootpart=[%s]" \ - "$disk" "$bootpart" f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /boot/zfsboot /dev/\$disk\$bootpart \ + /boot/zfsboot /dev/$disk$bootpart \ "skip=1 seek=1024" || return $FAILURE done fi @@ -1143,42 +1144,42 @@ zfs_create_boot() # Re-import the ZFS pool(s) f_dprintf "$funcname: Re-importing ZFS pool(s)..." f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ - "-o altroot=\"\$BSDINSTALL_CHROOT\"" \$poolname || + "-o altroot=\"$BSDINSTALL_CHROOT\"" "$poolname" || return $FAILURE if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ "-o altroot=\"\$BSDINSTALL_CHROOT\"" \ - \$ZFSBOOT_GELI_POOL_NAME || return $FAILURE + "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE fi # While this is apparently not needed, it seems to help MBR f_dprintf "$funcname: Configuring zpool.cache..." - f_eval_catch $funcname mkdir "$MKDIR_P" \$BSDINSTALL_CHROOT/boot/zfs || + f_eval_catch $funcname mkdir "$MKDIR_P" $BSDINSTALL_CHROOT/boot/zfs || return $FAILURE f_eval_catch $funcname zpool "$ZPOOL_SET" \ - cachefile=\"\$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\" \ - \$poolname || return $FAILURE + "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \ + "$poolname" || return $FAILURE # Last, but not least... required lines for rc.conf(5)/loader.conf(5) # NOTE: We later concatenate these into their destination f_dprintf "%s: Configuring rc.conf(5)/loader.conf(5) additions..." \ "$funcname" f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_enable=\"YES\"' \ - \$BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE + $BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_load=\"YES\"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE + $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE # We're all done unless we should go on to do encryption [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS # Some additional geli(8) requirements for loader.conf(5) for option in \ - zpool_cache_load=\"YES\" \ - zpool_cache_type=\"/boot/zfs/zpool.cache\" \ - zpool_cache_name=\"/boot/zfs/zpool.cache\" \ + 'zpool_cache_load=\"YES\"' \ + 'zpool_cache_type=\"/boot/zfs/zpool.cache\"' \ + 'zpool_cache_name=\"/boot/zfs/zpool.cache\"' \ ; do - f_eval_catch $funcname echo "$ECHO_APPEND" \$option \ - \$BSDINSTALL_TMPBOOT/loader.conf.zfs || + f_eval_catch $funcname echo "$ECHO_APPEND" "$option" \ + $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE done @@ -1187,30 +1188,26 @@ zfs_create_boot() # f_dprintf "$funcname: Configuring disk encryption..." f_eval_catch $funcname echo "$ECHO_APPEND" 'aesni_load=\"YES\"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE + $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" 'geom_eli_load=\"YES\"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE + $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE f_eval_catch $funcname printf "$PRINTF_CONF" vfs.root.mountfrom \ - '"zfs:$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE - f_dprintf "$funcname: disks=[%s]" "$disks" + "\"zfs:$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME\"" \ + $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE for disk in $disks; do - f_dprintf "$funcname: %s %s %s" \ - "disk=[$disk]" "targetpart=[$targetpart]" \ - "ZFSBOOT_GELI_KEY_FILE=[$ZFSBOOT_GELI_KEY_FILE]" f_eval_catch $funcname printf "$PRINTF_CONF" \ - geli_%s_keyfile0_load '"$disk$targetpart" YES' \ - \$BSDINSTALL_TMPBOOT/loader.conf.\$disk\$targetpart || + geli_%s_keyfile0_load "$disk$targetpart YES" \ + $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_type \ - '"$disk$targetpart" "$disk$targetpart:geli_keyfile0"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.\$disk\$targetpart || + "$disk$targetpart $disk$targetpart:geli_keyfile0" \ + $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_name \ - '"$disk$targetpart" "$ZFSBOOT_GELI_KEY_FILE"' \ - \$BSDINSTALL_TMPBOOT/loader.conf.\$disk\$targetpart || + "$disk$targetpart \"$ZFSBOOT_GELI_KEY_FILE\"" \ + $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE done @@ -1259,7 +1256,7 @@ f_dialog_backtitle "$msg_freebsd_installer" # f_dprintf "BSDINSTALL_CHROOT=[%s]" "$BSDINSTALL_CHROOT" f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC" -f_dprintf "PRINTF_FSTAB=[%s]" "$PRINTF_FSTAB" +f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT" # # Loop over the main menu until we've accomplished what we came here to do From 73242a5ee17c54f7a0d1fc2281416ee1a458139c Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 16 Dec 2013 19:31:23 +0000 Subject: [PATCH 091/172] Migrate the sendfile_sync struct to use a UMA zone rather than M_TEMP. This allows it to be better tracked as well as being able to leverage UMA for more interesting/useful behaviour at a later date. Sponsored by: Netflix, Inc. --- sys/kern/uipc_syscalls.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index e43cd4bb353a..c45597b677ab 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -80,6 +80,9 @@ __FBSDID("$FreeBSD$"); #include #endif +#include +#include +#include #include #include @@ -130,6 +133,7 @@ static int sfreadahead = 1; SYSCTL_INT(_kern_ipc_sendfile, OID_AUTO, readahead, CTLFLAG_RW, &sfreadahead, 0, "Number of sendfile(2) read-ahead MAXBSIZE blocks"); +static uma_zone_t zone_sfsync; static void sfstat_init(const void *unused) @@ -140,6 +144,22 @@ sfstat_init(const void *unused) } SYSINIT(sfstat, SI_SUB_MBUF, SI_ORDER_FIRST, sfstat_init, NULL); +static void +sf_sync_init(const void *unused) +{ + + zone_sfsync = uma_zcreate("sendfile_sync", sizeof(struct sendfile_sync), + NULL, NULL, +#ifdef INVARIANTS + trash_init, trash_fini, +#else + NULL, NULL, +#endif + UMA_ALIGN_CACHE, + 0); +} +SYSINIT(sf_sync, SI_SUB_MBUF, SI_ORDER_FIRST, sf_sync_init, NULL); + static int sfstat_sysctl(SYSCTL_HANDLER_ARGS) { @@ -1898,7 +1918,7 @@ sf_sync_alloc(uint32_t flags) { struct sendfile_sync *sfs; - sfs = malloc(sizeof *sfs, M_TEMP, M_WAITOK | M_ZERO); + sfs = uma_zalloc(zone_sfsync, M_WAITOK | M_ZERO); mtx_init(&sfs->mtx, "sendfile", NULL, MTX_DEF); cv_init(&sfs->cv, "sendfile"); sfs->flags = flags; @@ -1953,7 +1973,7 @@ sf_sync_free(struct sendfile_sync *sfs) KASSERT(sfs->count == 0, ("sendfile sync still busy")); cv_destroy(&sfs->cv); mtx_destroy(&sfs->mtx); - free(sfs, M_TEMP); + uma_zfree(zone_sfsync, sfs); } /* From 7cae6aab5b78eec527b58fb327a8b2025ae5abb0 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:37:15 +0000 Subject: [PATCH 092/172] Improve default ZFS disk layout (tested): + For GPT, always provision zfs# partition after swap [for resizability] + For MBR, always use a boot pool to relialy place root vdevs at EOD NB: Fixes edge-cases where MBR combination failed boot (e.g. swap-less) + Generalize boot pool logic so it can be used for any scheme (namely MBR) + Update existing comments and some whitespace fixes + Change some variable names to make reading/debugging the code easier in zfs_create_boot() (namely prepend zroot_ or bootpool_ to property) + Because zroot vdevs are at EOD, no longer need to calculate partsize (vdev consumes remaining space after allocating swap) + Optimize processing of disks -- no reason to loop over the disks 3-4 separate times when we can logically use a single loop to do everything Discussed on: -stable MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 407 ++++++++++++++-------------- 1 file changed, 201 insertions(+), 206 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 1503d6cb58c9..a274cf55bbd1 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -66,24 +66,31 @@ f_include $BSDCFG_SHARE/variable.subr # # Should we use geli(8) to encrypt the drives? +# NB: Automatically enables ZFSBOOT_BOOT_POOL # : ${ZFSBOOT_GELI_ENCRYPTION=} -# -# Default name the unencrypted pool when using geli(8) to encrypt the drives -# -: ${ZFSBOOT_GELI_POOL_NAME:=bootpool} - -# -# Default size for the unencrypted boot pool when using geli(8) -# -: ${ZFSBOOT_GELI_BOOT_SIZE:=2g} - # # Default path to the geli(8) keyfile used in drive encryption # : ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key} +# +# Create a separate boot pool? +# NB: Automatically set when using geli(8) or MBR +# +: ${ZFSBOOT_BOOT_POOL=} + +# +# Default name for boot pool when enabled (e.g., geli(8) or MBR) +# +: ${ZFSBOOT_BOOT_POOL_NAME:=bootpool} + +# +# Default size for boot pool when enabled (e.g., geli(8) or MBR) +# +: ${ZFSBOOT_BOOT_POOL_SIZE:=2g} + # # Default disks to use (always empty unless being scripted) # @@ -212,8 +219,8 @@ msg_geli_setup="Initializing encryption on the selected disks, this will take se msg_install="Install" msg_install_desc="Proceed with Installation" msg_install_help="Create ZFS boot pool with displayed options" +msg_invalid_boot_pool_size="Invalid boot pool size \`%s'" msg_invalid_disk_argument="Invalid disk argument \`%s'" -msg_invalid_geli_boot_size="Invalid geli(8) boot size \`%s'" msg_invalid_index_argument="Invalid index argument \`%s'" msg_invalid_swap_size="Invalid swap size \`%s'" msg_invalid_virtual_device_type="Invalid Virtual Device type \`%s'" @@ -617,15 +624,13 @@ dialog_menu_layout() # so we can have some real swap. This also provides wiggle room incase your # replacement drivers do not have the exact same sector counts. # -# NOTE: The MBR layout is more complicated (GPT is preferred). -# NOTE: $swapsize and $gelisize should be defined by the calling function. +# NOTE: $swapsize and $bootsize should be defined by the calling function. # NOTE: Sets $bootpart and $targetpart for the calling function. # zfs_create_diskpart() { local funcname=zfs_create_diskpart local disk="$1" index="$2" - local disksize partsize # Check arguments if [ ! "$disk" ]; then @@ -680,18 +685,10 @@ zfs_create_diskpart() f_eval_catch -d $funcname gpart "$GPART_CREATE" gpt $disk f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk - # Calculate partition size given desired amount of swap - f_dprintf "$funcname: Getting disk capactiy for \`%s'" "$disk" - if ! device_$disk get capacity disksize; then - f_dprintf "$funcname: Unable to get disk capacity of \`%s'" \ - "$disk" - msg_error="$msg_error: $funcname" \ - f_show_err "$msg_unable_to_get_disk_capacity" "$disk" - return $FAILURE - fi - partsize=$(( $disksize - $swapsize )) - f_dprintf "$funcname: disksize=[%s] partsize=[%s]" \ - "$disksize" "$partsize" + # + # Enable boot pool if encryption is desired + # + [ "$ZFSBOOT_GELI_ENCRYPTION" ] && ZFSBOOT_BOOT_POOL=1 # # Lay down the desired type of partition scheme @@ -717,45 +714,36 @@ zfs_create_diskpart() # NB: zpool will use the `zfs#' GPT labels bootpart=p2 targetpart=p2 + [ ${swapsize:-0} -gt 0 ] && targetpart=p3 - # Change things around if we are using geli(8) - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + # + # Prepare boot pool if enabled (e.g., for geli(8)) + # + if [ "$ZFSBOOT_BOOT_POOL" ]; then bootpart=p2 targetpart=p3 - partsize=$(( $partsize - $gelisize )) + [ ${swapsize:-0} -gt 0 ] && targetpart=p4 f_eval_catch $funcname gpart \ "$GPART_ADD_LABEL_WITH_SIZE" boot$index \ - freebsd-zfs ${gelisize}b $disk || + freebsd-zfs ${bootsize}b $disk || return $FAILURE - # Pedantically nuke any old labels, stop geli + # Pedantically nuke any old labels f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$bootpart - f_eval_catch -d $funcname geli "$GELI_DETACH_F" \ - /dev/$disk$targetpart + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + # Pedantically detach targetpart for later + f_eval_catch -d $funcname geli \ + "$GELI_DETACH_F" \ + /dev/$disk$targetpart + fi fi # - # 3. Add freebsd-zfs partition labeled `zfs#' for zpool - # NOTE: Using above calculated partsize to leave room for swap. + # 3. Add freebsd-swap partition labeled `swap#' # if [ ${swapsize:-0} -gt 0 ]; then f_eval_catch $funcname gpart \ - "$GPART_ADD_LABEL_WITH_SIZE" zfs$index \ - freebsd-zfs ${partsize}b $disk || - return $FAILURE - else - f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ - zfs$index freebsd-zfs $disk || - return $FAILURE - fi - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/$disk$targetpart - - # - # 4. Add freebsd-swap partition labeled `swap#' - # - if [ $swapsize -gt 0 ]; then - f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ - swap$index freebsd-swap $disk || + "$GPART_ADD_LABEL_WITH_SIZE" swap$index \ + freebsd-swap ${swapsize}b $disk || return $FAILURE # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ @@ -763,6 +751,14 @@ zfs_create_diskpart() $BSDINSTALL_TMPETC/fstab || return $FAILURE fi + + # + # 4. Add freebsd-zfs partition labeled `zfs#' for zroot + # + f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ + zfs$index freebsd-zfs $disk || return $FAILURE + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$targetpart ;; MBR) f_dprintf "$funcname: Creating MBR layout..." @@ -793,21 +789,21 @@ zfs_create_diskpart() f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 || return $FAILURE - # zpool will use s1a (no labels) - bootpart=s1a targetpart=s1a mbrindex=1 + # NB: zpool will use s1a (no labels) + bootpart=s1a targetpart=s1d mbrindex=4 - # Change things around if we are using geli(8) + # + # Always prepare a boot pool on MBR + # + ZFSBOOT_BOOT_POOL=1 + f_eval_catch $funcname gpart \ + "$GPART_ADD_INDEX_WITH_SIZE" \ + 1 freebsd-zfs ${bootsize}b ${disk}s1 || + return $FAILURE + # Pedantically nuke any old labels + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$bootpart if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - bootpart=s1a targetpart=s1d - partsize=$(( $partsize - $gelisize )) - mbrindex=4 # If this is s1a then make the zpool s1d - f_eval_catch $funcname gpart \ - "$GPART_ADD_INDEX_WITH_SIZE" \ - 1 freebsd-zfs ${gelisize}b ${disk}s1 || - return $FAILURE - # Pedantically nuke any old labels - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/$disk$bootpart # Pedantically detach targetpart for later f_eval_catch -d $funcname geli \ "$GELI_DETACH_F" \ @@ -815,28 +811,12 @@ zfs_create_diskpart() fi # - # 4. Partition the BSD slice for ZFS - # NOTE: Using above calculated partsize to leave room for swap. + # 4. Add freebsd-swap partition # if [ ${swapsize:-0} -gt 0 ]; then f_eval_catch $funcname gpart \ - "$GPART_ADD_INDEX_WITH_SIZE" \ - $mbrindex freebsd-zfs ${partsize}b \ - ${disk}s1 || return $FAILURE - else - f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ - $mbrindex freebsd-zfs ${disk}s1 || - return $FAILURE - fi - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/$disk$targetpart # Pedantic - - # - # 5. Add freebsd-swap partition - # - if [ $swapsize -gt 0 ]; then - f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ - 2 freebsd-swap \${disk}s1 || + "$GPART_ADD_INDEX_WITH_SIZE" 2 \ + freebsd-swap ${swapsize}b ${disk}s1 || return $FAILURE # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ @@ -844,6 +824,17 @@ zfs_create_diskpart() $BSDINSTALL_TMPETC/fstab || return $FAILURE fi + + # + # 5. Add freebsd-zfs partition for zroot + # + f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ + $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/$disk$targetpart # Pedantic + f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ + /boot/zfsboot /dev/${disk}s1 count=1 || + return $FAILURE ;; esac # $ZFSBOOT_PARTITION_SCHEME @@ -859,8 +850,10 @@ zfs_create_diskpart() zfs_create_boot() { local funcname=zfs_create_boot - local poolname="$1" vdev_type="$2" - local bootpart targetpart + local zroot_name="$1" + local zroot_vdevtype="$2" + local zroot_vdevs= # Calculated below + local boot_vdevs= # Used for geli(8) and/or MBR layouts shift 2 # poolname vdev_type local disks="$*" disk local bootpart targetpart # Set by zfs_create_diskpart() below @@ -868,7 +861,7 @@ zfs_create_boot() # # Pedantic checks; should never be seen # - if [ ! "$poolname" ]; then + if [ ! "$zroot_name" ]; then f_dprintf "$funcname: NULL poolname" msg_error="$msg_error: $funcname" \ f_show_err "$msg_null_poolname" @@ -881,7 +874,7 @@ zfs_create_boot() return $FAILURE fi f_dprintf "$funcname: poolname=[%s] vdev_type=[%s]" \ - "$poolname" "$vdev_type" + "$zroot_name" "$zroot_vdevtype" # # Initialize fstab(5) @@ -896,114 +889,114 @@ zfs_create_boot() # # Expand SI units in desired sizes # - f_dprintf "$funcname: Expanding supplied swapsize/gelisize values..." - local swapsize gelisize + f_dprintf "$funcname: Expanding supplied size values..." + local swapsize bootsize if ! f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize; then f_dprintf "$funcname: Invalid swap size \`%s'" \ "$ZFSBOOT_SWAP_SIZE" f_show_err "$msg_invalid_swap_size" "$ZFSBOOT_SWAP_SIZE" return $FAILURE fi - if ! f_expand_number "$ZFSBOOT_GELI_BOOT_SIZE" gelisize; then - f_dprintf "$funcname: Invalid geli(8) boot size \`%s'" \ - "$ZFSBOOT_GELI_BOOT_SIZE" - f_show_err "$msg_invalid_geli_boot_size" \ - "$ZFSBOOT_GELI_BOOT_SIZE" + if ! f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize; then + f_dprintf "$funcname: Invalid boot pool size \`%s'" \ + "$ZFSBOOT_BOOT_POOL_SIZE" + f_show_err "$msg_invalid_boot_pool_size" \ + "$ZFSBOOT_BOOT_POOL_SIZE" return $FAILURE fi f_dprintf "$funcname: ZFSBOOT_SWAP_SIZE=[%s] swapsize=[%s]" \ "$ZFSBOOT_SWAP_SIZE" "$swapsize" - f_dprintf "$funcname: ZFSBOOT_GELI_BOOT_SIZE=[%s] gelisize=[%s]" \ - "$ZFSBOOT_GELI_BOOT_SIZE" "$gelisize" + f_dprintf "$funcname: ZFSBOOT_BOOT_POOL_SIZE=[%s] bootsize=[%s]" \ + "$ZFSBOOT_BOOT_POOL_SIZE" "$bootsize" # - # Prepare the disks + # Prepare the disks and build pool device list(s) # f_dprintf "$funcname: Preparing disk partitions for ZFS pool..." + [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ] && + f_dprintf "$funcname: With 4k alignment using gnop(8)..." local n=0 for disk in $disks; do zfs_create_diskpart $disk $n || return $FAILURE - n=$(( $n + 1 )) - done - # Now $bootpart and $targetpart are set (suffix for $disk) - - # MBR boot loader hack part 1 - # We have to do this early because geli gets in the way later - if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then - f_dprintf "$funcname: Copying MBR boot loader to disks..." - for disk in $disks; do - f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /boot/zfsboot /dev/${disk}s1 count=1 || - return $FAILURE - done - fi - - # Forced 4k alignment support provided by Geom NOP (see gnop(8)) - local unenc_list= - if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then - local part="$targetpart" new_list= - - # We don't gnop the encrypted partition because geli will do - # this for us gnop the unencrypted disk - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && part="$bootpart" - - f_dprintf "$funcname: Applying 4k alignment with gnop(8)..." - for disk in $disks; do - f_eval_catch $funcname gnop "$GNOP_CREATE" \ - $disk$part || return $FAILURE - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - unenc_list="$unenc_list $disk$part.nop" - else - new_list="$new_list $disk$targetpart.nop" + # Now $bootpart and $targetpart are set (suffix for $disk) + + # Forced 4k alignment support using Geom NOP (see gnop(8)) + if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then + if [ "$ZFSBOOT_BOOT_POOL" ]; then + boot_vdevs="$boot_vdevs $disk$bootpart.nop" + f_eval_catch $funcname gnop "$GNOP_CREATE" \ + $disk$bootpart || return $FAILURE fi - done - set -- $new_list - else - local new_list= - for disk in $disks; do - new_list="$new_list $disk$targetpart" - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && - unenc_list="$unenc_list $disk$bootpart" - done - set -- $new_list - fi + # Don't gnop encrypted partition + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + zroot_vdevs="$zroot_vdevs $disk$targetpart.eli" + else + zroot_vdevs="$zroot_vdevs $disk$targetpart.nop" + f_eval_catch $funcname gnop "$GNOP_CREATE" \ + $disk$targetpart || + return $FAILURE + fi + else + if [ "$ZFSBOOT_BOOT_POOL" ]; then + boot_vdevs="$boot_vdevs $disk$bootpart" + fi + zroot_vdevs="$zroot_vdevs $disk$targetpart" + fi + + n=$(( $n + 1 )) + done # disks # - # If encryption is enabled, we need to create the GEOMs + # If we need/want a boot pool, create it # - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - local bootvdev= options= - local geli_pool="$BSDINSTALL_CHROOT/$ZFSBOOT_GELI_POOL_NAME" - local key="$ZFSBOOT_GELI_KEY_FILE" + if [ "$ZFSBOOT_BOOT_POOL" ]; then + local bootpool_vdevtype= # Calculated below + local bootpool_options= # Calculated below + local bootpool_name="$ZFSBOOT_BOOT_POOL_NAME" + local bootpool="$BSDINSTALL_CHROOT/$bootpool_name" + local zroot_key="${ZFSBOOT_GELI_KEY_FILE#/}" - f_dprintf "$funcname: Setting up disk encryption..." + f_dprintf "$funcname: Setting up boot pool..." + [ "$ZFSBOOT_GELI_ENCRYPTION" ] && + f_dprintf "$funcname: For encrypted root disk..." - # Create the parent directories for our unencrypted pool + # Create parent directory for boot pool f_eval_catch -d $funcname umount "$UMOUNT" /mnt f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \ $BSDINSTALL_CHROOT || return $FAILURE - # Create mirror across the unencrypted partition on all disks - [ $( set -- $unenc_list; echo $# ) -gt 1 ] && bootvdev=mirror + # Create mirror across the boot partition on all disks + [ $( set -- $boot_vdevs; echo $# ) -gt 1 ] && + bootpool_vdevtype=mirror - options="-o altroot=$BSDINSTALL_CHROOT" - options="$options -m \"/$ZFSBOOT_GELI_POOL_NAME\" -f" + bootpool_options="-o altroot=$BSDINSTALL_CHROOT" + bootpool_options="$bootpool_options -m \"/$bootpool_name\" -f" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ - "$options" "$ZFSBOOT_GELI_POOL_NAME" $bootvdev \ - \$unenc_list || return $FAILURE + "$bootpool_options" "$bootpool_name" \ + $bootpool_vdevtype $boot_vdevs || return $FAILURE - f_eval_catch $funcname mkdir "$MKDIR_P" $geli_pool/boot || + f_eval_catch $funcname mkdir "$MKDIR_P" "$bootpool/boot" || return $FAILURE - # Generate an encryption key using random(4) - f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /dev/random $geli_pool/$key "bs=4096 count=1" || - return $FAILURE + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + # Generate an encryption key using random(4) + f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ + /dev/random "$bootpool/$zroot_key" \ + "bs=4096 count=1" || return $FAILURE + else + # Clean up + f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \ + "$bootpool_name" || return $FAILURE + f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs + fi - # - # Create the geli(8) GEOMS - # - local geli_list + fi + + # + # Create the geli(8) GEOMS + # + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + # Prompt user for password (twice) if ! msg_enter_new_password="$msg_geli_password" \ f_dialog_input_password then @@ -1018,8 +1011,8 @@ zfs_create_boot() 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD if ! echo "$pw_password" | f_eval_catch \ $funcname geli "$GELI_PASSWORD_INIT" \ - "$geli_pool/boot/$disk$targetpart.eli" \ - AES-XTS "$geli_pool/$key" \ + "$bootpool/boot/$disk$targetpart.eli" \ + AES-XTS "$bootpool/$zroot_key" \ $disk$targetpart then f_interactive || f_die @@ -1028,42 +1021,39 @@ zfs_create_boot() fi if ! echo "$pw_password" | f_eval_catch \ $funcname geli "$GELI_ATTACH" \ - "$geli_pool/\$key" $disk$targetpart + "$bootpool/$zroot_key" $disk$targetpart then f_interactive || f_die unset pw_password # Sensitive info return $FAILURE fi - geli_list="$geli_list $disk$targetpart.eli" done unset pw_password # Sensitive info - set -- $geli_list # Clean up - f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \ - "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE + f_eval_catch $funcname zfs "$ZFS_UNMOUNT" "$bootpool_name" || + return $FAILURE f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs fi # # Create the ZFS root pool with desired type and disk devices # - local vdevs="$*" - f_dprintf "$funcname: Creating boot pool..." + f_dprintf "$funcname: Creating root pool..." f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ "-o altroot=$BSDINSTALL_CHROOT -m none -f" \ - $poolname $vdev_type $vdevs + "$zroot_name" $zroot_vdevtype $zroot_vdevs - # Customize the zpool a bit... + # Customize the zroot a bit... local option - f_dprintf "$funcname: Setting miscellaneous options on boot pool..." + f_dprintf "$funcname: Setting miscellaneous options on root pool..." for option in checksum=fletcher4 atime=off; do - f_eval_catch $funcname zfs "$ZFS_SET" $option "$poolname" || + f_eval_catch $funcname zfs "$ZFS_SET" $option "$zroot_name" || return $FAILURE done # - # Create ZFS dataset layout within the new boot pool + # Create ZFS dataset layout within the new root pool # f_dprintf "$funcname: Creating ZFS datasets..." echo "$ZFSBOOT_DATASETS" | while read dataset options; do @@ -1083,7 +1073,7 @@ zfs_create_boot() f_replaceall "$options" "[ ,]" " -o " options # Create the dataset with desired options f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \ - "${options:+-o $options}" "$poolname$dataset" || + "${options:+-o $options}" "$zroot_name$dataset" || return $FAILURE done @@ -1096,40 +1086,41 @@ zfs_create_boot() done # Create symlink(s) - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - f_dprintf "$funcname: Creating /boot symlink for GELI..." - f_eval_catch $funcname ln "$LN_SF" \ - "$ZFSBOOT_GELI_POOL_NAME/boot" \ + if [ "$ZFSBOOT_BOOT_POOL" ]; then + f_dprintf "$funcname: Creating /boot symlink for boot pool..." + f_eval_catch $funcname ln "$LN_SF" "$bootpool_name/boot" \ $BSDINSTALL_CHROOT/boot || return $FAILURE fi # Set bootfs property + local zroot_bootfs="$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME" f_dprintf "$funcname: Setting bootfs property..." f_eval_catch $funcname zpool "$ZPOOL_SET" \ - "bootfs=\"$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME\"" \ - "$poolname" || return $FAILURE + "bootfs=\"$zroot_name/$zroot_bootfs\"" "$zroot_name" || + return $FAILURE # Export the pool(s) f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..." - f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$poolname" || + f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$zroot_name" || return $FAILURE - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \ - "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE + "$bootpool_name" || return $FAILURE fi # Destroy the gnop devices (if enabled) for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$disks}; do - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \ $disk$bootpart.nop - else + fi + if [ ! "$ZFSBOOT_GELI_ENCRYPTION" ]; then f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \ $disk$targetpart.nop fi done - # MBR boot loader hack part 2 + # MBR boot loader touch-up if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then f_dprintf "$funcname: Updating MBR boot loader on disks..." # Stick the ZFS boot loader in the "convienient hole" after @@ -1144,12 +1135,12 @@ zfs_create_boot() # Re-import the ZFS pool(s) f_dprintf "$funcname: Re-importing ZFS pool(s)..." f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ - "-o altroot=\"$BSDINSTALL_CHROOT\"" "$poolname" || + "-o altroot=\"$BSDINSTALL_CHROOT\"" "$zroot_name" || return $FAILURE - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ - "-o altroot=\"\$BSDINSTALL_CHROOT\"" \ - "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE + "-o altroot=\"$BSDINSTALL_CHROOT\"" \ + "$bootpool_name" || return $FAILURE fi # While this is apparently not needed, it seems to help MBR @@ -1158,7 +1149,7 @@ zfs_create_boot() return $FAILURE f_eval_catch $funcname zpool "$ZPOOL_SET" \ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \ - "$poolname" || return $FAILURE + "$zroot_name" || return $FAILURE # Last, but not least... required lines for rc.conf(5)/loader.conf(5) # NOTE: We later concatenate these into their destination @@ -1169,8 +1160,8 @@ zfs_create_boot() f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE - # We're all done unless we should go on to do encryption - [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS + # We're all done unless we should go on for boot pool + [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS # Some additional geli(8) requirements for loader.conf(5) for option in \ @@ -1182,6 +1173,12 @@ zfs_create_boot() $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE done + f_eval_catch $funcname printf "$PRINTF_CONF" vfs.root.mountfrom \ + "\"zfs:$zroot_name/$zroot_bootfs\"" \ + $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE + + # We're all done unless we should go on to do encryption + [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS # # Configure geli(8)-based encryption @@ -1191,9 +1188,6 @@ zfs_create_boot() $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" 'geom_eli_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE - f_eval_catch $funcname printf "$PRINTF_CONF" vfs.root.mountfrom \ - "\"zfs:$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME\"" \ - $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE for disk in $disks; do f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_load "$disk$targetpart YES" \ @@ -1294,11 +1288,11 @@ while :; do # Make sure each disk will be at least 50% ZFS if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize && - f_expand_number "$ZFSBOOT_GELI_BOOT_SIZE" gelisize + f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize then minsize=$swapsize teeny_disks= - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && - minsize=$(( $minsize + $gelisize )) + [ "$ZFSBOOT_BOOT_POOL" ] && + minsize=$(( $minsize + $bootsize )) for disk in $ZFSBOOT_DISKS; do device_$disk get capacity disksize || continue disksize=$(( $disksize - $minsize )) @@ -1306,14 +1300,15 @@ while :; do teeny_disks="$teeny_disks $disk" done if [ "$teeny_disks" ]; then - f_dprintf "swapsize=[%s] gelisize[%s]" \ + f_dprintf "swapsize=[%s] bootsize[%s] %s" \ "$ZFSBOOT_SWAP_SIZE" \ - "$ZFSBOOT_GELI_BOOT_SIZE" + "$ZFSBOOT_BOOT_POOL_SIZE" \ + "minsize=[$minsize]" f_dprintf "These disks are too small: %s" \ "$teeny_disks" f_show_err "$msg_these_disks_are_too_small" \ "$ZFSBOOT_SWAP_SIZE" \ - "$ZFSBOOT_GELI_BOOT_SIZE" \ + "$ZFSBOOT_BOOT_POOL_SIZE" \ "$teeny_disks" continue fi From ca2d97c2c866a7b1cc42034a2f289b51da8b446f Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:43:04 +0000 Subject: [PATCH 093/172] fletcher4 is currently the default. Discussed on: -current MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index a274cf55bbd1..f3f66566eb05 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -1047,7 +1047,7 @@ zfs_create_boot() # Customize the zroot a bit... local option f_dprintf "$funcname: Setting miscellaneous options on root pool..." - for option in checksum=fletcher4 atime=off; do + for option in atime=off; do f_eval_catch $funcname zfs "$ZFS_SET" $option "$zroot_name" || return $FAILURE done From 7a434c5cc727a9753087b567d2e77de34ce59467 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:44:45 +0000 Subject: [PATCH 094/172] De-uglify the geli(8)-setup infobox by adding a newline. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index f3f66566eb05..62d51d415aa3 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -215,7 +215,7 @@ msg_force_4k_sectors="Force 4K Sectors?" msg_force_4k_sectors_help="Use gnop(8) to configure forced 4K sector alignment" msg_freebsd_installer="FreeBSD Installer" msg_geli_password="Enter a strong passphrase, used to protect your encryption keys. You will be required to enter this passphrase each time the system is booted" -msg_geli_setup="Initializing encryption on the selected disks, this will take several seconds per disk" +msg_geli_setup="Initializing encryption on selected disks,\n this will take several seconds per disk" msg_install="Install" msg_install_desc="Proceed with Installation" msg_install_help="Create ZFS boot pool with displayed options" From ee482f2c28e5675eba7f868427a4750c3121c57a Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:47:04 +0000 Subject: [PATCH 095/172] Add kern.geom.label.disk_ident.enable="0" to loader.conf(5). Discussed on: -current, -stable MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 62d51d415aa3..61e896acd929 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -1159,6 +1159,9 @@ zfs_create_boot() $BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE + f_eval_catch $funcname echo "$ECHO_APPEND" \ + 'kern.geom.label.disk_ident.enable=\"0\"' \ + $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE # We're all done unless we should go on for boot pool [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS From cf9c3e5697bc69f08820d7e3b7a4c21f989a7f64 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:51:11 +0000 Subject: [PATCH 096/172] Fix a long-standing edge-case that would result in a ghosted `zroot' pool and subsequent headaches caused by multiple pools with the same name. Specifically, blast away any labels on the designated swap partition. Problem was when you install to a given layout *with* swap and then turn around and re-install the same layout *without* swap (we weren't doing a labelclear for the swap device, so would end up with an "UNAVAIL" status zroot pool that may only exist in the pool cache). MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 61e896acd929..2645d6d97300 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -745,6 +745,9 @@ zfs_create_diskpart() "$GPART_ADD_LABEL_WITH_SIZE" swap$index \ freebsd-swap ${swapsize}b $disk || return $FAILURE + # Pedantically nuke any old labels on the swap + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/gpt/swap$index # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/gpt/swap$index none swap sw 0 0 \ @@ -818,6 +821,9 @@ zfs_create_diskpart() "$GPART_ADD_INDEX_WITH_SIZE" 2 \ freebsd-swap ${swapsize}b ${disk}s1 || return $FAILURE + # Pedantically nuke any old labels on the swap + f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ + /dev/${disk}s1b # Update fstab(5) f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/${disk}s1b none swap sw 0 0 \ From 926ec73fe2ee856832809aae43d1089b107341ae Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 16 Dec 2013 19:54:55 +0000 Subject: [PATCH 097/172] Auto-enable 4k sector alignment when disk encryption is requested (it is required in such a case). But don't prevent the user from pointing the gun at his/her foot -- you can disable 4k alignment after enabling geli). MFC after: 3 days --- usr.sbin/bsdinstall/scripts/zfsboot | 1 + 1 file changed, 1 insertion(+) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 2645d6d97300..2a0460a89d7b 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -1372,6 +1372,7 @@ while :; do if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then ZFSBOOT_GELI_ENCRYPTION= else + ZFSBOOT_GNOP_4K_FORCE_ALIGN=1 ZFSBOOT_GELI_ENCRYPTION=1 fi ;; From 4f8be175d57e157601e0f6a22685d4e6a64b61ad Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Mon, 16 Dec 2013 19:59:31 +0000 Subject: [PATCH 098/172] Add an API to deliver message signalled interrupts to vcpus. This allows callers treat the MSI 'addr' and 'data' fields as opaque and also lets bhyve implement multiple destination modes: physical, flat and clustered. Submitted by: Tycho Nightingale (tycho.nightingale@pluribusnetworks.com) Reviewed by: grehan@ --- lib/libvmmapi/vmmapi.c | 20 ++- lib/libvmmapi/vmmapi.h | 5 +- sys/amd64/include/vmm_dev.h | 14 ++- sys/amd64/vmm/io/ppt.c | 24 ++-- sys/amd64/vmm/io/ppt.h | 4 +- sys/amd64/vmm/io/vhpet.c | 25 +--- sys/amd64/vmm/io/vioapic.c | 58 ++------- sys/amd64/vmm/io/vlapic.c | 224 ++++++++++++++++++++++++++++++++-- sys/amd64/vmm/io/vlapic.h | 2 + sys/amd64/vmm/vmm_dev.c | 11 +- sys/amd64/vmm/vmm_lapic.c | 47 +++++++ sys/amd64/vmm/vmm_lapic.h | 1 + usr.sbin/bhyve/pci_emul.c | 33 ++--- usr.sbin/bhyve/pci_emul.h | 8 +- usr.sbin/bhyve/pci_passthru.c | 26 ++-- 15 files changed, 359 insertions(+), 143 deletions(-) diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index c2851a4cd6b4..9d15175452a7 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -396,6 +396,18 @@ vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector) return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq)); } +int +vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg) +{ + struct vm_lapic_msi vmmsi; + + bzero(&vmmsi, sizeof(vmmsi)); + vmmsi.addr = addr; + vmmsi.msg = msg; + + return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi)); +} + int vm_ioapic_assert_irq(struct vmctx *ctx, int irq) { @@ -552,7 +564,7 @@ vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func, int vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int destcpu, int vector, int numvec) + uint64_t addr, uint64_t msg, int numvec) { struct vm_pptdev_msi pptmsi; @@ -561,8 +573,8 @@ vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, pptmsi.bus = bus; pptmsi.slot = slot; pptmsi.func = func; - pptmsi.destcpu = destcpu; - pptmsi.vector = vector; + pptmsi.msg = msg; + pptmsi.addr = addr; pptmsi.numvec = numvec; return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi)); @@ -570,7 +582,7 @@ vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, int vm_setup_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int idx, uint32_t msg, uint32_t vector_control, uint64_t addr) + int idx, uint64_t addr, uint64_t msg, uint32_t vector_control) { struct vm_pptdev_msix pptmsix; diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index 293c4311ed3a..6de584d69b5e 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -67,6 +67,7 @@ int vm_inject_event(struct vmctx *ctx, int vcpu, enum vm_event_type type, int vm_inject_event2(struct vmctx *ctx, int vcpu, enum vm_event_type type, int vector, int error_code); int vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector); +int vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg); int vm_ioapic_assert_irq(struct vmctx *ctx, int irq); int vm_ioapic_deassert_irq(struct vmctx *ctx, int irq); int vm_ioapic_pulse_irq(struct vmctx *ctx, int irq); @@ -82,9 +83,9 @@ int vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func); int vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int dest, int vector, int numvec); + uint64_t addr, uint64_t msg, int numvec); int vm_setup_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int idx, uint32_t msg, uint32_t vector_control, uint64_t addr); + int idx, uint64_t addr, uint64_t msg, uint32_t vector_control); /* * Return a pointer to the statistics buffer. Note that this is not MT-safe. diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index 19a5b0221629..b71b745795e9 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -66,6 +66,11 @@ struct vm_event { int error_code_valid; }; +struct vm_lapic_msi { + uint64_t msg; + uint64_t addr; +}; + struct vm_lapic_irq { int cpuid; int vector; @@ -103,8 +108,8 @@ struct vm_pptdev_msi { int slot; int func; int numvec; /* 0 means disabled */ - int vector; - int destcpu; + uint64_t msg; + uint64_t addr; }; struct vm_pptdev_msix { @@ -113,7 +118,7 @@ struct vm_pptdev_msix { int slot; int func; int idx; - uint32_t msg; + uint64_t msg; uint32_t vector_control; uint64_t addr; }; @@ -175,6 +180,7 @@ enum { IOCNUM_IOAPIC_ASSERT_IRQ = 33, IOCNUM_IOAPIC_DEASSERT_IRQ = 34, IOCNUM_IOAPIC_PULSE_IRQ = 35, + IOCNUM_LAPIC_MSI = 36, /* PCI pass-thru */ IOCNUM_BIND_PPTDEV = 40, @@ -211,6 +217,8 @@ enum { _IOW('v', IOCNUM_INJECT_EVENT, struct vm_event) #define VM_LAPIC_IRQ \ _IOW('v', IOCNUM_LAPIC_IRQ, struct vm_lapic_irq) +#define VM_LAPIC_MSI \ + _IOW('v', IOCNUM_LAPIC_MSI, struct vm_lapic_msi) #define VM_IOAPIC_ASSERT_IRQ \ _IOW('v', IOCNUM_IOAPIC_ASSERT_IRQ, struct vm_ioapic_irq) #define VM_IOAPIC_DEASSERT_IRQ \ diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index fce4bbd34ad2..32d59a0fbb50 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -72,8 +72,8 @@ MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources"); struct pptintr_arg { /* pptintr(pptintr_arg) */ struct pptdev *pptdev; - int vec; - int vcpu; + uint64_t addr; + uint64_t msg_data; }; static struct pptdev { @@ -412,16 +412,14 @@ ppt_map_mmio(struct vm *vm, int bus, int slot, int func, static int pptintr(void *arg) { - int vec; struct pptdev *ppt; struct pptintr_arg *pptarg; pptarg = arg; ppt = pptarg->pptdev; - vec = pptarg->vec; if (ppt->vm != NULL) - lapic_intr_edge(ppt->vm, pptarg->vcpu, vec); + lapic_intr_msi(ppt->vm, pptarg->addr, pptarg->msg_data); else { /* * XXX @@ -441,15 +439,13 @@ pptintr(void *arg) int ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, - int destcpu, int vector, int numvec) + uint64_t addr, uint64_t msg, int numvec) { int i, rid, flags; int msi_count, startrid, error, tmp; struct pptdev *ppt; - if ((destcpu >= VM_MAXCPU || destcpu < 0) || - (vector < 0 || vector > 255) || - (numvec < 0 || numvec > MAX_MSIMSGS)) + if (numvec < 0 || numvec > MAX_MSIMSGS) return (EINVAL); ppt = ppt_find(bus, slot, func); @@ -513,8 +509,8 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, break; ppt->msi.arg[i].pptdev = ppt; - ppt->msi.arg[i].vec = vector + i; - ppt->msi.arg[i].vcpu = destcpu; + ppt->msi.arg[i].addr = addr; + ppt->msi.arg[i].msg_data = msg + i; error = bus_setup_intr(ppt->dev, ppt->msi.res[i], INTR_TYPE_NET | INTR_MPSAFE, @@ -534,7 +530,7 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, int ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func, - int idx, uint32_t msg, uint32_t vector_control, uint64_t addr) + int idx, uint64_t addr, uint64_t msg, uint32_t vector_control) { struct pptdev *ppt; struct pci_devinfo *dinfo; @@ -605,8 +601,8 @@ ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func, return (ENXIO); ppt->msix.arg[idx].pptdev = ppt; - ppt->msix.arg[idx].vec = msg & 0xFF; - ppt->msix.arg[idx].vcpu = (addr >> 12) & 0xFF; + ppt->msix.arg[idx].addr = addr; + ppt->msix.arg[idx].msg_data = msg; /* Setup the MSI-X interrupt */ error = bus_setup_intr(ppt->dev, ppt->msix.res[idx], diff --git a/sys/amd64/vmm/io/ppt.h b/sys/amd64/vmm/io/ppt.h index 7670bc44fdfb..45ba323aa9aa 100644 --- a/sys/amd64/vmm/io/ppt.h +++ b/sys/amd64/vmm/io/ppt.h @@ -33,9 +33,9 @@ int ppt_unassign_all(struct vm *vm); int ppt_map_mmio(struct vm *vm, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, - int destcpu, int vector, int numvec); + uint64_t addr, uint64_t msg, int numvec); int ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func, - int idx, uint32_t msg, uint32_t vector_control, uint64_t addr); + int idx, uint64_t addr, uint64_t msg, uint32_t vector_control); int ppt_num_devices(struct vm *vm); boolean_t ppt_is_mmio(struct vm *vm, vm_paddr_t gpa); diff --git a/sys/amd64/vmm/io/vhpet.c b/sys/amd64/vmm/io/vhpet.c index 112480ee859d..929b34343311 100644 --- a/sys/amd64/vmm/io/vhpet.c +++ b/sys/amd64/vmm/io/vhpet.c @@ -240,8 +240,7 @@ vhpet_timer_edge_trig(struct vhpet *vhpet, int n) static void vhpet_timer_interrupt(struct vhpet *vhpet, int n) { - int apicid, vector, vcpuid, pin; - cpuset_t dmask; + int pin; /* If interrupts are not enabled for this timer then just return. */ if (!vhpet_timer_interrupt_enabled(vhpet, n)) @@ -256,26 +255,8 @@ vhpet_timer_interrupt(struct vhpet *vhpet, int n) } if (vhpet_timer_msi_enabled(vhpet, n)) { - /* - * XXX should have an API 'vlapic_deliver_msi(vm, addr, data)' - * - assuming physical delivery mode - * - no need to interpret contents of 'msireg' here - */ - vector = vhpet->timer[n].msireg & 0xff; - apicid = (vhpet->timer[n].msireg >> (32 + 12)) & 0xff; - if (apicid != 0xff) { - /* unicast */ - vcpuid = vm_apicid2vcpuid(vhpet->vm, apicid); - lapic_intr_edge(vhpet->vm, vcpuid, vector); - } else { - /* broadcast */ - dmask = vm_active_cpus(vhpet->vm); - while ((vcpuid = CPU_FFS(&dmask)) != 0) { - vcpuid--; - CPU_CLR(vcpuid, &dmask); - lapic_intr_edge(vhpet->vm, vcpuid, vector); - } - } + lapic_intr_msi(vhpet->vm, vhpet->timer[n].msireg >> 32, + vhpet->timer[n].msireg & 0xffffffff); return; } diff --git a/sys/amd64/vmm/io/vioapic.c b/sys/amd64/vmm/io/vioapic.c index 167e8ab9a1b8..151065a96cf4 100644 --- a/sys/amd64/vmm/io/vioapic.c +++ b/sys/amd64/vmm/io/vioapic.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include "vmm_ktr.h" #include "vmm_lapic.h" +#include "vlapic.h" #include "vioapic.h" #define IOREGSEL 0x00 @@ -91,25 +92,14 @@ pinstate_str(bool asserted) else return ("deasserted"); } - -static const char * -trigger_str(bool level) -{ - - if (level) - return ("level"); - else - return ("edge"); -} #endif static void vioapic_send_intr(struct vioapic *vioapic, int pin) { - int vector, apicid, vcpuid; - uint32_t low, high; - cpuset_t dmask; - bool level; + int vector, delmode; + uint32_t low, high, dest; + bool level, phys; KASSERT(pin >= 0 && pin < REDIR_ENTRIES, ("vioapic_set_pinstate: invalid pin number %d", pin)); @@ -120,52 +110,20 @@ vioapic_send_intr(struct vioapic *vioapic, int pin) low = vioapic->rtbl[pin].reg; high = vioapic->rtbl[pin].reg >> 32; - /* - * XXX We only deal with: - * - physical destination - * - fixed delivery mode - */ - if ((low & IOART_DESTMOD) != IOART_DESTPHY) { - VIOAPIC_CTR2(vioapic, "ioapic pin%d: unsupported dest mode " - "0x%08x", pin, low); - return; - } - - if ((low & IOART_DELMOD) != IOART_DELFIXED) { - VIOAPIC_CTR2(vioapic, "ioapic pin%d: unsupported delivery mode " - "0x%08x", pin, low); - return; - } - if ((low & IOART_INTMASK) == IOART_INTMSET) { VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", pin); return; } + phys = ((low & IOART_DESTMOD) == IOART_DESTPHY); + delmode = low & IOART_DELMOD; level = low & IOART_TRGRLVL ? true : false; if (level) vioapic->rtbl[pin].reg |= IOART_REM_IRR; vector = low & IOART_INTVEC; - apicid = high >> APIC_ID_SHIFT; - if (apicid != 0xff) { - /* unicast */ - vcpuid = vm_apicid2vcpuid(vioapic->vm, apicid); - VIOAPIC_CTR4(vioapic, "ioapic pin%d: %s triggered intr " - "vector %d on vcpuid %d", pin, trigger_str(level), - vector, vcpuid); - lapic_set_intr(vioapic->vm, vcpuid, vector, level); - } else { - /* broadcast */ - VIOAPIC_CTR3(vioapic, "ioapic pin%d: %s triggered intr " - "vector %d on all vcpus", pin, trigger_str(level), vector); - dmask = vm_active_cpus(vioapic->vm); - while ((vcpuid = CPU_FFS(&dmask)) != 0) { - vcpuid--; - CPU_CLR(vcpuid, &dmask); - lapic_set_intr(vioapic->vm, vcpuid, vector, level); - } - } + dest = high >> APIC_ID_SHIFT; + vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector); } static void diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index 71bc1424f745..4a5f5033e55a 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -145,6 +145,84 @@ struct vlapic { #define VLAPIC_BUS_FREQ tsc_freq +static __inline uint32_t +vlapic_get_id(struct vlapic *vlapic) +{ + + if (x2apic(vlapic)) + return (vlapic->vcpuid); + else + return (vlapic->vcpuid << 24); +} + +static __inline uint32_t +vlapic_get_ldr(struct vlapic *vlapic) +{ + struct LAPIC *lapic; + int apicid; + uint32_t ldr; + + lapic = &vlapic->apic; + if (x2apic(vlapic)) { + apicid = vlapic_get_id(vlapic); + ldr = 1 << (apicid & 0xf); + ldr |= (apicid & 0xffff0) << 12; + return (ldr); + } else + return (lapic->ldr); +} + +static __inline uint32_t +vlapic_get_dfr(struct vlapic *vlapic) +{ + struct LAPIC *lapic; + + lapic = &vlapic->apic; + if (x2apic(vlapic)) + return (0); + else + return (lapic->dfr); +} + +static void +vlapic_set_dfr(struct vlapic *vlapic, uint32_t data) +{ + uint32_t dfr; + struct LAPIC *lapic; + + if (x2apic(vlapic)) { + VM_CTR1(vlapic->vm, "write to DFR in x2apic mode: %#x", data); + return; + } + + lapic = &vlapic->apic; + dfr = (lapic->dfr & APIC_DFR_RESERVED) | (data & APIC_DFR_MODEL_MASK); + if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_FLAT) + VLAPIC_CTR0(vlapic, "vlapic DFR in Flat Model"); + else if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_CLUSTER) + VLAPIC_CTR0(vlapic, "vlapic DFR in Cluster Model"); + else + VLAPIC_CTR1(vlapic, "vlapic DFR in Unknown Model %#x", dfr); + + lapic->dfr = dfr; +} + +static void +vlapic_set_ldr(struct vlapic *vlapic, uint32_t data) +{ + struct LAPIC *lapic; + + /* LDR is read-only in x2apic mode */ + if (x2apic(vlapic)) { + VLAPIC_CTR1(vlapic, "write to LDR in x2apic mode: %#x", data); + return; + } + + lapic = &vlapic->apic; + lapic->ldr = data & ~APIC_LDR_RESERVED; + VLAPIC_CTR1(vlapic, "vlapic LDR set to %#x", lapic->ldr); +} + static int vlapic_timer_divisor(uint32_t dcr) { @@ -610,12 +688,115 @@ vlapic_set_icr_timer(struct vlapic *vlapic, uint32_t icr_timer) VLAPIC_TIMER_UNLOCK(vlapic); } +/* + * This function populates 'dmask' with the set of vcpus that match the + * addressing specified by the (dest, phys, lowprio) tuple. + * + * 'x2apic_dest' specifies whether 'dest' is interpreted as x2APIC (32-bit) + * or xAPIC (8-bit) destination field. + */ +static void +vlapic_calcdest(struct vm *vm, cpuset_t *dmask, uint32_t dest, bool phys, + bool lowprio, bool x2apic_dest) +{ + struct vlapic *vlapic; + uint32_t dfr, ldr, ldest, cluster; + uint32_t mda_flat_ldest, mda_cluster_ldest, mda_ldest, mda_cluster_id; + cpuset_t amask; + int vcpuid; + + if ((x2apic_dest && dest == 0xffffffff) || + (!x2apic_dest && dest == 0xff)) { + /* + * Broadcast in both logical and physical modes. + */ + *dmask = vm_active_cpus(vm); + return; + } + + if (phys) { + /* + * Physical mode: destination is APIC ID. + */ + CPU_ZERO(dmask); + vcpuid = vm_apicid2vcpuid(vm, dest); + if (vcpuid < VM_MAXCPU) + CPU_SET(vcpuid, dmask); + } else { + /* + * In the "Flat Model" the MDA is interpreted as an 8-bit wide + * bitmask. This model is only avilable in the xAPIC mode. + */ + mda_flat_ldest = dest & 0xff; + + /* + * In the "Cluster Model" the MDA is used to identify a + * specific cluster and a set of APICs in that cluster. + */ + if (x2apic_dest) { + mda_cluster_id = dest >> 16; + mda_cluster_ldest = dest & 0xffff; + } else { + mda_cluster_id = (dest >> 4) & 0xf; + mda_cluster_ldest = dest & 0xf; + } + + /* + * Logical mode: match each APIC that has a bit set + * in it's LDR that matches a bit in the ldest. + */ + CPU_ZERO(dmask); + amask = vm_active_cpus(vm); + while ((vcpuid = CPU_FFS(&amask)) != 0) { + vcpuid--; + CPU_CLR(vcpuid, &amask); + + vlapic = vm_lapic(vm, vcpuid); + dfr = vlapic_get_dfr(vlapic); + ldr = vlapic_get_ldr(vlapic); + + if ((dfr & APIC_DFR_MODEL_MASK) == + APIC_DFR_MODEL_FLAT) { + ldest = ldr >> 24; + mda_ldest = mda_flat_ldest; + } else if ((dfr & APIC_DFR_MODEL_MASK) == + APIC_DFR_MODEL_CLUSTER) { + if (x2apic(vlapic)) { + cluster = ldr >> 16; + ldest = ldr & 0xffff; + } else { + cluster = ldr >> 28; + ldest = (ldr >> 24) & 0xf; + } + if (cluster != mda_cluster_id) + continue; + mda_ldest = mda_cluster_ldest; + } else { + /* + * Guest has configured a bad logical + * model for this vcpu - skip it. + */ + VLAPIC_CTR1(vlapic, "vlapic has bad logical " + "model %x - cannot deliver interrupt", dfr); + continue; + } + + if ((mda_ldest & ldest) != 0) { + CPU_SET(vcpuid, dmask); + if (lowprio) + break; + } + } + } +} + static VMM_STAT_ARRAY(IPIS_SENT, VM_MAXCPU, "ipis sent to vcpu"); static int lapic_process_icr(struct vlapic *vlapic, uint64_t icrval, bool *retu) { int i; + bool phys; cpuset_t dmask; uint32_t dest, vec, mode; struct vlapic *vlapic2; @@ -631,7 +812,9 @@ lapic_process_icr(struct vlapic *vlapic, uint64_t icrval, bool *retu) if (mode == APIC_DELMODE_FIXED || mode == APIC_DELMODE_NMI) { switch (icrval & APIC_DEST_MASK) { case APIC_DEST_DESTFLD: - CPU_SETOF(dest, &dmask); + phys = ((icrval & APIC_DESTMODE_LOG) == 0); + vlapic_calcdest(vlapic->vm, &dmask, dest, phys, false, + x2apic(vlapic)); break; case APIC_DEST_SELF: CPU_SETOF(vlapic->vcpuid, &dmask); @@ -820,10 +1003,7 @@ vlapic_read(struct vlapic *vlapic, uint64_t offset, uint64_t *data, bool *retu) switch(offset) { case APIC_OFFSET_ID: - if (x2apic(vlapic)) - *data = vlapic->vcpuid; - else - *data = vlapic->vcpuid << 24; + *data = vlapic_get_id(vlapic); break; case APIC_OFFSET_VER: *data = lapic->version; @@ -841,10 +1021,10 @@ vlapic_read(struct vlapic *vlapic, uint64_t offset, uint64_t *data, bool *retu) *data = lapic->eoi; break; case APIC_OFFSET_LDR: - *data = lapic->ldr; + *data = vlapic_get_ldr(vlapic); break; case APIC_OFFSET_DFR: - *data = lapic->dfr; + *data = vlapic_get_dfr(vlapic); break; case APIC_OFFSET_SVR: *data = lapic->svr; @@ -921,8 +1101,10 @@ vlapic_write(struct vlapic *vlapic, uint64_t offset, uint64_t data, bool *retu) vlapic_process_eoi(vlapic); break; case APIC_OFFSET_LDR: + vlapic_set_ldr(vlapic, data); break; case APIC_OFFSET_DFR: + vlapic_set_dfr(vlapic, data); break; case APIC_OFFSET_SVR: lapic_set_svr(vlapic, data); @@ -1041,6 +1223,34 @@ vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state) vlapic->msr_apicbase &= ~APICBASE_X2APIC; } +void +vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, + int delmode, int vec) +{ + bool lowprio; + int vcpuid; + cpuset_t dmask; + + if (delmode != APIC_DELMODE_FIXED && delmode != APIC_DELMODE_LOWPRIO) { + VM_CTR1(vm, "vlapic intr invalid delmode %#x", delmode); + return; + } + lowprio = (delmode == APIC_DELMODE_LOWPRIO); + + /* + * We don't provide any virtual interrupt redirection hardware so + * all interrupts originating from the ioapic or MSI specify the + * 'dest' in the legacy xAPIC format. + */ + vlapic_calcdest(vm, &dmask, dest, phys, lowprio, false); + + while ((vcpuid = CPU_FFS(&dmask)) != 0) { + vcpuid--; + CPU_CLR(vcpuid, &dmask); + lapic_set_intr(vm, vcpuid, vec, level); + } +} + bool vlapic_enabled(struct vlapic *vlapic) { diff --git a/sys/amd64/vmm/io/vlapic.h b/sys/amd64/vmm/io/vlapic.h index d88fa71dd7e8..f66994074c35 100644 --- a/sys/amd64/vmm/io/vlapic.h +++ b/sys/amd64/vmm/io/vlapic.h @@ -103,4 +103,6 @@ void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val); void vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state s); bool vlapic_enabled(struct vlapic *vlapic); +void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, + int delmode, int vec); #endif /* _VLAPIC_H_ */ diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index f248f685bb81..c3f25deeb509 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -152,6 +152,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct vm_run *vmrun; struct vm_event *vmevent; struct vm_lapic_irq *vmirq; + struct vm_lapic_msi *vmmsi; struct vm_ioapic_irq *ioapic_irq; struct vm_capability *vmcap; struct vm_pptdev *pptdev; @@ -254,7 +255,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, pptmsi = (struct vm_pptdev_msi *)data; error = ppt_setup_msi(sc->vm, pptmsi->vcpu, pptmsi->bus, pptmsi->slot, pptmsi->func, - pptmsi->destcpu, pptmsi->vector, + pptmsi->addr, pptmsi->msg, pptmsi->numvec); break; case VM_PPTDEV_MSIX: @@ -262,8 +263,8 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, error = ppt_setup_msix(sc->vm, pptmsix->vcpu, pptmsix->bus, pptmsix->slot, pptmsix->func, pptmsix->idx, - pptmsix->msg, pptmsix->vector_control, - pptmsix->addr); + pptmsix->addr, pptmsix->msg, + pptmsix->vector_control); break; case VM_MAP_PPTDEV_MMIO: pptmmio = (struct vm_pptdev_mmio *)data; @@ -296,6 +297,10 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, vmirq = (struct vm_lapic_irq *)data; error = lapic_intr_edge(sc->vm, vmirq->cpuid, vmirq->vector); break; + case VM_LAPIC_MSI: + vmmsi = (struct vm_lapic_msi *)data; + error = lapic_intr_msi(sc->vm, vmmsi->addr, vmmsi->msg); + break; case VM_IOAPIC_ASSERT_IRQ: ioapic_irq = (struct vm_ioapic_irq *)data; error = vioapic_assert_irq(sc->vm, ioapic_irq->irq); diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c index 13fab8cb1c2f..96234a186ed1 100644 --- a/sys/amd64/vmm/vmm_lapic.c +++ b/sys/amd64/vmm/vmm_lapic.c @@ -38,9 +38,18 @@ __FBSDID("$FreeBSD$"); #include #include "vmm_ipi.h" +#include "vmm_ktr.h" #include "vmm_lapic.h" #include "vlapic.h" +/* + * Some MSI message definitions + */ +#define MSI_X86_ADDR_MASK 0xfff00000 +#define MSI_X86_ADDR_BASE 0xfee00000 +#define MSI_X86_ADDR_RH 0x00000008 /* Redirection Hint */ +#define MSI_X86_ADDR_LOG 0x00000004 /* Destination Mode */ + int lapic_pending_intr(struct vm *vm, int cpu) { @@ -80,6 +89,44 @@ lapic_set_intr(struct vm *vm, int cpu, int vector, bool level) return (0); } +int +lapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg) +{ + int delmode, vec; + uint32_t dest; + bool phys; + + VM_CTR2(vm, "lapic MSI addr: %#lx msg: %#lx", addr, msg); + + if ((addr & MSI_X86_ADDR_MASK) != MSI_X86_ADDR_BASE) { + VM_CTR1(vm, "lapic MSI invalid addr %#lx", addr); + return (-1); + } + + /* + * Extract the x86-specific fields from the MSI addr/msg + * params according to the Intel Arch spec, Vol3 Ch 10. + * + * The PCI specification does not support level triggered + * MSI/MSI-X so ignore trigger level in 'msg'. + * + * The 'dest' is interpreted as a logical APIC ID if both + * the Redirection Hint and Destination Mode are '1' and + * physical otherwise. + */ + dest = (addr >> 12) & 0xff; + phys = ((addr & (MSI_X86_ADDR_RH | MSI_X86_ADDR_LOG)) != + (MSI_X86_ADDR_RH | MSI_X86_ADDR_LOG)); + delmode = msg & APIC_DELMODE_MASK; + vec = msg & 0xff; + + VM_CTR3(vm, "lapic MSI %s dest %#x, vec %d", + phys ? "physical" : "logical", dest, vec); + + vlapic_deliver_intr(vm, LAPIC_TRIG_EDGE, dest, phys, delmode, vec); + return (0); +} + static boolean_t x2apic_msr(u_int msr) { diff --git a/sys/amd64/vmm/vmm_lapic.h b/sys/amd64/vmm/vmm_lapic.h index 09b7f57145a5..d7e75a960c03 100644 --- a/sys/amd64/vmm/vmm_lapic.h +++ b/sys/amd64/vmm/vmm_lapic.h @@ -84,4 +84,5 @@ lapic_intr_edge(struct vm *vm, int cpu, int vector) return (lapic_set_intr(vm, cpu, vector, LAPIC_TRIG_EDGE)); } +int lapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg); #endif diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index c7086ddcbcf5..d22873fbb46e 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -850,19 +850,14 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, else msgdata = pci_get_cfgdata16(pi, capoff + 8); - /* - * XXX check delivery mode, destination mode etc - */ mme = msgctrl & PCIM_MSICTRL_MME_MASK; pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0; if (pi->pi_msi.enabled) { - pi->pi_msi.cpu = (addrlo >> 12) & 0xff; - pi->pi_msi.vector = msgdata & 0xff; - pi->pi_msi.msgnum = 1 << (mme >> 4); + pi->pi_msi.addr = addrlo; + pi->pi_msi.msg_data = msgdata; + pi->pi_msi.maxmsgnum = 1 << (mme >> 4); } else { - pi->pi_msi.cpu = 0; - pi->pi_msi.vector = 0; - pi->pi_msi.msgnum = 0; + pi->pi_msi.maxmsgnum = 0; } } @@ -1060,10 +1055,10 @@ pci_msi_enabled(struct pci_devinst *pi) } int -pci_msi_msgnum(struct pci_devinst *pi) +pci_msi_maxmsgnum(struct pci_devinst *pi) { if (pi->pi_msi.enabled) - return (pi->pi_msi.msgnum); + return (pi->pi_msi.maxmsgnum); else return (0); } @@ -1092,19 +1087,17 @@ pci_generate_msix(struct pci_devinst *pi, int index) mte = &pi->pi_msix.table[index]; if ((mte->vector_control & PCIM_MSIX_VCTRL_MASK) == 0) { /* XXX Set PBA bit if interrupt is disabled */ - vm_lapic_irq(pi->pi_vmctx, - (mte->addr >> 12) & 0xff, mte->msg_data & 0xff); + vm_lapic_msi(pi->pi_vmctx, mte->addr, mte->msg_data); } } void -pci_generate_msi(struct pci_devinst *pi, int msg) +pci_generate_msi(struct pci_devinst *pi, int index) { - if (pci_msi_enabled(pi) && msg < pci_msi_msgnum(pi)) { - vm_lapic_irq(pi->pi_vmctx, - pi->pi_msi.cpu, - pi->pi_msi.vector + msg); + if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) { + vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr, + pi->pi_msi.msg_data + index); } } @@ -1511,10 +1504,10 @@ pci_emul_diow(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, * Special magic value to generate an interrupt */ if (offset == 4 && size == 4 && pci_msi_enabled(pi)) - pci_generate_msi(pi, value % pci_msi_msgnum(pi)); + pci_generate_msi(pi, value % pci_msi_maxmsgnum(pi)); if (value == 0xabcdef) { - for (i = 0; i < pci_msi_msgnum(pi); i++) + for (i = 0; i < pci_msi_maxmsgnum(pi); i++) pci_generate_msi(pi, i); } } diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 6a1d7575b44c..09fad073c55a 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -109,10 +109,10 @@ struct pci_devinst { int pi_bar_getsize; struct { - int enabled; - int cpu; - int vector; - int msgnum; + int enabled; + uint64_t addr; + uint64_t msg_data; + int maxmsgnum; } pi_msi; struct { diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index 43c542d3c18b..25654750938b 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -348,9 +348,9 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc, error = vm_setup_msix(ctx, vcpu, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, - index, entry->msg_data, - entry->vector_control, - entry->addr); + index, entry->addr, + entry->msg_data, + entry->vector_control); } } } @@ -653,8 +653,9 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, msicap_cfgwrite(pi, sc->psc_msi.capoff, coff, bytes, val); error = vm_setup_msi(ctx, vcpu, sc->psc_sel.pc_bus, - sc->psc_sel.pc_dev, sc->psc_sel.pc_func, pi->pi_msi.cpu, - pi->pi_msi.vector, pi->pi_msi.msgnum); + sc->psc_sel.pc_dev, sc->psc_sel.pc_func, + pi->pi_msi.addr, pi->pi_msi.msg_data, + pi->pi_msi.maxmsgnum); if (error != 0) { printf("vm_setup_msi returned error %d\r\n", errno); exit(1); @@ -667,15 +668,16 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, if (pi->pi_msix.enabled) { msix_table_entries = pi->pi_msix.table_count; for (i = 0; i < msix_table_entries; i++) { - error = vm_setup_msix(ctx, vcpu, sc->psc_sel.pc_bus, - sc->psc_sel.pc_dev, - sc->psc_sel.pc_func, i, - pi->pi_msix.table[i].msg_data, - pi->pi_msix.table[i].vector_control, - pi->pi_msix.table[i].addr); + error = vm_setup_msix(ctx, vcpu, + sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, + sc->psc_sel.pc_func, i, + pi->pi_msix.table[i].addr, + pi->pi_msix.table[i].msg_data, + pi->pi_msix.table[i].vector_control); if (error) { - printf("vm_setup_msix returned error %d\r\n", errno); + printf("vm_setup_msix error %d\r\n", + errno); exit(1); } } From c826a64307d3015b05b739d34bcdb4ecf31b3337 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Mon, 16 Dec 2013 22:04:47 +0000 Subject: [PATCH 099/172] Use the common Open Firmware PCI interrupt routing code instead of the duplicate version in dev/fdt. Tested by: zbb --- sys/arm/mv/mv_pci.c | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c index f708b90ec9ce..4d100d33c488 100644 --- a/sys/arm/mv/mv_pci.c +++ b/sys/arm/mv/mv_pci.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -142,7 +143,7 @@ struct mv_pcib_softc { int sc_type; int sc_mode; /* Endpoint / Root Complex */ - struct fdt_pci_intr sc_intr_info; + struct ofw_bus_iinfo sc_pci_iinfo; }; /* Local forward prototypes */ @@ -155,7 +156,6 @@ static void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int, static int mv_pcib_init(struct mv_pcib_softc *, int, int); static int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int); static void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int); -static int mv_pcib_intr_info(phandle_t, struct mv_pcib_softc *); static inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t); static void mv_pcib_enable(struct mv_pcib_softc *, uint32_t); static int mv_pcib_mem_init(struct mv_pcib_softc *); @@ -243,8 +243,8 @@ mv_pcib_probe(device_t self) if (!fdt_is_type(node, "pci")) return (ENXIO); - if (!(fdt_is_compatible(node, "mrvl,pcie") || - fdt_is_compatible(node, "mrvl,pci"))) + if (!(ofw_bus_is_compatible(self, "mrvl,pcie") || + ofw_bus_is_compatible(self, "mrvl,pci"))) return (ENXIO); device_set_desc(self, "Marvell Integrated PCI/PCI-E Controller"); @@ -299,11 +299,8 @@ mv_pcib_attach(device_t self) /* * Get PCI interrupt info. */ - if ((sc->sc_mode == MV_MODE_ROOT) && - (mv_pcib_intr_info(node, sc) != 0)) { - device_printf(self, "could not retrieve interrupt info\n"); - return (ENXIO); - } + if (sc->sc_mode == MV_MODE_ROOT) + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(pcell_t)); /* * Configure decode windows for PCI(E) access. @@ -881,19 +878,33 @@ mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, } static int -mv_pcib_route_interrupt(device_t pcib, device_t dev, int pin) +mv_pcib_route_interrupt(device_t bus, device_t dev, int pin) { struct mv_pcib_softc *sc; - int err, interrupt; + struct ofw_pci_register reg; + uint32_t pintr, mintr; + phandle_t iparent; + uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; - sc = device_get_softc(pcib); + sc = device_get_softc(bus); + pintr = pin; - err = fdt_pci_route_intr(pci_get_bus(dev), pci_get_slot(dev), - pci_get_function(dev), pin, &sc->sc_intr_info, &interrupt); - if (err == 0) - return (interrupt); + /* Fabricate imap information in case this isn't an OFW device */ + bzero(®, sizeof(reg)); + reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) | + (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | + (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); - device_printf(pcib, "could not route pin %d for device %d.%d\n", + if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, + sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), + &iparent, maskbuf)) + return (ofw_bus_map_intr(dev, iparent, mintr)); + + /* Maybe it's a real interrupt, not an intpin */ + if (pin > 4) + return (pin); + + device_printf(bus, "could not route pin %d for device %d.%d\n", pin, pci_get_slot(dev), pci_get_function(dev)); return (PCI_INVALID_IRQ); } @@ -938,17 +949,6 @@ mv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc) return (0); } -static int -mv_pcib_intr_info(phandle_t node, struct mv_pcib_softc *sc) -{ - int error; - - if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0) - return (error); - - return (0); -} - #if defined(SOC_MV_ARMADAXP) static int mv_pcib_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, From 2e159ef0b597a1f1b78c02b771524eabfa502626 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Mon, 16 Dec 2013 23:57:43 +0000 Subject: [PATCH 100/172] fix the build using __builtin_prefetch() instead of redefining prefetch() --- sys/dev/netmap/ixgbe_netmap.h | 8 ++++---- sys/dev/netmap/netmap_kern.h | 1 - sys/dev/netmap/netmap_vale.c | 4 +--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h index 7fd67d2b57ff..4dea6639d325 100644 --- a/sys/dev/netmap/ixgbe_netmap.h +++ b/sys/dev/netmap/ixgbe_netmap.h @@ -220,8 +220,8 @@ ixgbe_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) if (nm_i != cur) { /* we have new packets to send */ nic_i = netmap_idx_k2n(kring, nm_i); - prefetch(&ring->slot[nm_i]); - prefetch(&txr->tx_buffers[nic_i]); + __builtin_prefetch(&ring->slot[nm_i]); + __builtin_prefetch(&txr->tx_buffers[nic_i]); for (n = 0; nm_i != cur; n++) { struct netmap_slot *slot = &ring->slot[nm_i]; @@ -237,8 +237,8 @@ ixgbe_netmap_txsync(struct netmap_adapter *na, u_int ring_nr, int flags) IXGBE_TXD_CMD_RS : 0; /* prefetch for next round */ - prefetch(&ring->slot[nm_i + 1]); - prefetch(&txr->tx_buffers[nic_i + 1]); + __builtin_prefetch(&ring->slot[nm_i + 1]); + __builtin_prefetch(&txr->tx_buffers[nic_i + 1]); NM_CHECK_ADDR_LEN(addr, len); diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h index c009f5e62684..9381cd4cedd3 100644 --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -61,7 +61,6 @@ #define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1)) #define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0) -#define prefetch(x) __builtin_prefetch(x) MALLOC_DECLARE(M_NETMAP); diff --git a/sys/dev/netmap/netmap_vale.c b/sys/dev/netmap/netmap_vale.c index e0ce94cccb7d..32d6422de120 100644 --- a/sys/dev/netmap/netmap_vale.c +++ b/sys/dev/netmap/netmap_vale.c @@ -79,8 +79,6 @@ __FBSDID("$FreeBSD$"); #include #include -// #define prefetch(x) __builtin_prefetch(x) - #define BDG_RWLOCK_T struct rwlock // struct rwlock @@ -1003,7 +1001,7 @@ nm_bdg_preflush(struct netmap_vp_adapter *na, u_int ring_nr, ft[ft_i].ft_next = NM_FT_NULL; buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ? (void *)(uintptr_t)slot->ptr : BDG_NMB(&na->up, slot); - prefetch(buf); + __builtin_prefetch(buf); ++ft_i; if (slot->flags & NS_MOREFRAG) { frags++; From dc3bdd4ad937e9e3552ee4b96da81ae23b2adf36 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 17 Dec 2013 03:06:21 +0000 Subject: [PATCH 101/172] Remove the invariants stuff I copy/paste'd from the mbuf code when setting up the UMA zone. This should (a) be correct(er) and (b) it should build on non-amd64. Pointed out by: glebius --- sys/kern/uipc_syscalls.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index c45597b677ab..3243f562787c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -80,9 +80,6 @@ __FBSDID("$FreeBSD$"); #include #endif -#include -#include -#include #include #include @@ -95,6 +92,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #if defined(INET) || defined(INET6) #ifdef SCTP @@ -150,11 +148,7 @@ sf_sync_init(const void *unused) zone_sfsync = uma_zcreate("sendfile_sync", sizeof(struct sendfile_sync), NULL, NULL, -#ifdef INVARIANTS - trash_init, trash_fini, -#else NULL, NULL, -#endif UMA_ALIGN_CACHE, 0); } From 577973f5f9f123d24bbcc6f16764f26a9bf8b795 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Tue, 17 Dec 2013 03:38:36 +0000 Subject: [PATCH 102/172] Add release note items from Chelsio. Submitted by: np --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 647d6c756d60..49acccb00983 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -248,6 +248,12 @@ The &man.wpi.4; driver has been updated to include a number of stability fixes. + The &man.cxgbe.4; driver has been updated to support + 40G/10G Ethernet NICs based on Chelsio's Terminator 5 (T5) ASIC. + + The iw_cxgbe driver has been added. This is an experimental iWARP/RDMA driver + (kernel verbs only) for Chelsio's T4 and T5 based cards. + From 0fe7bfaef41ad7a2992369fc0305f60fe564670f Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Tue, 17 Dec 2013 04:19:03 +0000 Subject: [PATCH 103/172] Add OFED and Mellanox items to release notes. Submitted by: Meny Yossefi --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 49acccb00983..e3c3b6c1298f 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -254,6 +254,15 @@ The iw_cxgbe driver has been added. This is an experimental iWARP/RDMA driver (kernel verbs only) for Chelsio's T4 and T5 based cards. + The Open Fabrics Enterprise Distribution (OFED) and OFED Infiniband core has been + updated to the same version as supplied by Linux version 3.7 + + The Mellanox Infiniband driver has been updated to firmware + version 2.30.3200 for ConnectX3 NICs. Support has been added for ConnectX3 VPI NICs, where + each port can be used as Infiniband 56 GB/s or Ethernet 40 GB/s. Support has been added + for dynamically loading kernel modules for Infiniband core (ibcore) and + IP over Infiniband (ipoib). + From a91afa209154483a9c9444601297623297741bc2 Mon Sep 17 00:00:00 2001 From: Jonathan Chu Date: Tue, 17 Dec 2013 05:13:37 +0000 Subject: [PATCH 104/172] milki is a new committer for ports. Approved by: swills (mentor) --- share/misc/committers-ports.dot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot index 6367237cc37b..ac7be699c015 100644 --- a/share/misc/committers-ports.dot +++ b/share/misc/committers-ports.dot @@ -154,6 +154,7 @@ mat [label="Mathieu Arnold\nmat@FreeBSD.org\n2003/08/15"] matthew [label="Matthew Seaman\nmatthew@FreeBSD.org\n2012/02/07"] mezz [label="Jeremy Messenger\nmezz@FreeBSD.org\n2004/04/30"] mharo [label="Michael Haro\nmharo@FreeBSD.org\n1999/04/13"] +milki [label="Jonathan Chu\nmilki@FreeBSD.org\n2013/12/15"] miwi [label="Martin Wilke\nmiwi@FreeBSD.org\n2006/06/04"] mm [label="Martin Matuska\nmm@FreeBSD.org\n2007/04/04"] mnag [label="Marcus Alves Grando\nmnag@FreeBSD.org\n2005/09/15"] @@ -301,6 +302,7 @@ eadler -> antoine eadler -> dbn eadler -> bdrewery eadler -> gjb +eadler -> milki eadler -> tj eadler -> vg @@ -510,6 +512,7 @@ stas -> araujo steve -> netchild swills -> feld +swills -> milki swills -> pclin tabthorpe -> ashish From 5fdb31912124d2229b6c0a1c9d8a75a5ff07c64c Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 17 Dec 2013 07:47:27 +0000 Subject: [PATCH 105/172] Nuke symbols.raw This file seems to be unused since the switch to the ELF binary format. Discussed with: jhb --- sys/i386/i386/symbols.raw | 73 --------------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 sys/i386/i386/symbols.raw diff --git a/sys/i386/i386/symbols.raw b/sys/i386/i386/symbols.raw deleted file mode 100644 index 314a1af4c4a9..000000000000 --- a/sys/i386/i386/symbols.raw +++ /dev/null @@ -1,73 +0,0 @@ -# @(#)symbols.raw 7.6 (Berkeley) 5/8/91 -# -# $FreeBSD$ -# - - -#gdb - _IdlePTD - _PTD - _panicstr -# _version -#dmesg - _msgbufp -# _msgbuf -#iostat - _tk_nin - _tk_nout - _cp_time -# _io_info -#ps - _nswap - _maxslp - _ccpu - _fscale - _avail_start - _avail_end -#pstat -# _cons - _nswap - _swapblist -# _swaplist -#vmstat - _cp_time -# _rate -# _total -# _sum -# _rectime -# _pgintime - _boottime -#w - _swapdev - _nswap - _averunnable - _boottime -#netstat - _ipstat - _tcb - _tcpstat - _udb - _udpstat -# _rawcb - _ifnet -# _rthost -# _rtnet - _icmpstat - _filehead - _nfiles -# _rthashsize -# _radix_node_head -#routed - _ifnet -#rwho - _boottime -#savecore - _dumpdev - _dumplo - _time_second - _version - _dumpsize - _panicstr - _dumpmag -#deprecated -# _avenrun From b177d064d74eb4da2d1a07df9980fead5f225a62 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 17 Dec 2013 07:59:00 +0000 Subject: [PATCH 106/172] Pull in r197399 from upstream clang trunk: Add bit_FXSAVE as an alias for bit_FXSR, for gcc compat. MFC after: 3 days --- contrib/llvm/tools/clang/lib/Headers/cpuid.h | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/llvm/tools/clang/lib/Headers/cpuid.h b/contrib/llvm/tools/clang/lib/Headers/cpuid.h index 8f12caeb4978..f9254e9738e7 100644 --- a/contrib/llvm/tools/clang/lib/Headers/cpuid.h +++ b/contrib/llvm/tools/clang/lib/Headers/cpuid.h @@ -79,6 +79,7 @@ #define bit_ACPI 0x00400000 #define bit_MMX 0x00800000 #define bit_FXSR 0x01000000 +#define bit_FXSAVE bit_FXSR /* for gcc compat */ #define bit_SSE 0x02000000 #define bit_SSE2 0x04000000 #define bit_SS 0x08000000 From 4f1c67053fe3cb81d2c2ae7bd303b23c7725ae8b Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 17 Dec 2013 10:33:27 +0000 Subject: [PATCH 107/172] Reword the part about mutual CHAP. MFC after: 2 weeks Sponsored by: The FreeBSD Foundation --- sbin/iscontrol/iscsi.conf.5 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sbin/iscontrol/iscsi.conf.5 b/sbin/iscontrol/iscsi.conf.5 index f87fef6e89cd..2e7a68dc6476 100644 --- a/sbin/iscontrol/iscsi.conf.5 +++ b/sbin/iscontrol/iscsi.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 10, 2013 +.Dd December 17, 2013 .Dt ISCSI.CONF 5 .Os .Sh NAME @@ -145,10 +145,9 @@ the chap-name, defaults to .Em hostname . .It Cm chapDigest can be MD5 or SHA1. -.It Cm tgtChapSecret/tgtChapName -same as the none -.Em tgt -counterpart, but to authenticate the target. +.It Cm tgtChapName/tgtChapSecret +name and secret used for mutual CHAP; by default, mutual CHAP +is not used. .El .Sh FILES .Bl -tag -width indent From 569aad57d2ca18e77acd2b746ebd49b17ad1b468 Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Tue, 17 Dec 2013 10:53:17 +0000 Subject: [PATCH 108/172] Free mbuf in case of error. MFC after: 1 week --- sys/netinet6/send.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c index 79748387b662..b946ded155d1 100644 --- a/sys/netinet6/send.c +++ b/sys/netinet6/send.c @@ -163,6 +163,7 @@ send_output(struct mbuf *m, struct ifnet *ifp, int direction) nd6_ra_input(m, sizeof(struct ip6_hdr), icmp6len); break; default: + m_freem(m); return (ENOSYS); } return (0); From e7a9eed7a8a9d58f1e322103266e6b75a1aab156 Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Tue, 17 Dec 2013 13:37:02 +0000 Subject: [PATCH 109/172] - Assert for not leaking readers rw locks counter on userland return. - Use a correct spin_cnt for KDTRACE_HOOK case in rw read lock. Sponsored by: EMC / Isilon storage division --- sys/kern/kern_rwlock.c | 3 +++ sys/kern/subr_trap.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 0e9f3a53920b..65fcdee0a7f2 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -440,6 +440,9 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line) break; cpu_spinwait(); } +#ifdef KDTRACE_HOOKS + spin_cnt += rowner_loops - i; +#endif if (i != rowner_loops) continue; } diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 65a31cdaeec8..07d63f81b6b7 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -152,6 +152,9 @@ userret(struct thread *td, struct trapframe *frame) ("userret: Returning in a critical section")); KASSERT(td->td_locks == 0, ("userret: Returning with %d locks held", td->td_locks)); + KASSERT(td->td_rw_rlocks == 0, + ("userret: Returning with %d rwlocks held in read mode", + td->td_rw_rlocks)); KASSERT((td->td_pflags & TDP_NOFAULTING) == 0, ("userret: Returning with pagefaults disabled")); KASSERT(td->td_no_sleeping == 0, From cb6d9d6cb1aeda72d934a1c7bc1ee4d6924e4d55 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Tue, 17 Dec 2013 14:50:35 +0000 Subject: [PATCH 110/172] Configure interrupt sense based on device tree information. This extends the OF interrupt map API to return sense information to the caller and the PowerPC Open Firmware PCI base driver to use it to program the PIC. --- sys/dev/ofw/ofw_bus_subr.c | 12 +++--------- sys/powerpc/ofw/ofw_pci.c | 16 +++++++++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 26a675937c12..8c2d64af8bbf 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -285,7 +285,7 @@ ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, * maskbuf must point to a buffer of length physsz + intrsz. * The interrupt is returned in result, which must point to a buffer of length * rintrsz (which gives the expected size of the mapped interrupt). - * Returns 1 if a mapping was found, 0 otherwise. + * Returns number of cells in the interrupt if a mapping was found, 0 otherwise. */ int ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, @@ -325,19 +325,13 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz; KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map")); - /* - * XXX: Apple hardware uses a second cell to set information - * on the interrupt trigger type. This information should - * be used somewhere to program the PIC. - */ - if (bcmp(ref, mptr, physsz + intrsz) == 0) { bcopy(mptr + physsz + intrsz + sizeof(parent), - result, rintrsz); + result, MIN(rintrsz, pintrsz)); if (iparent != NULL) *iparent = parent; - return (1); + return (pintrsz/sizeof(pcell_t)); } mptr += tsz; i -= tsz; diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c index 957a8caed2f9..b80f07a66873 100644 --- a/sys/powerpc/ofw/ofw_pci.c +++ b/sys/powerpc/ofw/ofw_pci.c @@ -256,7 +256,8 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) { struct ofw_pci_softc *sc; struct ofw_pci_register reg; - uint32_t pintr, mintr; + uint32_t pintr, mintr[2]; + int intrcells; phandle_t iparent; uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; @@ -269,10 +270,15 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent, maskbuf)) - return (ofw_bus_map_intr(dev, iparent, mintr)); + intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), + &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), + mintr, sizeof(mintr), &iparent, maskbuf); + if (intrcells) { + pintr = ofw_bus_map_intr(dev, iparent, mintr[0]); + if (intrcells == 2) + ofw_bus_config_intr(dev, pintr, mintr[1]); + return (pintr); + } /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) From fc54707f7df7dfef2b86c009524827921b945f10 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Tue, 17 Dec 2013 14:51:47 +0000 Subject: [PATCH 111/172] Remove dead code. Most of this was in an #if 0 block; the rest is not used and duplicates functionality in dev/ofw. --- sys/dev/fdt/fdt_common.h | 10 -- sys/dev/fdt/fdt_pci.c | 367 --------------------------------------- 2 files changed, 377 deletions(-) diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 8c16257215a4..499d1f81022b 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -47,14 +47,6 @@ struct fdt_pci_range { u_long len; }; -struct fdt_pci_intr { - int addr_cells; - int intr_cells; - int map_len; - pcell_t *map; - pcell_t *mask; -}; - struct fdt_sense_level { enum intr_trigger trig; enum intr_polarity pol; @@ -110,11 +102,9 @@ int fdt_is_enabled(phandle_t); int fdt_pm_is_enabled(phandle_t); int fdt_is_type(phandle_t, const char *); int fdt_parent_addr_cells(phandle_t); -int fdt_pci_intr_info(phandle_t, struct fdt_pci_intr *); int fdt_pci_ranges(phandle_t, struct fdt_pci_range *, struct fdt_pci_range *); int fdt_pci_ranges_decode(phandle_t, struct fdt_pci_range *, struct fdt_pci_range *); -int fdt_pci_route_intr(int, int, int, int, struct fdt_pci_intr *, int *); int fdt_ranges_verify(pcell_t *, int, int, int, int); int fdt_reg_to_rl(phandle_t, struct resource_list *); int fdt_pm(phandle_t); diff --git a/sys/dev/fdt/fdt_pci.c b/sys/dev/fdt/fdt_pci.c index fae5f07aa867..d4f4b6c170a3 100644 --- a/sys/dev/fdt/fdt_pci.c +++ b/sys/dev/fdt/fdt_pci.c @@ -180,159 +180,6 @@ fdt_pci_ranges(phandle_t node, struct fdt_pci_range *io_space, return (0); } -static int -fdt_addr_cells(phandle_t node, int *addr_cells) -{ - pcell_t cell; - int cell_size; - - cell_size = sizeof(cell); - if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size) - return (EINVAL); - *addr_cells = fdt32_to_cpu((int)cell); - - if (*addr_cells > 3) - return (ERANGE); - return (0); -} - -static int -fdt_interrupt_cells(phandle_t node) -{ - pcell_t intr_cells; - - if (OF_getprop(node, "#interrupt-cells", &intr_cells, - sizeof(intr_cells)) <= 0) { - debugf("no intr-cells defined, defaulting to 1\n"); - intr_cells = 1; - } - intr_cells = fdt32_to_cpu(intr_cells); - - return ((int)intr_cells); -} - -int -fdt_pci_intr_info(phandle_t node, struct fdt_pci_intr *intr_info) -{ - void *map, *mask; - int acells, icells; - int error, len; - - error = fdt_addr_cells(node, &acells); - if (error) - return (error); - - icells = fdt_interrupt_cells(node); - - /* - * Retrieve the interrupt map and mask properties. - */ - len = OF_getprop_alloc(node, "interrupt-map-mask", 1, &mask); - if (len / sizeof(pcell_t) != (acells + icells)) { - debugf("bad mask len = %d\n", len); - goto err; - } - - len = OF_getprop_alloc(node, "interrupt-map", 1, &map); - if (len <= 0) { - debugf("bad map len = %d\n", len); - goto err; - } - - intr_info->map_len = len; - intr_info->map = map; - intr_info->mask = mask; - intr_info->addr_cells = acells; - intr_info->intr_cells = icells; - - debugf("acells=%u, icells=%u, map_len=%u\n", acells, icells, len); - return (0); - -err: - free(mask, M_OFWPROP); - return (ENXIO); -} - -int -fdt_pci_route_intr(int bus, int slot, int func, int pin, - struct fdt_pci_intr *intr_info, int *interrupt) -{ - pcell_t child_spec[4], masked[4]; - phandle_t iph; - pcell_t intr_par; - pcell_t *map_ptr; - uint32_t addr; - int i, j, map_len; - int par_intr_cells, par_addr_cells, child_spec_cells, row_cells; - int par_idx, spec_idx, err, trig, pol; - - child_spec_cells = intr_info->addr_cells + intr_info->intr_cells; - if (child_spec_cells > sizeof(child_spec) / sizeof(pcell_t)) - return (ENOMEM); - - addr = (bus << 16) | (slot << 11) | (func << 8); - child_spec[0] = addr; - child_spec[1] = 0; - child_spec[2] = 0; - child_spec[3] = pin; - - map_len = intr_info->map_len; - map_ptr = intr_info->map; - - par_idx = child_spec_cells; - i = 0; - while (i < map_len) { - iph = fdt32_to_cpu(map_ptr[par_idx]); - intr_par = OF_xref_phandle(iph); - - err = fdt_addr_cells(intr_par, &par_addr_cells); - if (err != 0) { - debugf("could not retrieve intr parent #addr-cells\n"); - return (err); - } - par_intr_cells = fdt_interrupt_cells(intr_par); - - row_cells = child_spec_cells + 1 + par_addr_cells + - par_intr_cells; - - /* - * Apply mask and look up the entry in interrupt map. - */ - for (j = 0; j < child_spec_cells; j++) { - masked[j] = child_spec[j] & - fdt32_to_cpu(intr_info->mask[j]); - - if (masked[j] != fdt32_to_cpu(map_ptr[j])) - goto next; - } - - /* - * Decode interrupt of the parent intr controller. - */ - spec_idx = child_spec_cells + 1 + par_addr_cells; - err = fdt_intr_decode(intr_par, &map_ptr[spec_idx], - interrupt, &trig, &pol); - if (err != 0) { - debugf("could not decode interrupt\n"); - return (err); - } - debugf("decoded intr = %d, trig = %d, pol = %d\n", *interrupt, - trig, pol); - -#if defined(__powerpc__) - powerpc_config_intr(FDT_MAP_IRQ(iph, *interrupt), trig, - pol); -#endif - return (0); - -next: - map_ptr += row_cells; - i += (row_cells * sizeof(pcell_t)); - } - - return (ENXIO); -} - #if defined(__arm__) int fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap, vm_offset_t io_va, @@ -360,217 +207,3 @@ fdt_pci_devmap(phandle_t node, struct arm_devmap_entry *devmap, vm_offset_t io_v } #endif -#if 0 -static int -fdt_pci_config_bar(device_t dev, int bus, int slot, int func, int bar) -{ -} - -static int -fdt_pci_config_normal(device_t dev, int bus, int slot, int func) -{ - int bar; - uint8_t command, intline, intpin; - - command = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_COMMAND, 1); - command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); - PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1); - - /* Program the base address registers. */ - bar = 0; - while (bar <= PCIR_MAX_BAR_0) - bar += fdt_pci_config_bar(dev, bus, slot, func, bar); - - /* Perform interrupt routing. */ - intpin = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_INTPIN, 1); - intline = fsl_pcib_route_int(dev, bus, slot, func, intpin); - PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_INTLINE, intline, 1); - - command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; - PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1); -} - -static int -fdt_pci_config_bridge(device_t dev, int bus, int secbus, int slot, int func) -{ - int maxbar; - uint8_t command; - - command = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_COMMAND, 1); - command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); - PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1); - - /* Program the base address registers. */ - maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6; - bar = 0; - while (bar < maxbar) - bar += fsl_pcib_init_bar(sc, bus, slot, func, - bar); - - /* Perform interrupt routing. */ - intpin = fsl_pcib_read_config(sc->sc_dev, bus, slot, - func, PCIR_INTPIN, 1); - intline = fsl_pcib_route_int(sc, bus, slot, func, - intpin); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_INTLINE, intline, 1); - - command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_COMMAND, command, 1); - - /* - * Handle PCI-PCI bridges - */ - class = fsl_pcib_read_config(sc->sc_dev, bus, slot, - func, PCIR_CLASS, 1); - subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot, - func, PCIR_SUBCLASS, 1); - - /* Allow only proper PCI-PCI briges */ - if (class != PCIC_BRIDGE) - continue; - if (subclass != PCIS_BRIDGE_PCI) - continue; - - secbus++; - - /* Program I/O decoder. */ - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2); - - /* Program (non-prefetchable) memory decoder. */ - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2); - - /* Program prefetchable memory decoder. */ - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMBASEL_1, 0x0010, 2); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMLIMITL_1, 0x000f, 2); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMBASEH_1, 0x00000000, 4); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMLIMITH_1, 0x00000000, 4); - - /* Read currect bus register configuration */ - old_pribus = fsl_pcib_read_config(sc->sc_dev, bus, - slot, func, PCIR_PRIBUS_1, 1); - old_secbus = fsl_pcib_read_config(sc->sc_dev, bus, - slot, func, PCIR_SECBUS_1, 1); - old_subbus = fsl_pcib_read_config(sc->sc_dev, bus, - slot, func, PCIR_SUBBUS_1, 1); - - if (bootverbose) - printf("PCI: reading firmware bus numbers for " - "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n", - secbus, old_pribus, old_secbus, old_subbus); - - new_pribus = bus; - new_secbus = secbus; - - secbus = fsl_pcib_init(sc, secbus, - (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0); - - new_subbus = secbus; - - if (bootverbose) - printf("PCI: translate firmware bus numbers " - "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n", - secbus, old_pribus, old_secbus, old_subbus, - new_pribus, new_secbus, new_subbus); - - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_PRIBUS_1, new_pribus, 1); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_SECBUS_1, new_secbus, 1); - fsl_pcib_write_config(sc->sc_dev, bus, slot, func, - PCIR_SUBBUS_1, new_subbus, 1); - -} - -static int -fdt_pci_config_slot(device_t dev, int bus, int secbus, int slot) -{ - int func, maxfunc; - uint16_t vendor; - uint8_t hdrtype; - - maxfunc = 0; - for (func = 0; func <= maxfunc; func++) { - hdrtype = PCIB_READ_CONFIG(dev, bus, slot, func, - PCIR_HDRTYPE, 1); - if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) - continue; - if (func == 0 && (hdrtype & PCIM_MFDEV)) - maxfunc = PCI_FUNCMAX; - - vendor = PCIB_READ_CONFIG(dev, bus, slot, func, - PCIR_VENDOR, 2); - if (vendor == 0xffff) - continue; - - if ((hdrtype & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL) - fdt_pci_config_normal(dev, bus, slot, func); - else - secbus = fdt_pci_config_bridge(dev, bus, secbus, - slot, func); - } - - return (secbus); -} - -static int -fdt_pci_config_bus(device_t dev, int bus, int maxslot) -{ - int func, maxfunc, secbus, slot; - - secbus = bus; - for (slot = 0; slot <= maxslot; slot++) - secbus = fdt_pci_config_slot(dev, bus, secbus, slot); - - return (secbus); -} - -int -fdt_pci_config_domain(device_t dev) -{ - pcell_t bus_range[2]; - phandle_t root; - int bus, error, maxslot; - - root = ofw_bus_get_node(dev); - if (root == 0) - return (EINVAL); - if (!fdt_is_type(root, "pci")) - return (EINVAL); - - /* - * Determine the bus number of the root in this domain. - * Lacking any information, this will be bus 0. - * Write the bus number to the bus device, using the IVAR. - */ - if ((OF_getprop(root, "bus-range", bus_range, sizeof(bus_range)) <= 0) - bus = 0; - else - bus = fdt32_to_cpu(bus_range[0]); - - error = BUS_WRITE_IVAR(dev, NULL, PCIB_IVAR_BUS, bus); - if (error) - return (error); - - /* Get the maximum slot number for bus-enumeration. */ - maxslot = PCIB_MAXSLOTS(dev); - - bus = fdt_pci_config_bus(dev, bus, maxslot); - return (0); -} -#endif From 95e3bfe889f9b5d6d6982a8eee60172dd674b492 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Tue, 17 Dec 2013 15:11:24 +0000 Subject: [PATCH 112/172] Simplify the ofw_bus_lookup_imap() API slightly: make it allocate maskbuf internally instead of requiring the caller to allocate it. --- sys/arm/mv/mv_pci.c | 3 +-- sys/dev/ofw/ofw_bus_subr.c | 3 ++- sys/dev/ofw/ofw_bus_subr.h | 2 +- sys/powerpc/ofw/ofw_pci.c | 3 +-- sys/powerpc/ofw/ofw_pcib_pci.c | 17 +++++++++++------ sys/sparc64/ebus/ebus.c | 3 +-- sys/sparc64/isa/ofw_isa.c | 3 +-- sys/sparc64/pci/fire.c | 3 +-- sys/sparc64/pci/ofw_pcib_subr.c | 3 +-- sys/sparc64/pci/psycho.c | 3 +-- sys/sparc64/pci/schizo.c | 3 +-- 11 files changed, 22 insertions(+), 24 deletions(-) diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c index 4d100d33c488..ff129744ce19 100644 --- a/sys/arm/mv/mv_pci.c +++ b/sys/arm/mv/mv_pci.c @@ -884,7 +884,6 @@ mv_pcib_route_interrupt(device_t bus, device_t dev, int pin) struct ofw_pci_register reg; uint32_t pintr, mintr; phandle_t iparent; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bus); pintr = pin; @@ -897,7 +896,7 @@ mv_pcib_route_interrupt(device_t bus, device_t dev, int pin) if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent, maskbuf)) + &iparent)) return (ofw_bus_map_intr(dev, iparent, mintr)); /* Maybe it's a real interrupt, not an intpin */ diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 8c2d64af8bbf..bf552a8b2f5b 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -251,8 +251,9 @@ ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz) int ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz, - phandle_t *iparent, void *maskbuf) + phandle_t *iparent) { + uint8_t maskbuf[regsz + pintrsz]; int rv; if (ii->opi_imapsz <= 0) diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index 184ab07b2412..e9ef5e43128f 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -68,7 +68,7 @@ bus_child_pnpinfo_str_t ofw_bus_gen_child_pnpinfo_str; /* Routines for processing firmware interrupt maps */ void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int); int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, - void *, int, void *, int, phandle_t *, void *); + void *, int, void *, int, phandle_t *); int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c index b80f07a66873..692b1abf5018 100644 --- a/sys/powerpc/ofw/ofw_pci.c +++ b/sys/powerpc/ofw/ofw_pci.c @@ -259,7 +259,6 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) uint32_t pintr, mintr[2]; int intrcells; phandle_t iparent; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bus); pintr = pin; @@ -272,7 +271,7 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), - mintr, sizeof(mintr), &iparent, maskbuf); + mintr, sizeof(mintr), &iparent); if (intrcells) { pintr = ofw_bus_map_intr(dev, iparent, mintr[0]); if (intrcells == 2) diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c index 6e3faeafb325..df274c492b3a 100644 --- a/sys/powerpc/ofw/ofw_pcib_pci.c +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -134,9 +134,9 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin) struct ofw_pcib_softc *sc; struct ofw_bus_iinfo *ii; struct ofw_pci_register reg; - cell_t pintr, mintr; + cell_t pintr, mintr[2]; + int intrcells; phandle_t iparent; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); ii = &sc->ops_iinfo; @@ -149,15 +149,20 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin) (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent, maskbuf)) { + intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, + sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr), + &iparent); + if (intrcells) { /* * If we've found a mapping, return it and don't map * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ - return (ofw_bus_map_intr(dev, iparent, mintr)); + mintr[0] = ofw_bus_map_intr(dev, iparent, mintr[0]); + if (intrcells == 2) + ofw_bus_config_intr(dev, mintr[0], mintr[1]); + + return (mintr[0]); } } else if (intpin >= 1 && intpin <= 4) { /* diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c index 677e31d75a91..93ad3422a062 100644 --- a/sys/sparc64/ebus/ebus.c +++ b/sys/sparc64/ebus/ebus.c @@ -638,7 +638,6 @@ ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) uint64_t start; uint32_t rintr; int i, nintr, nreg, rv; - uint8_t maskbuf[sizeof(reg) + sizeof(intr)]; edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) { @@ -673,7 +672,7 @@ ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) intr = intrs[i]; rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, ®, sizeof(reg), &intr, sizeof(intr), &rintr, - sizeof(rintr), NULL, maskbuf); + sizeof(rintr), NULL); #ifndef SUN4V if (rv != 0) rintr = INTMAP_VEC(sc->sc_ign, rintr); diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c index 0d0f5b6afc72..dbe5d8a252d1 100644 --- a/sys/sparc64/isa/ofw_isa.c +++ b/sys/sparc64/isa/ofw_isa.c @@ -129,7 +129,6 @@ ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii, ofw_isa_intr_t intr) { struct isa_regs reg; - uint8_t maskbuf[sizeof(reg) + sizeof(intr)]; device_t pbridge; ofw_isa_intr_t mintr; @@ -139,7 +138,7 @@ ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii, * fully specified, so we may not continue to map. */ if (!ofw_bus_lookup_imap(node, ii, ®, sizeof(reg), - &intr, sizeof(intr), &mintr, sizeof(mintr), NULL, maskbuf)) { + &intr, sizeof(intr), &mintr, sizeof(mintr), NULL)) { /* Try routing at the parent bridge. */ mintr = PCIB_ROUTE_INTERRUPT(pbridge, bridge, intr); } diff --git a/sys/sparc64/pci/fire.c b/sys/sparc64/pci/fire.c index 9bbfab61aac3..ff47487c55a8 100644 --- a/sys/sparc64/pci/fire.c +++ b/sys/sparc64/pci/fire.c @@ -1470,13 +1470,12 @@ fire_route_interrupt(device_t bridge, device_t dev, int pin) struct fire_softc *sc; struct ofw_pci_register reg; ofw_pci_intr_t pintr, mintr; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); pintr = pin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL, maskbuf) != 0) + NULL) != 0) return (mintr); device_printf(bridge, "could not route pin %d for device %d.%d\n", diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c index 2ffb32d1ba3b..14fa72b2a8af 100644 --- a/sys/sparc64/pci/ofw_pcib_subr.c +++ b/sys/sparc64/pci/ofw_pcib_subr.c @@ -70,7 +70,6 @@ ofw_pcib_gen_route_interrupt(device_t bridge, device_t dev, int intpin) struct ofw_bus_iinfo *ii; struct ofw_pci_register reg; ofw_pci_intr_t pintr, mintr; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); ii = &sc->ops_iinfo; @@ -78,7 +77,7 @@ ofw_pcib_gen_route_interrupt(device_t bridge, device_t dev, int intpin) pintr = intpin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL, maskbuf)) { + NULL)) { /* * If we've found a mapping, return it and don't map * it again on higher levels - that causes problems diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index d42fdadee8f5..ec8d90fe22cb 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -1046,13 +1046,12 @@ psycho_route_interrupt(device_t bridge, device_t dev, int pin) struct ofw_pci_register reg; bus_addr_t intrmap; ofw_pci_intr_t pintr, mintr; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); pintr = pin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL, maskbuf)) + NULL)) return (mintr); /* * If this is outside of the range for an intpin, it's likely a full diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c index 9e522c024434..e7ebaf189878 100644 --- a/sys/sparc64/pci/schizo.c +++ b/sys/sparc64/pci/schizo.c @@ -1119,13 +1119,12 @@ schizo_route_interrupt(device_t bridge, device_t dev, int pin) struct schizo_softc *sc; struct ofw_pci_register reg; ofw_pci_intr_t pintr, mintr; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); pintr = pin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - NULL, maskbuf)) + NULL)) return (mintr); device_printf(bridge, "could not route pin %d for device %d.%d\n", From 0f705e869b25fae6a4d551dd2a252b3a0571ed34 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybalko Date: Tue, 17 Dec 2013 15:23:47 +0000 Subject: [PATCH 113/172] Add vt support for RPi. (No early stage yet.) Sponsored by: The FreeBSD Foundation --- sys/arm/broadcom/bcm2835/bcm2835_fbd.c | 307 +++++++++++++++++++++++++ sys/arm/broadcom/bcm2835/files.bcm2835 | 1 + sys/arm/conf/RPI-B | 2 +- 3 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 sys/arm/broadcom/bcm2835/bcm2835_fbd.c diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c new file mode 100644 index 000000000000..c5e6c77a2e52 --- /dev/null +++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2012 Oleksandr Tymoshenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include "fb_if.h" +#include "mbox_if.h" + +#define FB_WIDTH 640 +#define FB_HEIGHT 480 +#define FB_DEPTH 24 + +struct bcm_fb_config { + uint32_t xres; + uint32_t yres; + uint32_t vxres; + uint32_t vyres; + uint32_t pitch; + uint32_t bpp; + uint32_t xoffset; + uint32_t yoffset; + /* Filled by videocore */ + uint32_t base; + uint32_t screen_size; +}; + +struct bcmsc_softc { + device_t dev; + struct fb_info *info; + bus_dma_tag_t dma_tag; + bus_dmamap_t dma_map; + struct bcm_fb_config* fb_config; + bus_addr_t fb_config_phys; + struct intr_config_hook init_hook; + +}; + +static int bcm_fb_probe(device_t); +static int bcm_fb_attach(device_t); +static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); + +static void +bcm_fb_init(void *arg) +{ + struct bcmsc_softc *sc = arg; + volatile struct bcm_fb_config* fb_config = sc->fb_config; + struct fb_info *info; + phandle_t node; + pcell_t cell; + device_t mbox; + device_t fbd; + int err = 0; + + node = ofw_bus_get_node(sc->dev); + + fb_config->xres = 0; + fb_config->yres = 0; + fb_config->bpp = 0; + fb_config->vxres = 0; + fb_config->vyres = 0; + fb_config->xoffset = 0; + fb_config->yoffset = 0; + fb_config->base = 0; + fb_config->pitch = 0; + fb_config->screen_size = 0; + + if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) + fb_config->xres = (int)fdt32_to_cpu(cell); + if (fb_config->xres == 0) + fb_config->xres = FB_WIDTH; + + if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) + fb_config->yres = (uint32_t)fdt32_to_cpu(cell); + if (fb_config->yres == 0) + fb_config->yres = FB_HEIGHT; + + if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) + fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); + if (fb_config->bpp == 0) + fb_config->bpp = FB_DEPTH; + + bus_dmamap_sync(sc->dma_tag, sc->dma_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + mbox = devclass_get_device(devclass_find("mbox"), 0); + if (mbox) { + MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); + MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); + } + bus_dmamap_sync(sc->dma_tag, sc->dma_map, + BUS_DMASYNC_POSTREAD); + + if (fb_config->base != 0) { + device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", + fb_config->xres, fb_config->yres, + fb_config->vxres, fb_config->vyres, + fb_config->xoffset, fb_config->yoffset, + fb_config->bpp); + + + device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", + fb_config->pitch, fb_config->base, + fb_config->screen_size); + + + + + info = malloc(sizeof(struct fb_info), M_DEVBUF, M_WAITOK | M_ZERO); + info->fb_name = device_get_nameunit(sc->dev); + info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); + info->fb_pbase = fb_config->base; + info->fb_size = fb_config->screen_size; + info->fb_bpp = info->fb_depth = fb_config->bpp; + info->fb_stride = fb_config->pitch; + info->fb_width = fb_config->xres; + info->fb_height = fb_config->yres; + + sc->info = info; + + fbd = device_add_child(sc->dev, "fbd", device_get_unit(sc->dev)); + if (fbd == NULL) { + device_printf(sc->dev, "Failed to add fbd child\n"); + return; + } + if (device_probe_and_attach(fbd) != 0) { + device_printf(sc->dev, "Failed to attach fbd device\n"); + return; + } + + + } else { + device_printf(sc->dev, "Failed to set framebuffer info\n"); + return; + } + + config_intrhook_disestablish(&sc->init_hook); +} + +static int +bcm_fb_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb")) + return (ENXIO); + + device_set_desc(dev, "BCM2835 VT framebuffer driver"); + + return (BUS_PROBE_DEFAULT); +} + +static int +bcm_fb_attach(device_t dev) +{ + struct bcmsc_softc *sc = device_get_softc(dev); + int dma_size = sizeof(struct bcm_fb_config); + int err; + + sc->dev = dev; + + err = bus_dma_tag_create( + bus_get_dma_tag(sc->dev), + PAGE_SIZE, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + dma_size, 1, /* maxsize, nsegments */ + dma_size, 0, /* maxsegsize, flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->dma_tag); + + err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, 0, + &sc->dma_map); + if (err) { + device_printf(dev, "cannot allocate framebuffer\n"); + goto fail; + } + + err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, + dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); + + if (err) { + device_printf(dev, "cannot load DMA map\n"); + goto fail; + } + + /* + * We have to wait until interrupts are enabled. + * Mailbox relies on it to get data from VideoCore + */ + sc->init_hook.ich_func = bcm_fb_init; + sc->init_hook.ich_arg = sc; + + if (config_intrhook_establish(&sc->init_hook) != 0) { + device_printf(dev, "failed to establish intrhook\n"); + return (ENOMEM); + } + + return (0); + +fail: + return (ENXIO); +} + + +static void +bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) +{ + bus_addr_t *addr; + + if (err) + return; + + addr = (bus_addr_t*)arg; + *addr = PHYS_TO_VCBUS(segs[0].ds_addr); +} + +static struct fb_info * +bcm_fb_helper_getinfo(device_t dev) +{ + struct bcmsc_softc *sc; + + sc = device_get_softc(dev); + + return (sc->info); +} + +static device_method_t bcm_fb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bcm_fb_probe), + DEVMETHOD(device_attach, bcm_fb_attach), + + /* Framebuffer service methods */ + DEVMETHOD(fb_getinfo, bcm_fb_helper_getinfo), + + DEVMETHOD_END +}; + +static devclass_t bcm_fb_devclass; + +static driver_t bcm_fb_driver = { + "fb", + bcm_fb_methods, + sizeof(struct bcmsc_softc), +}; + +DRIVER_MODULE(bcm2835fb, nexus, bcm_fb_driver, bcm_fb_devclass, 0, 0); diff --git a/sys/arm/broadcom/bcm2835/files.bcm2835 b/sys/arm/broadcom/bcm2835/files.bcm2835 index 6aa7c027eb57..1a905c472afe 100644 --- a/sys/arm/broadcom/bcm2835/files.bcm2835 +++ b/sys/arm/broadcom/bcm2835/files.bcm2835 @@ -3,6 +3,7 @@ arm/broadcom/bcm2835/bcm2835_bsc.c optional bcm2835_bsc arm/broadcom/bcm2835/bcm2835_dma.c standard arm/broadcom/bcm2835/bcm2835_fb.c optional sc +arm/broadcom/bcm2835/bcm2835_fbd.c optional vt arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio arm/broadcom/bcm2835/bcm2835_intr.c standard arm/broadcom/bcm2835/bcm2835_machdep.c standard diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B index f0498eaac4c5..5fe031b9f540 100644 --- a/sys/arm/conf/RPI-B +++ b/sys/arm/conf/RPI-B @@ -66,7 +66,7 @@ device pl011 device pty # Comment following lines for boot console on serial port -device sc +device vt device kbdmux options SC_DFLT_FONT # compile font in makeoptions SC_DFLT_FONT=cp437 From 86b04d42ec2627b9082ff1d34ca11d499383d223 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybalko Date: Tue, 17 Dec 2013 15:34:38 +0000 Subject: [PATCH 114/172] Fix copyright and some style(9) things. Sponsored by: The FreeBSD Foundation --- sys/arm/broadcom/bcm2835/bcm2835_fbd.c | 30 +++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c index c5e6c77a2e52..60a05631f2a9 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c @@ -1,7 +1,11 @@ /*- * Copyright (c) 2012 Oleksandr Tymoshenko + * Copyright (c) 2012, 2013 The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed by Oleksandr Rybalko + * 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: @@ -99,13 +103,14 @@ struct bcmsc_softc { static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); -static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); +static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, + int err); static void bcm_fb_init(void *arg) { - struct bcmsc_softc *sc = arg; - volatile struct bcm_fb_config* fb_config = sc->fb_config; + volatile struct bcm_fb_config *fb_config; + struct bcmsc_softc *sc; struct fb_info *info; phandle_t node; pcell_t cell; @@ -113,6 +118,8 @@ bcm_fb_init(void *arg) device_t fbd; int err = 0; + sc = arg; + fb_config = sc->fb_config; node = ofw_bus_get_node(sc->dev); fb_config->xres = 0; @@ -153,23 +160,25 @@ bcm_fb_init(void *arg) BUS_DMASYNC_POSTREAD); if (fb_config->base != 0) { - device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", + device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb_config->xres, fb_config->yres, fb_config->vxres, fb_config->vyres, fb_config->xoffset, fb_config->yoffset, fb_config->bpp); - device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", + device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", fb_config->pitch, fb_config->base, fb_config->screen_size); - info = malloc(sizeof(struct fb_info), M_DEVBUF, M_WAITOK | M_ZERO); + info = malloc(sizeof(struct fb_info), M_DEVBUF, + M_WAITOK | M_ZERO); info->fb_name = device_get_nameunit(sc->dev); - info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); + info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base, + fb_config->screen_size); info->fb_pbase = fb_config->base; info->fb_size = fb_config->screen_size; info->fb_bpp = info->fb_depth = fb_config->bpp; @@ -179,7 +188,8 @@ bcm_fb_init(void *arg) sc->info = info; - fbd = device_add_child(sc->dev, "fbd", device_get_unit(sc->dev)); + fbd = device_add_child(sc->dev, "fbd", + device_get_unit(sc->dev)); if (fbd == NULL) { device_printf(sc->dev, "Failed to add fbd child\n"); return; @@ -244,8 +254,8 @@ bcm_fb_attach(device_t dev) goto fail; } - /* - * We have to wait until interrupts are enabled. + /* + * We have to wait until interrupts are enabled. * Mailbox relies on it to get data from VideoCore */ sc->init_hook.ich_func = bcm_fb_init; From da0770bd571f551818d86cac0d10f4e65d7e262c Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Tue, 17 Dec 2013 16:45:19 +0000 Subject: [PATCH 115/172] Fix copy/paste typo. MFC after: 1 week --- sys/kern/kern_jail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index e5d0ad70e258..700b7d6c9ad4 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -3047,7 +3047,7 @@ prison_restrict_ip6(struct prison *pr, struct in6_addr *newip6) ii++; continue; } - switch (ij >= ppr->pr_ip4s ? -1 : + switch (ij >= ppr->pr_ip6s ? -1 : qcmp_v6(&pr->pr_ip6[ii], &ppr->pr_ip6[ij])) { case -1: bcopy(pr->pr_ip6 + ii + 1, pr->pr_ip6 + ii, From f26ca5ecde64d1181ffd67c692ed29a8041e01a5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 17 Dec 2013 17:28:02 +0000 Subject: [PATCH 116/172] Do not allow O_EXEC opens for fifo, return EINVAL. Besides not making sense, open(O_EXEC) for fifo creates fifoinfo with zero readers and writers counts, which causes premature free of pipes. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/fs/fifofs/fifo_vnops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index bdb136716294..d3eb281779a4 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -143,7 +143,7 @@ fifo_open(ap) fp = ap->a_fp; td = ap->a_td; ASSERT_VOP_ELOCKED(vp, "fifo_open"); - if (fp == NULL) + if (fp == NULL || (ap->a_mode & FEXEC) != 0) return (EINVAL); if ((fip = vp->v_fifoinfo) == NULL) { error = pipe_named_ctor(&fpipe, td); From 65f05eeb3d0669b49ffa5389c5b4a73bd5e331d4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 17 Dec 2013 17:31:16 +0000 Subject: [PATCH 117/172] If vn_open_vnode() succeeded in opening the vnode, but subsequent advisory lock cannot be obtained, prevent double-close of the vnode in vn_close() called from the fdrop(), by resetting file' f_ops methods. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/kern/vfs_vnops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index da4a914be35a..ec995c7e18a6 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -313,6 +313,9 @@ vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred, vn_lock(vp, lock_flags | LK_RETRY); (void)VOP_CLOSE(vp, fmode, cred, td); vn_finished_write(mp); + /* Prevent second close from fdrop()->vn_close(). */ + if (fp != NULL) + fp->f_ops= &badfileops; return (error); } fp->f_flag |= FHASLOCK; From 7c27d02398c04cb2dad6336dc76d5141ea92ca3e Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 17 Dec 2013 18:30:37 +0000 Subject: [PATCH 118/172] Require a C++11 compiler to build LLDB In practice the old test (using MK_CLANG_IS_CC) is similar, but COMPILER_FEATURES provides the information we actually want to test. Sponsored by: DARPA, AFRL --- share/mk/bsd.own.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index c99ab84a72f1..6aaf32070d67 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -552,10 +552,6 @@ MK_CLANG_EXTRAS:= no MK_CLANG_FULL:= no .endif -.if ${MK_CLANG_IS_CC} == "no" -MK_LLDB:= no -.endif - .if defined(NO_TESTS) # This should be handled above along the handling of all other NO_* options. # However, the above is broken when WITH_*=yes are passed to make(1) as @@ -650,6 +646,10 @@ MK_${var}:= no .endif .endfor +.if !${COMPILER_FEATURES:Mc++11} +MK_LLDB:= no +.endif + .if ${MK_CTF} != "no" CTFCONVERT_CMD= ${CTFCONVERT} ${CTFFLAGS} ${.TARGET} .elif defined(.PARSEDIR) || (defined(MAKE_VERSION) && ${MAKE_VERSION} >= 5201111300) From 08fd2c8bd777e5a0949b2586f13abb9304dcfb9b Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 17 Dec 2013 20:53:22 +0000 Subject: [PATCH 119/172] gcc: fix ICE in rs600 when using -fno-trapping-math. Solves GCC-PR target/30485 Obtained from: gcc 4.3 (rev. 120902; GPLv2) MFC after: 2 weeks --- contrib/gcc/ChangeLog.gcc43 | 6 ++++++ contrib/gcc/config/rs6000/rs6000.c | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/contrib/gcc/ChangeLog.gcc43 b/contrib/gcc/ChangeLog.gcc43 index 98b368d7f18b..3658d190f0d7 100644 --- a/contrib/gcc/ChangeLog.gcc43 +++ b/contrib/gcc/ChangeLog.gcc43 @@ -399,6 +399,12 @@ (override_options): Add PTA_CX16 flag. Set x86_cmpxchg16b for CPUs that have PTA_CX16 set. +2007-01-18 Josh Conner (r120902) + + PR target/30485 + * config/rs6000/rs6000.c (rs6000_emit_vector_compare): Add + support for UNLE, UNLT, UNGE, and UNGT. + 2007-01-17 Eric Christopher (r120846) * config.gcc: Support core2 processor. diff --git a/contrib/gcc/config/rs6000/rs6000.c b/contrib/gcc/config/rs6000/rs6000.c index 287902f0b019..a4d2020c79ea 100644 --- a/contrib/gcc/config/rs6000/rs6000.c +++ b/contrib/gcc/config/rs6000/rs6000.c @@ -11738,10 +11738,18 @@ rs6000_emit_vector_compare (enum rtx_code rcode, try_again = true; break; case NE: - /* Treat A != B as ~(A==B). */ + case UNLE: + case UNLT: + case UNGE: + case UNGT: + /* Invert condition and try again. + e.g., A != B becomes ~(A==B). */ { + enum rtx_code rev_code; enum insn_code nor_code; - rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1, + + rev_code = reverse_condition_maybe_unordered (rcode); + rtx eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, dest_mode); nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code; From 5244c21dd019363b3879761fc657941382ea72c7 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 17 Dec 2013 21:39:40 +0000 Subject: [PATCH 120/172] gcc: fix ICE in rs600 when using -fno-trapping-math. Solve build issue with previous change. Obtained from: gcc 4.3 (rev. 120902; GPLv2) MFC after: 2 weeks --- contrib/gcc/config/rs6000/rs6000.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/gcc/config/rs6000/rs6000.c b/contrib/gcc/config/rs6000/rs6000.c index a4d2020c79ea..7878ed127d64 100644 --- a/contrib/gcc/config/rs6000/rs6000.c +++ b/contrib/gcc/config/rs6000/rs6000.c @@ -11747,10 +11747,11 @@ rs6000_emit_vector_compare (enum rtx_code rcode, { enum rtx_code rev_code; enum insn_code nor_code; + rtx eq_rtx; rev_code = reverse_condition_maybe_unordered (rcode); - rtx eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, - dest_mode); + eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, + dest_mode); nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code; gcc_assert (nor_code != CODE_FOR_nothing); From 88bb82e5118b19bbd29036638f4a4811635b6028 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Tue, 17 Dec 2013 21:41:23 +0000 Subject: [PATCH 121/172] Do not create a hardware IPv6 server if the listen address is not in6addr_any and is not in the CLIP table either. This fixes a reported TOE+IPv6 NULL-dereference panic in do_pass_open_rpl(). While here, stop creating hardware servers for any loopback address. It's just a waste of server tids. MFC after: 1 week --- sys/dev/cxgbe/tom/t4_listen.c | 20 ++++++++++++++++++++ sys/dev/cxgbe/tom/t4_tom.h | 1 + 2 files changed, 21 insertions(+) diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index 17f4adb65dc9..0dc02e3a3ee5 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -203,6 +203,17 @@ alloc_lctx(struct adapter *sc, struct inpcb *inp, struct port_info *pi) return (NULL); } + if (inp->inp_vflag & INP_IPV6 && + !IN6_ARE_ADDR_EQUAL(&in6addr_any, &inp->in6p_laddr)) { + struct tom_data *td = sc->tom_softc; + + lctx->ce = hold_lip(td, &inp->in6p_laddr); + if (lctx->ce == NULL) { + free(lctx, M_CXGBE); + return (NULL); + } + } + lctx->ctrlq = &sc->sge.ctrlq[pi->port_id]; lctx->ofld_rxq = &sc->sge.ofld_rxq[pi->first_ofld_rxq]; refcount_init(&lctx->refcount, 1); @@ -219,6 +230,7 @@ static int free_lctx(struct adapter *sc, struct listen_ctx *lctx) { struct inpcb *inp = lctx->inp; + struct tom_data *td = sc->tom_softc; INP_WLOCK_ASSERT(inp); KASSERT(lctx->refcount == 0, @@ -230,6 +242,8 @@ free_lctx(struct adapter *sc, struct listen_ctx *lctx) CTR4(KTR_CXGBE, "%s: stid %u, lctx %p, inp %p", __func__, lctx->stid, lctx, lctx->inp); + if (lctx->ce) + release_lip(td, lctx->ce); free_stid(sc, lctx); free(lctx, M_CXGBE); @@ -495,6 +509,12 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp) INP_WLOCK_ASSERT(inp); + /* Don't start a hardware listener for any loopback address. */ + if (inp->inp_vflag & INP_IPV6 && IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr)) + return (0); + if (!(inp->inp_vflag & INP_IPV6) && + IN_LOOPBACK(ntohl(inp->inp_laddr.s_addr))) + return (0); #if 0 ADAPTER_LOCK(sc); if (IS_BUSY(sc)) { diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h index 927bc94e1e09..6328240cd494 100644 --- a/sys/dev/cxgbe/tom/t4_tom.h +++ b/sys/dev/cxgbe/tom/t4_tom.h @@ -176,6 +176,7 @@ struct listen_ctx { struct inpcb *inp; /* listening socket's inp */ struct sge_wrq *ctrlq; struct sge_ofld_rxq *ofld_rxq; + struct clip_entry *ce; TAILQ_HEAD(, synq_entry) synq; }; From 78aed5e800412ae5f8d62e60bbd6bb936fad3b07 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Tue, 17 Dec 2013 22:16:27 +0000 Subject: [PATCH 122/172] Simplify contiguous mask checking. Suggested by: glebius MFC after: 2 weeks --- sys/net/radix.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sys/net/radix.c b/sys/net/radix.c index 6b67f6642517..ada27ab022a5 100644 --- a/sys/net/radix.c +++ b/sys/net/radix.c @@ -484,13 +484,13 @@ rn_insert(v_arg, head, dupentry, nodes) struct radix_node * rn_addmask(void *n_arg, struct radix_node_head *maskhead, int search, int skip) { - caddr_t netmask = (caddr_t)n_arg; - register struct radix_node *x; - register caddr_t cp, cplim; - register int b = 0, mlen, j; + unsigned char *netmask = n_arg; + unsigned char *cp, *cplim; + struct radix_node *x; + int b = 0, mlen, j; int maskduplicated, isnormal; struct radix_node *saved_x; - char addmask_key[RADIX_MAX_KEY_LEN]; + unsigned char addmask_key[RADIX_MAX_KEY_LEN]; if ((mlen = LEN(netmask)) > RADIX_MAX_KEY_LEN) mlen = RADIX_MAX_KEY_LEN; @@ -532,20 +532,18 @@ rn_addmask(void *n_arg, struct radix_node_head *maskhead, int search, int skip) * Calculate index of mask, and check for normalcy. * First find the first byte with a 0 bit, then if there are * more bits left (remember we already trimmed the trailing 0's), - * the pattern must be one of those in normal_chars[], or we have + * the bits should be contiguous, otherwise we have got * a non-contiguous mask. */ +#define CONTIG(_c) (((~(_c) + 1) & (_c)) == (unsigned char)(~(_c) + 1)) cplim = netmask + mlen; isnormal = 1; for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) cp++; if (cp != cplim) { - static char normal_chars[] = { - 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; - for (j = 0x80; (j & *cp) != 0; j >>= 1) b++; - if (*cp != normal_chars[b] || cp != (cplim - 1)) + if (!CONTIG(*cp) || cp != (cplim - 1)) isnormal = 0; } b += (cp - netmask) << 3; From 2dcaa2963df6cab0dffe3c6c8562951974260385 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 17 Dec 2013 23:31:51 +0000 Subject: [PATCH 123/172] gcc: small merges from upstream Solves GCC issues: PR middle-end/32602 PR middle-end/32603 Updates the to documentation and processing improvement. Obtained from: gcc 4.3 (rev. 119427, 126278, 126422; GPLv2) MFC after: 2 weeks --- contrib/gcc/ChangeLog.gcc43 | 14 +++++++ contrib/gcc/calls.c | 17 ++++++++- contrib/gcc/cp/ChangeLog.gcc43 | 12 ++++++ contrib/gcc/cp/decl.c | 69 ++++++++++++++++++++++------------ contrib/gcc/cp/method.c | 12 +++--- contrib/gcc/cp/parser.c | 10 +++++ contrib/gcc/doc/cppopts.texi | 4 ++ contrib/gcc/doc/invoke.texi | 6 ++- 8 files changed, 113 insertions(+), 31 deletions(-) diff --git a/contrib/gcc/ChangeLog.gcc43 b/contrib/gcc/ChangeLog.gcc43 index 3658d190f0d7..8537c3bc4ecd 100644 --- a/contrib/gcc/ChangeLog.gcc43 +++ b/contrib/gcc/ChangeLog.gcc43 @@ -45,6 +45,20 @@ * flags.h (force_align_functions_log): Delete. * toplev.c (force_align_functions_log): Delete. +2007-07-06 Josh Conner (r126422) + + PR middle-end/32602 + PR middle-end/32603 + * calls.c (store_one_arg): Handle arguments which are partially + on the stack when detecting argument overlap. + +2007-07-03 Eric Christopher (r126278) + + * doc/cppopts.texi: Add conflicting option note to -dM. + * doc/invoke.texi: Add note about possible conflicts with + -E for -dCHARS and note that -dM will not produce + any results if there is no machine dependent reorg. + 2007-06-28 Geoffrey Keating (r126088) * doc/invoke.texi (C++ Dialect Options): Document diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c index d1fcdadda33e..aa272dfdad26 100644 --- a/contrib/gcc/calls.c +++ b/contrib/gcc/calls.c @@ -4297,6 +4297,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, /* expand_call should ensure this. */ gcc_assert (!arg->locate.offset.var + && arg->locate.size.var == 0 && GET_CODE (size_rtx) == CONST_INT); if (arg->locate.offset.constant > i) @@ -4306,7 +4307,21 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, } else if (arg->locate.offset.constant < i) { - if (i < arg->locate.offset.constant + INTVAL (size_rtx)) + /* Use arg->locate.size.constant instead of size_rtx + because we only care about the part of the argument + on the stack. */ + if (i < (arg->locate.offset.constant + + arg->locate.size.constant)) + sibcall_failure = 1; + } + else + { + /* Even though they appear to be at the same location, + if part of the outgoing argument is in registers, + they aren't really at the same location. Check for + this by making sure that the incoming size is the + same as the outgoing size. */ + if (arg->locate.size.constant != INTVAL (size_rtx)) sibcall_failure = 1; } } diff --git a/contrib/gcc/cp/ChangeLog.gcc43 b/contrib/gcc/cp/ChangeLog.gcc43 index a92ca72fc795..0aa70d1f7c6d 100644 --- a/contrib/gcc/cp/ChangeLog.gcc43 +++ b/contrib/gcc/cp/ChangeLog.gcc43 @@ -62,6 +62,18 @@ * semantics.c (finish_unary_op_expr): Warn only if result overflowed and operands did not. +2006-12-01 Geoffrey Keating (r119427) + + * decl.c (poplevel): Check DECL_INITIAL invariant. + (duplicate_decls): Preserve DECL_INITIAL when eliminating + a new definition in favour of an old declaration. + (start_preparsed_function): Define and document value of + DECL_INITIAL before and after routine. + (finish_function): Check DECL_INITIAL invariant. + * parser.c + (cp_parser_function_definition_from_specifiers_and_declarator): + Skip duplicate function definitions. + 2006-10-31 Geoffrey Keating (r118360) * name-lookup.c (get_anonymous_namespace_name): New. diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index d261165874b2..dcceebaf1fd9 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -758,7 +758,12 @@ poplevel (int keep, int reverse, int functionbody) leave_scope (); if (functionbody) - DECL_INITIAL (current_function_decl) = block; + { + /* The current function is being defined, so its DECL_INITIAL + should be error_mark_node. */ + gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node); + DECL_INITIAL (current_function_decl) = block; + } else if (block) current_binding_level->blocks = chainon (current_binding_level->blocks, block); @@ -1635,13 +1640,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } /* If the new declaration is a definition, update the file and - line information on the declaration. */ + line information on the declaration, and also make + the old declaration the same definition. */ if (DECL_INITIAL (old_result) == NULL_TREE && DECL_INITIAL (new_result) != NULL_TREE) { DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (old_result) = DECL_SOURCE_LOCATION (newdecl); + DECL_INITIAL (old_result) = DECL_INITIAL (new_result); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) DECL_ARGUMENTS (old_result) = DECL_ARGUMENTS (new_result); @@ -10509,7 +10516,13 @@ check_function_type (tree decl, tree current_function_parms) For C++, we must first check whether that datum makes any sense. For example, "class A local_a(1,2);" means that variable local_a is an aggregate of type A, which should have a constructor - applied to it with the argument list [1, 2]. */ + applied to it with the argument list [1, 2]. + + On entry, DECL_INITIAL (decl1) should be NULL_TREE or error_mark_node, + or may be a BLOCK if the function has been defined previously + in this translation unit. On exit, DECL_INITIAL (decl1) will be + error_mark_node if the function has never been defined, or + a BLOCK if the function has been defined somewhere. */ void start_preparsed_function (tree decl1, tree attrs, int flags) @@ -10638,24 +10651,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags) cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl); } - /* Initialize RTL machinery. We cannot do this until - CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this - even when processing a template; this is how we get - CFUN set up, and our per-function variables initialized. - FIXME factor out the non-RTL stuff. */ - bl = current_binding_level; - allocate_struct_function (decl1); - current_binding_level = bl; - - /* Even though we're inside a function body, we still don't want to - call expand_expr to calculate the size of a variable-sized array. - We haven't necessarily assigned RTL to all variables yet, so it's - not safe to try to expand expressions involving them. */ - cfun->x_dont_save_pending_sizes_p = 1; - - /* Start the statement-tree, start the tree now. */ - DECL_SAVED_TREE (decl1) = push_stmt_list (); - /* Let the user know we're compiling this function. */ announce_function (decl1); @@ -10701,9 +10696,33 @@ start_preparsed_function (tree decl1, tree attrs, int flags) maybe_apply_pragma_weak (decl1); } - /* Reset these in case the call to pushdecl changed them. */ + /* Reset this in case the call to pushdecl changed it. */ current_function_decl = decl1; - cfun->decl = decl1; + + gcc_assert (DECL_INITIAL (decl1)); + + /* This function may already have been parsed, in which case just + return; our caller will skip over the body without parsing. */ + if (DECL_INITIAL (decl1) != error_mark_node) + return; + + /* Initialize RTL machinery. We cannot do this until + CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this + even when processing a template; this is how we get + CFUN set up, and our per-function variables initialized. + FIXME factor out the non-RTL stuff. */ + bl = current_binding_level; + allocate_struct_function (decl1); + current_binding_level = bl; + + /* Even though we're inside a function body, we still don't want to + call expand_expr to calculate the size of a variable-sized array. + We haven't necessarily assigned RTL to all variables yet, so it's + not safe to try to expand expressions involving them. */ + cfun->x_dont_save_pending_sizes_p = 1; + + /* Start the statement-tree, start the tree now. */ + DECL_SAVED_TREE (decl1) = push_stmt_list (); /* If we are (erroneously) defining a function that we have already defined before, wipe out what we knew before. */ @@ -11212,6 +11231,10 @@ finish_function (int flags) which then got a warning when stored in a ptr-to-function variable. */ gcc_assert (building_stmt_tree ()); + /* The current function is being defined, so its DECL_INITIAL should + be set, and unless there's a multiple definition, it should be + error_mark_node. */ + gcc_assert (DECL_INITIAL (fndecl) == error_mark_node); /* For a cloned function, we've already got all the code we need; there's no need to add any extra bits. */ diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c index ded0af047161..71e34f064c1a 100644 --- a/contrib/gcc/cp/method.c +++ b/contrib/gcc/cp/method.c @@ -407,10 +407,6 @@ use_thunk (tree thunk_fndecl, bool emit_p) } } - /* The back-end expects DECL_INITIAL to contain a BLOCK, so we - create one. */ - DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); - /* Set up cloned argument trees for the thunk. */ t = NULL_TREE; for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) @@ -424,17 +420,23 @@ use_thunk (tree thunk_fndecl, bool emit_p) } a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; - BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a; if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, virtual_value, alias)) { const char *fnname; + tree fn_block; + current_function_decl = thunk_fndecl; DECL_RESULT (thunk_fndecl) = build_decl (RESULT_DECL, 0, integer_type_node); fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); + /* The back-end expects DECL_INITIAL to contain a BLOCK, so we + create one. */ + fn_block = make_node (BLOCK); + BLOCK_VARS (fn_block) = a; + DECL_INITIAL (thunk_fndecl) = fn_block; init_function_start (thunk_fndecl); current_function_is_thunk = 1; assemble_start_function (thunk_fndecl, fnname); diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c index edbd37aa8eda..a021d5bcdfa0 100644 --- a/contrib/gcc/cp/parser.c +++ b/contrib/gcc/cp/parser.c @@ -15637,6 +15637,16 @@ cp_parser_function_definition_from_specifiers_and_declarator cp_parser_skip_to_end_of_block_or_statement (parser); fn = error_mark_node; } + else if (DECL_INITIAL (current_function_decl) != error_mark_node) + { + /* Seen already, skip it. An error message has already been output. */ + cp_parser_skip_to_end_of_block_or_statement (parser); + fn = current_function_decl; + current_function_decl = NULL_TREE; + /* If this is a function from a class, pop the nested class. */ + if (current_class_name) + pop_nested_class (); + } else fn = cp_parser_function_definition_after_declarator (parser, /*inline_p=*/false); diff --git a/contrib/gcc/doc/cppopts.texi b/contrib/gcc/doc/cppopts.texi index 69738cc2202f..af93320da104 100644 --- a/contrib/gcc/doc/cppopts.texi +++ b/contrib/gcc/doc/cppopts.texi @@ -645,6 +645,10 @@ touch foo.h; cpp -dM foo.h @noindent will show all the predefined macros. +If you use @option{-dM} without the @option{-E} option, @option{-dM} is +interpreted as a synonym for @option{-fdump-rtl-mach}. +@xref{Debugging Options, , ,gcc}. + @item D @opindex dD Like @samp{M} except in two respects: it does @emph{not} include the diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi index 165bcc4fe945..5263e915c336 100644 --- a/contrib/gcc/doc/invoke.texi +++ b/contrib/gcc/doc/invoke.texi @@ -3675,7 +3675,9 @@ Says to make debugging dumps during compilation at times specified by compiler. The file names for most of the dumps are made by appending a pass number and a word to the @var{dumpname}. @var{dumpname} is generated from the name of the output file, if explicitly specified and it is not -an executable, otherwise it is the basename of the source file. +an executable, otherwise it is the basename of the source file. These +switches may have different effects when @option{-E} is used for +preprocessing. Most debug dumps can be enabled either passing a letter to the @option{-d} option, or with a long @option{-fdump-rtl} switch; here are the possible @@ -3810,7 +3812,7 @@ Dump after modulo scheduling, to @file{@var{file}.136r.sms}. @opindex dM @opindex fdump-rtl-mach Dump after performing the machine dependent reorganization pass, to -@file{@var{file}.155r.mach}. +@file{@var{file}.155r.mach} if that pass exists. @item -dn @itemx -fdump-rtl-rnreg From 9596cafea096f3e4e7846a9821e13472a77b95a9 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 18 Dec 2013 00:10:30 +0000 Subject: [PATCH 124/172] gcc: point to our address for bug reports. As recommended by the FSF in gcc/version.c : "If you distribute a modified version of GCC, please change this to refer to a document giving instructions for reporting bugs to you, not us." MFC after: 2 weeks --- contrib/gcc/version.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gcc/version.c b/contrib/gcc/version.c index 0da50b1c7b9f..dd972acf127b 100644 --- a/contrib/gcc/version.c +++ b/contrib/gcc/version.c @@ -18,7 +18,7 @@ forward us bugs reported to you, if you determine that they are not bugs in your modifications.) */ -const char bug_report_url[] = ""; +const char bug_report_url[] = ""; /* The complete version string, assembled from several pieces. BASEVER, DATESTAMP, and DEVPHASE are defined by the Makefile. */ From fdc3c84b5be61b1aeadf02ba30c4ef632f107205 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybalko Date: Wed, 18 Dec 2013 00:14:58 +0000 Subject: [PATCH 125/172] Skip processing of R.Alt as a second Alt key, if sysctl kern.vt.enable_altgr is not zero. Submitted by: andreast Sponsored by: The FreeBSD Foundation --- sys/dev/vt/vt_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 95bc531cf70c..8cb2a5e66c21 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -113,6 +113,7 @@ const struct terminal_class vt_termclass = { int sc_txtmouse_no_retrace_wait; static SYSCTL_NODE(_kern, OID_AUTO, vt, CTLFLAG_RD, 0, "Newcons parameters"); +VT_SYSCTL_INT(enable_altgr, 0, "Enable AltGr key (Do not assume R.Alt as Alt)"); VT_SYSCTL_INT(debug, 0, "Newcons debug level"); VT_SYSCTL_INT(deadtimer, 15, "Time to wait busy process in VT_PROCESS mode"); VT_SYSCTL_INT(suspendswitch, 1, "Switch to VT0 before suspend"); @@ -404,6 +405,8 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c) if (c & RELKEY) { switch (c & ~RELKEY) { case (SPCLKEY | RALT): + if (vt_enable_altgr != 0) + break; case (SPCLKEY | LALT): vd->vd_kbstate &= ~ALKED; } From 7159310fa68979b45de779f0e49522d3262eb0a4 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 18 Dec 2013 01:41:52 +0000 Subject: [PATCH 126/172] The fasttrap fork handler is responsible for removing tracepoints in the child process that were inherited from its parent. However, this should not be done in the case of a vfork, since the fork handler ends up removing the tracepoints from the shared vm space, and userland DTrace probes in the parent will no longer fire as a result. Now the child of a vfork may trigger userland DTrace probes enabled in its parent, so modify the fasttrap probe handler to handle this case and handle the child process in the same way that it would handle the traced process. In particular, if once traces function foo() in a process that vforks, and the child calls foo(), fasttrap will treat this call as having come from the parent. This is the behaviour of the upstream code. While here, add #ifdef guards to some code that isn't present upstream. MFC after: 1 month --- .../uts/intel/dtrace/fasttrap_isa.c | 33 ++++++++++++++----- sys/kern/kern_fork.c | 10 +++--- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c index c803a01a79f4..53ad33b39cf1 100644 --- a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c +++ b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c @@ -1001,6 +1001,9 @@ int fasttrap_pid_probe(struct reg *rp) { proc_t *p = curproc; +#if !defined(sun) + proc_t *pp; +#endif uintptr_t pc = rp->r_rip - 1; uintptr_t new_pc = 0; fasttrap_bucket_t *bucket; @@ -1036,24 +1039,32 @@ fasttrap_pid_probe(struct reg *rp) curthread->t_dtrace_regv = 0; #endif -#if defined(sun) /* * Treat a child created by a call to vfork(2) as if it were its * parent. We know that there's only one thread of control in such a * process: this one. */ +#if defined(sun) while (p->p_flag & SVFORK) { p = p->p_parent; } -#endif + + pid = p->p_pid; + pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; + mutex_enter(pid_mtx); +#else + pp = p; + sx_slock(&proctree_lock); + while (pp->p_vmspace == pp->p_pptr->p_vmspace) + pp = pp->p_pptr; + pid = pp->p_pid; + sx_sunlock(&proctree_lock); + pp = NULL; PROC_LOCK(p); _PHOLD(p); - pid = p->p_pid; -#if defined(sun) - pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; - mutex_enter(pid_mtx); #endif + bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; /* @@ -1073,9 +1084,10 @@ fasttrap_pid_probe(struct reg *rp) if (tp == NULL) { #if defined(sun) mutex_exit(pid_mtx); -#endif +#else _PRELE(p); PROC_UNLOCK(p); +#endif return (-1); } @@ -1197,9 +1209,10 @@ fasttrap_pid_probe(struct reg *rp) * tracepoint again later if we need to light up any return probes. */ tp_local = *tp; - PROC_UNLOCK(p); #if defined(sun) mutex_exit(pid_mtx); +#else + PROC_UNLOCK(p); #endif tp = &tp_local; @@ -1749,7 +1762,7 @@ fasttrap_pid_probe(struct reg *rp) #if defined(sun) if (fasttrap_copyout(scratch, (char *)addr, i)) { #else - if (uwrite(curproc, scratch, i, addr)) { + if (uwrite(p, scratch, i, addr)) { #endif fasttrap_sigtrap(p, curthread, pc); new_pc = pc; @@ -1808,10 +1821,12 @@ fasttrap_pid_probe(struct reg *rp) rp->r_rip = new_pc; +#if !defined(sun) PROC_LOCK(p); proc_write_regs(curthread, rp); _PRELE(p); PROC_UNLOCK(p); +#endif return (0); } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 3198bd5938be..b3d9c243f942 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -676,12 +676,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, #ifdef KDTRACE_HOOKS /* - * Tell the DTrace fasttrap provider about the new process - * if it has registered an interest. We have to do this only after - * p_state is PRS_NORMAL since the fasttrap module will use pfind() - * later on. + * Tell the DTrace fasttrap provider about the new process so that any + * tracepoints inherited from the parent can be removed. We have to do + * this only after p_state is PRS_NORMAL since the fasttrap module will + * use pfind() later on. */ - if (dtrace_fasttrap_fork) + if ((flags & RFMEM) == 0 && dtrace_fasttrap_fork) dtrace_fasttrap_fork(p1, p2); #endif if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED | From 55888cfaa2584256e00c6252483c743da83ea9f9 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Wed, 18 Dec 2013 03:58:51 +0000 Subject: [PATCH 127/172] Rename the ambiguously named 'vm_setup_msi()' and 'vm_setup_msix()' to 'vm_setup_pptdev_msi()' and 'vm_setup_pptdev_msix()' respectively. It should now be clear that these functions operate on passthru devices. --- lib/libvmmapi/vmmapi.c | 8 ++++---- lib/libvmmapi/vmmapi.h | 9 +++++---- usr.sbin/bhyve/pci_passthru.c | 20 +++++++++----------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 9d15175452a7..463ae7e5ec38 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -563,8 +563,8 @@ vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func, } int -vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - uint64_t addr, uint64_t msg, int numvec) +vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, + uint64_t addr, uint64_t msg, int numvec) { struct vm_pptdev_msi pptmsi; @@ -581,8 +581,8 @@ vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, } int -vm_setup_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int idx, uint64_t addr, uint64_t msg, uint32_t vector_control) +vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, + int idx, uint64_t addr, uint64_t msg, uint32_t vector_control) { struct vm_pptdev_msix pptmsix; diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index 6de584d69b5e..52e7e92bebbd 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -82,10 +82,11 @@ int vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func); int vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func); int vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); -int vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - uint64_t addr, uint64_t msg, int numvec); -int vm_setup_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func, - int idx, uint64_t addr, uint64_t msg, uint32_t vector_control); +int vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, + int func, uint64_t addr, uint64_t msg, int numvec); +int vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, + int func, int idx, uint64_t addr, uint64_t msg, + uint32_t vector_control); /* * Return a pointer to the statistics buffer. Note that this is not MT-safe. diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index 25654750938b..dab5ffc03bcf 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -345,12 +345,10 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc, /* If the entry is masked, don't set it up */ if ((entry->vector_control & PCIM_MSIX_VCTRL_MASK) == 0 || (vector_control & PCIM_MSIX_VCTRL_MASK) == 0) { - error = vm_setup_msix(ctx, vcpu, sc->psc_sel.pc_bus, - sc->psc_sel.pc_dev, - sc->psc_sel.pc_func, - index, entry->addr, - entry->msg_data, - entry->vector_control); + error = vm_setup_pptdev_msix(ctx, vcpu, + sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, + sc->psc_sel.pc_func, index, entry->addr, + entry->msg_data, entry->vector_control); } } } @@ -652,12 +650,12 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, if (msicap_access(sc, coff)) { msicap_cfgwrite(pi, sc->psc_msi.capoff, coff, bytes, val); - error = vm_setup_msi(ctx, vcpu, sc->psc_sel.pc_bus, + error = vm_setup_pptdev_msi(ctx, vcpu, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, pi->pi_msi.addr, pi->pi_msi.msg_data, pi->pi_msi.maxmsgnum); if (error != 0) { - printf("vm_setup_msi returned error %d\r\n", errno); + printf("vm_setup_pptdev_msi error %d\r\n", errno); exit(1); } return (0); @@ -668,7 +666,7 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, if (pi->pi_msix.enabled) { msix_table_entries = pi->pi_msix.table_count; for (i = 0; i < msix_table_entries; i++) { - error = vm_setup_msix(ctx, vcpu, + error = vm_setup_pptdev_msix(ctx, vcpu, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, i, pi->pi_msix.table[i].addr, @@ -676,8 +674,8 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, pi->pi_msix.table[i].vector_control); if (error) { - printf("vm_setup_msix error %d\r\n", - errno); + printf("vm_setup_pptdev_msix error " + "%d\r\n", errno); exit(1); } } From 256d9417f824070f10af7b6f07cf84a0a2176ba3 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Wed, 18 Dec 2013 04:36:35 +0000 Subject: [PATCH 128/172] Fix build. --- sys/dev/netmap/netmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c index 033cd3059e17..478d9374937f 100644 --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -151,6 +151,7 @@ ports attached to the switch) #include /* bus_dmamap_* */ #include #include +#include /* reduce conditional code */ From 157a2d49a0145a43cfa4d9116608afddf61e5ced Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 18 Dec 2013 04:44:38 +0000 Subject: [PATCH 129/172] Support long filenames. Obtained from: Juniper Networks, Inc. --- lib/libstand/dosfs.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/libstand/dosfs.c b/lib/libstand/dosfs.c index e15ecdcf6fb3..f43b7213ee7e 100644 --- a/lib/libstand/dosfs.c +++ b/lib/libstand/dosfs.c @@ -381,21 +381,32 @@ dos_readdir(struct open_file *fd, struct dirent *d) if (dd.de.name[0] == 0xe5) continue; - /* Skip volume labels */ - if (dd.de.attr & FA_LABEL) - continue; - - if ((dd.de.attr & FA_MASK) == FA_XDE) { - if (dd.xde.seq & 0x40) - chk = dd.xde.chk; - else if (dd.xde.seq != xdn - 1 || dd.xde.chk != chk) - continue; - x = dd.xde.seq & ~0x40; - if (x < 1 || x > 20) { - x = 0; + /* Check if directory entry is volume label */ + if (dd.de.attr & FA_LABEL) { + /* + * If volume label set, check if the current entry is + * extended entry (FA_XDE) for long file names. + */ + if ((dd.de.attr & FA_MASK) == FA_XDE) { + /* + * Read through all following extended entries + * to get the long file name. 0x40 marks the + * last entry containing part of long file name. + */ + if (dd.xde.seq & 0x40) + chk = dd.xde.chk; + else if (dd.xde.seq != xdn - 1 || dd.xde.chk != chk) + continue; + x = dd.xde.seq & ~0x40; + if (x < 1 || x > 20) { + x = 0; + continue; + } + cp_xdnm(fn, &dd.xde); + } else { + /* skip only volume label entries */ continue; } - cp_xdnm(fn, &dd.xde); } else { if (xdn == 1) { x = 0; From 983d2efd201a744b938622d1564002a524fcf9f9 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 18 Dec 2013 04:52:30 +0000 Subject: [PATCH 130/172] Clear f_rabuf after freeing the memory it points to. This prevents a possible double free. Obtained from: Juniper Networks, Inc. --- lib/libstand/close.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/libstand/close.c b/lib/libstand/close.c index 61b1b0d99ffe..939f025b8fd0 100644 --- a/lib/libstand/close.c +++ b/lib/libstand/close.c @@ -75,8 +75,10 @@ close(int fd) errno = EBADF; return (-1); } - if (f->f_rabuf != NULL) + if (f->f_rabuf != NULL) { free(f->f_rabuf); + f->f_rabuf = NULL; + } if (!(f->f_flags & F_RAW) && f->f_ops) err1 = (f->f_ops->fo_close)(f); if (!(f->f_flags & F_NODEV) && f->f_dev) From 3de8386283e6a27d8cbadc8da6c0839ba3399b3b Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Wed, 18 Dec 2013 06:24:21 +0000 Subject: [PATCH 131/172] Use vmcs_read() and vmcs_write() in preference to vmread() and vmwrite() respectively. The vmcs_xxx() functions provide inline error checking of all accesses to the VMCS. --- sys/amd64/vmm/intel/vmcs.c | 15 +-- sys/amd64/vmm/intel/vmcs.h | 21 +++- sys/amd64/vmm/intel/vmx.c | 173 +++++++---------------------- sys/amd64/vmm/intel/vmx_genassym.c | 2 +- 4 files changed, 62 insertions(+), 149 deletions(-) diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c index 5b30accc7961..980eac11a5f5 100644 --- a/sys/amd64/vmm/intel/vmcs.c +++ b/sys/amd64/vmm/intel/vmcs.c @@ -41,8 +41,8 @@ __FBSDID("$FreeBSD$"); #include #include #include "vmm_host.h" -#include "vmcs.h" #include "vmx_cpufunc.h" +#include "vmcs.h" #include "ept.h" #include "vmx.h" @@ -454,19 +454,6 @@ vmcs_set_defaults(struct vmcs *vmcs, return (error); } -uint64_t -vmcs_read(uint32_t encoding) -{ - int error; - uint64_t val; - - error = vmread(encoding, &val); - if (error != 0) - panic("vmcs_read(%u) error %d", encoding, error); - - return (val); -} - #ifdef DDB extern int vmxon_enabled[]; diff --git a/sys/amd64/vmm/intel/vmcs.h b/sys/amd64/vmm/intel/vmcs.h index a915c409557d..b1e288398d5c 100644 --- a/sys/amd64/vmm/intel/vmcs.h +++ b/sys/amd64/vmm/intel/vmcs.h @@ -58,7 +58,26 @@ int vmcs_getdesc(struct vmcs *vmcs, int ident, struct seg_desc *desc); int vmcs_setdesc(struct vmcs *vmcs, int ident, struct seg_desc *desc); -uint64_t vmcs_read(uint32_t encoding); + +static __inline uint64_t +vmcs_read(uint32_t encoding) +{ + int error; + uint64_t val; + + error = vmread(encoding, &val); + KASSERT(error == 0, ("vmcs_read(%u) error %d", encoding, error)); + return (val); +} + +static __inline void +vmcs_write(uint32_t encoding, uint64_t val) +{ + int error; + + error = vmwrite(encoding, val); + KASSERT(error == 0, ("vmcs_write(%u) error %d", encoding, error)); +} #define vmexit_instruction_length() vmcs_read(VMCS_EXIT_INSTRUCTION_LENGTH) #define vmcs_guest_rip() vmcs_read(VMCS_GUEST_RIP) diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 1877598f10f1..42daa7f6f4a8 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -324,9 +324,8 @@ vmx_setjmp_trace(struct vmx *vmx, int vcpu, struct vmxctx *vmxctx, int rc) VCPU_CTR2((vmx)->vm, (vcpu), "setjmp return code %s(%d)", vmx_setjmp_rc2str(rc), rc); - host_rsp = host_rip = ~0; - vmread(VMCS_HOST_RIP, &host_rip); - vmread(VMCS_HOST_RSP, &host_rsp); + host_rip = vmcs_read(VMCS_HOST_RIP); + host_rsp = vmcs_read(VMCS_HOST_RSP); VCPU_CTR2((vmx)->vm, (vcpu), "vmcs host_rip 0x%016lx, host_rsp %#lx", host_rip, host_rsp); @@ -909,10 +908,10 @@ vmx_astpending_trace(struct vmx *vmx, int vcpu, uint64_t rip) #endif } -static int +static void vmx_set_pcpu_defaults(struct vmx *vmx, int vcpu) { - int error, lastcpu; + int lastcpu; struct vmxstate *vmxstate; struct invvpid_desc invvpid_desc = { 0 }; @@ -920,24 +919,14 @@ vmx_set_pcpu_defaults(struct vmx *vmx, int vcpu) lastcpu = vmxstate->lastcpu; vmxstate->lastcpu = curcpu; - if (lastcpu == curcpu) { - error = 0; - goto done; - } + if (lastcpu == curcpu) + return; vmm_stat_incr(vmx->vm, vcpu, VCPU_MIGRATIONS, 1); - error = vmwrite(VMCS_HOST_TR_BASE, vmm_get_host_trbase()); - if (error != 0) - goto done; - - error = vmwrite(VMCS_HOST_GDTR_BASE, vmm_get_host_gdtrbase()); - if (error != 0) - goto done; - - error = vmwrite(VMCS_HOST_GS_BASE, vmm_get_host_gsbase()); - if (error != 0) - goto done; + vmcs_write(VMCS_HOST_TR_BASE, vmm_get_host_trbase()); + vmcs_write(VMCS_HOST_GDTR_BASE, vmm_get_host_gdtrbase()); + vmcs_write(VMCS_HOST_GS_BASE, vmm_get_host_gsbase()); /* * If we are using VPIDs then invalidate all mappings tagged with 'vpid' @@ -958,18 +947,6 @@ vmx_set_pcpu_defaults(struct vmx *vmx, int vcpu) invvpid_desc.vpid = vmxstate->vpid; invvpid(INVVPID_TYPE_SINGLE_CONTEXT, invvpid_desc); } -done: - return (error); -} - -static void -vm_exit_update_rip(struct vm_exit *vmexit) -{ - int error; - - error = vmwrite(VMCS_GUEST_RIP, vmexit->rip + vmexit->inst_length); - if (error) - panic("vmx_run: error %d writing to VMCS_GUEST_RIP", error); } /* @@ -980,66 +957,45 @@ CTASSERT((PROCBASED_CTLS_ONE_SETTING & PROCBASED_INT_WINDOW_EXITING) != 0); static void __inline vmx_set_int_window_exiting(struct vmx *vmx, int vcpu) { - int error; vmx->cap[vcpu].proc_ctls |= PROCBASED_INT_WINDOW_EXITING; - - error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); - if (error) - panic("vmx_set_int_window_exiting: vmwrite error %d", error); + vmcs_write(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); } static void __inline vmx_clear_int_window_exiting(struct vmx *vmx, int vcpu) { - int error; vmx->cap[vcpu].proc_ctls &= ~PROCBASED_INT_WINDOW_EXITING; - - error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); - if (error) - panic("vmx_clear_int_window_exiting: vmwrite error %d", error); + vmcs_write(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); } static void __inline vmx_set_nmi_window_exiting(struct vmx *vmx, int vcpu) { - int error; vmx->cap[vcpu].proc_ctls |= PROCBASED_NMI_WINDOW_EXITING; - - error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); - if (error) - panic("vmx_set_nmi_window_exiting: vmwrite error %d", error); + vmcs_write(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); } static void __inline vmx_clear_nmi_window_exiting(struct vmx *vmx, int vcpu) { - int error; vmx->cap[vcpu].proc_ctls &= ~PROCBASED_NMI_WINDOW_EXITING; - - error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); - if (error) - panic("vmx_clear_nmi_window_exiting: vmwrite error %d", error); + vmcs_write(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls); } static int vmx_inject_nmi(struct vmx *vmx, int vcpu) { - int error; uint64_t info, interruptibility; /* Bail out if no NMI requested */ if (!vm_nmi_pending(vmx->vm, vcpu)) return (0); - error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility); - if (error) { - panic("vmx_inject_nmi: vmread(interruptibility) %d", - error); - } + interruptibility = vmcs_read(VMCS_GUEST_INTERRUPTIBILITY); if (interruptibility & nmi_blocking_bits) goto nmiblocked; @@ -1049,10 +1005,7 @@ vmx_inject_nmi(struct vmx *vmx, int vcpu) */ info = VMCS_INTERRUPTION_INFO_NMI | VMCS_INTERRUPTION_INFO_VALID; info |= IDT_NMI; - - error = vmwrite(VMCS_ENTRY_INTR_INFO, info); - if (error) - panic("vmx_inject_nmi: vmwrite(intrinfo) %d", error); + vmcs_write(VMCS_ENTRY_INTR_INFO, info); VCPU_CTR0(vmx->vm, vcpu, "Injecting vNMI"); @@ -1074,7 +1027,7 @@ vmx_inject_nmi(struct vmx *vmx, int vcpu) static void vmx_inject_interrupts(struct vmx *vmx, int vcpu) { - int error, vector; + int vector; uint64_t info, rflags, interruptibility; const int HWINTR_BLOCKED = VMCS_INTERRUPTIBILITY_STI_BLOCKING | @@ -1087,9 +1040,7 @@ vmx_inject_interrupts(struct vmx *vmx, int vcpu) * VM entry but the actual entry into guest mode was aborted * because of a pending AST. */ - error = vmread(VMCS_ENTRY_INTR_INFO, &info); - if (error) - panic("vmx_inject_interrupts: vmread(intrinfo) %d", error); + info = vmcs_read(VMCS_ENTRY_INTR_INFO); if (info & VMCS_INTERRUPTION_INFO_VALID) return; @@ -1108,27 +1059,18 @@ vmx_inject_interrupts(struct vmx *vmx, int vcpu) panic("vmx_inject_interrupts: invalid vector %d\n", vector); /* Check RFLAGS.IF and the interruptibility state of the guest */ - error = vmread(VMCS_GUEST_RFLAGS, &rflags); - if (error) - panic("vmx_inject_interrupts: vmread(rflags) %d", error); - + rflags = vmcs_read(VMCS_GUEST_RFLAGS); if ((rflags & PSL_I) == 0) goto cantinject; - error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility); - if (error) { - panic("vmx_inject_interrupts: vmread(interruptibility) %d", - error); - } + interruptibility = vmcs_read(VMCS_GUEST_INTERRUPTIBILITY); if (interruptibility & HWINTR_BLOCKED) goto cantinject; /* Inject the interrupt */ info = VMCS_INTERRUPTION_INFO_HW_INTR | VMCS_INTERRUPTION_INFO_VALID; info |= vector; - error = vmwrite(VMCS_ENTRY_INTR_INFO, info); - if (error) - panic("vmx_inject_interrupts: vmwrite(intrinfo) %d", error); + vmcs_write(VMCS_ENTRY_INTR_INFO, info); /* Update the Local APIC ISR */ lapic_intr_accepted(vmx->vm, vcpu, vector); @@ -1150,7 +1092,7 @@ vmx_inject_interrupts(struct vmx *vmx, int vcpu) static int vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) { - int error, cr, vmcs_guest_cr, vmcs_shadow_cr; + int cr, vmcs_guest_cr, vmcs_shadow_cr; uint64_t crval, regval, ones_mask, zeros_mask; const struct vmxctx *vmxctx; @@ -1165,7 +1107,7 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) vmxctx = &vmx->ctx[vcpu]; /* - * We must use vmwrite() directly here because vmcs_setreg() will + * We must use vmcs_write() directly here because vmcs_setreg() will * call vmclear(vmcs) as a side-effect which we certainly don't want. */ switch ((exitqual >> 8) & 0xf) { @@ -1182,11 +1124,7 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) regval = vmxctx->guest_rbx; break; case 4: - error = vmread(VMCS_GUEST_RSP, ®val); - if (error) { - panic("vmx_emulate_cr_access: " - "error %d reading guest rsp", error); - } + regval = vmcs_read(VMCS_GUEST_RSP); break; case 5: regval = vmxctx->guest_rbp; @@ -1234,20 +1172,11 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) vmcs_guest_cr = VMCS_GUEST_CR4; vmcs_shadow_cr = VMCS_CR4_SHADOW; } - - error = vmwrite(vmcs_shadow_cr, regval); - if (error) { - panic("vmx_emulate_cr_access: error %d writing cr%d shadow", - error, cr); - } + vmcs_write(vmcs_shadow_cr, regval); crval = regval | ones_mask; crval &= ~zeros_mask; - error = vmwrite(vmcs_guest_cr, crval); - if (error) { - panic("vmx_emulate_cr_access: error %d writing cr%d", - error, cr); - } + vmcs_write(vmcs_guest_cr, crval); if (cr == 0 && regval & CR0_PG) { uint64_t efer, entry_ctls; @@ -1257,29 +1186,13 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) * the "IA-32e mode guest" bit in VM-entry control must be * equal. */ - error = vmread(VMCS_GUEST_IA32_EFER, &efer); - if (error) { - panic("vmx_emulate_cr_access: error %d efer read", - error); - } + efer = vmcs_read(VMCS_GUEST_IA32_EFER); if (efer & EFER_LME) { efer |= EFER_LMA; - error = vmwrite(VMCS_GUEST_IA32_EFER, efer); - if (error) { - panic("vmx_emulate_cr_access: error %d" - " efer write", error); - } - error = vmread(VMCS_ENTRY_CTLS, &entry_ctls); - if (error) { - panic("vmx_emulate_cr_access: error %d" - " entry ctls read", error); - } + vmcs_write(VMCS_GUEST_IA32_EFER, efer); + entry_ctls = vmcs_read(VMCS_ENTRY_CTLS); entry_ctls |= VM_ENTRY_GUEST_LMA; - error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls); - if (error) { - panic("vmx_emulate_cr_access: error %d" - " entry ctls write", error); - } + vmcs_write(VMCS_ENTRY_CTLS, entry_ctls); } } @@ -1336,7 +1249,7 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) struct vmcs *vmcs; struct vmxctx *vmxctx; uint32_t eax, ecx, edx, idtvec_info, idtvec_err, reason; - uint64_t qual, gpa, rflags; + uint64_t qual, gpa; bool retu; handled = 0; @@ -1365,12 +1278,13 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) idtvec_info = vmcs_idt_vectoring_info(); if (idtvec_info & VMCS_IDT_VEC_VALID) { idtvec_info &= ~(1 << 12); /* clear undefined bit */ - vmwrite(VMCS_ENTRY_INTR_INFO, idtvec_info); + vmcs_write(VMCS_ENTRY_INTR_INFO, idtvec_info); if (idtvec_info & VMCS_IDT_VEC_ERRCODE_VALID) { idtvec_err = vmcs_idt_vectoring_err(); - vmwrite(VMCS_ENTRY_EXCEPTION_ERROR, idtvec_err); + vmcs_write(VMCS_ENTRY_EXCEPTION_ERROR, + idtvec_err); } - vmwrite(VMCS_ENTRY_INST_LENGTH, vmexit->inst_length); + vmcs_write(VMCS_ENTRY_INST_LENGTH, vmexit->inst_length); } default: break; @@ -1419,10 +1333,8 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) break; case EXIT_REASON_HLT: vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1); - if ((error = vmread(VMCS_GUEST_RFLAGS, &rflags)) != 0) - panic("vmx_exit_process: vmread(rflags) %d", error); vmexit->exitcode = VM_EXITCODE_HLT; - vmexit->u.hlt.rflags = rflags; + vmexit->u.hlt.rflags = vmcs_read(VMCS_GUEST_RFLAGS); break; case EXIT_REASON_MTF: vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1); @@ -1509,9 +1421,9 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) * the one we just processed. Therefore we update the * guest rip in the VMCS and in 'vmexit'. */ - vm_exit_update_rip(vmexit); vmexit->rip += vmexit->inst_length; vmexit->inst_length = 0; + vmcs_write(VMCS_GUEST_RIP, vmexit->rip); } else { if (vmexit->exitcode == VM_EXITCODE_BOGUS) { /* @@ -1533,7 +1445,7 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) static int vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap) { - int error, vie, rc, handled, astpending; + int vie, rc, handled, astpending; uint32_t exit_reason; struct vmx *vmx; struct vmxctx *vmxctx; @@ -1566,14 +1478,9 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap) * If the life of a virtual machine was spent entirely in the context * of a single process we could do this once in vmcs_set_defaults(). */ - if ((error = vmwrite(VMCS_HOST_CR3, rcr3())) != 0) - panic("vmx_run: error %d writing to VMCS_HOST_CR3", error); - - if ((error = vmwrite(VMCS_GUEST_RIP, rip)) != 0) - panic("vmx_run: error %d writing to VMCS_GUEST_RIP", error); - - if ((error = vmx_set_pcpu_defaults(vmx, vcpu)) != 0) - panic("vmx_run: error %d setting up pcpu defaults", error); + vmcs_write(VMCS_HOST_CR3, rcr3()); + vmcs_write(VMCS_GUEST_RIP, rip); + vmx_set_pcpu_defaults(vmx, vcpu); do { vmx_inject_interrupts(vmx, vcpu); diff --git a/sys/amd64/vmm/intel/vmx_genassym.c b/sys/amd64/vmm/intel/vmx_genassym.c index 8775f504adc9..4f39ef907f55 100644 --- a/sys/amd64/vmm/intel/vmx_genassym.c +++ b/sys/amd64/vmm/intel/vmx_genassym.c @@ -39,8 +39,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include "vmx.h" #include "vmx_cpufunc.h" +#include "vmx.h" ASSYM(VMXCTX_TMPSTKTOP, offsetof(struct vmxctx, tmpstktop)); ASSYM(VMXCTX_GUEST_RDI, offsetof(struct vmxctx, guest_rdi)); From 2e6383a8e8ede6c437544a3bdc211b465b643bfc Mon Sep 17 00:00:00 2001 From: Pyun YongHyeon Date: Wed, 18 Dec 2013 07:23:42 +0000 Subject: [PATCH 132/172] Failed m_devget(9) indicates lack of free mbuf cluster. Update if_iqdrops counter for that case since the received frame is ok. While here, simplify updating counter logic. --- sys/dev/ae/if_ae.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c index cd7ed5481de9..ab15bbd2a153 100644 --- a/sys/dev/ae/if_ae.c +++ b/sys/dev/ae/if_ae.c @@ -135,7 +135,7 @@ static void ae_mac_config(ae_softc_t *sc); static int ae_intr(void *arg); static void ae_int_task(void *arg, int pending); static void ae_tx_intr(ae_softc_t *sc); -static int ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd); +static void ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd); static void ae_rx_intr(ae_softc_t *sc); static void ae_watchdog(ae_softc_t *sc); static void ae_tick(void *arg); @@ -1884,7 +1884,7 @@ ae_tx_intr(ae_softc_t *sc) BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } -static int +static void ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd) { struct ifnet *ifp; @@ -1903,12 +1903,15 @@ ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd) size = le16toh(rxd->len) - ETHER_CRC_LEN; if (size < (ETHER_MIN_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)) { if_printf(ifp, "Runt frame received."); - return (EIO); + ifp->if_ierrors++; + return; } m = m_devget(&rxd->data[0], size, ETHER_ALIGN, ifp, NULL); - if (m == NULL) - return (ENOBUFS); + if (m == NULL) { + ifp->if_iqdrops++; + return; + } if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && (flags & AE_RXD_HAS_VLAN) != 0) { @@ -1916,14 +1919,13 @@ ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd) m->m_flags |= M_VLANTAG; } + ifp->if_ipackets++; /* * Pass it through. */ AE_UNLOCK(sc); (*ifp->if_input)(ifp, m); AE_LOCK(sc); - - return (0); } static void @@ -1932,7 +1934,7 @@ ae_rx_intr(ae_softc_t *sc) ae_rxd_t *rxd; struct ifnet *ifp; uint16_t flags; - int count, error; + int count; KASSERT(sc != NULL, ("[ae, %d]: sc is NULL!", __LINE__)); @@ -1960,17 +1962,10 @@ ae_rx_intr(ae_softc_t *sc) */ sc->rxd_cur = (sc->rxd_cur + 1) % AE_RXD_COUNT_DEFAULT; - if ((flags & AE_RXD_SUCCESS) == 0) { + if ((flags & AE_RXD_SUCCESS) != 0) + ae_rxeof(sc, rxd); + else ifp->if_ierrors++; - continue; - } - error = ae_rxeof(sc, rxd); - if (error != 0) { - ifp->if_ierrors++; - continue; - } else { - ifp->if_ipackets++; - } } if (count > 0) { From 010b13fa949b8e8a50d971055e2155d8b273f754 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Wed, 18 Dec 2013 07:34:57 +0000 Subject: [PATCH 133/172] Add support to IQ calibration. --- sys/dev/usb/wlan/if_run.c | 150 ++++++++++++++++++++++++++++++++++- sys/dev/usb/wlan/if_runreg.h | 43 +++++----- 2 files changed, 168 insertions(+), 25 deletions(-) diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 701a895a793b..f45527d05a0a 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -345,6 +345,7 @@ static int run_write(struct run_softc *, uint16_t, uint32_t); static int run_write_region_1(struct run_softc *, uint16_t, const uint8_t *, int); static int run_set_region_4(struct run_softc *, uint16_t, uint32_t, int); +static int run_efuse_read(struct run_softc *, uint16_t, uint16_t *, int); static int run_efuse_read_2(struct run_softc *, uint16_t, uint16_t *); static int run_eeprom_read_2(struct run_softc *, uint16_t, uint16_t *); static int run_rt2870_rf_write(struct run_softc *, uint32_t); @@ -391,6 +392,7 @@ static int run_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void run_start(struct ifnet *); static int run_ioctl(struct ifnet *, u_long, caddr_t); +static void run_iq_calib(struct run_softc *, u_int); static void run_set_agc(struct run_softc *, uint8_t); static void run_select_chan_group(struct run_softc *, int); static void run_set_rx_antenna(struct run_softc *, int); @@ -436,6 +438,28 @@ static void run_init_locked(struct run_softc *); static void run_stop(void *); static void run_delay(struct run_softc *, u_int); +static const struct rt2860_rate { + uint8_t rate; + uint8_t mcs; + enum ieee80211_phytype phy; + uint8_t ctl_ridx; + uint16_t sp_ack_dur; + uint16_t lp_ack_dur; +} rt2860_rates[] = { + { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, + { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, + { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, + { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, + { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, + { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, + { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, + { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 }, + { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, + { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, + { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, + { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } +}; + static const struct { uint16_t reg; uint32_t val; @@ -1249,9 +1273,8 @@ run_set_region_4(struct run_softc *sc, uint16_t reg, uint32_t val, int len) return (error); } -/* Read 16-bit from eFUSE ROM (RT3070 only.) */ static int -run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) +run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count) { uint32_t tmp; uint16_t reg; @@ -1260,7 +1283,8 @@ run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0) return (error); - addr *= 2; + if (count == 2) + addr *= 2; /*- * Read one 16-byte block into registers EFUSE_DATA[0-3]: * DATA0: F E D C @@ -1290,10 +1314,23 @@ run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) if ((error = run_read(sc, reg, &tmp)) != 0) return (error); - *val = (addr & 2) ? tmp >> 16 : tmp & 0xffff; + if (count == 2) + *val = (addr & 2) ? tmp >> 16 : tmp & 0xffff; + else { + tmp >>= (8 *(addr & 0x3)); + memmove(val, &tmp, sizeof(*val)); + } return (0); } + +/* Read 16-bit from eFUSE ROM (RT3070 only.) */ +static int +run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) +{ + return (run_efuse_read(sc, addr, val, 2)); +} + static int run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) { @@ -3599,6 +3636,107 @@ run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (error); } +static void +run_iq_calib(struct run_softc *sc, u_int chan) +{ + uint16_t val; + + /* Tx0 IQ gain. */ + run_bbp_write(sc, 158, 0x2c); + if (chan <= 14) + run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1); + else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val & 0xff); + + /* Tx0 IQ phase. */ + run_bbp_write(sc, 158, 0x2d); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val & 0xff); + + /* Tx1 IQ gain. */ + run_bbp_write(sc, 158, 0x4a); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val & 0xff); + + /* Tx1 IQ phase. */ + run_bbp_write(sc, 158, 0x4b); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val & 0xff); + + /* RF IQ compensation control. */ + run_bbp_write(sc, 158, 0x04); + run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL, + &val, 1); + run_bbp_write(sc, 159, val & 0xff); + + /* RF IQ imbalance compensation control. */ + run_bbp_write(sc, 158, 0x03); + run_efuse_read(sc, + RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1); + run_bbp_write(sc, 159, val & 0xff); +} + static void run_set_agc(struct run_softc *sc, uint8_t agc) { @@ -4333,6 +4471,10 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) run_delay(sc, 10); + /* Perform IQ calibrations. */ + if (sc->mac_ver >= 0x5392) + run_iq_calib(sc, chan); + return (0); } diff --git a/sys/dev/usb/wlan/if_runreg.h b/sys/dev/usb/wlan/if_runreg.h index 0a71cb66b369..261efd29faf8 100644 --- a/sys/dev/usb/wlan/if_runreg.h +++ b/sys/dev/usb/wlan/if_runreg.h @@ -905,31 +905,32 @@ struct rt2860_rxwi { #define RT2860_EEPROM_BBP_BASE 0x78 #define RT3071_EEPROM_RF_BASE 0x82 +/* + * EEPROM IQ calibration. + */ +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ 0x130 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ 0x131 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ 0x133 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ 0x134 +#define RT5390_EEPROM_RF_IQ_COMPENSATION_CTL 0x13c +#define RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL 0x13d +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ 0x144 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ 0x145 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ 0x146 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ 0x147 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ 0x148 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ 0x149 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ 0x14a +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ 0x14b +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ 0x14c +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ 0x14d +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f + #define RT2860_RIDX_CCK1 0 #define RT2860_RIDX_CCK11 3 #define RT2860_RIDX_OFDM6 4 #define RT2860_RIDX_MAX 12 -static const struct rt2860_rate { - uint8_t rate; - uint8_t mcs; - enum ieee80211_phytype phy; - uint8_t ctl_ridx; - uint16_t sp_ack_dur; - uint16_t lp_ack_dur; -} rt2860_rates[] = { - { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, - { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, - { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, - { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, - { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, - { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, - { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, - { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 }, - { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, - { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, - { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, - { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } -}; /* * EEPROM access macro. From c48c6bf8fcf5bfa42b79fd5ae506975bc1bff008 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Wed, 18 Dec 2013 07:47:50 +0000 Subject: [PATCH 134/172] Fix typo in comment. --- sys/dev/usb/wlan/if_run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index f45527d05a0a..91585c25a600 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -4471,7 +4471,7 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) run_delay(sc, 10); - /* Perform IQ calibrations. */ + /* Perform IQ calibration. */ if (sc->mac_ver >= 0x5392) run_iq_calib(sc, chan); From fd8fcee579b9ef4e5a7224a5a3b61258dd1e0ee0 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Wed, 18 Dec 2013 08:39:12 +0000 Subject: [PATCH 135/172] Fix style: add tab after #define. --- sys/dev/usb/wlan/if_run.c | 14 +- sys/dev/usb/wlan/if_runreg.h | 1314 +++++++++++++++++----------------- sys/dev/usb/wlan/if_runvar.h | 38 +- 3 files changed, 682 insertions(+), 684 deletions(-) diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 91585c25a600..f6c654cba10a 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -70,14 +70,14 @@ __FBSDID("$FreeBSD$"); #include #include "usbdevs.h" -#define USB_DEBUG_VAR run_debug +#define USB_DEBUG_VAR run_debug #include #include #include #ifdef USB_DEBUG -#define RUN_DEBUG +#define RUN_DEBUG #endif #ifdef RUN_DEBUG @@ -87,17 +87,17 @@ SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, CTLFLAG_RW, &run_debug, 0, "run debug level"); #endif -#define IEEE80211_HAS_ADDR4(wh) \ +#define IEEE80211_HAS_ADDR4(wh) \ (((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) /* * Because of LOR in run_key_delete(), use atomic instead. * '& RUN_CMDQ_MASQ' is to loop cmdq[]. */ -#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) +#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) static const STRUCT_USB_HOST_ID run_devs[] = { -#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } +#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } RUN_DEV(ABOCOM, RT2770), RUN_DEV(ABOCOM, RT2870), RUN_DEV(ABOCOM, RT3070), @@ -4772,8 +4772,8 @@ run_enable_tsf_sync(struct run_softc *sc) static void run_enable_mrr(struct run_softc *sc) { -#define CCK(mcs) (mcs) -#define OFDM(mcs) (1 << 3 | (mcs)) +#define CCK(mcs) (mcs) +#define OFDM(mcs) (1 << 3 | (mcs)) run_write(sc, RT2860_LG_FBK_CFG0, OFDM(6) << 28 | /* 54->48 */ OFDM(5) << 24 | /* 48->36 */ diff --git a/sys/dev/usb/wlan/if_runreg.h b/sys/dev/usb/wlan/if_runreg.h index 261efd29faf8..6c09aa431fc6 100644 --- a/sys/dev/usb/wlan/if_runreg.h +++ b/sys/dev/usb/wlan/if_runreg.h @@ -22,689 +22,687 @@ #ifndef _IF_RUNREG_H_ #define _IF_RUNREG_H_ -#define RT2860_CONFIG_NO 1 -#define RT2860_IFACE_INDEX 0 +#define RT2860_CONFIG_NO 1 +#define RT2860_IFACE_INDEX 0 -#define RT3070_OPT_14 0x0114 +#define RT3070_OPT_14 0x0114 /* SCH/DMA registers */ -#define RT2860_INT_STATUS 0x0200 -#define RT2860_INT_MASK 0x0204 -#define RT2860_WPDMA_GLO_CFG 0x0208 -#define RT2860_WPDMA_RST_IDX 0x020c -#define RT2860_DELAY_INT_CFG 0x0210 -#define RT2860_WMM_AIFSN_CFG 0x0214 -#define RT2860_WMM_CWMIN_CFG 0x0218 -#define RT2860_WMM_CWMAX_CFG 0x021c -#define RT2860_WMM_TXOP0_CFG 0x0220 -#define RT2860_WMM_TXOP1_CFG 0x0224 -#define RT2860_GPIO_CTRL 0x0228 -#define RT2860_MCU_CMD_REG 0x022c -#define RT2860_TX_BASE_PTR(qid) (0x0230 + (qid) * 16) -#define RT2860_TX_MAX_CNT(qid) (0x0234 + (qid) * 16) -#define RT2860_TX_CTX_IDX(qid) (0x0238 + (qid) * 16) -#define RT2860_TX_DTX_IDX(qid) (0x023c + (qid) * 16) -#define RT2860_RX_BASE_PTR 0x0290 -#define RT2860_RX_MAX_CNT 0x0294 -#define RT2860_RX_CALC_IDX 0x0298 -#define RT2860_FS_DRX_IDX 0x029c -#define RT2860_USB_DMA_CFG 0x02a0 /* RT2870 only */ -#define RT2860_US_CYC_CNT 0x02a4 +#define RT2860_INT_STATUS 0x0200 +#define RT2860_INT_MASK 0x0204 +#define RT2860_WPDMA_GLO_CFG 0x0208 +#define RT2860_WPDMA_RST_IDX 0x020c +#define RT2860_DELAY_INT_CFG 0x0210 +#define RT2860_WMM_AIFSN_CFG 0x0214 +#define RT2860_WMM_CWMIN_CFG 0x0218 +#define RT2860_WMM_CWMAX_CFG 0x021c +#define RT2860_WMM_TXOP0_CFG 0x0220 +#define RT2860_WMM_TXOP1_CFG 0x0224 +#define RT2860_GPIO_CTRL 0x0228 +#define RT2860_MCU_CMD_REG 0x022c +#define RT2860_TX_BASE_PTR(qid) (0x0230 + (qid) * 16) +#define RT2860_TX_MAX_CNT(qid) (0x0234 + (qid) * 16) +#define RT2860_TX_CTX_IDX(qid) (0x0238 + (qid) * 16) +#define RT2860_TX_DTX_IDX(qid) (0x023c + (qid) * 16) +#define RT2860_RX_BASE_PTR 0x0290 +#define RT2860_RX_MAX_CNT 0x0294 +#define RT2860_RX_CALC_IDX 0x0298 +#define RT2860_FS_DRX_IDX 0x029c +#define RT2860_USB_DMA_CFG 0x02a0 /* RT2870 only */ +#define RT2860_US_CYC_CNT 0x02a4 /* PBF registers */ -#define RT2860_SYS_CTRL 0x0400 -#define RT2860_HOST_CMD 0x0404 -#define RT2860_PBF_CFG 0x0408 -#define RT2860_MAX_PCNT 0x040c -#define RT2860_BUF_CTRL 0x0410 -#define RT2860_MCU_INT_STA 0x0414 -#define RT2860_MCU_INT_ENA 0x0418 -#define RT2860_TXQ_IO(qid) (0x041c + (qid) * 4) -#define RT2860_RX0Q_IO 0x0424 -#define RT2860_BCN_OFFSET0 0x042c -#define RT2860_BCN_OFFSET1 0x0430 -#define RT2860_TXRXQ_STA 0x0434 -#define RT2860_TXRXQ_PCNT 0x0438 -#define RT2860_PBF_DBG 0x043c -#define RT2860_CAP_CTRL 0x0440 +#define RT2860_SYS_CTRL 0x0400 +#define RT2860_HOST_CMD 0x0404 +#define RT2860_PBF_CFG 0x0408 +#define RT2860_MAX_PCNT 0x040c +#define RT2860_BUF_CTRL 0x0410 +#define RT2860_MCU_INT_STA 0x0414 +#define RT2860_MCU_INT_ENA 0x0418 +#define RT2860_TXQ_IO(qid) (0x041c + (qid) * 4) +#define RT2860_RX0Q_IO 0x0424 +#define RT2860_BCN_OFFSET0 0x042c +#define RT2860_BCN_OFFSET1 0x0430 +#define RT2860_TXRXQ_STA 0x0434 +#define RT2860_TXRXQ_PCNT 0x0438 +#define RT2860_PBF_DBG 0x043c +#define RT2860_CAP_CTRL 0x0440 /* RT3070 registers */ -#define RT3070_RF_CSR_CFG 0x0500 -#define RT3070_EFUSE_CTRL 0x0580 -#define RT3070_EFUSE_DATA0 0x0590 -#define RT3070_EFUSE_DATA1 0x0594 -#define RT3070_EFUSE_DATA2 0x0598 -#define RT3070_EFUSE_DATA3 0x059c -#define RT3070_LDO_CFG0 0x05d4 -#define RT3070_GPIO_SWITCH 0x05dc +#define RT3070_RF_CSR_CFG 0x0500 +#define RT3070_EFUSE_CTRL 0x0580 +#define RT3070_EFUSE_DATA0 0x0590 +#define RT3070_EFUSE_DATA1 0x0594 +#define RT3070_EFUSE_DATA2 0x0598 +#define RT3070_EFUSE_DATA3 0x059c +#define RT3070_LDO_CFG0 0x05d4 +#define RT3070_GPIO_SWITCH 0x05dc /* RT5592 registers */ -#define RT5592_DEBUG_INDEX 0x05e8 +#define RT5592_DEBUG_INDEX 0x05e8 /* MAC registers */ -#define RT2860_ASIC_VER_ID 0x1000 -#define RT2860_MAC_SYS_CTRL 0x1004 -#define RT2860_MAC_ADDR_DW0 0x1008 -#define RT2860_MAC_ADDR_DW1 0x100c -#define RT2860_MAC_BSSID_DW0 0x1010 -#define RT2860_MAC_BSSID_DW1 0x1014 -#define RT2860_MAX_LEN_CFG 0x1018 -#define RT2860_BBP_CSR_CFG 0x101c -#define RT2860_RF_CSR_CFG0 0x1020 -#define RT2860_RF_CSR_CFG1 0x1024 -#define RT2860_RF_CSR_CFG2 0x1028 -#define RT2860_LED_CFG 0x102c +#define RT2860_ASIC_VER_ID 0x1000 +#define RT2860_MAC_SYS_CTRL 0x1004 +#define RT2860_MAC_ADDR_DW0 0x1008 +#define RT2860_MAC_ADDR_DW1 0x100c +#define RT2860_MAC_BSSID_DW0 0x1010 +#define RT2860_MAC_BSSID_DW1 0x1014 +#define RT2860_MAX_LEN_CFG 0x1018 +#define RT2860_BBP_CSR_CFG 0x101c +#define RT2860_RF_CSR_CFG0 0x1020 +#define RT2860_RF_CSR_CFG1 0x1024 +#define RT2860_RF_CSR_CFG2 0x1028 +#define RT2860_LED_CFG 0x102c /* undocumented registers */ -#define RT2860_DEBUG 0x10f4 +#define RT2860_DEBUG 0x10f4 /* MAC Timing control registers */ -#define RT2860_XIFS_TIME_CFG 0x1100 -#define RT2860_BKOFF_SLOT_CFG 0x1104 -#define RT2860_NAV_TIME_CFG 0x1108 -#define RT2860_CH_TIME_CFG 0x110c -#define RT2860_PBF_LIFE_TIMER 0x1110 -#define RT2860_BCN_TIME_CFG 0x1114 -#define RT2860_TBTT_SYNC_CFG 0x1118 -#define RT2860_TSF_TIMER_DW0 0x111c -#define RT2860_TSF_TIMER_DW1 0x1120 -#define RT2860_TBTT_TIMER 0x1124 -#define RT2860_INT_TIMER_CFG 0x1128 -#define RT2860_INT_TIMER_EN 0x112c -#define RT2860_CH_IDLE_TIME 0x1130 +#define RT2860_XIFS_TIME_CFG 0x1100 +#define RT2860_BKOFF_SLOT_CFG 0x1104 +#define RT2860_NAV_TIME_CFG 0x1108 +#define RT2860_CH_TIME_CFG 0x110c +#define RT2860_PBF_LIFE_TIMER 0x1110 +#define RT2860_BCN_TIME_CFG 0x1114 +#define RT2860_TBTT_SYNC_CFG 0x1118 +#define RT2860_TSF_TIMER_DW0 0x111c +#define RT2860_TSF_TIMER_DW1 0x1120 +#define RT2860_TBTT_TIMER 0x1124 +#define RT2860_INT_TIMER_CFG 0x1128 +#define RT2860_INT_TIMER_EN 0x112c +#define RT2860_CH_IDLE_TIME 0x1130 /* MAC Power Save configuration registers */ -#define RT2860_MAC_STATUS_REG 0x1200 -#define RT2860_PWR_PIN_CFG 0x1204 -#define RT2860_AUTO_WAKEUP_CFG 0x1208 +#define RT2860_MAC_STATUS_REG 0x1200 +#define RT2860_PWR_PIN_CFG 0x1204 +#define RT2860_AUTO_WAKEUP_CFG 0x1208 /* MAC TX configuration registers */ -#define RT2860_EDCA_AC_CFG(aci) (0x1300 + (aci) * 4) -#define RT2860_EDCA_TID_AC_MAP 0x1310 -#define RT2860_TX_PWR_CFG(ridx) (0x1314 + (ridx) * 4) -#define RT2860_TX_PIN_CFG 0x1328 -#define RT2860_TX_BAND_CFG 0x132c -#define RT2860_TX_SW_CFG0 0x1330 -#define RT2860_TX_SW_CFG1 0x1334 -#define RT2860_TX_SW_CFG2 0x1338 -#define RT2860_TXOP_THRES_CFG 0x133c -#define RT2860_TXOP_CTRL_CFG 0x1340 -#define RT2860_TX_RTS_CFG 0x1344 -#define RT2860_TX_TIMEOUT_CFG 0x1348 -#define RT2860_TX_RTY_CFG 0x134c -#define RT2860_TX_LINK_CFG 0x1350 -#define RT2860_HT_FBK_CFG0 0x1354 -#define RT2860_HT_FBK_CFG1 0x1358 -#define RT2860_LG_FBK_CFG0 0x135c -#define RT2860_LG_FBK_CFG1 0x1360 -#define RT2860_CCK_PROT_CFG 0x1364 -#define RT2860_OFDM_PROT_CFG 0x1368 -#define RT2860_MM20_PROT_CFG 0x136c -#define RT2860_MM40_PROT_CFG 0x1370 -#define RT2860_GF20_PROT_CFG 0x1374 -#define RT2860_GF40_PROT_CFG 0x1378 -#define RT2860_EXP_CTS_TIME 0x137c -#define RT2860_EXP_ACK_TIME 0x1380 +#define RT2860_EDCA_AC_CFG(aci) (0x1300 + (aci) * 4) +#define RT2860_EDCA_TID_AC_MAP 0x1310 +#define RT2860_TX_PWR_CFG(ridx) (0x1314 + (ridx) * 4) +#define RT2860_TX_PIN_CFG 0x1328 +#define RT2860_TX_BAND_CFG 0x132c +#define RT2860_TX_SW_CFG0 0x1330 +#define RT2860_TX_SW_CFG1 0x1334 +#define RT2860_TX_SW_CFG2 0x1338 +#define RT2860_TXOP_THRES_CFG 0x133c +#define RT2860_TXOP_CTRL_CFG 0x1340 +#define RT2860_TX_RTS_CFG 0x1344 +#define RT2860_TX_TIMEOUT_CFG 0x1348 +#define RT2860_TX_RTY_CFG 0x134c +#define RT2860_TX_LINK_CFG 0x1350 +#define RT2860_HT_FBK_CFG0 0x1354 +#define RT2860_HT_FBK_CFG1 0x1358 +#define RT2860_LG_FBK_CFG0 0x135c +#define RT2860_LG_FBK_CFG1 0x1360 +#define RT2860_CCK_PROT_CFG 0x1364 +#define RT2860_OFDM_PROT_CFG 0x1368 +#define RT2860_MM20_PROT_CFG 0x136c +#define RT2860_MM40_PROT_CFG 0x1370 +#define RT2860_GF20_PROT_CFG 0x1374 +#define RT2860_GF40_PROT_CFG 0x1378 +#define RT2860_EXP_CTS_TIME 0x137c +#define RT2860_EXP_ACK_TIME 0x1380 /* MAC RX configuration registers */ -#define RT2860_RX_FILTR_CFG 0x1400 -#define RT2860_AUTO_RSP_CFG 0x1404 -#define RT2860_LEGACY_BASIC_RATE 0x1408 -#define RT2860_HT_BASIC_RATE 0x140c -#define RT2860_HT_CTRL_CFG 0x1410 -#define RT2860_SIFS_COST_CFG 0x1414 -#define RT2860_RX_PARSER_CFG 0x1418 +#define RT2860_RX_FILTR_CFG 0x1400 +#define RT2860_AUTO_RSP_CFG 0x1404 +#define RT2860_LEGACY_BASIC_RATE 0x1408 +#define RT2860_HT_BASIC_RATE 0x140c +#define RT2860_HT_CTRL_CFG 0x1410 +#define RT2860_SIFS_COST_CFG 0x1414 +#define RT2860_RX_PARSER_CFG 0x1418 /* MAC Security configuration registers */ -#define RT2860_TX_SEC_CNT0 0x1500 -#define RT2860_RX_SEC_CNT0 0x1504 -#define RT2860_CCMP_FC_MUTE 0x1508 +#define RT2860_TX_SEC_CNT0 0x1500 +#define RT2860_RX_SEC_CNT0 0x1504 +#define RT2860_CCMP_FC_MUTE 0x1508 /* MAC HCCA/PSMP configuration registers */ -#define RT2860_TXOP_HLDR_ADDR0 0x1600 -#define RT2860_TXOP_HLDR_ADDR1 0x1604 -#define RT2860_TXOP_HLDR_ET 0x1608 -#define RT2860_QOS_CFPOLL_RA_DW0 0x160c -#define RT2860_QOS_CFPOLL_A1_DW1 0x1610 -#define RT2860_QOS_CFPOLL_QC 0x1614 +#define RT2860_TXOP_HLDR_ADDR0 0x1600 +#define RT2860_TXOP_HLDR_ADDR1 0x1604 +#define RT2860_TXOP_HLDR_ET 0x1608 +#define RT2860_QOS_CFPOLL_RA_DW0 0x160c +#define RT2860_QOS_CFPOLL_A1_DW1 0x1610 +#define RT2860_QOS_CFPOLL_QC 0x1614 /* MAC Statistics Counters */ -#define RT2860_RX_STA_CNT0 0x1700 -#define RT2860_RX_STA_CNT1 0x1704 -#define RT2860_RX_STA_CNT2 0x1708 -#define RT2860_TX_STA_CNT0 0x170c -#define RT2860_TX_STA_CNT1 0x1710 -#define RT2860_TX_STA_CNT2 0x1714 -#define RT2860_TX_STAT_FIFO 0x1718 +#define RT2860_RX_STA_CNT0 0x1700 +#define RT2860_RX_STA_CNT1 0x1704 +#define RT2860_RX_STA_CNT2 0x1708 +#define RT2860_TX_STA_CNT0 0x170c +#define RT2860_TX_STA_CNT1 0x1710 +#define RT2860_TX_STA_CNT2 0x1714 +#define RT2860_TX_STAT_FIFO 0x1718 /* RX WCID search table */ -#define RT2860_WCID_ENTRY(wcid) (0x1800 + (wcid) * 8) +#define RT2860_WCID_ENTRY(wcid) (0x1800 + (wcid) * 8) -#define RT2860_FW_BASE 0x2000 -#define RT2870_FW_BASE 0x3000 +#define RT2860_FW_BASE 0x2000 +#define RT2870_FW_BASE 0x3000 /* Pair-wise key table */ -#define RT2860_PKEY(wcid) (0x4000 + (wcid) * 32) +#define RT2860_PKEY(wcid) (0x4000 + (wcid) * 32) /* IV/EIV table */ -#define RT2860_IVEIV(wcid) (0x6000 + (wcid) * 8) +#define RT2860_IVEIV(wcid) (0x6000 + (wcid) * 8) /* WCID attribute table */ -#define RT2860_WCID_ATTR(wcid) (0x6800 + (wcid) * 4) +#define RT2860_WCID_ATTR(wcid) (0x6800 + (wcid) * 4) /* Shared Key Table */ -#define RT2860_SKEY(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32) +#define RT2860_SKEY(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32) /* Shared Key Mode */ -#define RT2860_SKEY_MODE_0_7 0x7000 -#define RT2860_SKEY_MODE_8_15 0x7004 -#define RT2860_SKEY_MODE_16_23 0x7008 -#define RT2860_SKEY_MODE_24_31 0x700c +#define RT2860_SKEY_MODE_0_7 0x7000 +#define RT2860_SKEY_MODE_8_15 0x7004 +#define RT2860_SKEY_MODE_16_23 0x7008 +#define RT2860_SKEY_MODE_24_31 0x700c /* Shared Memory between MCU and host */ -#define RT2860_H2M_MAILBOX 0x7010 -#define RT2860_H2M_MAILBOX_CID 0x7014 -#define RT2860_H2M_MAILBOX_STATUS 0x701c -#define RT2860_H2M_INTSRC 0x7024 -#define RT2860_H2M_BBPAGENT 0x7028 -#define RT2860_BCN_BASE(vap) (0x7800 + (vap) * 512) +#define RT2860_H2M_MAILBOX 0x7010 +#define RT2860_H2M_MAILBOX_CID 0x7014 +#define RT2860_H2M_MAILBOX_STATUS 0x701c +#define RT2860_H2M_INTSRC 0x7024 +#define RT2860_H2M_BBPAGENT 0x7028 +#define RT2860_BCN_BASE(vap) (0x7800 + (vap) * 512) /* possible flags for register RT2860_PCI_EECTRL */ -#define RT2860_C (1 << 0) -#define RT2860_S (1 << 1) -#define RT2860_D (1 << 2) -#define RT2860_SHIFT_D 2 -#define RT2860_Q (1 << 3) -#define RT2860_SHIFT_Q 3 +#define RT2860_C (1 << 0) +#define RT2860_S (1 << 1) +#define RT2860_D (1 << 2) +#define RT2860_SHIFT_D 2 +#define RT2860_Q (1 << 3) +#define RT2860_SHIFT_Q 3 /* possible flags for registers INT_STATUS/INT_MASK */ -#define RT2860_TX_COHERENT (1 << 17) -#define RT2860_RX_COHERENT (1 << 16) -#define RT2860_MAC_INT_4 (1 << 15) -#define RT2860_MAC_INT_3 (1 << 14) -#define RT2860_MAC_INT_2 (1 << 13) -#define RT2860_MAC_INT_1 (1 << 12) -#define RT2860_MAC_INT_0 (1 << 11) -#define RT2860_TX_RX_COHERENT (1 << 10) -#define RT2860_MCU_CMD_INT (1 << 9) -#define RT2860_TX_DONE_INT5 (1 << 8) -#define RT2860_TX_DONE_INT4 (1 << 7) -#define RT2860_TX_DONE_INT3 (1 << 6) -#define RT2860_TX_DONE_INT2 (1 << 5) -#define RT2860_TX_DONE_INT1 (1 << 4) -#define RT2860_TX_DONE_INT0 (1 << 3) -#define RT2860_RX_DONE_INT (1 << 2) -#define RT2860_TX_DLY_INT (1 << 1) -#define RT2860_RX_DLY_INT (1 << 0) +#define RT2860_TX_COHERENT (1 << 17) +#define RT2860_RX_COHERENT (1 << 16) +#define RT2860_MAC_INT_4 (1 << 15) +#define RT2860_MAC_INT_3 (1 << 14) +#define RT2860_MAC_INT_2 (1 << 13) +#define RT2860_MAC_INT_1 (1 << 12) +#define RT2860_MAC_INT_0 (1 << 11) +#define RT2860_TX_RX_COHERENT (1 << 10) +#define RT2860_MCU_CMD_INT (1 << 9) +#define RT2860_TX_DONE_INT5 (1 << 8) +#define RT2860_TX_DONE_INT4 (1 << 7) +#define RT2860_TX_DONE_INT3 (1 << 6) +#define RT2860_TX_DONE_INT2 (1 << 5) +#define RT2860_TX_DONE_INT1 (1 << 4) +#define RT2860_TX_DONE_INT0 (1 << 3) +#define RT2860_RX_DONE_INT (1 << 2) +#define RT2860_TX_DLY_INT (1 << 1) +#define RT2860_RX_DLY_INT (1 << 0) /* possible flags for register WPDMA_GLO_CFG */ -#define RT2860_HDR_SEG_LEN_SHIFT 8 -#define RT2860_BIG_ENDIAN (1 << 7) -#define RT2860_TX_WB_DDONE (1 << 6) -#define RT2860_WPDMA_BT_SIZE_SHIFT 4 -#define RT2860_WPDMA_BT_SIZE16 0 -#define RT2860_WPDMA_BT_SIZE32 1 -#define RT2860_WPDMA_BT_SIZE64 2 -#define RT2860_WPDMA_BT_SIZE128 3 -#define RT2860_RX_DMA_BUSY (1 << 3) -#define RT2860_RX_DMA_EN (1 << 2) -#define RT2860_TX_DMA_BUSY (1 << 1) -#define RT2860_TX_DMA_EN (1 << 0) +#define RT2860_HDR_SEG_LEN_SHIFT 8 +#define RT2860_BIG_ENDIAN (1 << 7) +#define RT2860_TX_WB_DDONE (1 << 6) +#define RT2860_WPDMA_BT_SIZE_SHIFT 4 +#define RT2860_WPDMA_BT_SIZE16 0 +#define RT2860_WPDMA_BT_SIZE32 1 +#define RT2860_WPDMA_BT_SIZE64 2 +#define RT2860_WPDMA_BT_SIZE128 3 +#define RT2860_RX_DMA_BUSY (1 << 3) +#define RT2860_RX_DMA_EN (1 << 2) +#define RT2860_TX_DMA_BUSY (1 << 1) +#define RT2860_TX_DMA_EN (1 << 0) /* possible flags for register DELAY_INT_CFG */ -#define RT2860_TXDLY_INT_EN (1U << 31) -#define RT2860_TXMAX_PINT_SHIFT 24 -#define RT2860_TXMAX_PTIME_SHIFT 16 -#define RT2860_RXDLY_INT_EN (1 << 15) -#define RT2860_RXMAX_PINT_SHIFT 8 -#define RT2860_RXMAX_PTIME_SHIFT 0 +#define RT2860_TXDLY_INT_EN (1U << 31) +#define RT2860_TXMAX_PINT_SHIFT 24 +#define RT2860_TXMAX_PTIME_SHIFT 16 +#define RT2860_RXDLY_INT_EN (1 << 15) +#define RT2860_RXMAX_PINT_SHIFT 8 +#define RT2860_RXMAX_PTIME_SHIFT 0 /* possible flags for register GPIO_CTRL */ -#define RT2860_GPIO_D_SHIFT 8 -#define RT2860_GPIO_O_SHIFT 0 +#define RT2860_GPIO_D_SHIFT 8 +#define RT2860_GPIO_O_SHIFT 0 /* possible flags for register USB_DMA_CFG */ -#define RT2860_USB_TX_BUSY (1U << 31) -#define RT2860_USB_RX_BUSY (1 << 30) -#define RT2860_USB_EPOUT_VLD_SHIFT 24 -#define RT2860_USB_TX_EN (1 << 23) -#define RT2860_USB_RX_EN (1 << 22) -#define RT2860_USB_RX_AGG_EN (1 << 21) -#define RT2860_USB_TXOP_HALT (1 << 20) -#define RT2860_USB_TX_CLEAR (1 << 19) -#define RT2860_USB_PHY_WD_EN (1 << 16) -#define RT2860_USB_PHY_MAN_RST (1 << 15) -#define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */ -#define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */ +#define RT2860_USB_TX_BUSY (1U << 31) +#define RT2860_USB_RX_BUSY (1 << 30) +#define RT2860_USB_EPOUT_VLD_SHIFT 24 +#define RT2860_USB_TX_EN (1 << 23) +#define RT2860_USB_RX_EN (1 << 22) +#define RT2860_USB_RX_AGG_EN (1 << 21) +#define RT2860_USB_TXOP_HALT (1 << 20) +#define RT2860_USB_TX_CLEAR (1 << 19) +#define RT2860_USB_PHY_WD_EN (1 << 16) +#define RT2860_USB_PHY_MAN_RST (1 << 15) +#define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */ +#define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */ /* possible flags for register US_CYC_CNT */ -#define RT2860_TEST_EN (1 << 24) -#define RT2860_TEST_SEL_SHIFT 16 -#define RT2860_BT_MODE_EN (1 << 8) -#define RT2860_US_CYC_CNT_SHIFT 0 +#define RT2860_TEST_EN (1 << 24) +#define RT2860_TEST_SEL_SHIFT 16 +#define RT2860_BT_MODE_EN (1 << 8) +#define RT2860_US_CYC_CNT_SHIFT 0 /* possible flags for register SYS_CTRL */ -#define RT2860_HST_PM_SEL (1 << 16) -#define RT2860_CAP_MODE (1 << 14) -#define RT2860_PME_OEN (1 << 13) -#define RT2860_CLKSELECT (1 << 12) -#define RT2860_PBF_CLK_EN (1 << 11) -#define RT2860_MAC_CLK_EN (1 << 10) -#define RT2860_DMA_CLK_EN (1 << 9) -#define RT2860_MCU_READY (1 << 7) -#define RT2860_ASY_RESET (1 << 4) -#define RT2860_PBF_RESET (1 << 3) -#define RT2860_MAC_RESET (1 << 2) -#define RT2860_DMA_RESET (1 << 1) -#define RT2860_MCU_RESET (1 << 0) +#define RT2860_HST_PM_SEL (1 << 16) +#define RT2860_CAP_MODE (1 << 14) +#define RT2860_PME_OEN (1 << 13) +#define RT2860_CLKSELECT (1 << 12) +#define RT2860_PBF_CLK_EN (1 << 11) +#define RT2860_MAC_CLK_EN (1 << 10) +#define RT2860_DMA_CLK_EN (1 << 9) +#define RT2860_MCU_READY (1 << 7) +#define RT2860_ASY_RESET (1 << 4) +#define RT2860_PBF_RESET (1 << 3) +#define RT2860_MAC_RESET (1 << 2) +#define RT2860_DMA_RESET (1 << 1) +#define RT2860_MCU_RESET (1 << 0) /* possible values for register HOST_CMD */ -#define RT2860_MCU_CMD_SLEEP 0x30 -#define RT2860_MCU_CMD_WAKEUP 0x31 -#define RT2860_MCU_CMD_LEDS 0x50 -#define RT2860_MCU_CMD_LED_RSSI 0x51 -#define RT2860_MCU_CMD_LED1 0x52 -#define RT2860_MCU_CMD_LED2 0x53 -#define RT2860_MCU_CMD_LED3 0x54 -#define RT2860_MCU_CMD_RFRESET 0x72 -#define RT2860_MCU_CMD_ANTSEL 0x73 -#define RT2860_MCU_CMD_BBP 0x80 -#define RT2860_MCU_CMD_PSLEVEL 0x83 +#define RT2860_MCU_CMD_SLEEP 0x30 +#define RT2860_MCU_CMD_WAKEUP 0x31 +#define RT2860_MCU_CMD_LEDS 0x50 +#define RT2860_MCU_CMD_LED_RSSI 0x51 +#define RT2860_MCU_CMD_LED1 0x52 +#define RT2860_MCU_CMD_LED2 0x53 +#define RT2860_MCU_CMD_LED3 0x54 +#define RT2860_MCU_CMD_RFRESET 0x72 +#define RT2860_MCU_CMD_ANTSEL 0x73 +#define RT2860_MCU_CMD_BBP 0x80 +#define RT2860_MCU_CMD_PSLEVEL 0x83 /* possible flags for register PBF_CFG */ -#define RT2860_TX1Q_NUM_SHIFT 21 -#define RT2860_TX2Q_NUM_SHIFT 16 -#define RT2860_NULL0_MODE (1 << 15) -#define RT2860_NULL1_MODE (1 << 14) -#define RT2860_RX_DROP_MODE (1 << 13) -#define RT2860_TX0Q_MANUAL (1 << 12) -#define RT2860_TX1Q_MANUAL (1 << 11) -#define RT2860_TX2Q_MANUAL (1 << 10) -#define RT2860_RX0Q_MANUAL (1 << 9) -#define RT2860_HCCA_EN (1 << 8) -#define RT2860_TX0Q_EN (1 << 4) -#define RT2860_TX1Q_EN (1 << 3) -#define RT2860_TX2Q_EN (1 << 2) -#define RT2860_RX0Q_EN (1 << 1) +#define RT2860_TX1Q_NUM_SHIFT 21 +#define RT2860_TX2Q_NUM_SHIFT 16 +#define RT2860_NULL0_MODE (1 << 15) +#define RT2860_NULL1_MODE (1 << 14) +#define RT2860_RX_DROP_MODE (1 << 13) +#define RT2860_TX0Q_MANUAL (1 << 12) +#define RT2860_TX1Q_MANUAL (1 << 11) +#define RT2860_TX2Q_MANUAL (1 << 10) +#define RT2860_RX0Q_MANUAL (1 << 9) +#define RT2860_HCCA_EN (1 << 8) +#define RT2860_TX0Q_EN (1 << 4) +#define RT2860_TX1Q_EN (1 << 3) +#define RT2860_TX2Q_EN (1 << 2) +#define RT2860_RX0Q_EN (1 << 1) /* possible flags for register BUF_CTRL */ -#define RT2860_WRITE_TXQ(qid) (1 << (11 - (qid))) -#define RT2860_NULL0_KICK (1 << 7) -#define RT2860_NULL1_KICK (1 << 6) -#define RT2860_BUF_RESET (1 << 5) -#define RT2860_READ_TXQ(qid) (1 << (3 - (qid)) -#define RT2860_READ_RX0Q (1 << 0) +#define RT2860_WRITE_TXQ(qid) (1 << (11 - (qid))) +#define RT2860_NULL0_KICK (1 << 7) +#define RT2860_NULL1_KICK (1 << 6) +#define RT2860_BUF_RESET (1 << 5) +#define RT2860_READ_TXQ(qid) (1 << (3 - (qid)) +#define RT2860_READ_RX0Q (1 << 0) /* possible flags for registers MCU_INT_STA/MCU_INT_ENA */ -#define RT2860_MCU_MAC_INT_8 (1 << 24) -#define RT2860_MCU_MAC_INT_7 (1 << 23) -#define RT2860_MCU_MAC_INT_6 (1 << 22) -#define RT2860_MCU_MAC_INT_4 (1 << 20) -#define RT2860_MCU_MAC_INT_3 (1 << 19) -#define RT2860_MCU_MAC_INT_2 (1 << 18) -#define RT2860_MCU_MAC_INT_1 (1 << 17) -#define RT2860_MCU_MAC_INT_0 (1 << 16) -#define RT2860_DTX0_INT (1 << 11) -#define RT2860_DTX1_INT (1 << 10) -#define RT2860_DTX2_INT (1 << 9) -#define RT2860_DRX0_INT (1 << 8) -#define RT2860_HCMD_INT (1 << 7) -#define RT2860_N0TX_INT (1 << 6) -#define RT2860_N1TX_INT (1 << 5) -#define RT2860_BCNTX_INT (1 << 4) -#define RT2860_MTX0_INT (1 << 3) -#define RT2860_MTX1_INT (1 << 2) -#define RT2860_MTX2_INT (1 << 1) -#define RT2860_MRX0_INT (1 << 0) +#define RT2860_MCU_MAC_INT_8 (1 << 24) +#define RT2860_MCU_MAC_INT_7 (1 << 23) +#define RT2860_MCU_MAC_INT_6 (1 << 22) +#define RT2860_MCU_MAC_INT_4 (1 << 20) +#define RT2860_MCU_MAC_INT_3 (1 << 19) +#define RT2860_MCU_MAC_INT_2 (1 << 18) +#define RT2860_MCU_MAC_INT_1 (1 << 17) +#define RT2860_MCU_MAC_INT_0 (1 << 16) +#define RT2860_DTX0_INT (1 << 11) +#define RT2860_DTX1_INT (1 << 10) +#define RT2860_DTX2_INT (1 << 9) +#define RT2860_DRX0_INT (1 << 8) +#define RT2860_HCMD_INT (1 << 7) +#define RT2860_N0TX_INT (1 << 6) +#define RT2860_N1TX_INT (1 << 5) +#define RT2860_BCNTX_INT (1 << 4) +#define RT2860_MTX0_INT (1 << 3) +#define RT2860_MTX1_INT (1 << 2) +#define RT2860_MTX2_INT (1 << 1) +#define RT2860_MRX0_INT (1 << 0) /* possible flags for register TXRXQ_PCNT */ -#define RT2860_RX0Q_PCNT_MASK 0xff000000 -#define RT2860_TX2Q_PCNT_MASK 0x00ff0000 -#define RT2860_TX1Q_PCNT_MASK 0x0000ff00 -#define RT2860_TX0Q_PCNT_MASK 0x000000ff +#define RT2860_RX0Q_PCNT_MASK 0xff000000 +#define RT2860_TX2Q_PCNT_MASK 0x00ff0000 +#define RT2860_TX1Q_PCNT_MASK 0x0000ff00 +#define RT2860_TX0Q_PCNT_MASK 0x000000ff /* possible flags for register CAP_CTRL */ -#define RT2860_CAP_ADC_FEQ (1U << 31) -#define RT2860_CAP_START (1 << 30) -#define RT2860_MAN_TRIG (1 << 29) -#define RT2860_TRIG_OFFSET_SHIFT 16 -#define RT2860_START_ADDR_SHIFT 0 +#define RT2860_CAP_ADC_FEQ (1U << 31) +#define RT2860_CAP_START (1 << 30) +#define RT2860_MAN_TRIG (1 << 29) +#define RT2860_TRIG_OFFSET_SHIFT 16 +#define RT2860_START_ADDR_SHIFT 0 /* possible flags for register RF_CSR_CFG */ -#define RT3070_RF_KICK (1 << 17) -#define RT3070_RF_WRITE (1 << 16) +#define RT3070_RF_KICK (1 << 17) +#define RT3070_RF_WRITE (1 << 16) /* possible flags for register EFUSE_CTRL */ -#define RT3070_SEL_EFUSE (1U << 31) -#define RT3070_EFSROM_KICK (1 << 30) -#define RT3070_EFSROM_AIN_MASK 0x03ff0000 -#define RT3070_EFSROM_AIN_SHIFT 16 -#define RT3070_EFSROM_MODE_MASK 0x000000c0 -#define RT3070_EFUSE_AOUT_MASK 0x0000003f +#define RT3070_SEL_EFUSE (1U << 31) +#define RT3070_EFSROM_KICK (1 << 30) +#define RT3070_EFSROM_AIN_MASK 0x03ff0000 +#define RT3070_EFSROM_AIN_SHIFT 16 +#define RT3070_EFSROM_MODE_MASK 0x000000c0 +#define RT3070_EFUSE_AOUT_MASK 0x0000003f /* possible flag for register DEBUG_INDEX */ -#define RT5592_SEL_XTAL (1U << 31) +#define RT5592_SEL_XTAL (1U << 31) /* possible flags for register MAC_SYS_CTRL */ -#define RT2860_RX_TS_EN (1 << 7) -#define RT2860_WLAN_HALT_EN (1 << 6) -#define RT2860_PBF_LOOP_EN (1 << 5) -#define RT2860_CONT_TX_TEST (1 << 4) -#define RT2860_MAC_RX_EN (1 << 3) -#define RT2860_MAC_TX_EN (1 << 2) -#define RT2860_BBP_HRST (1 << 1) -#define RT2860_MAC_SRST (1 << 0) +#define RT2860_RX_TS_EN (1 << 7) +#define RT2860_WLAN_HALT_EN (1 << 6) +#define RT2860_PBF_LOOP_EN (1 << 5) +#define RT2860_CONT_TX_TEST (1 << 4) +#define RT2860_MAC_RX_EN (1 << 3) +#define RT2860_MAC_TX_EN (1 << 2) +#define RT2860_BBP_HRST (1 << 1) +#define RT2860_MAC_SRST (1 << 0) /* possible flags for register MAC_BSSID_DW1 */ -#define RT2860_MULTI_BCN_NUM_SHIFT 18 -#define RT2860_MULTI_BSSID_MODE_SHIFT 16 +#define RT2860_MULTI_BCN_NUM_SHIFT 18 +#define RT2860_MULTI_BSSID_MODE_SHIFT 16 /* possible flags for register MAX_LEN_CFG */ -#define RT2860_MIN_MPDU_LEN_SHIFT 16 -#define RT2860_MAX_PSDU_LEN_SHIFT 12 -#define RT2860_MAX_PSDU_LEN8K 0 -#define RT2860_MAX_PSDU_LEN16K 1 -#define RT2860_MAX_PSDU_LEN32K 2 -#define RT2860_MAX_PSDU_LEN64K 3 -#define RT2860_MAX_MPDU_LEN_SHIFT 0 +#define RT2860_MIN_MPDU_LEN_SHIFT 16 +#define RT2860_MAX_PSDU_LEN_SHIFT 12 +#define RT2860_MAX_PSDU_LEN8K 0 +#define RT2860_MAX_PSDU_LEN16K 1 +#define RT2860_MAX_PSDU_LEN32K 2 +#define RT2860_MAX_PSDU_LEN64K 3 +#define RT2860_MAX_MPDU_LEN_SHIFT 0 /* possible flags for registers BBP_CSR_CFG/H2M_BBPAGENT */ -#define RT2860_BBP_RW_PARALLEL (1 << 19) -#define RT2860_BBP_PAR_DUR_112_5 (1 << 18) -#define RT2860_BBP_CSR_KICK (1 << 17) -#define RT2860_BBP_CSR_READ (1 << 16) -#define RT2860_BBP_ADDR_SHIFT 8 -#define RT2860_BBP_DATA_SHIFT 0 +#define RT2860_BBP_RW_PARALLEL (1 << 19) +#define RT2860_BBP_PAR_DUR_112_5 (1 << 18) +#define RT2860_BBP_CSR_KICK (1 << 17) +#define RT2860_BBP_CSR_READ (1 << 16) +#define RT2860_BBP_ADDR_SHIFT 8 +#define RT2860_BBP_DATA_SHIFT 0 /* possible flags for register RF_CSR_CFG0 */ -#define RT2860_RF_REG_CTRL (1U << 31) -#define RT2860_RF_LE_SEL1 (1 << 30) -#define RT2860_RF_LE_STBY (1 << 29) -#define RT2860_RF_REG_WIDTH_SHIFT 24 -#define RT2860_RF_REG_0_SHIFT 0 +#define RT2860_RF_REG_CTRL (1U << 31) +#define RT2860_RF_LE_SEL1 (1 << 30) +#define RT2860_RF_LE_STBY (1 << 29) +#define RT2860_RF_REG_WIDTH_SHIFT 24 +#define RT2860_RF_REG_0_SHIFT 0 /* possible flags for register RF_CSR_CFG1 */ -#define RT2860_RF_DUR_5 (1 << 24) -#define RT2860_RF_REG_1_SHIFT 0 +#define RT2860_RF_DUR_5 (1 << 24) +#define RT2860_RF_REG_1_SHIFT 0 /* possible flags for register LED_CFG */ -#define RT2860_LED_POL (1 << 30) -#define RT2860_Y_LED_MODE_SHIFT 28 -#define RT2860_G_LED_MODE_SHIFT 26 -#define RT2860_R_LED_MODE_SHIFT 24 -#define RT2860_LED_MODE_OFF 0 -#define RT2860_LED_MODE_BLINK_TX 1 -#define RT2860_LED_MODE_SLOW_BLINK 2 -#define RT2860_LED_MODE_ON 3 -#define RT2860_SLOW_BLK_TIME_SHIFT 16 -#define RT2860_LED_OFF_TIME_SHIFT 8 -#define RT2860_LED_ON_TIME_SHIFT 0 +#define RT2860_LED_POL (1 << 30) +#define RT2860_Y_LED_MODE_SHIFT 28 +#define RT2860_G_LED_MODE_SHIFT 26 +#define RT2860_R_LED_MODE_SHIFT 24 +#define RT2860_LED_MODE_OFF 0 +#define RT2860_LED_MODE_BLINK_TX 1 +#define RT2860_LED_MODE_SLOW_BLINK 2 +#define RT2860_LED_MODE_ON 3 +#define RT2860_SLOW_BLK_TIME_SHIFT 16 +#define RT2860_LED_OFF_TIME_SHIFT 8 +#define RT2860_LED_ON_TIME_SHIFT 0 /* possible flags for register XIFS_TIME_CFG */ -#define RT2860_BB_RXEND_EN (1 << 29) -#define RT2860_EIFS_TIME_SHIFT 20 -#define RT2860_OFDM_XIFS_TIME_SHIFT 16 -#define RT2860_OFDM_SIFS_TIME_SHIFT 8 -#define RT2860_CCK_SIFS_TIME_SHIFT 0 +#define RT2860_BB_RXEND_EN (1 << 29) +#define RT2860_EIFS_TIME_SHIFT 20 +#define RT2860_OFDM_XIFS_TIME_SHIFT 16 +#define RT2860_OFDM_SIFS_TIME_SHIFT 8 +#define RT2860_CCK_SIFS_TIME_SHIFT 0 /* possible flags for register BKOFF_SLOT_CFG */ -#define RT2860_CC_DELAY_TIME_SHIFT 8 -#define RT2860_SLOT_TIME 0 +#define RT2860_CC_DELAY_TIME_SHIFT 8 +#define RT2860_SLOT_TIME 0 /* possible flags for register NAV_TIME_CFG */ -#define RT2860_NAV_UPD (1U << 31) -#define RT2860_NAV_UPD_VAL_SHIFT 16 -#define RT2860_NAV_CLR_EN (1 << 15) -#define RT2860_NAV_TIMER_SHIFT 0 +#define RT2860_NAV_UPD (1U << 31) +#define RT2860_NAV_UPD_VAL_SHIFT 16 +#define RT2860_NAV_CLR_EN (1 << 15) +#define RT2860_NAV_TIMER_SHIFT 0 /* possible flags for register CH_TIME_CFG */ -#define RT2860_EIFS_AS_CH_BUSY (1 << 4) -#define RT2860_NAV_AS_CH_BUSY (1 << 3) -#define RT2860_RX_AS_CH_BUSY (1 << 2) -#define RT2860_TX_AS_CH_BUSY (1 << 1) -#define RT2860_CH_STA_TIMER_EN (1 << 0) +#define RT2860_EIFS_AS_CH_BUSY (1 << 4) +#define RT2860_NAV_AS_CH_BUSY (1 << 3) +#define RT2860_RX_AS_CH_BUSY (1 << 2) +#define RT2860_TX_AS_CH_BUSY (1 << 1) +#define RT2860_CH_STA_TIMER_EN (1 << 0) /* possible values for register BCN_TIME_CFG */ -#define RT2860_TSF_INS_COMP_SHIFT 24 -#define RT2860_BCN_TX_EN (1 << 20) -#define RT2860_TBTT_TIMER_EN (1 << 19) -#define RT2860_TSF_SYNC_MODE_SHIFT 17 -#define RT2860_TSF_SYNC_MODE_DIS 0 -#define RT2860_TSF_SYNC_MODE_STA 1 -#define RT2860_TSF_SYNC_MODE_IBSS 2 -#define RT2860_TSF_SYNC_MODE_HOSTAP 3 -#define RT2860_TSF_TIMER_EN (1 << 16) -#define RT2860_BCN_INTVAL_SHIFT 0 +#define RT2860_TSF_INS_COMP_SHIFT 24 +#define RT2860_BCN_TX_EN (1 << 20) +#define RT2860_TBTT_TIMER_EN (1 << 19) +#define RT2860_TSF_SYNC_MODE_SHIFT 17 +#define RT2860_TSF_SYNC_MODE_DIS 0 +#define RT2860_TSF_SYNC_MODE_STA 1 +#define RT2860_TSF_SYNC_MODE_IBSS 2 +#define RT2860_TSF_SYNC_MODE_HOSTAP 3 +#define RT2860_TSF_TIMER_EN (1 << 16) +#define RT2860_BCN_INTVAL_SHIFT 0 /* possible flags for register TBTT_SYNC_CFG */ -#define RT2860_BCN_CWMIN_SHIFT 20 -#define RT2860_BCN_AIFSN_SHIFT 16 -#define RT2860_BCN_EXP_WIN_SHIFT 8 -#define RT2860_TBTT_ADJUST_SHIFT 0 +#define RT2860_BCN_CWMIN_SHIFT 20 +#define RT2860_BCN_AIFSN_SHIFT 16 +#define RT2860_BCN_EXP_WIN_SHIFT 8 +#define RT2860_TBTT_ADJUST_SHIFT 0 /* possible flags for register INT_TIMER_CFG */ -#define RT2860_GP_TIMER_SHIFT 16 -#define RT2860_PRE_TBTT_TIMER_SHIFT 0 +#define RT2860_GP_TIMER_SHIFT 16 +#define RT2860_PRE_TBTT_TIMER_SHIFT 0 /* possible flags for register INT_TIMER_EN */ -#define RT2860_GP_TIMER_EN (1 << 1) -#define RT2860_PRE_TBTT_INT_EN (1 << 0) +#define RT2860_GP_TIMER_EN (1 << 1) +#define RT2860_PRE_TBTT_INT_EN (1 << 0) /* possible flags for register MAC_STATUS_REG */ -#define RT2860_RX_STATUS_BUSY (1 << 1) -#define RT2860_TX_STATUS_BUSY (1 << 0) +#define RT2860_RX_STATUS_BUSY (1 << 1) +#define RT2860_TX_STATUS_BUSY (1 << 0) /* possible flags for register PWR_PIN_CFG */ -#define RT2860_IO_ADDA_PD (1 << 3) -#define RT2860_IO_PLL_PD (1 << 2) -#define RT2860_IO_RA_PE (1 << 1) -#define RT2860_IO_RF_PE (1 << 0) +#define RT2860_IO_ADDA_PD (1 << 3) +#define RT2860_IO_PLL_PD (1 << 2) +#define RT2860_IO_RA_PE (1 << 1) +#define RT2860_IO_RF_PE (1 << 0) /* possible flags for register AUTO_WAKEUP_CFG */ -#define RT2860_AUTO_WAKEUP_EN (1 << 15) -#define RT2860_SLEEP_TBTT_NUM_SHIFT 8 -#define RT2860_WAKEUP_LEAD_TIME_SHIFT 0 +#define RT2860_AUTO_WAKEUP_EN (1 << 15) +#define RT2860_SLEEP_TBTT_NUM_SHIFT 8 +#define RT2860_WAKEUP_LEAD_TIME_SHIFT 0 /* possible flags for register TX_PIN_CFG */ -#define RT2860_TRSW_POL (1 << 19) -#define RT2860_TRSW_EN (1 << 18) -#define RT2860_RFTR_POL (1 << 17) -#define RT2860_RFTR_EN (1 << 16) -#define RT2860_LNA_PE_G1_POL (1 << 15) -#define RT2860_LNA_PE_A1_POL (1 << 14) -#define RT2860_LNA_PE_G0_POL (1 << 13) -#define RT2860_LNA_PE_A0_POL (1 << 12) -#define RT2860_LNA_PE_G1_EN (1 << 11) -#define RT2860_LNA_PE_A1_EN (1 << 10) -#define RT2860_LNA_PE1_EN (RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN) -#define RT2860_LNA_PE_G0_EN (1 << 9) -#define RT2860_LNA_PE_A0_EN (1 << 8) -#define RT2860_LNA_PE0_EN (RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN) -#define RT2860_PA_PE_G1_POL (1 << 7) -#define RT2860_PA_PE_A1_POL (1 << 6) -#define RT2860_PA_PE_G0_POL (1 << 5) -#define RT2860_PA_PE_A0_POL (1 << 4) -#define RT2860_PA_PE_G1_EN (1 << 3) -#define RT2860_PA_PE_A1_EN (1 << 2) -#define RT2860_PA_PE_G0_EN (1 << 1) -#define RT2860_PA_PE_A0_EN (1 << 0) +#define RT2860_TRSW_POL (1 << 19) +#define RT2860_TRSW_EN (1 << 18) +#define RT2860_RFTR_POL (1 << 17) +#define RT2860_RFTR_EN (1 << 16) +#define RT2860_LNA_PE_G1_POL (1 << 15) +#define RT2860_LNA_PE_A1_POL (1 << 14) +#define RT2860_LNA_PE_G0_POL (1 << 13) +#define RT2860_LNA_PE_A0_POL (1 << 12) +#define RT2860_LNA_PE_G1_EN (1 << 11) +#define RT2860_LNA_PE_A1_EN (1 << 10) +#define RT2860_LNA_PE1_EN (RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN) +#define RT2860_LNA_PE_G0_EN (1 << 9) +#define RT2860_LNA_PE_A0_EN (1 << 8) +#define RT2860_LNA_PE0_EN (RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN) +#define RT2860_PA_PE_G1_POL (1 << 7) +#define RT2860_PA_PE_A1_POL (1 << 6) +#define RT2860_PA_PE_G0_POL (1 << 5) +#define RT2860_PA_PE_A0_POL (1 << 4) +#define RT2860_PA_PE_G1_EN (1 << 3) +#define RT2860_PA_PE_A1_EN (1 << 2) +#define RT2860_PA_PE_G0_EN (1 << 1) +#define RT2860_PA_PE_A0_EN (1 << 0) /* possible flags for register TX_BAND_CFG */ -#define RT2860_5G_BAND_SEL_N (1 << 2) -#define RT2860_5G_BAND_SEL_P (1 << 1) -#define RT2860_TX_BAND_SEL (1 << 0) +#define RT2860_5G_BAND_SEL_N (1 << 2) +#define RT2860_5G_BAND_SEL_P (1 << 1) +#define RT2860_TX_BAND_SEL (1 << 0) /* possible flags for register TX_SW_CFG0 */ -#define RT2860_DLY_RFTR_EN_SHIFT 24 -#define RT2860_DLY_TRSW_EN_SHIFT 16 -#define RT2860_DLY_PAPE_EN_SHIFT 8 -#define RT2860_DLY_TXPE_EN_SHIFT 0 +#define RT2860_DLY_RFTR_EN_SHIFT 24 +#define RT2860_DLY_TRSW_EN_SHIFT 16 +#define RT2860_DLY_PAPE_EN_SHIFT 8 +#define RT2860_DLY_TXPE_EN_SHIFT 0 /* possible flags for register TX_SW_CFG1 */ -#define RT2860_DLY_RFTR_DIS_SHIFT 16 -#define RT2860_DLY_TRSW_DIS_SHIFT 8 -#define RT2860_DLY_PAPE_DIS SHIFT 0 +#define RT2860_DLY_RFTR_DIS_SHIFT 16 +#define RT2860_DLY_TRSW_DIS_SHIFT 8 +#define RT2860_DLY_PAPE_DIS SHIFT 0 /* possible flags for register TX_SW_CFG2 */ -#define RT2860_DLY_LNA_EN_SHIFT 24 -#define RT2860_DLY_LNA_DIS_SHIFT 16 -#define RT2860_DLY_DAC_EN_SHIFT 8 -#define RT2860_DLY_DAC_DIS_SHIFT 0 +#define RT2860_DLY_LNA_EN_SHIFT 24 +#define RT2860_DLY_LNA_DIS_SHIFT 16 +#define RT2860_DLY_DAC_EN_SHIFT 8 +#define RT2860_DLY_DAC_DIS_SHIFT 0 /* possible flags for register TXOP_THRES_CFG */ -#define RT2860_TXOP_REM_THRES_SHIFT 24 -#define RT2860_CF_END_THRES_SHIFT 16 -#define RT2860_RDG_IN_THRES 8 -#define RT2860_RDG_OUT_THRES 0 +#define RT2860_TXOP_REM_THRES_SHIFT 24 +#define RT2860_CF_END_THRES_SHIFT 16 +#define RT2860_RDG_IN_THRES 8 +#define RT2860_RDG_OUT_THRES 0 /* possible flags for register TXOP_CTRL_CFG */ -#define RT2860_EXT_CW_MIN_SHIFT 16 -#define RT2860_EXT_CCA_DLY_SHIFT 8 -#define RT2860_EXT_CCA_EN (1 << 7) -#define RT2860_LSIG_TXOP_EN (1 << 6) -#define RT2860_TXOP_TRUN_EN_MIMOPS (1 << 4) -#define RT2860_TXOP_TRUN_EN_TXOP (1 << 3) -#define RT2860_TXOP_TRUN_EN_RATE (1 << 2) -#define RT2860_TXOP_TRUN_EN_AC (1 << 1) -#define RT2860_TXOP_TRUN_EN_TIMEOUT (1 << 0) +#define RT2860_EXT_CW_MIN_SHIFT 16 +#define RT2860_EXT_CCA_DLY_SHIFT 8 +#define RT2860_EXT_CCA_EN (1 << 7) +#define RT2860_LSIG_TXOP_EN (1 << 6) +#define RT2860_TXOP_TRUN_EN_MIMOPS (1 << 4) +#define RT2860_TXOP_TRUN_EN_TXOP (1 << 3) +#define RT2860_TXOP_TRUN_EN_RATE (1 << 2) +#define RT2860_TXOP_TRUN_EN_AC (1 << 1) +#define RT2860_TXOP_TRUN_EN_TIMEOUT (1 << 0) /* possible flags for register TX_RTS_CFG */ -#define RT2860_RTS_FBK_EN (1 << 24) -#define RT2860_RTS_THRES_SHIFT 8 -#define RT2860_RTS_RTY_LIMIT_SHIFT 0 +#define RT2860_RTS_FBK_EN (1 << 24) +#define RT2860_RTS_THRES_SHIFT 8 +#define RT2860_RTS_RTY_LIMIT_SHIFT 0 /* possible flags for register TX_TIMEOUT_CFG */ -#define RT2860_TXOP_TIMEOUT_SHIFT 16 -#define RT2860_RX_ACK_TIMEOUT_SHIFT 8 -#define RT2860_MPDU_LIFE_TIME_SHIFT 4 +#define RT2860_TXOP_TIMEOUT_SHIFT 16 +#define RT2860_RX_ACK_TIMEOUT_SHIFT 8 +#define RT2860_MPDU_LIFE_TIME_SHIFT 4 /* possible flags for register TX_RTY_CFG */ -#define RT2860_TX_AUTOFB_EN (1 << 30) -#define RT2860_AGG_RTY_MODE_TIMER (1 << 29) -#define RT2860_NAG_RTY_MODE_TIMER (1 << 28) -#define RT2860_LONG_RTY_THRES_SHIFT 16 -#define RT2860_LONG_RTY_LIMIT_SHIFT 8 -#define RT2860_SHORT_RTY_LIMIT_SHIFT 0 +#define RT2860_TX_AUTOFB_EN (1 << 30) +#define RT2860_AGG_RTY_MODE_TIMER (1 << 29) +#define RT2860_NAG_RTY_MODE_TIMER (1 << 28) +#define RT2860_LONG_RTY_THRES_SHIFT 16 +#define RT2860_LONG_RTY_LIMIT_SHIFT 8 +#define RT2860_SHORT_RTY_LIMIT_SHIFT 0 /* possible flags for register TX_LINK_CFG */ -#define RT2860_REMOTE_MFS_SHIFT 24 -#define RT2860_REMOTE_MFB_SHIFT 16 -#define RT2860_TX_CFACK_EN (1 << 12) -#define RT2860_TX_RDG_EN (1 << 11) -#define RT2860_TX_MRQ_EN (1 << 10) -#define RT2860_REMOTE_UMFS_EN (1 << 9) -#define RT2860_TX_MFB_EN (1 << 8) -#define RT2860_REMOTE_MFB_LT_SHIFT 0 +#define RT2860_REMOTE_MFS_SHIFT 24 +#define RT2860_REMOTE_MFB_SHIFT 16 +#define RT2860_TX_CFACK_EN (1 << 12) +#define RT2860_TX_RDG_EN (1 << 11) +#define RT2860_TX_MRQ_EN (1 << 10) +#define RT2860_REMOTE_UMFS_EN (1 << 9) +#define RT2860_TX_MFB_EN (1 << 8) +#define RT2860_REMOTE_MFB_LT_SHIFT 0 /* possible flags for registers *_PROT_CFG */ -#define RT2860_RTSTH_EN (1 << 26) -#define RT2860_TXOP_ALLOW_GF40 (1 << 25) -#define RT2860_TXOP_ALLOW_GF20 (1 << 24) -#define RT2860_TXOP_ALLOW_MM40 (1 << 23) -#define RT2860_TXOP_ALLOW_MM20 (1 << 22) -#define RT2860_TXOP_ALLOW_OFDM (1 << 21) -#define RT2860_TXOP_ALLOW_CCK (1 << 20) -#define RT2860_TXOP_ALLOW_ALL (0x3f << 20) -#define RT2860_PROT_NAV_SHORT (1 << 18) -#define RT2860_PROT_NAV_LONG (2 << 18) -#define RT2860_PROT_CTRL_RTS_CTS (1 << 16) -#define RT2860_PROT_CTRL_CTS (2 << 16) +#define RT2860_RTSTH_EN (1 << 26) +#define RT2860_TXOP_ALLOW_GF40 (1 << 25) +#define RT2860_TXOP_ALLOW_GF20 (1 << 24) +#define RT2860_TXOP_ALLOW_MM40 (1 << 23) +#define RT2860_TXOP_ALLOW_MM20 (1 << 22) +#define RT2860_TXOP_ALLOW_OFDM (1 << 21) +#define RT2860_TXOP_ALLOW_CCK (1 << 20) +#define RT2860_TXOP_ALLOW_ALL (0x3f << 20) +#define RT2860_PROT_NAV_SHORT (1 << 18) +#define RT2860_PROT_NAV_LONG (2 << 18) +#define RT2860_PROT_CTRL_RTS_CTS (1 << 16) +#define RT2860_PROT_CTRL_CTS (2 << 16) /* possible flags for registers EXP_{CTS,ACK}_TIME */ -#define RT2860_EXP_OFDM_TIME_SHIFT 16 -#define RT2860_EXP_CCK_TIME_SHIFT 0 +#define RT2860_EXP_OFDM_TIME_SHIFT 16 +#define RT2860_EXP_CCK_TIME_SHIFT 0 /* possible flags for register RX_FILTR_CFG */ -#define RT2860_DROP_CTRL_RSV (1 << 16) -#define RT2860_DROP_BAR (1 << 15) -#define RT2860_DROP_BA (1 << 14) -#define RT2860_DROP_PSPOLL (1 << 13) -#define RT2860_DROP_RTS (1 << 12) -#define RT2860_DROP_CTS (1 << 11) -#define RT2860_DROP_ACK (1 << 10) -#define RT2860_DROP_CFEND (1 << 9) -#define RT2860_DROP_CFACK (1 << 8) -#define RT2860_DROP_DUPL (1 << 7) -#define RT2860_DROP_BC (1 << 6) -#define RT2860_DROP_MC (1 << 5) -#define RT2860_DROP_VER_ERR (1 << 4) -#define RT2860_DROP_NOT_MYBSS (1 << 3) -#define RT2860_DROP_UC_NOME (1 << 2) -#define RT2860_DROP_PHY_ERR (1 << 1) -#define RT2860_DROP_CRC_ERR (1 << 0) +#define RT2860_DROP_CTRL_RSV (1 << 16) +#define RT2860_DROP_BAR (1 << 15) +#define RT2860_DROP_BA (1 << 14) +#define RT2860_DROP_PSPOLL (1 << 13) +#define RT2860_DROP_RTS (1 << 12) +#define RT2860_DROP_CTS (1 << 11) +#define RT2860_DROP_ACK (1 << 10) +#define RT2860_DROP_CFEND (1 << 9) +#define RT2860_DROP_CFACK (1 << 8) +#define RT2860_DROP_DUPL (1 << 7) +#define RT2860_DROP_BC (1 << 6) +#define RT2860_DROP_MC (1 << 5) +#define RT2860_DROP_VER_ERR (1 << 4) +#define RT2860_DROP_NOT_MYBSS (1 << 3) +#define RT2860_DROP_UC_NOME (1 << 2) +#define RT2860_DROP_PHY_ERR (1 << 1) +#define RT2860_DROP_CRC_ERR (1 << 0) /* possible flags for register AUTO_RSP_CFG */ -#define RT2860_CTRL_PWR_BIT (1 << 7) -#define RT2860_BAC_ACK_POLICY (1 << 6) -#define RT2860_CCK_SHORT_EN (1 << 4) -#define RT2860_CTS_40M_REF_EN (1 << 3) -#define RT2860_CTS_40M_MODE_EN (1 << 2) -#define RT2860_BAC_ACKPOLICY_EN (1 << 1) -#define RT2860_AUTO_RSP_EN (1 << 0) +#define RT2860_CTRL_PWR_BIT (1 << 7) +#define RT2860_BAC_ACK_POLICY (1 << 6) +#define RT2860_CCK_SHORT_EN (1 << 4) +#define RT2860_CTS_40M_REF_EN (1 << 3) +#define RT2860_CTS_40M_MODE_EN (1 << 2) +#define RT2860_BAC_ACKPOLICY_EN (1 << 1) +#define RT2860_AUTO_RSP_EN (1 << 0) /* possible flags for register SIFS_COST_CFG */ -#define RT2860_OFDM_SIFS_COST_SHIFT 8 -#define RT2860_CCK_SIFS_COST_SHIFT 0 +#define RT2860_OFDM_SIFS_COST_SHIFT 8 +#define RT2860_CCK_SIFS_COST_SHIFT 0 /* possible flags for register TXOP_HLDR_ET */ -#define RT2860_TXOP_ETM1_EN (1 << 25) -#define RT2860_TXOP_ETM0_EN (1 << 24) -#define RT2860_TXOP_ETM_THRES_SHIFT 16 -#define RT2860_TXOP_ETO_EN (1 << 8) -#define RT2860_TXOP_ETO_THRES_SHIFT 1 -#define RT2860_PER_RX_RST_EN (1 << 0) +#define RT2860_TXOP_ETM1_EN (1 << 25) +#define RT2860_TXOP_ETM0_EN (1 << 24) +#define RT2860_TXOP_ETM_THRES_SHIFT 16 +#define RT2860_TXOP_ETO_EN (1 << 8) +#define RT2860_TXOP_ETO_THRES_SHIFT 1 +#define RT2860_PER_RX_RST_EN (1 << 0) /* possible flags for register TX_STAT_FIFO */ -#define RT2860_TXQ_MCS_SHIFT 16 -#define RT2860_TXQ_WCID_SHIFT 8 -#define RT2860_TXQ_ACKREQ (1 << 7) -#define RT2860_TXQ_AGG (1 << 6) -#define RT2860_TXQ_OK (1 << 5) -#define RT2860_TXQ_PID_SHIFT 1 -#define RT2860_TXQ_VLD (1 << 0) +#define RT2860_TXQ_MCS_SHIFT 16 +#define RT2860_TXQ_WCID_SHIFT 8 +#define RT2860_TXQ_ACKREQ (1 << 7) +#define RT2860_TXQ_AGG (1 << 6) +#define RT2860_TXQ_OK (1 << 5) +#define RT2860_TXQ_PID_SHIFT 1 +#define RT2860_TXQ_VLD (1 << 0) /* possible flags for register WCID_ATTR */ -#define RT2860_MODE_NOSEC 0 -#define RT2860_MODE_WEP40 1 -#define RT2860_MODE_WEP104 2 -#define RT2860_MODE_TKIP 3 -#define RT2860_MODE_AES_CCMP 4 -#define RT2860_MODE_CKIP40 5 -#define RT2860_MODE_CKIP104 6 -#define RT2860_MODE_CKIP128 7 -#define RT2860_RX_PKEY_EN (1 << 0) +#define RT2860_MODE_NOSEC 0 +#define RT2860_MODE_WEP40 1 +#define RT2860_MODE_WEP104 2 +#define RT2860_MODE_TKIP 3 +#define RT2860_MODE_AES_CCMP 4 +#define RT2860_MODE_CKIP40 5 +#define RT2860_MODE_CKIP104 6 +#define RT2860_MODE_CKIP128 7 +#define RT2860_RX_PKEY_EN (1 << 0) /* possible flags for register H2M_MAILBOX */ -#define RT2860_H2M_BUSY (1 << 24) -#define RT2860_TOKEN_NO_INTR 0xff - +#define RT2860_H2M_BUSY (1 << 24) +#define RT2860_TOKEN_NO_INTR 0xff /* possible flags for MCU command RT2860_MCU_CMD_LEDS */ -#define RT2860_LED_RADIO (1 << 13) -#define RT2860_LED_LINK_2GHZ (1 << 14) -#define RT2860_LED_LINK_5GHZ (1 << 15) - +#define RT2860_LED_RADIO (1 << 13) +#define RT2860_LED_LINK_2GHZ (1 << 14) +#define RT2860_LED_LINK_5GHZ (1 << 15) /* possible flags for RT3020 RF register 1 */ -#define RT3070_RF_BLOCK (1 << 0) -#define RT3070_PLL_PD (1 << 1) -#define RT3070_RX0_PD (1 << 2) -#define RT3070_TX0_PD (1 << 3) -#define RT3070_RX1_PD (1 << 4) -#define RT3070_TX1_PD (1 << 5) +#define RT3070_RF_BLOCK (1 << 0) +#define RT3070_PLL_PD (1 << 1) +#define RT3070_RX0_PD (1 << 2) +#define RT3070_TX0_PD (1 << 3) +#define RT3070_RX1_PD (1 << 4) +#define RT3070_TX1_PD (1 << 5) /* possible flags for RT3020 RF register 15 */ -#define RT3070_TX_LO2 (1 << 3) +#define RT3070_TX_LO2 (1 << 3) /* possible flags for RT3020 RF register 17 */ -#define RT3070_TX_LO1 (1 << 3) +#define RT3070_TX_LO1 (1 << 3) /* possible flags for RT3020 RF register 20 */ -#define RT3070_RX_LO1 (1 << 3) +#define RT3070_RX_LO1 (1 << 3) /* possible flags for RT3020 RF register 21 */ -#define RT3070_RX_LO2 (1 << 3) +#define RT3070_RX_LO2 (1 << 3) /* Possible flags for RT5390 RF register 2. */ #define RT5390_RESCAL (1 << 7) @@ -729,21 +727,21 @@ struct rt2860_txd { uint32_t sdp0; /* Segment Data Pointer 0 */ uint16_t sdl1; /* Segment Data Length 1 */ -#define RT2860_TX_BURST (1 << 15) -#define RT2860_TX_LS1 (1 << 14) /* SDP1 is the last segment */ +#define RT2860_TX_BURST (1 << 15) +#define RT2860_TX_LS1 (1 << 14) /* SDP1 is the last segment */ uint16_t sdl0; /* Segment Data Length 0 */ -#define RT2860_TX_DDONE (1 << 15) -#define RT2860_TX_LS0 (1 << 14) /* SDP0 is the last segment */ +#define RT2860_TX_DDONE (1 << 15) +#define RT2860_TX_LS0 (1 << 14) /* SDP0 is the last segment */ uint32_t sdp1; /* Segment Data Pointer 1 */ uint8_t reserved[3]; uint8_t flags; -#define RT2860_TX_QSEL_SHIFT 1 -#define RT2860_TX_QSEL_MGMT (0 << 1) -#define RT2860_TX_QSEL_HCCA (1 << 1) -#define RT2860_TX_QSEL_EDCA (2 << 1) -#define RT2860_TX_WIV (1 << 0) +#define RT2860_TX_QSEL_SHIFT 1 +#define RT2860_TX_QSEL_MGMT (0 << 1) +#define RT2860_TX_QSEL_HCCA (1 << 1) +#define RT2860_TX_QSEL_EDCA (2 << 1) +#define RT2860_TX_WIV (1 << 0) } __packed; /* RT2870 TX descriptor */ @@ -756,38 +754,38 @@ struct rt2870_txd { /* TX Wireless Information */ struct rt2860_txwi { uint8_t flags; -#define RT2860_TX_MPDU_DSITY_SHIFT 5 -#define RT2860_TX_AMPDU (1 << 4) -#define RT2860_TX_TS (1 << 3) -#define RT2860_TX_CFACK (1 << 2) -#define RT2860_TX_MMPS (1 << 1) -#define RT2860_TX_FRAG (1 << 0) +#define RT2860_TX_MPDU_DSITY_SHIFT 5 +#define RT2860_TX_AMPDU (1 << 4) +#define RT2860_TX_TS (1 << 3) +#define RT2860_TX_CFACK (1 << 2) +#define RT2860_TX_MMPS (1 << 1) +#define RT2860_TX_FRAG (1 << 0) uint8_t txop; -#define RT2860_TX_TXOP_HT 0 -#define RT2860_TX_TXOP_PIFS 1 -#define RT2860_TX_TXOP_SIFS 2 -#define RT2860_TX_TXOP_BACKOFF 3 +#define RT2860_TX_TXOP_HT 0 +#define RT2860_TX_TXOP_PIFS 1 +#define RT2860_TX_TXOP_SIFS 2 +#define RT2860_TX_TXOP_BACKOFF 3 uint16_t phy; -#define RT2860_PHY_MODE 0xc000 -#define RT2860_PHY_CCK (0 << 14) -#define RT2860_PHY_OFDM (1 << 14) -#define RT2860_PHY_HT (2 << 14) -#define RT2860_PHY_HT_GF (3 << 14) -#define RT2860_PHY_SGI (1 << 8) -#define RT2860_PHY_BW40 (1 << 7) -#define RT2860_PHY_MCS 0x7f -#define RT2860_PHY_SHPRE (1 << 3) +#define RT2860_PHY_MODE 0xc000 +#define RT2860_PHY_CCK (0 << 14) +#define RT2860_PHY_OFDM (1 << 14) +#define RT2860_PHY_HT (2 << 14) +#define RT2860_PHY_HT_GF (3 << 14) +#define RT2860_PHY_SGI (1 << 8) +#define RT2860_PHY_BW40 (1 << 7) +#define RT2860_PHY_MCS 0x7f +#define RT2860_PHY_SHPRE (1 << 3) uint8_t xflags; -#define RT2860_TX_BAWINSIZE_SHIFT 2 -#define RT2860_TX_NSEQ (1 << 1) -#define RT2860_TX_ACK (1 << 0) +#define RT2860_TX_BAWINSIZE_SHIFT 2 +#define RT2860_TX_NSEQ (1 << 1) +#define RT2860_TX_ACK (1 << 0) uint8_t wcid; /* Wireless Client ID */ uint16_t len; -#define RT2860_TX_PID_SHIFT 12 +#define RT2860_TX_PID_SHIFT 12 uint32_t iv; uint32_t eiv; @@ -798,28 +796,28 @@ struct rt2860_rxd { uint32_t sdp0; uint16_t sdl1; /* unused */ uint16_t sdl0; -#define RT2860_RX_DDONE (1 << 15) -#define RT2860_RX_LS0 (1 << 14) +#define RT2860_RX_DDONE (1 << 15) +#define RT2860_RX_LS0 (1 << 14) uint32_t sdp1; /* unused */ uint32_t flags; -#define RT2860_RX_DEC (1 << 16) -#define RT2860_RX_AMPDU (1 << 15) -#define RT2860_RX_L2PAD (1 << 14) -#define RT2860_RX_RSSI (1 << 13) -#define RT2860_RX_HTC (1 << 12) -#define RT2860_RX_AMSDU (1 << 11) -#define RT2860_RX_MICERR (1 << 10) -#define RT2860_RX_ICVERR (1 << 9) -#define RT2860_RX_CRCERR (1 << 8) -#define RT2860_RX_MYBSS (1 << 7) -#define RT2860_RX_BC (1 << 6) -#define RT2860_RX_MC (1 << 5) -#define RT2860_RX_UC2ME (1 << 4) -#define RT2860_RX_FRAG (1 << 3) -#define RT2860_RX_NULL (1 << 2) -#define RT2860_RX_DATA (1 << 1) -#define RT2860_RX_BA (1 << 0) +#define RT2860_RX_DEC (1 << 16) +#define RT2860_RX_AMPDU (1 << 15) +#define RT2860_RX_L2PAD (1 << 14) +#define RT2860_RX_RSSI (1 << 13) +#define RT2860_RX_HTC (1 << 12) +#define RT2860_RX_AMSDU (1 << 11) +#define RT2860_RX_MICERR (1 << 10) +#define RT2860_RX_ICVERR (1 << 9) +#define RT2860_RX_CRCERR (1 << 8) +#define RT2860_RX_MYBSS (1 << 7) +#define RT2860_RX_BC (1 << 6) +#define RT2860_RX_MC (1 << 5) +#define RT2860_RX_UC2ME (1 << 4) +#define RT2860_RX_FRAG (1 << 3) +#define RT2860_RX_NULL (1 << 2) +#define RT2860_RX_DATA (1 << 1) +#define RT2860_RX_BA (1 << 0) } __packed; /* RT2870 RX descriptor */ @@ -832,11 +830,11 @@ struct rt2870_rxd { struct rt2860_rxwi { uint8_t wcid; uint8_t keyidx; -#define RT2860_RX_UDF_SHIFT 5 -#define RT2860_RX_BSS_IDX_SHIFT 2 +#define RT2860_RX_UDF_SHIFT 5 +#define RT2860_RX_BSS_IDX_SHIFT 2 uint16_t len; -#define RT2860_RX_TID_SHIFT 12 +#define RT2860_RX_TID_SHIFT 12 uint16_t seq; uint16_t phy; @@ -846,64 +844,64 @@ struct rt2860_rxwi { uint16_t reserved2; } __packed; -#define RT2860_RF_2820 0x0001 /* 2T3R */ -#define RT2860_RF_2850 0x0002 /* dual-band 2T3R */ -#define RT2860_RF_2720 0x0003 /* 1T2R */ -#define RT2860_RF_2750 0x0004 /* dual-band 1T2R */ -#define RT3070_RF_3020 0x0005 /* 1T1R */ -#define RT3070_RF_2020 0x0006 /* b/g */ -#define RT3070_RF_3021 0x0007 /* 1T2R */ -#define RT3070_RF_3022 0x0008 /* 2T2R */ -#define RT3070_RF_3052 0x0009 /* dual-band 2T2R */ -#define RT5592_RF_5592 0x000f /* dual-band 2T2R */ -#define RT5390_RF_5370 0x5370 /* 1T1R */ -#define RT5390_RF_5372 0x5372 /* 2T2R */ +#define RT2860_RF_2820 0x0001 /* 2T3R */ +#define RT2860_RF_2850 0x0002 /* dual-band 2T3R */ +#define RT2860_RF_2720 0x0003 /* 1T2R */ +#define RT2860_RF_2750 0x0004 /* dual-band 1T2R */ +#define RT3070_RF_3020 0x0005 /* 1T1R */ +#define RT3070_RF_2020 0x0006 /* b/g */ +#define RT3070_RF_3021 0x0007 /* 1T2R */ +#define RT3070_RF_3022 0x0008 /* 2T2R */ +#define RT3070_RF_3052 0x0009 /* dual-band 2T2R */ +#define RT5592_RF_5592 0x000f /* dual-band 2T2R */ +#define RT5390_RF_5370 0x5370 /* 1T1R */ +#define RT5390_RF_5372 0x5372 /* 2T2R */ /* USB commands for RT2870 only */ -#define RT2870_RESET 1 -#define RT2870_WRITE_2 2 -#define RT2870_WRITE_REGION_1 6 -#define RT2870_READ_REGION_1 7 -#define RT2870_EEPROM_READ 9 +#define RT2870_RESET 1 +#define RT2870_WRITE_2 2 +#define RT2870_WRITE_REGION_1 6 +#define RT2870_READ_REGION_1 7 +#define RT2870_EEPROM_READ 9 -#define RT2860_EEPROM_DELAY 1 /* minimum hold time (microsecond) */ +#define RT2860_EEPROM_DELAY 1 /* minimum hold time (microsecond) */ -#define RT2860_EEPROM_VERSION 0x01 -#define RT2860_EEPROM_MAC01 0x02 -#define RT2860_EEPROM_MAC23 0x03 -#define RT2860_EEPROM_MAC45 0x04 -#define RT2860_EEPROM_PCIE_PSLEVEL 0x11 -#define RT2860_EEPROM_REV 0x12 -#define RT2860_EEPROM_ANTENNA 0x1a -#define RT2860_EEPROM_CONFIG 0x1b -#define RT2860_EEPROM_COUNTRY 0x1c -#define RT2860_EEPROM_FREQ_LEDS 0x1d -#define RT2860_EEPROM_LED1 0x1e -#define RT2860_EEPROM_LED2 0x1f -#define RT2860_EEPROM_LED3 0x20 -#define RT2860_EEPROM_LNA 0x22 -#define RT2860_EEPROM_RSSI1_2GHZ 0x23 -#define RT2860_EEPROM_RSSI2_2GHZ 0x24 -#define RT2860_EEPROM_RSSI1_5GHZ 0x25 -#define RT2860_EEPROM_RSSI2_5GHZ 0x26 -#define RT2860_EEPROM_DELTAPWR 0x28 -#define RT2860_EEPROM_PWR2GHZ_BASE1 0x29 -#define RT2860_EEPROM_PWR2GHZ_BASE2 0x30 -#define RT2860_EEPROM_TSSI1_2GHZ 0x37 -#define RT2860_EEPROM_TSSI2_2GHZ 0x38 -#define RT2860_EEPROM_TSSI3_2GHZ 0x39 -#define RT2860_EEPROM_TSSI4_2GHZ 0x3a -#define RT2860_EEPROM_TSSI5_2GHZ 0x3b -#define RT2860_EEPROM_PWR5GHZ_BASE1 0x3c -#define RT2860_EEPROM_PWR5GHZ_BASE2 0x53 -#define RT2860_EEPROM_TSSI1_5GHZ 0x6a -#define RT2860_EEPROM_TSSI2_5GHZ 0x6b -#define RT2860_EEPROM_TSSI3_5GHZ 0x6c -#define RT2860_EEPROM_TSSI4_5GHZ 0x6d -#define RT2860_EEPROM_TSSI5_5GHZ 0x6e -#define RT2860_EEPROM_RPWR 0x6f -#define RT2860_EEPROM_BBP_BASE 0x78 -#define RT3071_EEPROM_RF_BASE 0x82 +#define RT2860_EEPROM_VERSION 0x01 +#define RT2860_EEPROM_MAC01 0x02 +#define RT2860_EEPROM_MAC23 0x03 +#define RT2860_EEPROM_MAC45 0x04 +#define RT2860_EEPROM_PCIE_PSLEVEL 0x11 +#define RT2860_EEPROM_REV 0x12 +#define RT2860_EEPROM_ANTENNA 0x1a +#define RT2860_EEPROM_CONFIG 0x1b +#define RT2860_EEPROM_COUNTRY 0x1c +#define RT2860_EEPROM_FREQ_LEDS 0x1d +#define RT2860_EEPROM_LED1 0x1e +#define RT2860_EEPROM_LED2 0x1f +#define RT2860_EEPROM_LED3 0x20 +#define RT2860_EEPROM_LNA 0x22 +#define RT2860_EEPROM_RSSI1_2GHZ 0x23 +#define RT2860_EEPROM_RSSI2_2GHZ 0x24 +#define RT2860_EEPROM_RSSI1_5GHZ 0x25 +#define RT2860_EEPROM_RSSI2_5GHZ 0x26 +#define RT2860_EEPROM_DELTAPWR 0x28 +#define RT2860_EEPROM_PWR2GHZ_BASE1 0x29 +#define RT2860_EEPROM_PWR2GHZ_BASE2 0x30 +#define RT2860_EEPROM_TSSI1_2GHZ 0x37 +#define RT2860_EEPROM_TSSI2_2GHZ 0x38 +#define RT2860_EEPROM_TSSI3_2GHZ 0x39 +#define RT2860_EEPROM_TSSI4_2GHZ 0x3a +#define RT2860_EEPROM_TSSI5_2GHZ 0x3b +#define RT2860_EEPROM_PWR5GHZ_BASE1 0x3c +#define RT2860_EEPROM_PWR5GHZ_BASE2 0x53 +#define RT2860_EEPROM_TSSI1_5GHZ 0x6a +#define RT2860_EEPROM_TSSI2_5GHZ 0x6b +#define RT2860_EEPROM_TSSI3_5GHZ 0x6c +#define RT2860_EEPROM_TSSI4_5GHZ 0x6d +#define RT2860_EEPROM_TSSI5_5GHZ 0x6e +#define RT2860_EEPROM_RPWR 0x6f +#define RT2860_EEPROM_BBP_BASE 0x78 +#define RT3071_EEPROM_RF_BASE 0x82 /* * EEPROM IQ calibration. @@ -914,23 +912,23 @@ struct rt2860_rxwi { #define RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ 0x134 #define RT5390_EEPROM_RF_IQ_COMPENSATION_CTL 0x13c #define RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL 0x13d -#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ 0x144 -#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ 0x145 -#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ 0x146 -#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ 0x147 -#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ 0x148 -#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ 0x149 -#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ 0x14a -#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ 0x14b -#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ 0x14c -#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ 0x14d -#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e -#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ 0x144 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ 0x145 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ 0x146 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ 0x147 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ 0x148 +#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ 0x149 +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ 0x14a +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ 0x14b +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ 0x14c +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ 0x14d +#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e +#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f -#define RT2860_RIDX_CCK1 0 -#define RT2860_RIDX_CCK11 3 -#define RT2860_RIDX_OFDM6 4 -#define RT2860_RIDX_MAX 12 +#define RT2860_RIDX_CCK1 0 +#define RT2860_RIDX_CCK11 3 +#define RT2860_RIDX_OFDM6 4 +#define RT2860_RIDX_MAX 12 /* * EEPROM access macro. @@ -944,7 +942,7 @@ struct rt2860_rxwi { /* * Default values for MAC registers; values taken from the reference driver. */ -#define RT2870_DEF_MAC \ +#define RT2870_DEF_MAC \ { RT2860_BCN_OFFSET0, 0xf8f0e8e0 }, \ { RT2860_BCN_OFFSET1, 0x6f77d0c8 }, \ { RT2860_LEGACY_BASIC_RATE, 0x0000013f }, \ @@ -981,7 +979,7 @@ struct rt2860_rxwi { /* * Default values for BBP registers; values taken from the reference driver. */ -#define RT2860_DEF_BBP \ +#define RT2860_DEF_BBP \ { 65, 0x2c }, \ { 66, 0x38 }, \ { 68, 0x0b }, \ @@ -999,7 +997,7 @@ struct rt2860_rxwi { { 105, 0x05 }, \ { 106, 0x35 } -#define RT5390_DEF_BBP \ +#define RT5390_DEF_BBP \ { 31, 0x08 }, \ { 65, 0x2c }, \ { 66, 0x38 }, \ @@ -1023,7 +1021,7 @@ struct rt2860_rxwi { { 106, 0x03 }, \ { 128, 0x12 } -#define RT5592_DEF_BBP \ +#define RT5592_DEF_BBP \ { 20, 0x06 }, \ { 31, 0x08 }, \ { 65, 0x2c }, \ @@ -1058,7 +1056,7 @@ struct rt2860_rxwi { /* * Default settings for RF registers; values derived from the reference driver. */ -#define RT2860_RF2850 \ +#define RT2860_RF2850 \ { 1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b }, \ { 2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f }, \ { 3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b }, \ @@ -1120,7 +1118,7 @@ struct rt2860_rxwi { { 212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b }, \ { 216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23 } -#define RT3070_RF3052 \ +#define RT3070_RF3052 \ { 0xf1, 2, 2 }, \ { 0xf1, 2, 7 }, \ { 0xf2, 2, 2 }, \ @@ -1175,7 +1173,7 @@ struct rt2860_rxwi { { 0x61, 0, 7 }, \ { 0x61, 0, 9 } -#define RT5592_RF5592_20MHZ \ +#define RT5592_RF5592_20MHZ \ { 0x1e2, 4, 10, 3 }, \ { 0x1e3, 4, 10, 3 }, \ { 0x1e4, 4, 10, 3 }, \ @@ -1230,7 +1228,7 @@ struct rt2860_rxwi { { 0xa5, 8, 12, 1 }, \ { 0xa6, 0, 12, 1 } -#define RT5592_RF5592_40MHZ \ +#define RT5592_RF5592_40MHZ \ { 0xf1, 2, 10, 3 }, \ { 0xf1, 7, 10, 3 }, \ { 0xf2, 2, 10, 3 }, \ @@ -1285,7 +1283,7 @@ struct rt2860_rxwi { { 0x52, 8, 12, 1 }, \ { 0x53, 0, 12, 1 } -#define RT3070_DEF_RF \ +#define RT3070_DEF_RF \ { 4, 0x40 }, \ { 5, 0x03 }, \ { 6, 0x02 }, \ @@ -1306,7 +1304,7 @@ struct rt2860_rxwi { { 25, 0x03 }, \ { 29, 0x1f } -#define RT3572_DEF_RF \ +#define RT3572_DEF_RF \ { 0, 0x70 }, \ { 1, 0x81 }, \ { 2, 0xf1 }, \ @@ -1339,7 +1337,7 @@ struct rt2860_rxwi { { 30, 0x09 }, \ { 31, 0x10 } -#define RT5390_DEF_RF \ +#define RT5390_DEF_RF \ { 1, 0x0f }, \ { 2, 0x80 }, \ { 3, 0x88 }, \ @@ -1398,7 +1396,7 @@ struct rt2860_rxwi { { 62, 0x00 }, \ { 63, 0x00 } -#define RT5392_DEF_RF \ +#define RT5392_DEF_RF \ { 1, 0x17 }, \ { 3, 0x88 }, \ { 5, 0x10 }, \ @@ -1458,7 +1456,7 @@ struct rt2860_rxwi { { 62, 0x39 }, \ { 63, 0x07 } -#define RT5592_DEF_RF \ +#define RT5592_DEF_RF \ { 1, 0x3f }, \ { 3, 0x08 }, \ { 5, 0x10 }, \ @@ -1481,7 +1479,7 @@ struct rt2860_rxwi { { 53, 0x22 }, \ { 63, 0x07 } -#define RT5592_2GHZ_DEF_RF \ +#define RT5592_2GHZ_DEF_RF \ { 10, 0x90 }, \ { 11, 0x4a }, \ { 12, 0x52 }, \ @@ -1512,7 +1510,7 @@ struct rt2860_rxwi { { 61, 0x91 }, \ { 62, 0x39 } -#define RT5592_5GHZ_DEF_RF \ +#define RT5592_5GHZ_DEF_RF \ { 10, 0x97 }, \ { 11, 0x40 }, \ { 25, 0xbf }, \ @@ -1529,7 +1527,7 @@ struct rt2860_rxwi { { 60, 0x05 }, \ { 61, 0x01 } -#define RT5592_CHAN_5GHZ \ +#define RT5592_CHAN_5GHZ \ { 36, 64, 12, 0x2e }, \ { 100, 165, 12, 0x0e }, \ { 36, 64, 13, 0x22 }, \ diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index cc6f44cc8e5a..3576c4e05543 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -23,25 +23,25 @@ #ifndef _IF_RUNVAR_H_ #define _IF_RUNVAR_H_ -#define RUN_MAX_RXSZ \ +#define RUN_MAX_RXSZ \ MIN(4096, MJUMPAGESIZE) /* NB: "11" is the maximum number of padding bytes needed for Tx */ -#define RUN_MAX_TXSZ \ +#define RUN_MAX_TXSZ \ (sizeof (struct rt2870_txd) + \ sizeof (struct rt2860_txwi) + \ MCLBYTES + 11) -#define RUN_TX_TIMEOUT 5000 /* ms */ +#define RUN_TX_TIMEOUT 5000 /* ms */ /* Tx ring count was 8/endpoint, now 32 for all 4 (or 6) endpoints. */ -#define RUN_TX_RING_COUNT 32 -#define RUN_RX_RING_COUNT 1 +#define RUN_TX_RING_COUNT 32 +#define RUN_RX_RING_COUNT 1 -#define RT2870_WCID_MAX 64 -#define RUN_AID2WCID(aid) ((aid) & 0xff) +#define RT2870_WCID_MAX 64 +#define RUN_AID2WCID(aid) ((aid) & 0xff) -#define RUN_VAP_MAX 8 +#define RUN_VAP_MAX 8 struct run_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; @@ -54,7 +54,7 @@ struct run_rx_radiotap_header { uint8_t wr_antsignal; } __packed __aligned(8); -#define RUN_RX_RADIOTAP_PRESENT \ +#define RUN_RX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL | \ @@ -73,7 +73,7 @@ struct run_tx_radiotap_header { #define IEEE80211_RADIOTAP_HWQUEUE 15 -#define RUN_TX_RADIOTAP_PRESENT \ +#define RUN_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL | \ @@ -122,7 +122,7 @@ struct run_vap { uint8_t rvp_id; }; -#define RUN_VAP(vap) ((struct run_vap *)(vap)) +#define RUN_VAP(vap) ((struct run_vap *)(vap)) /* * There are 7 bulk endpoints: 1 for RX @@ -206,19 +206,19 @@ struct run_softc { struct task ratectl_task; struct usb_callout ratectl_ch; uint8_t ratectl_run; -#define RUN_RATECTL_OFF 0 +#define RUN_RATECTL_OFF 0 /* need to be power of 2, otherwise RUN_CMDQ_GET fails */ -#define RUN_CMDQ_MAX 16 -#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1) +#define RUN_CMDQ_MAX 16 +#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1) struct run_cmdq cmdq[RUN_CMDQ_MAX]; struct task cmdq_task; uint32_t cmdq_store; uint8_t cmdq_exec; uint8_t cmdq_run; uint8_t cmdq_key_set; -#define RUN_CMDQ_ABORT 0 -#define RUN_CMDQ_GO 1 +#define RUN_CMDQ_ABORT 0 +#define RUN_CMDQ_GO 1 struct usb_xfer *sc_xfer[RUN_N_XFER]; @@ -250,8 +250,8 @@ struct run_softc { int sc_txtap_len; }; -#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) +#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) +#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) +#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) #endif /* _IF_RUNVAR_H_ */ From 9df3ee075824277e7e5bcf42cdd738f426fd7356 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Wed, 18 Dec 2013 08:53:40 +0000 Subject: [PATCH 136/172] Use 'val' instead of 'val & 0xff' since the last argument of run_bbp_write() is uint8_t. Spotted by: yongari --- sys/dev/usb/wlan/if_run.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index f6c654cba10a..6e585e1d5e48 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -3659,7 +3659,7 @@ run_iq_calib(struct run_softc *sc, u_int chan) &val, 1); } else val = 0; - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); /* Tx0 IQ phase. */ run_bbp_write(sc, 158, 0x2d); @@ -3680,7 +3680,7 @@ run_iq_calib(struct run_softc *sc, u_int chan) &val, 1); } else val = 0; - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); /* Tx1 IQ gain. */ run_bbp_write(sc, 158, 0x4a); @@ -3701,7 +3701,7 @@ run_iq_calib(struct run_softc *sc, u_int chan) &val, 1); } else val = 0; - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); /* Tx1 IQ phase. */ run_bbp_write(sc, 158, 0x4b); @@ -3722,19 +3722,19 @@ run_iq_calib(struct run_softc *sc, u_int chan) &val, 1); } else val = 0; - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); /* RF IQ compensation control. */ run_bbp_write(sc, 158, 0x04); run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL, &val, 1); - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); /* RF IQ imbalance compensation control. */ run_bbp_write(sc, 158, 0x03); run_efuse_read(sc, RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1); - run_bbp_write(sc, 159, val & 0xff); + run_bbp_write(sc, 159, val); } static void From 0f987f1f08f8a1268034490eb2b1484ada0ae605 Mon Sep 17 00:00:00 2001 From: Ruslan Ermilov Date: Wed, 18 Dec 2013 12:18:17 +0000 Subject: [PATCH 137/172] shm_open(2): Fixed the history information. While here, sort xrefs. Reviewed by: jhb --- lib/libc/sys/shm_open.2 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libc/sys/shm_open.2 b/lib/libc/sys/shm_open.2 index a521e58412b3..76d8f3c150aa 100644 --- a/lib/libc/sys/shm_open.2 +++ b/lib/libc/sys/shm_open.2 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 20, 2007 +.Dd December 18, 2013 .Dt SHM_OPEN 2 .Os .Sh NAME @@ -253,8 +253,8 @@ requires write permission to the shared memory object. .El .Sh SEE ALSO .Xr close 2 , -.Xr ftruncate 2 , .Xr fstat 2 , +.Xr ftruncate 2 , .Xr mmap 2 , .Xr munmap 2 .Sh STANDARDS @@ -273,7 +273,7 @@ functions first appeared in .Fx 4.3 . The functions were reimplemented as system calls using shared memory objects directly rather than files in -.Fx 7.0 . +.Fx 8.0 . .Sh AUTHORS .An Garrett A. Wollman Aq wollman@FreeBSD.org (C library support and this manual page) From e1e585a87ce47b269cf17f20491b59d8f28486db Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Wed, 18 Dec 2013 12:50:43 +0000 Subject: [PATCH 138/172] - Rename tty_makedev() into tty_makedevf() and make it capable to fail and return error. - Use make_dev_p() in tty_makedevf() instead of make_dev_cred(). - Always pass MAKEDEV_CHECKNAME flag. - Optionally pass MAKEDEV_REF flag. - Provide macro for compatibility with old API. This fixes races with simultaneous creation and desctruction of ttys, and makes it possible to call tty_makedevf() from device cloners. A race in tty_watermarks() still exist, since the latter drops lock for M_WAITOK allocation. This will be addressed in separate commit. Reviewed by: kib Sponsored by: Nginx, Inc. --- sys/kern/tty.c | 105 +++++++++++++++++++++++++++++++++---------------- sys/sys/tty.h | 7 +++- 2 files changed, 76 insertions(+), 36 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index e181d1e62e46..1bf0ac8e3891 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -289,7 +289,7 @@ ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) goto done; ttydisc_open(tp); - tty_watermarks(tp); + tty_watermarks(tp); /* XXXGL: drops lock */ } /* Wait for Carrier Detect. */ @@ -1174,16 +1174,18 @@ SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, * the user. */ -void -tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...) +int +tty_makedevf(struct tty *tp, struct ucred *cred, int flags, + const char *fmt, ...) { va_list ap; - struct cdev *dev; + struct cdev *dev, *init, *lock, *cua, *cinit, *clock; const char *prefix = "tty"; char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */ uid_t uid; gid_t gid; mode_t mode; + int error; /* Remove "tty" prefix from devices like PTY's. */ if (tp->t_flags & TF_NOPREFIX) @@ -1205,57 +1207,92 @@ tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...) mode = S_IRUSR|S_IWUSR|S_IWGRP; } + flags = flags & TTYMK_CLONING ? MAKEDEV_REF : 0; + flags |= MAKEDEV_CHECKNAME; + /* Master call-in device. */ - dev = make_dev_cred(&ttydev_cdevsw, 0, cred, - uid, gid, mode, "%s%s", prefix, name); + error = make_dev_p(flags, &dev, &ttydev_cdevsw, cred, uid, gid, mode, + "%s%s", prefix, name); + if (error) + return (error); dev->si_drv1 = tp; wakeup(&dev->si_drv1); tp->t_dev = dev; + init = lock = cua = cinit = clock = NULL; + /* Slave call-in devices. */ if (tp->t_flags & TF_INITLOCK) { - dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_INIT, cred, - uid, gid, mode, "%s%s.init", prefix, name); - dev_depends(tp->t_dev, dev); - dev->si_drv1 = tp; - wakeup(&dev->si_drv1); - dev->si_drv2 = &tp->t_termios_init_in; + error = make_dev_p(flags, &init, &ttyil_cdevsw, cred, uid, + gid, mode, "%s%s.init", prefix, name); + if (error) + goto fail; + dev_depends(dev, init); + dev2unit(init) = TTYUNIT_INIT; + init->si_drv1 = tp; + wakeup(&init->si_drv1); + init->si_drv2 = &tp->t_termios_init_in; - dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_LOCK, cred, - uid, gid, mode, "%s%s.lock", prefix, name); - dev_depends(tp->t_dev, dev); - dev->si_drv1 = tp; - wakeup(&dev->si_drv1); - dev->si_drv2 = &tp->t_termios_lock_in; + error = make_dev_p(flags, &lock, &ttyil_cdevsw, cred, uid, + gid, mode, "%s%s.lock", prefix, name); + if (error) + goto fail; + dev_depends(dev, lock); + dev2unit(lock) = TTYUNIT_LOCK; + lock->si_drv1 = tp; + wakeup(&lock->si_drv1); + lock->si_drv2 = &tp->t_termios_lock_in; } /* Call-out devices. */ if (tp->t_flags & TF_CALLOUT) { - dev = make_dev_cred(&ttydev_cdevsw, TTYUNIT_CALLOUT, cred, + error = make_dev_p(flags, &cua, &ttydev_cdevsw, cred, UID_UUCP, GID_DIALER, 0660, "cua%s", name); - dev_depends(tp->t_dev, dev); - dev->si_drv1 = tp; - wakeup(&dev->si_drv1); + if (error) + goto fail; + dev_depends(dev, cua); + dev2unit(cua) = TTYUNIT_CALLOUT; + cua->si_drv1 = tp; + wakeup(&cua->si_drv1); /* Slave call-out devices. */ if (tp->t_flags & TF_INITLOCK) { - dev = make_dev_cred(&ttyil_cdevsw, - TTYUNIT_CALLOUT | TTYUNIT_INIT, cred, + error = make_dev_p(flags, &cinit, &ttyil_cdevsw, cred, UID_UUCP, GID_DIALER, 0660, "cua%s.init", name); - dev_depends(tp->t_dev, dev); - dev->si_drv1 = tp; - wakeup(&dev->si_drv1); - dev->si_drv2 = &tp->t_termios_init_out; + if (error) + goto fail; + dev_depends(dev, cinit); + dev2unit(cinit) = TTYUNIT_CALLOUT | TTYUNIT_INIT; + cinit->si_drv1 = tp; + wakeup(&cinit->si_drv1); + cinit->si_drv2 = &tp->t_termios_init_out; - dev = make_dev_cred(&ttyil_cdevsw, - TTYUNIT_CALLOUT | TTYUNIT_LOCK, cred, + error = make_dev_p(flags, &clock, &ttyil_cdevsw, cred, UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name); - dev_depends(tp->t_dev, dev); - dev->si_drv1 = tp; - wakeup(&dev->si_drv1); - dev->si_drv2 = &tp->t_termios_lock_out; + if (error) + goto fail; + dev_depends(dev, clock); + dev2unit(clock) = TTYUNIT_CALLOUT | TTYUNIT_LOCK; + clock->si_drv1 = tp; + wakeup(&clock->si_drv1); + clock->si_drv2 = &tp->t_termios_lock_out; } } + + return (0); + +fail: + destroy_dev(dev); + if (init) + destroy_dev(init); + if (lock) + destroy_dev(lock); + if (cinit) + destroy_dev(cinit); + if (clock) + destroy_dev(clock); + + return (error); } /* diff --git a/sys/sys/tty.h b/sys/sys/tty.h index b9552186d9a4..f1a044f1488c 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -171,8 +171,11 @@ void tty_rel_gone(struct tty *tp); #define tty_getlock(tp) ((tp)->t_mtx) /* Device node creation. */ -void tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...) - __printflike(3, 4); +int tty_makedevf(struct tty *tp, struct ucred *cred, int flags, + const char *fmt, ...) __printflike(4, 5); +#define TTYMK_CLONING 0x1 +#define tty_makedev(tp, cred, fmt, ...) \ + (void )tty_makedevf((tp), (cred), 0, (fmt), ## __VA_ARGS__) #define tty_makealias(tp,fmt,...) \ make_dev_alias((tp)->t_dev, fmt, ## __VA_ARGS__) From a95ecdf0cfc553f16ab02c4c42d8d56aa8d8e56e Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Wed, 18 Dec 2013 12:53:48 +0000 Subject: [PATCH 139/172] Make nmdm(4) destroy devices when both sides of a pair are disconnected. This makes it possible to kldunload nmdm.ko when there are no users of it. Reviewed by: kib Sponsored by: Nginx, Inc. --- sys/dev/nmdm/nmdm.c | 136 +++++++++++++++++++++++++++++++++----------- 1 file changed, 104 insertions(+), 32 deletions(-) diff --git a/sys/dev/nmdm/nmdm.c b/sys/dev/nmdm/nmdm.c index ceee762d277f..04a0b160c127 100644 --- a/sys/dev/nmdm/nmdm.c +++ b/sys/dev/nmdm/nmdm.c @@ -58,6 +58,8 @@ static tsw_inwakeup_t nmdm_outwakeup; static tsw_outwakeup_t nmdm_inwakeup; static tsw_param_t nmdm_param; static tsw_modem_t nmdm_modem; +static tsw_close_t nmdm_close; +static tsw_free_t nmdm_free; static struct ttydevsw nmdm_class = { .tsw_flags = TF_NOPREFIX, @@ -65,6 +67,8 @@ static struct ttydevsw nmdm_class = { .tsw_outwakeup = nmdm_outwakeup, .tsw_param = nmdm_param, .tsw_modem = nmdm_modem, + .tsw_close = nmdm_close, + .tsw_free = nmdm_free, }; static void nmdm_task_tty(void *, int); @@ -94,15 +98,83 @@ struct nmdmsoftc { static int nmdm_count = 0; -static struct nmdmsoftc * -nmdm_alloc(unsigned long unit) +static void +nmdm_close(struct tty *tp) +{ + struct nmdmpart *np; + struct nmdmpart *onp; + struct tty *otp; + + np = tty_softc(tp); + onp = np->np_other; + otp = onp->np_tty; + + /* If second part is opened, do not destroy ourselves. */ + if (tty_opened(otp)) + return; + + /* Shut down self. */ + tty_rel_gone(tp); + + /* Shut down second part. */ + tty_lock(tp); + onp = np->np_other; + if (onp == NULL) + return; + otp = onp->np_tty; + tty_rel_gone(otp); + tty_lock(tp); +} + +static void +nmdm_free(void *softc) +{ + struct nmdmpart *np = (struct nmdmpart *)softc; + struct nmdmsoftc *ns = np->np_pair; + + callout_drain(&np->np_callout); + taskqueue_drain(taskqueue_swi, &np->np_task); + + /* + * The function is called on both parts simultaneously. We serialize + * with help of ns_mtx. The first invocation should return and + * delegate freeing of resources to the second. + */ + mtx_lock(&ns->ns_mtx); + if (np->np_other != NULL) { + np->np_other->np_other = NULL; + mtx_unlock(&ns->ns_mtx); + return; + } + mtx_destroy(&ns->ns_mtx); + free(ns, M_NMDM); + atomic_subtract_int(&nmdm_count, 1); +} + +static void +nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen, + struct cdev **dev) { struct nmdmsoftc *ns; struct tty *tp; + unsigned long unit; + char *end; + int error; - atomic_add_int(&nmdm_count, 1); + if (*dev != NULL) + return; + if (strncmp(name, "nmdm", 4) != 0) + return; - ns = malloc(sizeof(*ns), M_NMDM, M_WAITOK|M_ZERO); + /* Device name must be "nmdm%lu%c", where %c is 'A' or 'B'. */ + name += 4; + unit = strtoul(name, &end, 10); + if (unit == ULONG_MAX || name == end) + return; + if ((end[0] != 'A' && end[0] != 'B') || end[1] != '\0') + return; + + ns = malloc(sizeof(*ns), M_NMDM, M_WAITOK | M_ZERO); mtx_init(&ns->ns_mtx, "nmdm", NULL, MTX_DEF); /* Hook the pairs together. */ @@ -119,43 +191,33 @@ nmdm_alloc(unsigned long unit) /* Create device nodes. */ tp = ns->ns_part1.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part1, &ns->ns_mtx); - tty_makedev(tp, NULL, "nmdm%luA", unit); + error = tty_makedevf(tp, NULL, end[0] == 'A' ? TTYMK_CLONING : 0, + "nmdm%luA", unit); + if (error) { + mtx_destroy(&ns->ns_mtx); + free(ns, M_NMDM); + return; + } tp = ns->ns_part2.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part2, &ns->ns_mtx); - tty_makedev(tp, NULL, "nmdm%luB", unit); - - return (ns); -} - -static void -nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen, - struct cdev **dev) -{ - unsigned long unit; - char *end; - struct nmdmsoftc *ns; - - if (*dev != NULL) + error = tty_makedevf(tp, NULL, end[0] == 'B' ? TTYMK_CLONING : 0, + "nmdm%luB", unit); + if (error) { + mtx_lock(&ns->ns_mtx); + /* see nmdm_free() */ + ns->ns_part1.np_other = NULL; + atomic_add_int(&nmdm_count, 1); + tty_rel_gone(ns->ns_part1.np_tty); return; - if (strncmp(name, "nmdm", 4) != 0) - return; - - /* Device name must be "nmdm%lu%c", where %c is 'A' or 'B'. */ - name += 4; - unit = strtoul(name, &end, 10); - if (unit == ULONG_MAX || name == end) - return; - if ((end[0] != 'A' && end[0] != 'B') || end[1] != '\0') - return; - - /* XXX: pass privileges? */ - ns = nmdm_alloc(unit); + } if (end[0] == 'A') *dev = ns->ns_part1.np_tty->t_dev; else *dev = ns->ns_part2.np_tty->t_dev; + + atomic_add_int(&nmdm_count, 1); } static void @@ -187,6 +249,10 @@ nmdm_task_tty(void *arg, int pending __unused) tp = np->np_tty; tty_lock(tp); + if (tty_gone(tp)) { + tty_unlock(tp); + return; + } otp = np->np_other->np_tty; KASSERT(otp != NULL, ("NULL otp in nmdmstart")); @@ -203,6 +269,12 @@ nmdm_task_tty(void *arg, int pending __unused) } } + /* This may happen when we are in detach process. */ + if (tty_gone(otp)) { + tty_unlock(otp); + return; + } + while (ttydisc_rint_poll(otp) > 0) { if (np->np_rate && !np->np_quota) break; From cfbe5d01ee1fbd7c9c63d0d321acc789902fbd0d Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 18 Dec 2013 14:53:36 +0000 Subject: [PATCH 140/172] gcc: add Apple compatible -Wnewline-eof GCC 4.2 and previous have always warned about "No newline at end of file". Upstream GCC removed the warning completely but Apple made it an optional warning. Adopt it for compatibility with older GCC and clang. While here, add comment to complement r258712. Obtained from: Apple Inc. (Apple GCC 4.2 - 5531) MFC after: 1 week --- contrib/gcc/c-opts.c | 6 ++++++ contrib/gcc/c.opt | 6 ++++++ contrib/gcc/doc/invoke.texi | 8 ++++++++ contrib/gcclibs/libcpp/ChangeLog.apple | 9 +++++++++ contrib/gcclibs/libcpp/charset.c | 1 + contrib/gcclibs/libcpp/include/cpplib.h | 5 +++++ contrib/gcclibs/libcpp/init.c | 4 ++++ contrib/gcclibs/libcpp/lex.c | 8 ++++++++ 8 files changed, 47 insertions(+) create mode 100644 contrib/gcclibs/libcpp/ChangeLog.apple diff --git a/contrib/gcc/c-opts.c b/contrib/gcc/c-opts.c index ed6b7718ecb5..6b290687c76d 100644 --- a/contrib/gcc/c-opts.c +++ b/contrib/gcc/c-opts.c @@ -487,6 +487,12 @@ c_common_handle_option (size_t scode, const char *arg, int value) cpp_opts->warn_multichar = value; break; + /* APPLE LOCAL begin -Wnewline-eof */ + case OPT_Wnewline_eof: + cpp_opts->warn_newline_at_eof = value; + break; + /* APPLE LOCAL end -Wnewline-eof */ + case OPT_Wnormalized_: if (!value || (arg && strcasecmp (arg, "none") == 0)) cpp_opts->warn_normalize = normalized_none; diff --git a/contrib/gcc/c.opt b/contrib/gcc/c.opt index 86e9460a7f71..58d13e8a7d65 100644 --- a/contrib/gcc/c.opt +++ b/contrib/gcc/c.opt @@ -292,6 +292,12 @@ Wnested-externs C ObjC Var(warn_nested_externs) Warn about \"extern\" declarations not at file scope +; APPLE LOCAL begin -Wnewline-eof +Wnewline-eof +C ObjC C++ ObjC++ +Warn about files missing a newline at the end of the file +; APPLE LOCAL end -Wnewline-eof + Wnon-template-friend C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warn when non-templatized friend functions are declared within a template diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi index 5263e915c336..ed42d6f58a64 100644 --- a/contrib/gcc/doc/invoke.texi +++ b/contrib/gcc/doc/invoke.texi @@ -169,6 +169,8 @@ in the following sections. -trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol -fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol -fsigned-bitfields -fsigned-char @gol +@c APPLE LOCAL -Wnewline-eof 2001-08-23 --sts ** +-Wnewline-eof (Apple compatible) @gol -funsigned-bitfields -funsigned-char} @item C++ Language Options @@ -2082,6 +2084,12 @@ Inhibit all warning messages. @opindex Wno-import Inhibit warning messages about the use of @samp{#import}. +@c APPLE LOCAL begin -Wnewline-eof 2001-08-23 --sts ** +@item -Wnewline-eof +@opindex Wnewline-eof +Warn about files missing a newline at the end of the file. (FreeBSD ONLY) +@c APPLE LOCAL end -Wnewline-eof 2001-08-23 --sts ** + @item -Wchar-subscripts @opindex Wchar-subscripts Warn if an array subscript has type @code{char}. This is a common cause diff --git a/contrib/gcclibs/libcpp/ChangeLog.apple b/contrib/gcclibs/libcpp/ChangeLog.apple new file mode 100644 index 000000000000..c38bfe23324a --- /dev/null +++ b/contrib/gcclibs/libcpp/ChangeLog.apple @@ -0,0 +1,9 @@ +2008-08-04 Bill Wendling + + Radar 6121572 + * charset.c (_cpp_convert_input): Don't read to.text[-1]. + +2005-02-17 Devang Patel + + Radar 3958387 + * libcpp/lex.c (_cpp_get_fresh_line): Check warn_newline_at_eof. diff --git a/contrib/gcclibs/libcpp/charset.c b/contrib/gcclibs/libcpp/charset.c index 6361f8c51321..009106b06761 100644 --- a/contrib/gcclibs/libcpp/charset.c +++ b/contrib/gcclibs/libcpp/charset.c @@ -1628,6 +1628,7 @@ _cpp_convert_input (cpp_reader *pfile, const char *input_charset, terminate with another \r, not an \n, so that we do not mistake the \r\n sequence for a single DOS line ending and erroneously issue the "No newline at end of file" diagnostic. */ + /* APPLE LOCAL don't access to.text[-1] radar 6121572 */ if (to.len > 0 && to.text[to.len - 1] == '\r') to.text[to.len] = '\r'; else diff --git a/contrib/gcclibs/libcpp/include/cpplib.h b/contrib/gcclibs/libcpp/include/cpplib.h index 5acef415c3d7..ac596d678bec 100644 --- a/contrib/gcclibs/libcpp/include/cpplib.h +++ b/contrib/gcclibs/libcpp/include/cpplib.h @@ -320,6 +320,11 @@ struct cpp_options /* Nonzero means warn if there are any trigraphs. */ unsigned char warn_trigraphs; + /* APPLE LOCAL begin -Wnewline-eof 2001-08-23 --sts */ + /* Nonzero means warn if no newline at end of file. */ + unsigned char warn_newline_at_eof; + /* APPLE LOCAL end -Wnewline-eof 2001-08-23 --sts */ + /* Nonzero means warn about multicharacter charconsts. */ unsigned char warn_multichar; diff --git a/contrib/gcclibs/libcpp/init.c b/contrib/gcclibs/libcpp/init.c index 248d84f53b75..9620676a6083 100644 --- a/contrib/gcclibs/libcpp/init.c +++ b/contrib/gcclibs/libcpp/init.c @@ -146,6 +146,10 @@ cpp_create_reader (enum c_lang lang, hash_table *table, pfile = XCNEW (cpp_reader); cpp_set_lang (pfile, lang); + /* APPLE LOCAL begin -Wnewline-eof 2001-08-23 --sts */ + /* Suppress warnings about missing newlines at ends of files. */ + CPP_OPTION (pfile, warn_newline_at_eof) = 0; + /* APPLE LOCAL end -Wnewline-eof 2001-08-23 --sts */ CPP_OPTION (pfile, warn_multichar) = 1; CPP_OPTION (pfile, discard_comments) = 1; CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1; diff --git a/contrib/gcclibs/libcpp/lex.c b/contrib/gcclibs/libcpp/lex.c index ef59f900c64a..1a3cad7efd83 100644 --- a/contrib/gcclibs/libcpp/lex.c +++ b/contrib/gcclibs/libcpp/lex.c @@ -854,6 +854,14 @@ _cpp_get_fresh_line (cpp_reader *pfile) { /* Clip to buffer size. */ buffer->next_line = buffer->rlimit; + /* APPLE LOCAL begin suppress no newline warning. */ + if ( CPP_OPTION (pfile, warn_newline_at_eof)) + { + cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line, + CPP_BUF_COLUMN (buffer, buffer->cur), + "no newline at end of file"); + } + /* APPLE LOCAL end suppress no newline warning. */ } return_at_eof = buffer->return_at_eof; From 505ca70a652ac4ded51c11a6531baffb425d9c9a Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 18 Dec 2013 15:27:48 +0000 Subject: [PATCH 141/172] gcc: add Apple compatible -Wnewline-eof Fix document: "Apple compatible" suits better the origin. MFC after: 1 week --- contrib/gcc/doc/invoke.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi index ed42d6f58a64..4549e22a4ddb 100644 --- a/contrib/gcc/doc/invoke.texi +++ b/contrib/gcc/doc/invoke.texi @@ -2087,7 +2087,7 @@ Inhibit warning messages about the use of @samp{#import}. @c APPLE LOCAL begin -Wnewline-eof 2001-08-23 --sts ** @item -Wnewline-eof @opindex Wnewline-eof -Warn about files missing a newline at the end of the file. (FreeBSD ONLY) +Warn about files missing a newline at the end of the file. (Apple compatible) @c APPLE LOCAL end -Wnewline-eof 2001-08-23 --sts ** @item -Wchar-subscripts From 07fb02c0d50dcdab2f4162c2819e503c3c5671c3 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 18 Dec 2013 17:03:43 +0000 Subject: [PATCH 142/172] Fix an inappropriate free of a non-dynamic value. While here, make the code more naive and robust: 1. When setting ev_value, also always set ev_flags appropriately 2. Always check ev_value and ev_flags before calling free. Both the value and the EV_DYNAMIC property can come directly from the consumers of the environment functionality, so it's good to be careful. And since this code is typically not looked at for long periods of time, it's good to have it be a little "dumb-looking". Trigger case for the bug: env_setenv("foo", 0, "1", NULL, NULL); env_setenv("foo", 0, "2", NULL, NULL); Obtained from: Juniper Networks, Inc. --- lib/libstand/environment.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/libstand/environment.c b/lib/libstand/environment.c index fde4cf9c3874..291e33004430 100644 --- a/lib/libstand/environment.c +++ b/lib/libstand/environment.c @@ -75,7 +75,14 @@ env_setenv(const char *name, int flags, const void *value, * for one already. */ if ((ev->ev_sethook != NULL) && !(flags & EV_NOHOOK)) - return(ev->ev_sethook(ev, flags, value)); + return (ev->ev_sethook(ev, flags, value)); + + /* If there is data in the variable, discard it. */ + if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0) + free(ev->ev_value); + ev->ev_value = NULL; + ev->ev_flags &= ~EV_DYNAMIC; + } else { /* @@ -84,6 +91,7 @@ env_setenv(const char *name, int flags, const void *value, ev = malloc(sizeof(struct env_var)); ev->ev_name = strdup(name); ev->ev_value = NULL; + ev->ev_flags = 0; /* hooks can only be set when the variable is instantiated */ ev->ev_sethook = sethook; ev->ev_unsethook = unsethook; @@ -117,21 +125,16 @@ env_setenv(const char *name, int flags, const void *value, } } } - - /* If there is data in the variable, discard it */ - if (ev->ev_value != NULL) - free(ev->ev_value); /* If we have a new value, use it */ if (flags & EV_VOLATILE) { ev->ev_value = strdup(value); + ev->ev_flags |= EV_DYNAMIC; } else { ev->ev_value = (char *)value; + ev->ev_flags |= flags & EV_DYNAMIC; } - /* Keep the flag components that are relevant */ - ev->ev_flags = flags & (EV_DYNAMIC); - return(0); } @@ -201,7 +204,7 @@ env_discard(struct env_var *ev) if (environ == ev) environ = ev->ev_next; free(ev->ev_name); - if (ev->ev_flags & EV_DYNAMIC) + if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0) free(ev->ev_value); free(ev); } From c49b4b80554de88a4b6468cb3b8a54e7a772990e Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Wed, 18 Dec 2013 18:25:27 +0000 Subject: [PATCH 143/172] Switch netstat -rn to use standard API for retrieving list of routes instead of peeking inside in-kernel radix via kget. This permits us to change kernel structures without breaking userland. Additionally, this change provide more reliable and faster output. `Refs` and `Use` fields available in IPv4 by default (and via -W for other families) were removed. `Refs` is radix-specific thing which is not informative for users. `Use` field value is handy sometimes, but a) current API does not support it and b) I'm not sure we will support per-rte pcpu counters in near future. Old method of retrieving data is still supported (either by defining NewTree=0 or running netstat with -A). However, Refs/Use fields are hidden. Sponsored by: Yandex LLC MFC after: 4 weeks PR: kern/167204 --- usr.bin/netstat/route.c | 178 +++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 58 deletions(-) diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c index 4381ffd31b6b..8f529ac12146 100644 --- a/usr.bin/netstat/route.c +++ b/usr.bin/netstat/route.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -113,13 +114,20 @@ typedef union { static sa_u pt_u; +struct ifmap_entry { + char ifname[IFNAMSIZ]; +}; + +static struct ifmap_entry *ifmap; +static int ifmap_size; + int do_rtent = 0; struct rtentry rtentry; struct radix_node rnode; struct radix_mask rmask; struct radix_node_head **rt_tables; -int NewTree = 0; +int NewTree = 1; struct timespec uptime; @@ -129,7 +137,7 @@ static void size_cols_tree(struct radix_node *rn); static void size_cols_rtentry(struct rtentry *rt); static void p_tree(struct radix_node *); static void p_rtnode(void); -static void ntreestuff(void); +static void ntreestuff(int fibnum, int af); static void np_rtentry(struct rt_msghdr *); static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, @@ -175,7 +183,7 @@ routepr(u_long rtree, int fibnum) printf("\n"); if (Aflag == 0 && NewTree) - ntreestuff(); + ntreestuff(fibnum, af); else { if (rtree == 0) { printf("rt_tables: symbol not in namelist\n"); @@ -288,7 +296,7 @@ static int wid_if; static int wid_expire; static void -size_cols(int ef __unused, struct radix_node *rn) +size_cols(int ef, struct radix_node *rn) { wid_dst = WID_DST_DEFAULT(ef); wid_gw = WID_GW_DEFAULT(ef); @@ -299,7 +307,7 @@ size_cols(int ef __unused, struct radix_node *rn) wid_if = WID_IF_DEFAULT(ef); wid_expire = 6; - if (Wflag) + if (Wflag && rn != NULL) size_cols_tree(rn); } @@ -397,27 +405,14 @@ pr_rthdr(int af1) if (Aflag) printf("%-8.8s ","Address"); - if (af1 == AF_INET || Wflag) { - if (Wflag) { - printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n", - wid_dst, wid_dst, "Destination", - wid_gw, wid_gw, "Gateway", - wid_flags, wid_flags, "Flags", - wid_refs, wid_refs, "Refs", - wid_use, wid_use, "Use", - wid_mtu, wid_mtu, "Mtu", - wid_if, wid_if, "Netif", - wid_expire, "Expire"); - } else { - printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n", - wid_dst, wid_dst, "Destination", - wid_gw, wid_gw, "Gateway", - wid_flags, wid_flags, "Flags", - wid_refs, wid_refs, "Refs", - wid_use, wid_use, "Use", - wid_if, wid_if, "Netif", - wid_expire, "Expire"); - } + if (Wflag) { + printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*s\n", + wid_dst, wid_dst, "Destination", + wid_gw, wid_gw, "Gateway", + wid_flags, wid_flags, "Flags", + wid_mtu, wid_mtu, "Mtu", + wid_if, wid_if, "Netif", + wid_expire, "Expire"); } else { printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n", wid_dst, wid_dst, "Destination", @@ -522,20 +517,61 @@ p_rtnode(void) } static void -ntreestuff(void) +ntreestuff(int fibnum, int af) { size_t needed; - int mib[6]; + int mib[7]; char *buf, *next, *lim; struct rt_msghdr *rtm; + struct sockaddr *sa; + int fam = 0, ifindex = 0, size; + + struct ifaddrs *ifap, *ifa; + struct sockaddr_dl *sdl; + + /* + * Retrieve interface list at first + * since we need #ifindex -> if_xname match + */ + if (getifaddrs(&ifap) != 0) + err(EX_OSERR, "getifaddrs"); + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + ifindex = sdl->sdl_index; + + if (ifindex >= ifmap_size) { + size = roundup(ifindex + 1, 32) * + sizeof(struct ifmap_entry); + if ((ifmap = realloc(ifmap, size)) == NULL) + errx(2, "realloc(%d) failed", size); + memset(&ifmap[ifmap_size], 0, + size - ifmap_size * + sizeof(struct ifmap_entry)); + + ifmap_size = roundup(ifindex + 1, 32); + } + + if (*ifmap[ifindex].ifname != '\0') + continue; + + strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ); + } + + freeifaddrs(ifap); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; - mib[3] = 0; + mib[3] = af; mib[4] = NET_RT_DUMP; mib[5] = 0; - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + mib[6] = fibnum; + if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) { err(1, "sysctl: net.route.0.0.dump estimate"); } @@ -548,6 +584,16 @@ ntreestuff(void) lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; + /* + * Peek inside header to determine AF + */ + sa = (struct sockaddr *)(rtm + 1); + if (fam != sa->sa_family) { + fam = sa->sa_family; + size_cols(fam, NULL); + pr_family(fam); + pr_rthdr(fam); + } np_rtentry(rtm); } } @@ -556,38 +602,52 @@ static void np_rtentry(struct rt_msghdr *rtm) { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); -#ifdef notdef - static int masks_done, banner_printed; -#endif - static int old_af; - int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; + char buffer[128]; + char prettyname[128]; + sa_u addr, mask, gw; + unsigned int l; -#ifdef notdef - /* for the moment, netmasks are skipped over */ - if (!banner_printed) { - printf("Netmasks:\n"); - banner_printed = 1; +#define GETSA(_s, _f) { \ + bzero(&(_s), sizeof(_s)); \ + if (rtm->rtm_addrs & _f) { \ + l = roundup(sa->sa_len, sizeof(long)); \ + memcpy(&(_s), sa, (l > sizeof(_s)) ? sizeof(_s) : l); \ + sa = (struct sockaddr *)((char *)sa + l); \ + } \ +} + + GETSA(addr, RTA_DST); + GETSA(gw, RTA_GATEWAY); + GETSA(mask, RTA_NETMASK); + p_sockaddr(&addr.u_sa, &mask.u_sa, rtm->rtm_flags, wid_dst); + p_sockaddr(&gw.u_sa, NULL, RTF_HOST, wid_gw); + + snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); + p_flags(rtm->rtm_flags, buffer); + if (Wflag) { + if (rtm->rtm_rmx.rmx_mtu != 0) + printf("%*lu ", wid_mtu, rtm->rtm_rmx.rmx_mtu); + else + printf("%*s ", wid_mtu, ""); } - if (masks_done == 0) { - if (rtm->rtm_addrs != RTA_DST ) { - masks_done = 1; - af1 = sa->sa_family; - } - } else -#endif - af1 = sa->sa_family; - if (af1 != old_af) { - pr_family(af1); - old_af = af1; + + memset(prettyname, 0, sizeof(prettyname)); + if (rtm->rtm_index < ifmap_size) { + strlcpy(prettyname, ifmap[rtm->rtm_index].ifname, + sizeof(prettyname)); + if (*prettyname == '\0') + strlcpy(prettyname, "---", sizeof(prettyname)); } - if (rtm->rtm_addrs == RTA_DST) - p_sockaddr(sa, NULL, 0, 36); - else { - p_sockaddr(sa, NULL, rtm->rtm_flags, 16); - sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); - p_sockaddr(sa, NULL, 0, 18); + + printf("%*.*s", wid_if, wid_if, prettyname); + if (rtm->rtm_rmx.rmx_expire) { + time_t expire_time; + + if ((expire_time = + rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0) + printf(" %*d", wid_expire, (int)expire_time); } - p_flags(rtm->rtm_flags & interesting, "%-6.6s "); + putchar('\n'); } @@ -775,8 +835,10 @@ p_rtentry(struct rtentry *rt) snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); p_flags(rt->rt_flags, buffer); if (addr.u_sa.sa_family == AF_INET || Wflag) { +#if 0 printf("%*d %*lu ", wid_refs, rt->rt_refcnt, wid_use, rt->rt_use); +#endif if (Wflag) { if (rt->rt_rmx.rmx_mtu != 0) printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu); From 224a78aeed00a7ab617e3cbce92f030044a8b7cb Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 18 Dec 2013 19:23:05 +0000 Subject: [PATCH 144/172] Commit 1/2: update arcmsr(4) to 1.20.00.29 in order to add support of ARC-1883 SAS 12Gb/s RAID controllers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many thanks to Areca for continuing to support FreeBSD. Submitted by: 黃清隆 --- share/man/man4/arcmsr.4 | 4 +- sys/dev/arcmsr/arcmsr.c | 85 ++++++++++++++++++++++++----------------- sys/dev/arcmsr/arcmsr.h | 8 ++-- 3 files changed, 58 insertions(+), 39 deletions(-) diff --git a/share/man/man4/arcmsr.4 b/share/man/man4/arcmsr.4 index 87c70509fec0..1d4d650702aa 100644 --- a/share/man/man4/arcmsr.4 +++ b/share/man/man4/arcmsr.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 27, 2013 +.Dd December 18, 2013 .Dt ARCMSR 4 .Os .Sh NAME @@ -143,6 +143,8 @@ ARC-1681 ARC-1880 .It ARC-1882 +.It +ARC-1883 .El .Sh FILES .Bl -tag -width ".Pa /dev/arcmsr?" -compact diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 7e993e7db90a..5b23acc3ec88 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -75,6 +75,7 @@ ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 ** 1.20.00.28 09/13/2013 Ching Huang Removed recursive mutex in arcmsr_abort_dr_ccbs +** 1.20.00.29 12/18/2013 Ching Huang Change simq allocation number, support ARC1883 ****************************************************************************************** */ @@ -146,7 +147,7 @@ __FBSDID("$FreeBSD$"); #define arcmsr_callout_init(a) callout_init(a); #endif -#define ARCMSR_DRIVER_VERSION "arcmsr version 1.20.00.28 2013-09-13" +#define ARCMSR_DRIVER_VERSION "arcmsr version 1.20.00.29 2013-12-18" #include /* ************************************************************************** @@ -1438,7 +1439,7 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, u_int8_t *iop_data; u_int32_t iop_len; - if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { + if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); } iop_data = (u_int8_t *)prbuffer->data; @@ -1533,7 +1534,7 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) u_int8_t *iop_data; int32_t allxfer_len=0; - if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { + if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { arcmsr_Write_data_2iop_wqbuffer_D(acb); return; } @@ -1785,7 +1786,7 @@ static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { */ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1794,14 +1795,12 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, - 0, outbound_doorbell); - CHIP_REG_WRITE32(HBA_MessageUnit, - 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); + CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ + if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } } @@ -1811,7 +1810,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) */ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1820,15 +1819,15 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); - CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); + CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ } } @@ -1838,7 +1837,7 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) */ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_Doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1847,22 +1846,22 @@ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; - if(outbound_Doorbell) - CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ - while( outbound_Doorbell & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; + if(doorbell_status) + CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ + while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ } - outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; - if(outbound_Doorbell) - CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ + doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; + if(doorbell_status) + CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ } } /* @@ -1932,9 +1931,7 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) ***************************************************************************** */ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - - while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { - + do { flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); /* check if command done with no error*/ error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; @@ -1944,7 +1941,7 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); throttling = 0; } - } /*drain reply FIFO*/ + } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); } /* ********************************************************************** @@ -2082,11 +2079,14 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) ** check outbound intstatus ********************************************* */ - host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); + host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & + (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | + ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); if(!host_interrupt_status) { /*it must be share irq*/ return; } + do { /* MU doorbell interrupts*/ if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { arcmsr_hbc_doorbell_isr(acb); @@ -2095,6 +2095,8 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { arcmsr_hbc_postqueue_isr(acb); } + host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); + } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); } /* ********************************************************************** @@ -2882,7 +2884,9 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(psim); #ifdef CAM_NEW_TRAN_CODE - if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) + if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) + cpi->base_transfer_speed = 1200000; + else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) cpi->base_transfer_speed = 600000; else cpi->base_transfer_speed = 300000; @@ -2980,7 +2984,9 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) cts->transport = XPORT_SAS; sas = &cts->xport_specific.sas; sas->valid = CTS_SAS_VALID_SPEED; - if((acb->vendor_device_id == PCIDevVenIDARC1880) || + if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) + sas->bitrate = 1200000; + else if((acb->vendor_device_id == PCIDevVenIDARC1880) || (acb->vendor_device_id == PCIDevVenIDARC1214)) sas->bitrate = 600000; else if(acb->vendor_device_id == PCIDevVenIDARC1680) @@ -3948,12 +3954,16 @@ static u_int32_t arcmsr_initialize(device_t dev) vendor_dev_id = pci_get_devid(dev); acb->vendor_device_id = vendor_dev_id; + acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); switch (vendor_dev_id) { case PCIDevVenIDARC1880: case PCIDevVenIDARC1882: case PCIDevVenIDARC1213: case PCIDevVenIDARC1223: { acb->adapter_type = ACB_ADAPTER_TYPE_C; + if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) + acb->adapter_bus_speed = ACB_BUS_SPEED_12G; + else acb->adapter_bus_speed = ACB_BUS_SPEED_6G; max_coherent_size = ARCMSR_SRBS_POOL_SIZE; } @@ -4286,7 +4296,7 @@ static int arcmsr_attach(device_t dev) * Create device queue of SIM(s) * (MAX_START_JOB - 1) : * max_sim_transactions */ - devq = cam_simq_alloc(ARCMSR_MAX_START_JOB); + devq = cam_simq_alloc(acb->maxOutstanding); if(devq == NULL) { arcmsr_free_resource(acb); bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); @@ -4360,6 +4370,7 @@ static int arcmsr_attach(device_t dev) static int arcmsr_probe(device_t dev) { u_int32_t id; + u_int16_t sub_device_id; static char buf[256]; char x_type[]={"unknown"}; char *type; @@ -4368,6 +4379,7 @@ static int arcmsr_probe(device_t dev) if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { return (ENXIO); } + sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); switch(id = pci_get_devid(dev)) { case PCIDevVenIDARC1110: case PCIDevVenIDARC1200: @@ -4400,6 +4412,9 @@ static int arcmsr_probe(device_t dev) case PCIDevVenIDARC1882: case PCIDevVenIDARC1213: case PCIDevVenIDARC1223: + if (sub_device_id == ARECA_SUB_DEV_ID_1883) + type = "SAS 12G"; + else type = "SAS 6G"; break; case PCIDevVenIDARC1214: diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h index e4f2d6fe4938..d3aa5d30ccd8 100644 --- a/sys/dev/arcmsr/arcmsr.h +++ b/sys/dev/arcmsr/arcmsr.h @@ -118,6 +118,7 @@ #define ARECA_SUB_DEV_ID_1880 0x1880 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1882 0x1882 /* Subsystem Device ID */ +#define ARECA_SUB_DEV_ID_1883 0x1883 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1212 0x1212 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1213 0x1213 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1222 0x1222 /* Subsystem Device ID */ @@ -1136,16 +1137,16 @@ struct AdapterControlBlock { u_int32_t phyadd_low; u_int32_t phyadd_high; }B; - } srb_phyaddr; + }srb_phyaddr; // unsigned long srb_phyaddr; /* Offset is used in making arc cdb physical to virtual calculations */ u_int32_t outbound_int_enable; struct MessageUnit_UNION *pmu; /* message unit ATU inbound base address0 */ - u_int8_t adapter_index; /* */ + u_int8_t adapter_index; u_int8_t irq; - u_int16_t acb_flags; /* */ + u_int16_t acb_flags; struct CommandControlBlock *psrb_pool[ARCMSR_MAX_FREESRB_NUM]; /* serial srb pointer array */ struct CommandControlBlock *srbworkingQ[ARCMSR_MAX_FREESRB_NUM]; /* working srb pointer array */ @@ -1183,6 +1184,7 @@ struct AdapterControlBlock { u_int32_t vendor_device_id; u_int32_t adapter_bus_speed; u_int32_t maxOutstanding; + u_int16_t sub_device_id; };/* HW_DEVICE_EXTENSION */ /* acb_flags */ #define ACB_F_SCSISTOPADAPTER 0x0001 From 47e52731cc0d32f1fe78bdb140c67b352a765dba Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 18 Dec 2013 19:25:40 +0000 Subject: [PATCH 145/172] Commit 2/2: vendor whitespace changes to the driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many thanks to Areca for continuing to support FreeBSD. Submitted by: 黃清隆 --- sys/dev/arcmsr/arcmsr.c | 30 +- sys/dev/arcmsr/arcmsr.h | 854 ++++++++++++++++++++-------------------- 2 files changed, 442 insertions(+), 442 deletions(-) diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 5b23acc3ec88..4c9210ef4cd4 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -1934,13 +1934,13 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) do { flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); /* check if command done with no error*/ - error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; + error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; arcmsr_drain_donequeue(acb, flag_srb, error); - throttling++; - if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { - CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); + throttling++; + if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { + CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); throttling = 0; - } + } } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); } /* @@ -2087,14 +2087,14 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) return; } do { - /* MU doorbell interrupts*/ - if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { - arcmsr_hbc_doorbell_isr(acb); - } - /* MU post queue interrupts*/ - if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { - arcmsr_hbc_postqueue_isr(acb); - } + /* MU doorbell interrupts*/ + if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { + arcmsr_hbc_doorbell_isr(acb); + } + /* MU post queue interrupts*/ + if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { + arcmsr_hbc_postqueue_isr(acb); + } host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); } @@ -3964,7 +3964,7 @@ static u_int32_t arcmsr_initialize(device_t dev) if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) acb->adapter_bus_speed = ACB_BUS_SPEED_12G; else - acb->adapter_bus_speed = ACB_BUS_SPEED_6G; + acb->adapter_bus_speed = ACB_BUS_SPEED_6G; max_coherent_size = ARCMSR_SRBS_POOL_SIZE; } break; @@ -4415,7 +4415,7 @@ static int arcmsr_probe(device_t dev) if (sub_device_id == ARECA_SUB_DEV_ID_1883) type = "SAS 12G"; else - type = "SAS 6G"; + type = "SAS 6G"; break; case PCIDevVenIDARC1214: type = "SATA 6G"; diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h index d3aa5d30ccd8..018b401e6eee 100644 --- a/sys/dev/arcmsr/arcmsr.h +++ b/sys/dev/arcmsr/arcmsr.h @@ -34,23 +34,23 @@ ************************************************************************** * $FreeBSD$ */ -#define ARCMSR_SCSI_INITIATOR_ID 255 -#define ARCMSR_DEV_SECTOR_SIZE 512 -#define ARCMSR_MAX_XFER_SECTORS 4096 -#define ARCMSR_MAX_TARGETID 17 /*16 max target id + 1*/ -#define ARCMSR_MAX_TARGETLUN 8 /*8*/ -#define ARCMSR_MAX_CHIPTYPE_NUM 4 -#define ARCMSR_MAX_OUTSTANDING_CMD 256 -#define ARCMSR_MAX_START_JOB 256 -#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD -#define ARCMSR_MAX_FREESRB_NUM 384 -#define ARCMSR_MAX_QBUFFER 4096 /* ioctl QBUFFER */ -#define ARCMSR_MAX_SG_ENTRIES 38 /* max 38*/ -#define ARCMSR_MAX_ADAPTER 4 -#define ARCMSR_RELEASE_SIMQ_LEVEL 230 -#define ARCMSR_MAX_HBB_POSTQUEUE 264 /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */ -#define ARCMSR_MAX_HBD_POSTQUEUE 256 -#define ARCMSR_TIMEOUT_DELAY 60 /* in sec */ +#define ARCMSR_SCSI_INITIATOR_ID 255 +#define ARCMSR_DEV_SECTOR_SIZE 512 +#define ARCMSR_MAX_XFER_SECTORS 4096 +#define ARCMSR_MAX_TARGETID 17 /*16 max target id + 1*/ +#define ARCMSR_MAX_TARGETLUN 8 /*8*/ +#define ARCMSR_MAX_CHIPTYPE_NUM 4 +#define ARCMSR_MAX_OUTSTANDING_CMD 256 +#define ARCMSR_MAX_START_JOB 256 +#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD +#define ARCMSR_MAX_FREESRB_NUM 384 +#define ARCMSR_MAX_QBUFFER 4096 /* ioctl QBUFFER */ +#define ARCMSR_MAX_SG_ENTRIES 38 /* max 38*/ +#define ARCMSR_MAX_ADAPTER 4 +#define ARCMSR_RELEASE_SIMQ_LEVEL 230 +#define ARCMSR_MAX_HBB_POSTQUEUE 264 /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */ +#define ARCMSR_MAX_HBD_POSTQUEUE 256 +#define ARCMSR_TIMEOUT_DELAY 60 /* in sec */ /* ********************************************************************* */ @@ -75,7 +75,7 @@ #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) #define arcmsr_htole32(x) htole32(x) - typedef struct mtx arcmsr_lock_t; + typedef struct mtx arcmsr_lock_t; #else #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) #define ARCMSR_LOCK_DESTROY(l) @@ -91,7 +91,7 @@ ** ********************************************************************************** */ -#define PCI_VENDOR_ID_ARECA 0x17D3 /* Vendor ID */ +#define PCI_VENDOR_ID_ARECA 0x17D3 /* Vendor ID */ #define PCI_DEVICE_ID_ARECA_1110 0x1110 /* Device ID */ #define PCI_DEVICE_ID_ARECA_1120 0x1120 /* Device ID */ #define PCI_DEVICE_ID_ARECA_1130 0x1130 /* Device ID */ @@ -133,11 +133,11 @@ #define PCIDevVenIDARC1201 0x120117D3 /* Vendor Device ID */ #define PCIDevVenIDARC1210 0x121017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1212 0x121217D3 /* Vendor Device ID */ -#define PCIDevVenIDARC1213 0x121317D3 /* Vendor Device ID */ -#define PCIDevVenIDARC1214 0x121417D3 /* Vendor Device ID */ +#define PCIDevVenIDARC1213 0x121317D3 /* Vendor Device ID */ +#define PCIDevVenIDARC1214 0x121417D3 /* Vendor Device ID */ #define PCIDevVenIDARC1220 0x122017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1222 0x122217D3 /* Vendor Device ID */ -#define PCIDevVenIDARC1223 0x122317D3 /* Vendor Device ID */ +#define PCIDevVenIDARC1223 0x122317D3 /* Vendor Device ID */ #define PCIDevVenIDARC1230 0x123017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1231 0x123117D3 /* Vendor Device ID */ #define PCIDevVenIDARC1260 0x126017D3 /* Vendor Device ID */ @@ -149,7 +149,7 @@ #define PCIDevVenIDARC1680 0x168017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1681 0x168117D3 /* Vendor Device ID */ #define PCIDevVenIDARC1880 0x188017D3 /* Vendor Device ID */ -#define PCIDevVenIDARC1882 0x188217D3 /* Vendor Device ID */ +#define PCIDevVenIDARC1882 0x188217D3 /* Vendor Device ID */ #ifndef PCIR_BARS #define PCIR_BARS 0x10 @@ -176,17 +176,17 @@ ** ********************************************************************************** */ -#define arcmsr_ccbsrb_ptr spriv_ptr0 -#define arcmsr_ccbacb_ptr spriv_ptr1 -#define dma_addr_hi32(addr) (u_int32_t) ((addr>>16)>>16) -#define dma_addr_lo32(addr) (u_int32_t) (addr & 0xffffffff) -#define get_min(x,y) ((x) < (y) ? (x) : (y)) -#define get_max(x,y) ((x) < (y) ? (y) : (x)) +#define arcmsr_ccbsrb_ptr spriv_ptr0 +#define arcmsr_ccbacb_ptr spriv_ptr1 +#define dma_addr_hi32(addr) (u_int32_t) ((addr>>16)>>16) +#define dma_addr_lo32(addr) (u_int32_t) (addr & 0xffffffff) +#define get_min(x,y) ((x) < (y) ? (x) : (y)) +#define get_max(x,y) ((x) < (y) ? (y) : (x)) /* ************************************************************************** ************************************************************************** */ -#define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) +#define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) /* ********************************************************************************** @@ -210,17 +210,17 @@ struct CMD_MESSAGE_FIELD { /************************************************************************/ /************************************************************************/ -#define ARCMSR_IOP_ERROR_ILLEGALPCI 0x0001 -#define ARCMSR_IOP_ERROR_VENDORID 0x0002 -#define ARCMSR_IOP_ERROR_DEVICEID 0x0002 -#define ARCMSR_IOP_ERROR_ILLEGALCDB 0x0003 -#define ARCMSR_IOP_ERROR_UNKNOW_CDBERR 0x0004 -#define ARCMSR_SYS_ERROR_MEMORY_ALLOCATE 0x0005 -#define ARCMSR_SYS_ERROR_MEMORY_CROSS4G 0x0006 -#define ARCMSR_SYS_ERROR_MEMORY_LACK 0x0007 -#define ARCMSR_SYS_ERROR_MEMORY_RANGE 0x0008 -#define ARCMSR_SYS_ERROR_DEVICE_BASE 0x0009 -#define ARCMSR_SYS_ERROR_PORT_VALIDATE 0x000A +#define ARCMSR_IOP_ERROR_ILLEGALPCI 0x0001 +#define ARCMSR_IOP_ERROR_VENDORID 0x0002 +#define ARCMSR_IOP_ERROR_DEVICEID 0x0002 +#define ARCMSR_IOP_ERROR_ILLEGALCDB 0x0003 +#define ARCMSR_IOP_ERROR_UNKNOW_CDBERR 0x0004 +#define ARCMSR_SYS_ERROR_MEMORY_ALLOCATE 0x0005 +#define ARCMSR_SYS_ERROR_MEMORY_CROSS4G 0x0006 +#define ARCMSR_SYS_ERROR_MEMORY_LACK 0x0007 +#define ARCMSR_SYS_ERROR_MEMORY_RANGE 0x0008 +#define ARCMSR_SYS_ERROR_DEVICE_BASE 0x0009 +#define ARCMSR_SYS_ERROR_PORT_VALIDATE 0x000A /*DeviceType*/ #define ARECA_SATA_RAID 0x90000000 @@ -252,44 +252,44 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE _IOWR('F', FUNCTION_FLUSH_ADAPTER_CACHE, struct CMD_MESSAGE_FIELD) /* ARECA IOCTL ReturnCode */ -#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 -#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 -#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F -#define ARCMSR_IOCTL_RETURNCODE_BUS_HANG_ON 0x00000088 +#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 +#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 +#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F +#define ARCMSR_IOCTL_RETURNCODE_BUS_HANG_ON 0x00000088 /* ************************************************************************ ** SPEC. for Areca HBA adapter ************************************************************************ */ /* signature of set and get firmware config */ -#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 -#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 +#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 +#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 /* message code of inbound message register */ -#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 -#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 -#define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 -#define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 -#define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 -#define ARCMSR_INBOUND_MESG0_FLUSH_CACHE 0x00000005 -#define ARCMSR_INBOUND_MESG0_START_BGRB 0x00000006 -#define ARCMSR_INBOUND_MESG0_CHK331PENDING 0x00000007 -#define ARCMSR_INBOUND_MESG0_SYNC_TIMER 0x00000008 +#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 +#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 +#define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 +#define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 +#define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 +#define ARCMSR_INBOUND_MESG0_FLUSH_CACHE 0x00000005 +#define ARCMSR_INBOUND_MESG0_START_BGRB 0x00000006 +#define ARCMSR_INBOUND_MESG0_CHK331PENDING 0x00000007 +#define ARCMSR_INBOUND_MESG0_SYNC_TIMER 0x00000008 /* doorbell interrupt generator */ -#define ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK 0x00000001 -#define ARCMSR_INBOUND_DRIVER_DATA_READ_OK 0x00000002 -#define ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK 0x00000001 -#define ARCMSR_OUTBOUND_IOP331_DATA_READ_OK 0x00000002 +#define ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK 0x00000001 +#define ARCMSR_INBOUND_DRIVER_DATA_READ_OK 0x00000002 +#define ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK 0x00000001 +#define ARCMSR_OUTBOUND_IOP331_DATA_READ_OK 0x00000002 /* srb areca cdb flag */ -#define ARCMSR_SRBPOST_FLAG_SGL_BSIZE 0x80000000 -#define ARCMSR_SRBPOST_FLAG_IAM_BIOS 0x40000000 -#define ARCMSR_SRBREPLY_FLAG_IAM_BIOS 0x40000000 -#define ARCMSR_SRBREPLY_FLAG_ERROR 0x10000000 -#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE0 0x10000000 -#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE1 0x00000001 +#define ARCMSR_SRBPOST_FLAG_SGL_BSIZE 0x80000000 +#define ARCMSR_SRBPOST_FLAG_IAM_BIOS 0x40000000 +#define ARCMSR_SRBREPLY_FLAG_IAM_BIOS 0x40000000 +#define ARCMSR_SRBREPLY_FLAG_ERROR 0x10000000 +#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE0 0x10000000 +#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE1 0x00000001 /* outbound firmware ok */ -#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 +#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 -#define ARCMSR_ARC1680_BUS_RESET 0x00000003 +#define ARCMSR_ARC1680_BUS_RESET 0x00000003 /* ************************************************************************ ** SPEC. for Areca HBB adapter @@ -307,20 +307,20 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_IOP2DRV_CDB_DONE 0x00000004 #define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 -#define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F +#define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F #define ARCMSR_DOORBELL_INT_CLEAR_PATTERN 0xFF00FFF0 #define ARCMSR_MESSAGE_INT_CLEAR_PATTERN 0xFF00FFF7 -#define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ -#define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ -#define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ -#define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ #define ARCMSR_MESSAGE_FLUSH_CACHE 0x00050008 /* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ -#define ARCMSR_MESSAGE_START_BGRB 0x00060008 /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ -#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 -#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 -#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008 -#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ +#define ARCMSR_MESSAGE_START_BGRB 0x00060008 /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 +#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 +#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008 +#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ #define ARCMSR_DRV2IOP_DATA_WRITE_OK 0x00000001 /* ioctl transfer */ #define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 /* ioctl transfer */ @@ -329,13 +329,13 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010 /* */ /* data tunnel buffer between user space program and its firmware */ -#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 /* iop msgcode_rwbuffer for message command */ -#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 /* user space data to iop 128bytes */ -#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 /* iop data to user space 128bytes */ -#define ARCMSR_HBB_BASE0_OFFSET 0x00000010 -#define ARCMSR_HBB_BASE1_OFFSET 0x00000018 -#define ARCMSR_HBB_BASE0_LEN 0x00021000 -#define ARCMSR_HBB_BASE1_LEN 0x00010000 +#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 /* iop msgcode_rwbuffer for message command */ +#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 /* user space data to iop 128bytes */ +#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 /* iop data to user space 128bytes */ +#define ARCMSR_HBB_BASE0_OFFSET 0x00000010 +#define ARCMSR_HBB_BASE1_OFFSET 0x00000018 +#define ARCMSR_HBB_BASE0_LEN 0x00021000 +#define ARCMSR_HBB_BASE1_LEN 0x00010000 /* ************************************************************************ ** SPEC. for Areca HBC adapter @@ -383,64 +383,64 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_HBCMU_IOP2DRV_DATA_READ_DOORBELL_CLEAR 0x00000004/*outbound DATA READ isr door bell clear*/ #define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008/*outbound message 0 ready*/ #define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR 0x00000008/*outbound message cmd isr door bell clear*/ -#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000/*ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK*/ +#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000/*ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK*/ #define ARCMSR_HBCMU_RESET_ADAPTER 0x00000024 -#define ARCMSR_HBCMU_DiagWrite_ENABLE 0x00000080 +#define ARCMSR_HBCMU_DiagWrite_ENABLE 0x00000080 /* ************************************************************************ ** SPEC. for Areca HBD adapter ************************************************************************ */ -#define ARCMSR_HBDMU_CHIP_ID 0x00004 +#define ARCMSR_HBDMU_CHIP_ID 0x00004 #define ARCMSR_HBDMU_CPU_MEMORY_CONFIGURATION 0x00008 -#define ARCMSR_HBDMU_I2_HOST_INTERRUPT_MASK 0x00034 -#define ARCMSR_HBDMU_MAIN_INTERRUPT_STATUS 0x00200 +#define ARCMSR_HBDMU_I2_HOST_INTERRUPT_MASK 0x00034 +#define ARCMSR_HBDMU_MAIN_INTERRUPT_STATUS 0x00200 #define ARCMSR_HBDMU_PCIE_F0_INTERRUPT_ENABLE 0x0020C -#define ARCMSR_HBDMU_INBOUND_MESSAGE0 0x00400 -#define ARCMSR_HBDMU_INBOUND_MESSAGE1 0x00404 -#define ARCMSR_HBDMU_OUTBOUND_MESSAGE0 0x00420 -#define ARCMSR_HBDMU_OUTBOUND_MESSAGE1 0x00424 -#define ARCMSR_HBDMU_INBOUND_DOORBELL 0x00460 -#define ARCMSR_HBDMU_OUTBOUND_DOORBELL 0x00480 +#define ARCMSR_HBDMU_INBOUND_MESSAGE0 0x00400 +#define ARCMSR_HBDMU_INBOUND_MESSAGE1 0x00404 +#define ARCMSR_HBDMU_OUTBOUND_MESSAGE0 0x00420 +#define ARCMSR_HBDMU_OUTBOUND_MESSAGE1 0x00424 +#define ARCMSR_HBDMU_INBOUND_DOORBELL 0x00460 +#define ARCMSR_HBDMU_OUTBOUND_DOORBELL 0x00480 #define ARCMSR_HBDMU_OUTBOUND_DOORBELL_ENABLE 0x00484 -#define ARCMSR_HBDMU_INBOUND_LIST_BASE_LOW 0x01000 -#define ARCMSR_HBDMU_INBOUND_LIST_BASE_HIGH 0x01004 +#define ARCMSR_HBDMU_INBOUND_LIST_BASE_LOW 0x01000 +#define ARCMSR_HBDMU_INBOUND_LIST_BASE_HIGH 0x01004 #define ARCMSR_HBDMU_INBOUND_LIST_WRITE_POINTER 0x01018 -#define ARCMSR_HBDMU_OUTBOUND_LIST_BASE_LOW 0x01060 +#define ARCMSR_HBDMU_OUTBOUND_LIST_BASE_LOW 0x01060 #define ARCMSR_HBDMU_OUTBOUND_LIST_BASE_HIGH 0x01064 #define ARCMSR_HBDMU_OUTBOUND_LIST_COPY_POINTER 0x0106C #define ARCMSR_HBDMU_OUTBOUND_LIST_READ_POINTER 0x01070 #define ARCMSR_HBDMU_OUTBOUND_INTERRUPT_CAUSE 0x01088 #define ARCMSR_HBDMU_OUTBOUND_INTERRUPT_ENABLE 0x0108C -#define ARCMSR_HBDMU_MESSAGE_WBUFFER 0x02000 -#define ARCMSR_HBDMU_MESSAGE_RBUFFER 0x02100 -#define ARCMSR_HBDMU_MESSAGE_RWBUFFER 0x02200 +#define ARCMSR_HBDMU_MESSAGE_WBUFFER 0x02000 +#define ARCMSR_HBDMU_MESSAGE_RBUFFER 0x02100 +#define ARCMSR_HBDMU_MESSAGE_RWBUFFER 0x02200 -#define ARCMSR_HBDMU_ISR_THROTTLING_LEVEL 16 -#define ARCMSR_HBDMU_ISR_MAX_DONE_QUEUE 20 +#define ARCMSR_HBDMU_ISR_THROTTLING_LEVEL 16 +#define ARCMSR_HBDMU_ISR_MAX_DONE_QUEUE 20 /* Host Interrupt Mask */ -#define ARCMSR_HBDMU_ALL_INT_ENABLE 0x00001010 /* enable all ISR */ -#define ARCMSR_HBDMU_ALL_INT_DISABLE 0x00000000 /* disable all ISR */ +#define ARCMSR_HBDMU_ALL_INT_ENABLE 0x00001010 /* enable all ISR */ +#define ARCMSR_HBDMU_ALL_INT_DISABLE 0x00000000 /* disable all ISR */ /* Host Interrupt Status */ -#define ARCMSR_HBDMU_OUTBOUND_INT 0x00001010 -#define ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT 0x00001000 -#define ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT 0x00000010 +#define ARCMSR_HBDMU_OUTBOUND_INT 0x00001010 +#define ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT 0x00001000 +#define ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT 0x00000010 /* DoorBell*/ -#define ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY 0x00000001 -#define ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ 0x00000002 +#define ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY 0x00000001 +#define ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ 0x00000002 -#define ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK 0x00000001 -#define ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK 0x00000002 +#define ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK 0x00000001 +#define ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK 0x00000002 /*outbound message 0 ready*/ #define ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE 0x02000000 -#define ARCMSR_HBDMU_F0_DOORBELL_CAUSE 0x02000003 +#define ARCMSR_HBDMU_F0_DOORBELL_CAUSE 0x02000003 /*outbound message cmd isr door bell clear*/ #define ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR 0x02000000 @@ -450,7 +450,7 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR 0x00000001 /*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/ -#define ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK 0x80000000 +#define ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK 0x80000000 /* ********************************************************************* ** Message Unit structure @@ -458,28 +458,28 @@ struct CMD_MESSAGE_FIELD { */ struct HBA_MessageUnit { - u_int32_t resrved0[4]; /*0000 000F*/ - u_int32_t inbound_msgaddr0; /*0010 0013*/ - u_int32_t inbound_msgaddr1; /*0014 0017*/ - u_int32_t outbound_msgaddr0; /*0018 001B*/ - u_int32_t outbound_msgaddr1; /*001C 001F*/ - u_int32_t inbound_doorbell; /*0020 0023*/ - u_int32_t inbound_intstatus; /*0024 0027*/ - u_int32_t inbound_intmask; /*0028 002B*/ - u_int32_t outbound_doorbell; /*002C 002F*/ - u_int32_t outbound_intstatus; /*0030 0033*/ - u_int32_t outbound_intmask; /*0034 0037*/ - u_int32_t reserved1[2]; /*0038 003F*/ - u_int32_t inbound_queueport; /*0040 0043*/ - u_int32_t outbound_queueport; /*0044 0047*/ - u_int32_t reserved2[2]; /*0048 004F*/ - u_int32_t reserved3[492]; /*0050 07FF ......local_buffer 492*/ - u_int32_t reserved4[128]; /*0800 09FF 128*/ - u_int32_t msgcode_rwbuffer[256]; /*0a00 0DFF 256*/ - u_int32_t message_wbuffer[32]; /*0E00 0E7F 32*/ - u_int32_t reserved5[32]; /*0E80 0EFF 32*/ - u_int32_t message_rbuffer[32]; /*0F00 0F7F 32*/ - u_int32_t reserved6[32]; /*0F80 0FFF 32*/ + u_int32_t resrved0[4]; /*0000 000F*/ + u_int32_t inbound_msgaddr0; /*0010 0013*/ + u_int32_t inbound_msgaddr1; /*0014 0017*/ + u_int32_t outbound_msgaddr0; /*0018 001B*/ + u_int32_t outbound_msgaddr1; /*001C 001F*/ + u_int32_t inbound_doorbell; /*0020 0023*/ + u_int32_t inbound_intstatus; /*0024 0027*/ + u_int32_t inbound_intmask; /*0028 002B*/ + u_int32_t outbound_doorbell; /*002C 002F*/ + u_int32_t outbound_intstatus; /*0030 0033*/ + u_int32_t outbound_intmask; /*0034 0037*/ + u_int32_t reserved1[2]; /*0038 003F*/ + u_int32_t inbound_queueport; /*0040 0043*/ + u_int32_t outbound_queueport; /*0044 0047*/ + u_int32_t reserved2[2]; /*0048 004F*/ + u_int32_t reserved3[492]; /*0050 07FF ......local_buffer 492*/ + u_int32_t reserved4[128]; /*0800 09FF 128*/ + u_int32_t msgcode_rwbuffer[256]; /*0a00 0DFF 256*/ + u_int32_t message_wbuffer[32]; /*0E00 0E7F 32*/ + u_int32_t reserved5[32]; /*0E80 0EFF 32*/ + u_int32_t message_rbuffer[32]; /*0F00 0F7F 32*/ + u_int32_t reserved6[32]; /*0F80 0FFF 32*/ }; /* ********************************************************************* @@ -488,11 +488,11 @@ struct HBA_MessageUnit */ struct HBB_DOORBELL { - u_int8_t doorbell_reserved[ARCMSR_DRV2IOP_DOORBELL]; /*reserved */ - u_int32_t drv2iop_doorbell; /*offset 0x00020400:00,01,02,03: window of "instruction flags" from driver to iop */ - u_int32_t drv2iop_doorbell_mask; /* 04,05,06,07: doorbell mask */ - u_int32_t iop2drv_doorbell; /* 08,09,10,11: window of "instruction flags" from iop to driver */ - u_int32_t iop2drv_doorbell_mask; /* 12,13,14,15: doorbell mask */ + u_int8_t doorbell_reserved[ARCMSR_DRV2IOP_DOORBELL]; /*reserved */ + u_int32_t drv2iop_doorbell; /*offset 0x00020400:00,01,02,03: window of "instruction flags" from driver to iop */ + u_int32_t drv2iop_doorbell_mask; /* 04,05,06,07: doorbell mask */ + u_int32_t iop2drv_doorbell; /* 08,09,10,11: window of "instruction flags" from iop to driver */ + u_int32_t iop2drv_doorbell_mask; /* 12,13,14,15: doorbell mask */ }; /* ********************************************************************* @@ -501,11 +501,11 @@ struct HBB_DOORBELL */ struct HBB_RWBUFFER { - u_int8_t message_reserved0[ARCMSR_MSGCODE_RWBUFFER]; /*reserved */ - u_int32_t msgcode_rwbuffer[256]; /*offset 0x0000fa00: 0, 1, 2, 3,...,1023: message code read write 1024bytes */ - u_int32_t message_wbuffer[32]; /*offset 0x0000fe00:1024,1025,1026,1027,...,1151: user space data to iop 128bytes */ - u_int32_t message_reserved1[32]; /* 1152,1153,1154,1155,...,1279: message reserved*/ - u_int32_t message_rbuffer[32]; /*offset 0x0000ff00:1280,1281,1282,1283,...,1407: iop data to user space 128bytes */ + u_int8_t message_reserved0[ARCMSR_MSGCODE_RWBUFFER]; /*reserved */ + u_int32_t msgcode_rwbuffer[256]; /*offset 0x0000fa00: 0, 1, 2, 3,...,1023: message code read write 1024bytes */ + u_int32_t message_wbuffer[32]; /*offset 0x0000fe00:1024,1025,1026,1027,...,1151: user space data to iop 128bytes */ + u_int32_t message_reserved1[32]; /* 1152,1153,1154,1155,...,1279: message reserved*/ + u_int32_t message_rbuffer[32]; /*offset 0x0000ff00:1280,1281,1282,1283,...,1407: iop data to user space 128bytes */ }; /* ********************************************************************* @@ -514,10 +514,10 @@ struct HBB_RWBUFFER */ struct HBB_MessageUnit { - u_int32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* post queue buffer for iop */ - u_int32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* done queue buffer for iop */ - int32_t postq_index; /* post queue index */ - int32_t doneq_index; /* done queue index */ + u_int32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* post queue buffer for iop */ + u_int32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* done queue buffer for iop */ + int32_t postq_index; /* post queue index */ + int32_t doneq_index; /* done queue index */ struct HBB_DOORBELL *hbb_doorbell; struct HBB_RWBUFFER *hbb_rwbuffer; }; @@ -531,71 +531,71 @@ struct HBC_MessageUnit { u_int32_t message_unit_status; /*0000 0003*/ u_int32_t slave_error_attribute; /*0004 0007*/ u_int32_t slave_error_address; /*0008 000B*/ - u_int32_t posted_outbound_doorbell; /*000C 000F*/ + u_int32_t posted_outbound_doorbell; /*000C 000F*/ u_int32_t master_error_attribute; /*0010 0013*/ - u_int32_t master_error_address_low; /*0014 0017*/ - u_int32_t master_error_address_high; /*0018 001B*/ + u_int32_t master_error_address_low; /*0014 0017*/ + u_int32_t master_error_address_high; /*0018 001B*/ u_int32_t hcb_size; /*001C 001F size of the PCIe window used for HCB_Mode accesses*/ - u_int32_t inbound_doorbell; /*0020 0023*/ - u_int32_t diagnostic_rw_data; /*0024 0027*/ - u_int32_t diagnostic_rw_address_low; /*0028 002B*/ - u_int32_t diagnostic_rw_address_high; /*002C 002F*/ - u_int32_t host_int_status; /*0030 0033 host interrupt status*/ - u_int32_t host_int_mask; /*0034 0037 host interrupt mask*/ - u_int32_t dcr_data; /*0038 003B*/ - u_int32_t dcr_address; /*003C 003F*/ - u_int32_t inbound_queueport; /*0040 0043 port32 host inbound queue port*/ - u_int32_t outbound_queueport; /*0044 0047 port32 host outbound queue port*/ - u_int32_t hcb_pci_address_low; /*0048 004B*/ - u_int32_t hcb_pci_address_high; /*004C 004F*/ - u_int32_t iop_int_status; /*0050 0053*/ - u_int32_t iop_int_mask; /*0054 0057*/ - u_int32_t iop_inbound_queue_port; /*0058 005B*/ - u_int32_t iop_outbound_queue_port; /*005C 005F*/ - u_int32_t inbound_free_list_index; /*0060 0063 inbound free list producer consumer index*/ - u_int32_t inbound_post_list_index; /*0064 0067 inbound post list producer consumer index*/ - u_int32_t outbound_free_list_index; /*0068 006B outbound free list producer consumer index*/ - u_int32_t outbound_post_list_index; /*006C 006F outbound post list producer consumer index*/ - u_int32_t inbound_doorbell_clear; /*0070 0073*/ - u_int32_t i2o_message_unit_control; /*0074 0077*/ - u_int32_t last_used_message_source_address_low; /*0078 007B*/ - u_int32_t last_used_message_source_address_high; /*007C 007F*/ - u_int32_t pull_mode_data_byte_count[4]; /*0080 008F pull mode data byte count0..count7*/ - u_int32_t message_dest_address_index; /*0090 0093*/ - u_int32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/ - u_int32_t utility_A_int_counter_timer; /*0098 009B*/ - u_int32_t outbound_doorbell; /*009C 009F*/ - u_int32_t outbound_doorbell_clear; /*00A0 00A3*/ - u_int32_t message_source_address_index; /*00A4 00A7 message accelerator source address consumer producer index*/ - u_int32_t message_done_queue_index; /*00A8 00AB message accelerator completion queue consumer producer index*/ - u_int32_t reserved0; /*00AC 00AF*/ - u_int32_t inbound_msgaddr0; /*00B0 00B3 scratchpad0*/ - u_int32_t inbound_msgaddr1; /*00B4 00B7 scratchpad1*/ - u_int32_t outbound_msgaddr0; /*00B8 00BB scratchpad2*/ - u_int32_t outbound_msgaddr1; /*00BC 00BF scratchpad3*/ - u_int32_t inbound_queueport_low; /*00C0 00C3 port64 host inbound queue port low*/ - u_int32_t inbound_queueport_high; /*00C4 00C7 port64 host inbound queue port high*/ - u_int32_t outbound_queueport_low; /*00C8 00CB port64 host outbound queue port low*/ - u_int32_t outbound_queueport_high; /*00CC 00CF port64 host outbound queue port high*/ - u_int32_t iop_inbound_queue_port_low; /*00D0 00D3*/ - u_int32_t iop_inbound_queue_port_high; /*00D4 00D7*/ - u_int32_t iop_outbound_queue_port_low; /*00D8 00DB*/ - u_int32_t iop_outbound_queue_port_high; /*00DC 00DF*/ - u_int32_t message_dest_queue_port_low; /*00E0 00E3 message accelerator destination queue port low*/ - u_int32_t message_dest_queue_port_high; /*00E4 00E7 message accelerator destination queue port high*/ - u_int32_t last_used_message_dest_address_low; /*00E8 00EB last used message accelerator destination address low*/ - u_int32_t last_used_message_dest_address_high; /*00EC 00EF last used message accelerator destination address high*/ - u_int32_t message_done_queue_base_address_low; /*00F0 00F3 message accelerator completion queue base address low*/ - u_int32_t message_done_queue_base_address_high; /*00F4 00F7 message accelerator completion queue base address high*/ - u_int32_t host_diagnostic; /*00F8 00FB*/ - u_int32_t write_sequence; /*00FC 00FF*/ - u_int32_t reserved1[34]; /*0100 0187*/ - u_int32_t reserved2[1950]; /*0188 1FFF*/ - u_int32_t message_wbuffer[32]; /*2000 207F*/ - u_int32_t reserved3[32]; /*2080 20FF*/ - u_int32_t message_rbuffer[32]; /*2100 217F*/ - u_int32_t reserved4[32]; /*2180 21FF*/ - u_int32_t msgcode_rwbuffer[256]; /*2200 23FF*/ + u_int32_t inbound_doorbell; /*0020 0023*/ + u_int32_t diagnostic_rw_data; /*0024 0027*/ + u_int32_t diagnostic_rw_address_low; /*0028 002B*/ + u_int32_t diagnostic_rw_address_high; /*002C 002F*/ + u_int32_t host_int_status; /*0030 0033 host interrupt status*/ + u_int32_t host_int_mask; /*0034 0037 host interrupt mask*/ + u_int32_t dcr_data; /*0038 003B*/ + u_int32_t dcr_address; /*003C 003F*/ + u_int32_t inbound_queueport; /*0040 0043 port32 host inbound queue port*/ + u_int32_t outbound_queueport; /*0044 0047 port32 host outbound queue port*/ + u_int32_t hcb_pci_address_low; /*0048 004B*/ + u_int32_t hcb_pci_address_high; /*004C 004F*/ + u_int32_t iop_int_status; /*0050 0053*/ + u_int32_t iop_int_mask; /*0054 0057*/ + u_int32_t iop_inbound_queue_port; /*0058 005B*/ + u_int32_t iop_outbound_queue_port; /*005C 005F*/ + u_int32_t inbound_free_list_index; /*0060 0063 inbound free list producer consumer index*/ + u_int32_t inbound_post_list_index; /*0064 0067 inbound post list producer consumer index*/ + u_int32_t outbound_free_list_index; /*0068 006B outbound free list producer consumer index*/ + u_int32_t outbound_post_list_index; /*006C 006F outbound post list producer consumer index*/ + u_int32_t inbound_doorbell_clear; /*0070 0073*/ + u_int32_t i2o_message_unit_control; /*0074 0077*/ + u_int32_t last_used_message_source_address_low; /*0078 007B*/ + u_int32_t last_used_message_source_address_high; /*007C 007F*/ + u_int32_t pull_mode_data_byte_count[4]; /*0080 008F pull mode data byte count0..count7*/ + u_int32_t message_dest_address_index; /*0090 0093*/ + u_int32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/ + u_int32_t utility_A_int_counter_timer; /*0098 009B*/ + u_int32_t outbound_doorbell; /*009C 009F*/ + u_int32_t outbound_doorbell_clear; /*00A0 00A3*/ + u_int32_t message_source_address_index; /*00A4 00A7 message accelerator source address consumer producer index*/ + u_int32_t message_done_queue_index; /*00A8 00AB message accelerator completion queue consumer producer index*/ + u_int32_t reserved0; /*00AC 00AF*/ + u_int32_t inbound_msgaddr0; /*00B0 00B3 scratchpad0*/ + u_int32_t inbound_msgaddr1; /*00B4 00B7 scratchpad1*/ + u_int32_t outbound_msgaddr0; /*00B8 00BB scratchpad2*/ + u_int32_t outbound_msgaddr1; /*00BC 00BF scratchpad3*/ + u_int32_t inbound_queueport_low; /*00C0 00C3 port64 host inbound queue port low*/ + u_int32_t inbound_queueport_high; /*00C4 00C7 port64 host inbound queue port high*/ + u_int32_t outbound_queueport_low; /*00C8 00CB port64 host outbound queue port low*/ + u_int32_t outbound_queueport_high; /*00CC 00CF port64 host outbound queue port high*/ + u_int32_t iop_inbound_queue_port_low; /*00D0 00D3*/ + u_int32_t iop_inbound_queue_port_high; /*00D4 00D7*/ + u_int32_t iop_outbound_queue_port_low; /*00D8 00DB*/ + u_int32_t iop_outbound_queue_port_high; /*00DC 00DF*/ + u_int32_t message_dest_queue_port_low; /*00E0 00E3 message accelerator destination queue port low*/ + u_int32_t message_dest_queue_port_high; /*00E4 00E7 message accelerator destination queue port high*/ + u_int32_t last_used_message_dest_address_low; /*00E8 00EB last used message accelerator destination address low*/ + u_int32_t last_used_message_dest_address_high; /*00EC 00EF last used message accelerator destination address high*/ + u_int32_t message_done_queue_base_address_low; /*00F0 00F3 message accelerator completion queue base address low*/ + u_int32_t message_done_queue_base_address_high; /*00F4 00F7 message accelerator completion queue base address high*/ + u_int32_t host_diagnostic; /*00F8 00FB*/ + u_int32_t write_sequence; /*00FC 00FF*/ + u_int32_t reserved1[34]; /*0100 0187*/ + u_int32_t reserved2[1950]; /*0188 1FFF*/ + u_int32_t message_wbuffer[32]; /*2000 207F*/ + u_int32_t reserved3[32]; /*2080 20FF*/ + u_int32_t message_rbuffer[32]; /*2100 217F*/ + u_int32_t reserved4[32]; /*2180 21FF*/ + u_int32_t msgcode_rwbuffer[256]; /*2200 23FF*/ }; /* ********************************************************************* @@ -617,46 +617,46 @@ struct OutBound_SRB { struct HBD_MessageUnit { uint32_t reserved0; uint32_t chip_id; //0x0004 - uint32_t cpu_mem_config; //0x0008 - uint32_t reserved1[10]; //0x000C + uint32_t cpu_mem_config; //0x0008 + uint32_t reserved1[10]; //0x000C uint32_t i2o_host_interrupt_mask; //0x0034 - uint32_t reserved2[114]; //0x0038 - uint32_t host_int_status; //0x0200 - uint32_t host_int_enable; //0x0204 - uint32_t reserved3[1]; //0x0208 - uint32_t pcief0_int_enable; //0x020C - uint32_t reserved4[124]; //0x0210 - uint32_t inbound_msgaddr0; //0x0400 - uint32_t inbound_msgaddr1; //0x0404 - uint32_t reserved5[6]; //0x0408 - uint32_t outbound_msgaddr0; //0x0420 - uint32_t outbound_msgaddr1; //0x0424 - uint32_t reserved6[14]; //0x0428 - uint32_t inbound_doorbell; //0x0460 - uint32_t reserved7[7]; //0x0464 - uint32_t outbound_doorbell; //0x0480 + uint32_t reserved2[114]; //0x0038 + uint32_t host_int_status; //0x0200 + uint32_t host_int_enable; //0x0204 + uint32_t reserved3[1]; //0x0208 + uint32_t pcief0_int_enable; //0x020C + uint32_t reserved4[124]; //0x0210 + uint32_t inbound_msgaddr0; //0x0400 + uint32_t inbound_msgaddr1; //0x0404 + uint32_t reserved5[6]; //0x0408 + uint32_t outbound_msgaddr0; //0x0420 + uint32_t outbound_msgaddr1; //0x0424 + uint32_t reserved6[14]; //0x0428 + uint32_t inbound_doorbell; //0x0460 + uint32_t reserved7[7]; //0x0464 + uint32_t outbound_doorbell; //0x0480 uint32_t outbound_doorbell_enable; //0x0484 uint32_t reserved8[734]; //0x0488 - uint32_t inboundlist_base_low; //0x1000 - uint32_t inboundlist_base_high; //0x1004 - uint32_t reserved9[4]; //0x1008 + uint32_t inboundlist_base_low; //0x1000 + uint32_t inboundlist_base_high; //0x1004 + uint32_t reserved9[4]; //0x1008 uint32_t inboundlist_write_pointer; //0x1018 uint32_t inboundlist_read_pointer; //0x101C uint32_t reserved10[16]; //0x1020 - uint32_t outboundlist_base_low; //0x1060 + uint32_t outboundlist_base_low; //0x1060 uint32_t outboundlist_base_high; //0x1064 - uint32_t reserved11; //0x1068 + uint32_t reserved11; //0x1068 uint32_t outboundlist_copy_pointer; //0x106C uint32_t outboundlist_read_pointer; //0x1070 0x1072 - uint32_t reserved12[5]; //0x1074 + uint32_t reserved12[5]; //0x1074 uint32_t outboundlist_interrupt_cause; //0x1088 uint32_t outboundlist_interrupt_enable; //0x108C uint32_t reserved13[988]; //0x1090 - uint32_t message_wbuffer[32]; //0x2000 + uint32_t message_wbuffer[32]; //0x2000 uint32_t reserved14[32]; //0x2080 - uint32_t message_rbuffer[32]; //0x2100 + uint32_t message_rbuffer[32]; //0x2100 uint32_t reserved15[32]; //0x2180 - uint32_t msgcode_rwbuffer[256]; //0x2200 + uint32_t msgcode_rwbuffer[256]; //0x2200 }; struct HBD_MessageUnit0 { @@ -675,10 +675,10 @@ struct HBD_MessageUnit0 { struct MessageUnit_UNION { union { - struct HBA_MessageUnit hbamu; - struct HBB_MessageUnit hbbmu; - struct HBC_MessageUnit hbcmu; - struct HBD_MessageUnit0 hbdmu; + struct HBA_MessageUnit hbamu; + struct HBB_MessageUnit hbbmu; + struct HBC_MessageUnit hbcmu; + struct HBD_MessageUnit0 hbdmu; } muu; }; /* @@ -686,7 +686,7 @@ struct MessageUnit_UNION ** structure for holding DMA address data ************************************************************* */ -#define IS_SG64_ADDR 0x01000000 /* bit24 */ +#define IS_SG64_ADDR 0x01000000 /* bit24 */ /* ************************************************************************************************ ** ARECA FIRMWARE SPEC @@ -695,10 +695,10 @@ struct MessageUnit_UNION ** (All In/Out is in IOP331's view) ** 1. Message 0 --> InitThread message and retrun code ** 2. Doorbell is used for RS-232 emulation -** inDoorBell : bit0 -- data in ready (DRIVER DATA WRITE OK) -** bit1 -- data out has been read (DRIVER DATA READ OK) -** outDooeBell: bit0 -- data out ready (IOP331 DATA WRITE OK) -** bit1 -- data in has been read (IOP331 DATA READ OK) +** inDoorBell : bit0 -- data in ready (DRIVER DATA WRITE OK) +** bit1 -- data out has been read (DRIVER DATA READ OK) +** outDooeBell: bit0 -- data out ready (IOP331 DATA WRITE OK) +** bit1 -- data in has been read (IOP331 DATA READ OK) ** 3. Index Memory Usage ** offset 0xf00 : for RS232 out (request buffer) ** offset 0xe00 : for RS232 in (scratch buffer) @@ -711,66 +711,66 @@ struct MessageUnit_UNION ** 5. PostQ ** All SCSI Command must be sent through postQ: ** (inbound queue port) Request frame must be 32 bytes aligned -** # bit27--bit31 => flag for post ccb -** # bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb -** bit31 : 0 : 256 bytes frame -** 1 : 512 bytes frame -** bit30 : 0 : normal request -** 1 : BIOS request -** bit29 : reserved -** bit28 : reserved -** bit27 : reserved +** # bit27--bit31 => flag for post ccb +** # bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb +** bit31 : 0 : 256 bytes frame +** 1 : 512 bytes frame +** bit30 : 0 : normal request +** 1 : BIOS request +** bit29 : reserved +** bit28 : reserved +** bit27 : reserved ** ------------------------------------------------------------------------------- ** (outbount queue port) Request reply -** # bit27--bit31 => flag for reply -** # bit0--bit26 => real address (bit27--bit31) of reply arcmsr_cdb -** bit31 : must be 0 (for this type of reply) -** bit30 : reserved for BIOS handshake -** bit29 : reserved -** bit28 : 0 : no error, ignore AdapStatus/DevStatus/SenseData -** 1 : Error, error code in AdapStatus/DevStatus/SenseData -** bit27 : reserved +** # bit27--bit31 => flag for reply +** # bit0--bit26 => real address (bit27--bit31) of reply arcmsr_cdb +** bit31 : must be 0 (for this type of reply) +** bit30 : reserved for BIOS handshake +** bit29 : reserved +** bit28 : 0 : no error, ignore AdapStatus/DevStatus/SenseData +** 1 : Error, error code in AdapStatus/DevStatus/SenseData +** bit27 : reserved ** 6. BIOS request ** All BIOS request is the same with request from PostQ ** Except : ** Request frame is sent from configuration space -** offset: 0x78 : Request Frame (bit30 == 1) -** offset: 0x18 : writeonly to generate IRQ to IOP331 +** offset: 0x78 : Request Frame (bit30 == 1) +** offset: 0x18 : writeonly to generate IRQ to IOP331 ** Completion of request: -** (bit30 == 0, bit28==err flag) +** (bit30 == 0, bit28==err flag) ** 7. Definition of SGL entry (structure) ** 8. Message1 Out - Diag Status Code (????) ** 9. Message0 message code : ** 0x00 : NOP ** 0x01 : Get Config ->offset 0xa00 :for outbound message code msgcode_rwbuffer (IOP331 send to driver) -** Signature 0x87974060(4) -** Request len 0x00000200(4) -** numbers of queue 0x00000100(4) -** SDRAM Size 0x00000100(4)-->256 MB -** IDE Channels 0x00000008(4) -** vendor 40 bytes char -** model 8 bytes char -** FirmVer 16 bytes char -** Device Map 16 bytes char +** Signature 0x87974060(4) +** Request len 0x00000200(4) +** numbers of queue 0x00000100(4) +** SDRAM Size 0x00000100(4)-->256 MB +** IDE Channels 0x00000008(4) +** vendor 40 bytes char +** model 8 bytes char +** FirmVer 16 bytes char +** Device Map 16 bytes char ** ** FirmwareVersion DWORD <== Added for checking of new firmware capability ** 0x02 : Set Config ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver send to IOP331) -** Signature 0x87974063(4) -** UPPER32 of Request Frame (4)-->Driver Only +** Signature 0x87974063(4) +** UPPER32 of Request Frame (4)-->Driver Only ** 0x03 : Reset (Abort all queued Command) ** 0x04 : Stop Background Activity ** 0x05 : Flush Cache ** 0x06 : Start Background Activity (re-start if background is halted) ** 0x07 : Check If Host Command Pending (Novell May Need This Function) ** 0x08 : Set controller time ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver to IOP331) -** byte 0 : 0xaa <-- signature -** byte 1 : 0x55 <-- signature -** byte 2 : year (04) -** byte 3 : month (1..12) -** byte 4 : date (1..31) -** byte 5 : hour (0..23) -** byte 6 : minute (0..59) -** byte 7 : second (0..59) +** byte 0 : 0xaa <-- signature +** byte 1 : 0x55 <-- signature +** byte 2 : year (04) +** byte 3 : month (1..12) +** byte 4 : date (1..31) +** byte 5 : hour (0..23) +** byte 6 : minute (0..59) +** byte 7 : second (0..59) ** ********************************************************************************* ** Porting Of LSI2108/2116 Based PCIE SAS/6G host raid adapter ** ==> Difference from IOP348 @@ -789,33 +789,33 @@ struct MessageUnit_UNION ** b. Message0: message code ** 0x00 : NOP ** 0x01 : Get Config ->offset 0xB8 :for outbound message code msgcode_rwbuffer (IOP send to driver) -** Signature 0x87974060(4) -** Request len 0x00000200(4) -** numbers of queue 0x00000100(4) -** SDRAM Size 0x00000100(4)-->256 MB -** IDE Channels 0x00000008(4) -** vendor 40 bytes char -** model 8 bytes char -** FirmVer 16 bytes char -** Device Map 16 bytes char -** cfgVersion ULONG <== Added for checking of new firmware capability +** Signature 0x87974060(4) +** Request len 0x00000200(4) +** numbers of queue 0x00000100(4) +** SDRAM Size 0x00000100(4)-->256 MB +** IDE Channels 0x00000008(4) +** vendor 40 bytes char +** model 8 bytes char +** FirmVer 16 bytes char +** Device Map 16 bytes char +** cfgVersion ULONG <== Added for checking of new firmware capability ** 0x02 : Set Config ->offset 0xB0 :for inbound message code msgcode_rwbuffer (driver send to IOP) -** Signature 0x87974063(4) -** UPPER32 of Request Frame (4)-->Driver Only +** Signature 0x87974063(4) +** UPPER32 of Request Frame (4)-->Driver Only ** 0x03 : Reset (Abort all queued Command) ** 0x04 : Stop Background Activity ** 0x05 : Flush Cache ** 0x06 : Start Background Activity (re-start if background is halted) ** 0x07 : Check If Host Command Pending (Novell May Need This Function) ** 0x08 : Set controller time ->offset 0xB0 : for inbound message code msgcode_rwbuffer (driver to IOP) -** byte 0 : 0xaa <-- signature -** byte 1 : 0x55 <-- signature -** byte 2 : year (04) -** byte 3 : month (1..12) -** byte 4 : date (1..31) -** byte 5 : hour (0..23) -** byte 6 : minute (0..59) -** byte 7 : second (0..59) +** byte 0 : 0xaa <-- signature +** byte 1 : 0x55 <-- signature +** byte 2 : year (04) +** byte 3 : month (1..12) +** byte 4 : date (1..31) +** byte 5 : hour (0..23) +** byte 6 : minute (0..59) +** byte 7 : second (0..59) ** ** <2> Doorbell Register is used for RS-232 emulation ** different clear register @@ -908,21 +908,21 @@ struct MessageUnit_UNION */ /* size 8 bytes */ /* 32bit Scatter-Gather list */ -struct SG32ENTRY { /* length bit 24 == 0 */ - u_int32_t length; /* high 8 bit == flag,low 24 bit == length */ - u_int32_t address; +struct SG32ENTRY { /* length bit 24 == 0 */ + u_int32_t length; /* high 8 bit == flag,low 24 bit == length */ + u_int32_t address; }; /* size 12 bytes */ /* 64bit Scatter-Gather list */ -struct SG64ENTRY { /* length bit 24 == 1 */ - u_int32_t length; /* high 8 bit == flag,low 24 bit == length */ - u_int32_t address; - u_int32_t addresshigh; +struct SG64ENTRY { /* length bit 24 == 1 */ + u_int32_t length; /* high 8 bit == flag,low 24 bit == length */ + u_int32_t address; + u_int32_t addresshigh; }; struct SGENTRY_UNION { union { - struct SG32ENTRY sg32entry; /* 30h Scatter gather address */ - struct SG64ENTRY sg64entry; /* 30h */ + struct SG32ENTRY sg32entry; /* 30h Scatter gather address */ + struct SG64ENTRY sg64entry; /* 30h */ }u; }; /* @@ -932,14 +932,14 @@ struct SGENTRY_UNION { */ struct QBUFFER { u_int32_t data_len; - u_int8_t data[124]; + u_int8_t data[124]; }; /* ********************************** */ typedef struct PHYS_ADDR64 { - u_int32_t phyadd_low; - u_int32_t phyadd_high; + u_int32_t phyadd_low; + u_int32_t phyadd_high; }PHYSADDR64; /* ************************************************************************************************ @@ -959,11 +959,11 @@ struct FIRMWARE_INFO { u_int32_t ide_channels; /*4,16-19*/ char vendor[40]; /*5,20-59*/ char model[8]; /*15,60-67*/ - char firmware_ver[16]; /*17,68-83*/ + char firmware_ver[16]; /*17,68-83*/ char device_map[16]; /*21,84-99*/ - u_int32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/ - char cfgSerial[16]; /*26,104-119*/ - u_int32_t cfgPicStatus; /*30,120-123*/ + u_int32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/ + char cfgSerial[16]; /*26,104-119*/ + u_int32_t cfgPicStatus; /*30,120-123*/ }; /* (A) For cfgVersion in FIRMWARE_INFO ** if low BYTE (byte#0) >= 3 (version 3) @@ -1023,8 +1023,8 @@ struct ARCMSR_CDB { u_int8_t SenseData[15]; /* 21h output */ union { - struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h Scatter gather address */ - struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h */ + struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h Scatter gather address */ + struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h */ } u; }; /* CDB flag */ @@ -1045,9 +1045,9 @@ struct ARCMSR_CDB { #define SCSISTAT_COMMAND_TERMINATED 0x22 #define SCSISTAT_QUEUE_FULL 0x28 /* DeviceStatus */ -#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 -#define ARCMSR_DEV_ABORTED 0xF1 -#define ARCMSR_DEV_INIT_FAIL 0xF2 +#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 +#define ARCMSR_DEV_ABORTED 0xF1 +#define ARCMSR_DEV_INIT_FAIL 0xF2 /* ********************************************************************* ** Command Control Block (SrbExtension) @@ -1057,40 +1057,40 @@ struct ARCMSR_CDB { ********************************************************************* */ struct CommandControlBlock { - struct ARCMSR_CDB arcmsr_cdb; /* 0 -503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */ - u_int32_t cdb_phyaddr_low; /* 504-507 */ - u_int32_t arc_cdb_size; /* 508-511 */ + struct ARCMSR_CDB arcmsr_cdb; /* 0 -503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */ + u_int32_t cdb_phyaddr_low; /* 504-507 */ + u_int32_t arc_cdb_size; /* 508-511 */ /* ======================512+32 bytes============================ */ - union ccb *pccb; /* 512-515 516-519 pointer of freebsd scsi command */ - struct AdapterControlBlock *acb; /* 520-523 524-527 */ - bus_dmamap_t dm_segs_dmamap; /* 528-531 532-535 */ - u_int16_t srb_flags; /* 536-537 */ - u_int16_t srb_state; /* 538-539 */ - u_int32_t cdb_phyaddr_high; /* 540-543 */ - struct callout ccb_callout; + union ccb *pccb; /* 512-515 516-519 pointer of freebsd scsi command */ + struct AdapterControlBlock *acb; /* 520-523 524-527 */ + bus_dmamap_t dm_segs_dmamap; /* 528-531 532-535 */ + u_int16_t srb_flags; /* 536-537 */ + u_int16_t srb_state; /* 538-539 */ + u_int32_t cdb_phyaddr_high; /* 540-543 */ + struct callout ccb_callout; /* ========================================================== */ }; /* srb_flags */ -#define SRB_FLAG_READ 0x0000 -#define SRB_FLAG_WRITE 0x0001 -#define SRB_FLAG_ERROR 0x0002 -#define SRB_FLAG_FLUSHCACHE 0x0004 +#define SRB_FLAG_READ 0x0000 +#define SRB_FLAG_WRITE 0x0001 +#define SRB_FLAG_ERROR 0x0002 +#define SRB_FLAG_FLUSHCACHE 0x0004 #define SRB_FLAG_MASTER_ABORTED 0x0008 -#define SRB_FLAG_DMAVALID 0x0010 +#define SRB_FLAG_DMAVALID 0x0010 #define SRB_FLAG_DMACONSISTENT 0x0020 -#define SRB_FLAG_DMAWRITE 0x0040 -#define SRB_FLAG_PKTBIND 0x0080 +#define SRB_FLAG_DMAWRITE 0x0040 +#define SRB_FLAG_PKTBIND 0x0080 #define SRB_FLAG_TIMER_START 0x0080 /* srb_state */ -#define ARCMSR_SRB_DONE 0x0000 -#define ARCMSR_SRB_UNBUILD 0x0000 -#define ARCMSR_SRB_TIMEOUT 0x1111 -#define ARCMSR_SRB_RETRY 0x2222 -#define ARCMSR_SRB_START 0x55AA -#define ARCMSR_SRB_PENDING 0xAA55 -#define ARCMSR_SRB_RESET 0xA5A5 -#define ARCMSR_SRB_ABORTED 0x5A5A -#define ARCMSR_SRB_ILLEGAL 0xFFFF +#define ARCMSR_SRB_DONE 0x0000 +#define ARCMSR_SRB_UNBUILD 0x0000 +#define ARCMSR_SRB_TIMEOUT 0x1111 +#define ARCMSR_SRB_RETRY 0x2222 +#define ARCMSR_SRB_START 0x55AA +#define ARCMSR_SRB_PENDING 0xAA55 +#define ARCMSR_SRB_RESET 0xA5A5 +#define ARCMSR_SRB_ABORTED 0x5A5A +#define ARCMSR_SRB_ILLEGAL 0xFFFF #define SRB_SIZE ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0) #define ARCMSR_SRBS_POOL_SIZE (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM) @@ -1100,109 +1100,109 @@ struct CommandControlBlock { ** Adapter Control Block ********************************************************************* */ -#define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */ -#define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ -#define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc L IOP */ -#define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd M IOP */ +#define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */ +#define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ +#define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc L IOP */ +#define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd M IOP */ struct AdapterControlBlock { - u_int32_t adapter_type; /* adapter A,B..... */ + u_int32_t adapter_type; /* adapter A,B..... */ - bus_space_tag_t btag[2]; - bus_space_handle_t bhandle[2]; - bus_dma_tag_t parent_dmat; - bus_dma_tag_t dm_segs_dmat; /* dmat for buffer I/O */ - bus_dma_tag_t srb_dmat; /* dmat for freesrb */ - bus_dmamap_t srb_dmamap; - device_t pci_dev; + bus_space_tag_t btag[2]; + bus_space_handle_t bhandle[2]; + bus_dma_tag_t parent_dmat; + bus_dma_tag_t dm_segs_dmat; /* dmat for buffer I/O */ + bus_dma_tag_t srb_dmat; /* dmat for freesrb */ + bus_dmamap_t srb_dmamap; + device_t pci_dev; #if __FreeBSD_version < 503000 - dev_t ioctl_dev; + dev_t ioctl_dev; #else - struct cdev *ioctl_dev; + struct cdev *ioctl_dev; #endif - int pci_unit; + int pci_unit; - struct resource *sys_res_arcmsr[2]; - struct resource *irqres; - void *ih; /* interrupt handle */ + struct resource *sys_res_arcmsr[2]; + struct resource *irqres; + void *ih; /* interrupt handle */ /* Hooks into the CAM XPT */ - struct cam_sim *psim; - struct cam_path *ppath; - u_int8_t *uncacheptr; - unsigned long vir2phy_offset; + struct cam_sim *psim; + struct cam_path *ppath; + u_int8_t *uncacheptr; + unsigned long vir2phy_offset; union { - unsigned long phyaddr; + unsigned long phyaddr; struct { - u_int32_t phyadd_low; - u_int32_t phyadd_high; + u_int32_t phyadd_low; + u_int32_t phyadd_high; }B; }srb_phyaddr; // unsigned long srb_phyaddr; /* Offset is used in making arc cdb physical to virtual calculations */ - u_int32_t outbound_int_enable; + u_int32_t outbound_int_enable; - struct MessageUnit_UNION *pmu; /* message unit ATU inbound base address0 */ + struct MessageUnit_UNION *pmu; /* message unit ATU inbound base address0 */ u_int8_t adapter_index; - u_int8_t irq; + u_int8_t irq; u_int16_t acb_flags; struct CommandControlBlock *psrb_pool[ARCMSR_MAX_FREESRB_NUM]; /* serial srb pointer array */ struct CommandControlBlock *srbworkingQ[ARCMSR_MAX_FREESRB_NUM]; /* working srb pointer array */ - int32_t workingsrb_doneindex; /* done srb array index */ - int32_t workingsrb_startindex; /* start srb array index */ - int32_t srboutstandingcount; + int32_t workingsrb_doneindex; /* done srb array index */ + int32_t workingsrb_startindex; /* start srb array index */ + int32_t srboutstandingcount; - u_int8_t rqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for read from 80331 */ - u_int32_t rqbuf_firstindex; /* first of read buffer */ - u_int32_t rqbuf_lastindex; /* last of read buffer */ + u_int8_t rqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for read from 80331 */ + u_int32_t rqbuf_firstindex; /* first of read buffer */ + u_int32_t rqbuf_lastindex; /* last of read buffer */ - u_int8_t wqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for write to 80331 */ - u_int32_t wqbuf_firstindex; /* first of write buffer */ - u_int32_t wqbuf_lastindex; /* last of write buffer */ + u_int8_t wqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for write to 80331 */ + u_int32_t wqbuf_firstindex; /* first of write buffer */ + u_int32_t wqbuf_lastindex; /* last of write buffer */ - arcmsr_lock_t isr_lock; - arcmsr_lock_t srb_lock; - arcmsr_lock_t postDone_lock; - arcmsr_lock_t qbuffer_lock; + arcmsr_lock_t isr_lock; + arcmsr_lock_t srb_lock; + arcmsr_lock_t postDone_lock; + arcmsr_lock_t qbuffer_lock; - u_int8_t devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */ - u_int32_t num_resets; - u_int32_t num_aborts; - u_int32_t firm_request_len; /*1,04-07*/ - u_int32_t firm_numbers_queue; /*2,08-11*/ - u_int32_t firm_sdram_size; /*3,12-15*/ - u_int32_t firm_ide_channels; /*4,16-19*/ - u_int32_t firm_cfg_version; - char firm_model[12]; /*15,60-67*/ - char firm_version[20]; /*17,68-83*/ - char device_map[20]; /*21,84-99 */ - struct callout devmap_callout; - u_int32_t pktRequestCount; - u_int32_t pktReturnCount; - u_int32_t vendor_device_id; - u_int32_t adapter_bus_speed; - u_int32_t maxOutstanding; + u_int8_t devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */ + u_int32_t num_resets; + u_int32_t num_aborts; + u_int32_t firm_request_len; /*1,04-07*/ + u_int32_t firm_numbers_queue; /*2,08-11*/ + u_int32_t firm_sdram_size; /*3,12-15*/ + u_int32_t firm_ide_channels; /*4,16-19*/ + u_int32_t firm_cfg_version; + char firm_model[12]; /*15,60-67*/ + char firm_version[20]; /*17,68-83*/ + char device_map[20]; /*21,84-99 */ + struct callout devmap_callout; + u_int32_t pktRequestCount; + u_int32_t pktReturnCount; + u_int32_t vendor_device_id; + u_int32_t adapter_bus_speed; + u_int32_t maxOutstanding; u_int16_t sub_device_id; };/* HW_DEVICE_EXTENSION */ /* acb_flags */ #define ACB_F_SCSISTOPADAPTER 0x0001 -#define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */ -#define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */ -#define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop ioctl data rqbuffer overflow */ -#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* ioctl clear wqbuffer */ -#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* ioctl clear rqbuffer */ +#define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */ +#define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */ +#define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop ioctl data rqbuffer overflow */ +#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* ioctl clear wqbuffer */ +#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* ioctl clear rqbuffer */ #define ACB_F_MESSAGE_WQBUFFER_READ 0x0040 #define ACB_F_BUS_RESET 0x0080 -#define ACB_F_IOP_INITED 0x0100 /* iop init */ -#define ACB_F_MAPFREESRB_FAILD 0x0200 /* arcmsr_map_freesrb faild */ +#define ACB_F_IOP_INITED 0x0100 /* iop init */ +#define ACB_F_MAPFREESRB_FAILD 0x0200 /* arcmsr_map_freesrb faild */ #define ACB_F_CAM_DEV_QFRZN 0x0400 -#define ACB_F_BUS_HANG_ON 0x0800 /* need hardware reset bus */ +#define ACB_F_BUS_HANG_ON 0x0800 /* need hardware reset bus */ #define ACB_F_SRB_FUNCTION_POWER 0x1000 /* devstate */ -#define ARECA_RAID_GONE 0x55 -#define ARECA_RAID_GOOD 0xaa +#define ARECA_RAID_GONE 0x55 +#define ARECA_RAID_GOOD 0xaa /* adapter_bus_speed */ #define ACB_BUS_SPEED_3G 0 #define ACB_BUS_SPEED_6G 1 @@ -1233,17 +1233,17 @@ struct SENSE_DATA { ** Peripheral Device Type definitions ********************************** */ -#define SCSI_DASD 0x00 /* Direct-access Device */ +#define SCSI_DASD 0x00 /* Direct-access Device */ #define SCSI_SEQACESS 0x01 /* Sequential-access device */ #define SCSI_PRINTER 0x02 /* Printer device */ #define SCSI_PROCESSOR 0x03 /* Processor device */ #define SCSI_WRITEONCE 0x04 /* Write-once device */ -#define SCSI_CDROM 0x05 /* CD-ROM device */ +#define SCSI_CDROM 0x05 /* CD-ROM device */ #define SCSI_SCANNER 0x06 /* Scanner device */ #define SCSI_OPTICAL 0x07 /* Optical memory device */ #define SCSI_MEDCHGR 0x08 /* Medium changer device */ -#define SCSI_COMM 0x09 /* Communications device */ -#define SCSI_NODEV 0x1F /* Unknown or no device type */ +#define SCSI_COMM 0x09 /* Communications device */ +#define SCSI_NODEV 0x1F /* Unknown or no device type */ /* ************************************************************************************************************ ** @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ From 11188df26099ed25efd6c59b8d23448296e0a9a5 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Wed, 18 Dec 2013 20:04:04 +0000 Subject: [PATCH 146/172] Restore corefiles handling via kvm(3). Found by: John-Mark Gurney MFC after: 4 weeks --- usr.bin/netstat/main.c | 2 ++ usr.bin/netstat/netstat.h | 1 + usr.bin/netstat/route.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index d733e9378102..7426bbd5c6f6 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -319,6 +319,7 @@ int gflag; /* show group (multicast) routing or stats */ int hflag; /* show counters in human readable format */ int iflag; /* show interfaces */ int Lflag; /* show size of listen queues */ +int Mflag; /* read statistics from core */ int mflag; /* show memory stats */ int noutputs = 0; /* how much outputs before we exit */ int numeric_addr; /* show addresses numerically */ @@ -424,6 +425,7 @@ main(int argc, char *argv[]) Lflag = 1; break; case 'M': + Mflag = 1; memf = optarg; break; case 'm': diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h index 114c84cdc66a..804a29e2930e 100644 --- a/usr.bin/netstat/netstat.h +++ b/usr.bin/netstat/netstat.h @@ -40,6 +40,7 @@ extern int gflag; /* show group (multicast) routing or stats */ extern int hflag; /* show counters in human readable format */ extern int iflag; /* show interfaces */ extern int Lflag; /* show size of listen queues */ +extern int Mflag; /* read statistics from core */ extern int mflag; /* show memory stats */ extern int noutputs; /* how much outputs before we exit */ extern int numeric_addr; /* show addresses numerically */ diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c index 8f529ac12146..31ef3c0e3217 100644 --- a/usr.bin/netstat/route.c +++ b/usr.bin/netstat/route.c @@ -182,7 +182,7 @@ routepr(u_long rtree, int fibnum) printf(" (fib: %d)", fibnum); printf("\n"); - if (Aflag == 0 && NewTree) + if (Aflag == 0 && Mflag == 0 && NewTree) ntreestuff(fibnum, af); else { if (rtree == 0) { From fb2b51fab1c732ba6463ac2ebb40662dd176de7c Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Wed, 18 Dec 2013 20:17:05 +0000 Subject: [PATCH 147/172] Add net.inet.ip.fw.dyn_keep_states sysctl which re-links dynamic states to default rule instead of flushing on rule deletion. This can be useful while performing ruleset reload (think about `atomic` reload via changing sets). Currently it is turned off by default. MFC after: 2 weeks Sponsored by: Yandex LLC --- sbin/ipfw/ipfw.8 | 5 +++++ sys/netpfil/ipfw/ip_fw_dynamic.c | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 65fa33499b99..a3ac41db9c7b 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -2933,6 +2933,11 @@ and must be strictly lower than 5 seconds, the period of repetition of keepalives. The firewall enforces that. +.It Va net.inet.ip.fw.dyn_keep_states: No 0 +Keep dynamic states on rule/set deletion. +States are relinked to default rule (65535). +This can be handly for ruleset reload. +Turned off by default. .It Va net.inet.ip.fw.enable : No 1 Enables the firewall. Setting this variable to 0 lets you run your machine without diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c index cf4071e0f448..f28dfcbd6936 100644 --- a/sys/netpfil/ipfw/ip_fw_dynamic.c +++ b/sys/netpfil/ipfw/ip_fw_dynamic.c @@ -106,7 +106,8 @@ __FBSDID("$FreeBSD$"); * * Each dynamic rule holds a pointer to the parent ipfw rule so * we know what action to perform. Dynamic rules are removed when - * the parent rule is deleted. XXX we should make them survive. + * the parent rule is deleted. This can be changed by dyn_keep_states + * sysctl. * * There are some limitations with dynamic rules -- we do not * obey the 'randomized match', and we do not do multiple @@ -141,6 +142,10 @@ static VNET_DEFINE(uma_zone_t, ipfw_dyn_rule_zone); #define IPFW_BUCK_UNLOCK(i) mtx_unlock(&V_ipfw_dyn_v[(i)].mtx) #define IPFW_BUCK_ASSERT(i) mtx_assert(&V_ipfw_dyn_v[(i)].mtx, MA_OWNED) + +static VNET_DEFINE(int, dyn_keep_states); +#define V_dyn_keep_states VNET(dyn_keep_states) + /* * Timeouts for various events in handing dynamic rules. */ @@ -234,6 +239,9 @@ SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW, &VNET_NAME(dyn_keepalive), 0, "Enable keepalives for dyn. rules"); +SYSCTL_VNET_UINT(_net_inet_ip_fw, OID_AUTO, dyn_keep_states, + CTLFLAG_RW, &VNET_NAME(dyn_keep_states), 0, + "Do not flush dynamic states on rule deletion"); SYSEND @@ -307,6 +315,7 @@ print_dyn_rule_flags(struct ipfw_flow_id *id, int dyn_type, int log_flags, print_dyn_rule_flags(id, dtype, LOG_DEBUG, prefix, postfix) #define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0) +#define TIME_LE(a,b) ((int)((a)-(b)) < 0) /* * Lookup a dynamic rule, locked version. @@ -1100,6 +1109,20 @@ check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule, if ((TIME_LEQ(q->expire, time_uptime)) || ((rule != NULL) && (q->rule == rule)) || ((set != RESVD_SET) && (q->rule->set == set))) { + if (TIME_LE(time_uptime, q->expire) && + q->dyn_type == O_KEEP_STATE && + V_dyn_keep_states != 0) { + /* + * Do not delete state if + * it is not expired and + * dyn_keep_states is ON. + * However we need to re-link it + * to any other stable rule + */ + q->rule = chain->default_rule; + NEXT_RULE(); + } + /* Unlink q from current list */ q_next = q->next; if (q == V_ipfw_dyn_v[i].head) From ad016cb8ab9fdcf0c1d61ebf1382df64b1184d23 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Wed, 18 Dec 2013 20:37:49 +0000 Subject: [PATCH 148/172] cxgbe.4: Belated update to the man page to reflect T5 support. MFC after: 1 day --- share/man/man4/cxgbe.4 | 68 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/share/man/man4/cxgbe.4 b/share/man/man4/cxgbe.4 index 93925a716532..68540c33b4f6 100644 --- a/share/man/man4/cxgbe.4 +++ b/share/man/man4/cxgbe.4 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2011-2012, Chelsio Inc +.\" Copyright (c) 2011-2013, Chelsio Inc .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -31,12 +31,12 @@ .\" .\" $FreeBSD$ .\" -.Dd February 25, 2012 +.Dd December 18, 2013 .Dt CXGBE 4 .Os .Sh NAME .Nm cxgbe -.Nd "Chelsio T4 10Gb and 1Gb Ethernet adapter driver" +.Nd "Chelsio T4 and T5 based 40Gb, 10Gb, and 1Gb Ethernet adapter driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your @@ -50,13 +50,14 @@ module at boot time, place the following lines in .Xr loader.conf 5 : .Bd -literal -offset indent t4fw_cfg_load="YES" +t5fw_cfg_load="YES" if_cxgbe_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for PCI Express Ethernet adapters based on -the Chelsio Terminator 4 (T4) ASIC. +the Chelsio Terminator 4 and Terminator 5 ASICs (T4 and T5). The driver supports Jumbo Frames, Transmit/Receive checksum offload, TCP segmentation offload (TSO), Large Receive Offload (LRO), VLAN tag insertion/extraction, VLAN checksum offload, VLAN TSO, and @@ -64,12 +65,51 @@ Receive Side Steering (RSS). For further hardware information and questions related to hardware requirements, see .Pa http://www.chelsio.com/ . +.Pp +Note that ports of T5 cards are named cxl and attach to a t5nex parent device +(in contrast to ports named cxgbe that attach to a t4nex parent for a T4 card). +Loader tunables with the hw.cxgbe prefix apply to both T4 and T5 cards. +The sysctl MIBs are at dev.t5nex and dev.cxl for T5 cards and at dev.t4nex and +dev.cxgbe for T4 cards. + .Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE The .Nm +driver supports 40Gb, 10Gb and 1Gb Ethernet adapters based on the T5 ASIC +(ports will be named cxl): +.Pp +.Bl -bullet -compact +.It +Chelsio T580-CR +.It +Chelsio T580-LP-CR +.It +Chelsio T580-LP-SO-CR +.It +Chelsio T560-CR +.It +Chelsio T540-CR +.It +Chelsio T540-LP-CR +.It +Chelsio T522-CR +.It +Chelsio T520-LL-CR +.It +Chelsio T520-CR +.It +Chelsio T520-SO +.It +Chelsio T520-BT +.It +Chelsio T504-BT +.El +.Pp +The +.Nm driver supports 10Gb and 1Gb Ethernet adapters based on the T4 ASIC: .Pp .Bl -bullet -compact @@ -139,8 +179,8 @@ by default (all values are in microseconds) and the index selects a value from this list. The default value is 1 for both 10Gb and 1Gb ports, which means the timer value is 5us. -Different cxgbe interfaces can be assigned different values at any time via the -dev.cxgbe.X.holdoff_tmr_idx sysctl. +Different interfaces can be assigned different values at any time via the +dev.cxgbe.X.holdoff_tmr_idx or dev.cxl.X.holdoff_tmr_idx sysctl. .It Va hw.cxgbe.holdoff_pktc_idx_10G .It Va hw.cxgbe.holdoff_pktc_idx_1G The packet-count index value to use to delay interrupts. @@ -149,8 +189,8 @@ and the index selects a value from this list. The default value is -1 for both 10Gb and 1Gb ports, which means packet counting is disabled and interrupts are generated based solely on the holdoff timer value. -Different cxgbe interfaces can be assigned different values via the -dev.cxgbe.X.holdoff_pktc_idx sysctl. +Different interfaces can be assigned different values via the +dev.cxgbe.X.holdoff_pktc_idx or dev.cxl.X.holdoff_pktc_idx sysctl. This sysctl works only when the interface has never been marked up (as done by ifconfig up). .It Va hw.cxgbe.qsize_txq @@ -161,16 +201,16 @@ software queuing. See .Xr ifnet 9 . The default value is 1024. -Different cxgbe interfaces can be assigned different values via the -dev.cxgbe.X.qsize_txq sysctl. +Different interfaces can be assigned different values via the +dev.cxgbe.X.qsize_txq sysctl or dev.cxl.X.qsize_txq sysctl. This sysctl works only when the interface has never been marked up (as done by ifconfig up). .It Va hw.cxgbe.qsize_rxq The size, in number of entries, of the descriptor ring used for an rx queue. The default value is 1024. -Different cxgbe interfaces can be assigned different values via the -dev.cxgbe.X.qsize_rxq sysctl. +Different interfaces can be assigned different values via the +dev.cxgbe.X.qsize_rxq or dev.cxl.X.qsize_rxq sysctl. This sysctl works only when the interface has never been marked up (as done by ifconfig up). .It Va hw.cxgbe.interrupt_types @@ -231,6 +271,10 @@ The .Nm device driver first appeared in .Fx 9.0 . +Support for T5 cards first appeared in +.Fx 9.2 +and +.Fx 10.0 . .Sh AUTHORS .An -nosplit The From 31a0cf130a6e79f3f8d0837aff9f5730a770e79b Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Wed, 18 Dec 2013 21:13:50 +0000 Subject: [PATCH 149/172] Fix "[: -eq: argument expected" error introduced by SVN r256343. The code should not have used DIALOG_CANCEL because dialog.subr wasn't included to define it. The effect of the error was that you could not cancel the partition dialog. Discovered by checking bsdinstall_log for something else. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/auto | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index 34a6918a6f36..0e003f49a5d9 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -124,8 +124,7 @@ exec 3>&1 PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \ --title "Partitioning" \ --menu "How would you like to partition your disk?" \ - 0 0 0 2>&1 1>&3` -if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi + 0 0 0 2>&1 1>&3` || exit 1 exec 3>&- case "$PARTMODE" in From 7e9787e2738343dffa43223bede70bf91e217ccf Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Wed, 18 Dec 2013 21:14:43 +0000 Subject: [PATCH 150/172] Add SVN revision numbers for Mellanox updates. --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index e3c3b6c1298f..46b8cf5f119a 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -254,10 +254,10 @@ The iw_cxgbe driver has been added. This is an experimental iWARP/RDMA driver (kernel verbs only) for Chelsio's T4 and T5 based cards. - The Open Fabrics Enterprise Distribution (OFED) and OFED Infiniband core has been + The Open Fabrics Enterprise Distribution (OFED) and OFED Infiniband core has been updated to the same version as supplied by Linux version 3.7 - The Mellanox Infiniband driver has been updated to firmware + The Mellanox Infiniband driver has been updated to firmware version 2.30.3200 for ConnectX3 NICs. Support has been added for ConnectX3 VPI NICs, where each port can be used as Infiniband 56 GB/s or Ethernet 40 GB/s. Support has been added for dynamically loading kernel modules for Infiniband core (ibcore) and From 2d5cf580aad907d588febad87104c04c280c7701 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Wed, 18 Dec 2013 21:16:57 +0000 Subject: [PATCH 151/172] In bsdinstall_log, it's rather confusing to see the following sequence: DEBUG: Running installation step: hostname rm: /tmp/bsdinstall_etc/fstab: No such file or directory The two lines are unrelated, and the rm is spurious. Let's add `-f' to that rm(1) so it doesn't confuse us when debugging an install. MFC after: 3 days --- usr.sbin/bsdinstall/scripts/auto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index 0e003f49a5d9..85e2231d14c3 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -103,7 +103,7 @@ if [ -n "$FETCH_DISTRIBUTIONS" ]; then export BSDINSTALL_DISTSITE fi -rm $PATH_FSTAB +rm -f $PATH_FSTAB touch $PATH_FSTAB PMODES="\ From 4c099f7e5c5476a3d95edb866c6333634a322b2e Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Wed, 18 Dec 2013 21:22:16 +0000 Subject: [PATCH 152/172] Add SVN revision numbers for Chelsio updates. --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 46b8cf5f119a..73f4add591d4 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -248,10 +248,11 @@ The &man.wpi.4; driver has been updated to include a number of stability fixes. - The &man.cxgbe.4; driver has been updated to support + The &man.cxgbe.4; driver has been updated to support 40G/10G Ethernet NICs based on Chelsio's Terminator 5 (T5) ASIC. - The iw_cxgbe driver has been added. This is an experimental iWARP/RDMA driver + The iw_cxgbe driver has been added. This is an + experimental iWARP/RDMA driver (kernel verbs only) for Chelsio's T4 and T5 based cards. The Open Fabrics Enterprise Distribution (OFED) and OFED Infiniband core has been From 6168ea49fe69532aa45fa469c3ba3009161c0059 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Wed, 18 Dec 2013 21:23:16 +0000 Subject: [PATCH 153/172] Indent. --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 73f4add591d4..36d673b77042 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -255,7 +255,8 @@ experimental iWARP/RDMA driver (kernel verbs only) for Chelsio's T4 and T5 based cards. - The Open Fabrics Enterprise Distribution (OFED) and OFED Infiniband core has been + The Open Fabrics Enterprise Distribution (OFED) and + OFED Infiniband core has been updated to the same version as supplied by Linux version 3.7 The Mellanox Infiniband driver has been updated to firmware From 8ff3952b7279d437be574f7c7a5d083b1a9bfe41 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Dec 2013 00:51:48 +0000 Subject: [PATCH 154/172] If we cannot connect to casperd we don't enter sandbox, but if we can connect to casperd, but we cannot access the service we need we exit with an error. This should not happen and just indicates some configuration error which should be fixed, so we force the user to do it by failing. Discussed with: emaste --- contrib/tcpdump/tcpdump.c | 20 ++++++-------------- usr.bin/kdump/kdump.c | 34 ++++++++++------------------------ 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c index e1a34f4ea934..f1e696f42b5b 100644 --- a/contrib/tcpdump/tcpdump.c +++ b/contrib/tcpdump/tcpdump.c @@ -710,24 +710,16 @@ capdns_setup(void) capdnsloc = cap_service_open(capcas, "system.dns"); /* Casper capability no longer needed. */ cap_close(capcas); - if (capdnsloc == NULL) { - warning("unable to open system.dns service"); - return (NULL); - } + if (capdnsloc == NULL) + error("unable to open system.dns service"); /* Limit system.dns to reverse DNS lookups. */ types[0] = "ADDR"; - if (cap_dns_type_limit(capdnsloc, types, 1) < 0) { - warning("unable to limit access to system.dns service"); - cap_close(capdnsloc); - return (NULL); - } + if (cap_dns_type_limit(capdnsloc, types, 1) < 0) + error("unable to limit access to system.dns service"); families[0] = AF_INET; families[1] = AF_INET6; - if (cap_dns_family_limit(capdnsloc, families, 2) < 0) { - warning("unable to limit access to system.dns service"); - cap_close(capdnsloc); - return (NULL); - } + if (cap_dns_family_limit(capdnsloc, families, 2) < 0) + error("unable to limit access to system.dns service"); return (capdnsloc); } diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 238f8fc16a13..3a9ba0e3f4e3 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -215,7 +215,7 @@ cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) capcas = cap_init(); if (capcas == NULL) { warn("unable to contact casperd"); - return (NULL); + return (-1); } cappwdloc = cap_service_open(capcas, "system.pwd"); capgrploc = cap_service_open(capcas, "system.grp"); @@ -226,40 +226,26 @@ cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) warn("unable to open system.pwd service"); if (capgrploc == NULL) warn("unable to open system.grp service"); - goto fail; + exit(1); } /* Limit system.pwd to only getpwuid() function and pw_name field. */ cmds[0] = "getpwuid"; - if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0) { - warn("unable to limit access to system.pwd service"); - goto fail; - } + if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0) + err(1, "unable to limit system.pwd service"); fields[0] = "pw_name"; - if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0) { - warn("unable to limit access to system.pwd service"); - goto fail; - } + if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0) + err(1, "unable to limit system.pwd service"); /* Limit system.grp to only getgrgid() function and gr_name field. */ cmds[0] = "getgrgid"; - if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0) { - warn("unable to limit access to system.grp service"); - goto fail; - } + if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0) + err(1, "unable to limit system.grp service"); fields[0] = "gr_name"; - if (cap_grp_limit_fields(capgrploc, fields, 1) < 0) { - warn("unable to limit access to system.grp service"); - goto fail; - } + if (cap_grp_limit_fields(capgrploc, fields, 1) < 0) + err(1, "unable to limit system.grp service"); *cappwdp = cappwdloc; *capgrpp = capgrploc; return (0); -fail: - if (capgrploc == NULL) - cap_close(cappwdloc); - if (capgrploc == NULL) - cap_close(capgrploc); - return (-1); } #endif /* HAVE_LIBCAPSICUM */ From f01f7446472b47340fbaddd4d582fa4006df3842 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Dec 2013 00:53:11 +0000 Subject: [PATCH 155/172] Make the world a bit more secure place (hopefully) and turn the casperd on by default. Sponsored by: The FreeBSD Foundation --- etc/defaults/rc.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index f217f420bcab..ef6739127106 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -658,7 +658,7 @@ newsyslog_enable="YES" # Run newsyslog at startup. newsyslog_flags="-CN" # Newsyslog flags to create marked files mixer_enable="YES" # Run the sound mixer. opensm_enable="NO" # Opensm(8) for infiniband devices defaults to off -casperd_enable="NO" # casperd(8) daemon +casperd_enable="YES" # casperd(8) daemon ############################################################## ### Jail Configuration (see rc.conf(5) manual page) ########## From 8cf9cdeb659c0539b73cc3360d3ab777fcc4a7de Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Thu, 19 Dec 2013 03:21:53 +0000 Subject: [PATCH 156/172] Add entry for bhyve. --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 36d673b77042..55d90529a82b 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -120,6 +120,11 @@ Kernel Changes + The BSD Hypervisor, &man.bhyve.8; is included + with &os;. &man.bhyve.8; requires Intel CPUs with VT-x and Extended Page Table (EPT) + support. These features are on all Nehalem models and beyond + (e.g. Nehalem and newer), but not on the lower-end Atom CPUs. + The maximum amount of memory the &os; kernel can address has been increased from 1TB to 4TB. From 8f7254629ff157b4352e6a1e1b6d1420290d23d5 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 19 Dec 2013 03:48:36 +0000 Subject: [PATCH 157/172] Invoke the kld_* event handlers from linker_load_file() and linker_unload_file() rather than kern_kldload() and kern_kldunload(). This ensures that the handlers are invoked for files that are loaded/unloaded automatically as dependencies. Previously, they were only invoked for files loaded by a user. As a side effect, the kld_load and kld_unload handlers are now invoked with the kernel linker lock exclusively held. Reported by: avg Reviewed by: jhb MFC after: 2 weeks --- sys/kern/kern_linker.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 7d322601c680..fa09b3ffbebf 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -434,6 +434,7 @@ linker_load_file(const char *filename, linker_file_t *result) linker_file_unload(lf, LINKER_UNLOAD_FORCE); return (ENOEXEC); } + EVENTHANDLER_INVOKE(kld_load, lf); *result = lf; return (0); } @@ -609,6 +610,12 @@ linker_file_unload(linker_file_t file, int flags) return (0); } + /* Give eventhandlers a chance to prevent the unload. */ + error = 0; + EVENTHANDLER_INVOKE(kld_unload_try, file, &error); + if (error != 0) + return (EBUSY); + KLD_DPF(FILE, ("linker_file_unload: file is unloading," " informing modules\n")); @@ -690,6 +697,10 @@ linker_file_unload(linker_file_t file, int flags) } LINKER_UNLOAD(file); + + EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address, + file->size); + if (file->filename) { free(file->filename, M_LINKER); file->filename = NULL; @@ -1033,10 +1044,7 @@ kern_kldload(struct thread *td, const char *file, int *fileid) lf->userrefs++; if (fileid != NULL) *fileid = lf->id; - - sx_downgrade(&kld_sx); - EVENTHANDLER_INVOKE(kld_load, lf); - sx_sunlock(&kld_sx); + sx_xunlock(&kld_sx); done: CURVNET_RESTORE(); @@ -1066,9 +1074,6 @@ int kern_kldunload(struct thread *td, int fileid, int flags) { linker_file_t lf; - char *filename = NULL; - caddr_t address; - size_t size; int error = 0; if ((error = securelevel_gt(td->td_ucred, 0)) != 0) @@ -1083,10 +1088,7 @@ kern_kldunload(struct thread *td, int fileid, int flags) if (lf) { KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); - EVENTHANDLER_INVOKE(kld_unload_try, lf, &error); - if (error != 0) - error = EBUSY; - else if (lf->userrefs == 0) { + if (lf->userrefs == 0) { /* * XXX: maybe LINKER_UNLOAD_FORCE should override ? */ @@ -1094,11 +1096,6 @@ kern_kldunload(struct thread *td, int fileid, int flags) " loaded by the kernel\n"); error = EBUSY; } else { - /* Save data needed for the kld_unload callbacks. */ - filename = strdup(lf->filename, M_TEMP); - address = lf->address; - size = lf->size; - lf->userrefs--; error = linker_file_unload(lf, flags); if (error) @@ -1106,14 +1103,7 @@ kern_kldunload(struct thread *td, int fileid, int flags) } } else error = ENOENT; - - if (error == 0) { - sx_downgrade(&kld_sx); - EVENTHANDLER_INVOKE(kld_unload, filename, address, size); - sx_sunlock(&kld_sx); - } else - sx_xunlock(&kld_sx); - free(filename, M_TEMP); + sx_xunlock(&kld_sx); CURVNET_RESTORE(); return (error); From 75381a059ae28d43367c38eea79362d4b854e9cd Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Thu, 19 Dec 2013 04:55:35 +0000 Subject: [PATCH 158/172] Add item for pkg(8). --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 55d90529a82b..2f88cb852f91 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -538,18 +538,10 @@ Ports/Packages Collection Infrastructure - The &man.pkg.create.1; utility now supports - . When this option is specified and a - package tarball exists, it will not be overwritten. This is - useful when multiple packages are saved with several consecutive - runs of &man.pkg.create.1; with the - options. - - The pkg_sign and pkg_check utilities for cryptographically - signing &os; packages have been removed. They were only useful - for packages compressed using &man.gzip.1;; however - &man.bzip2.1; compression has been the norm for some time - now. + The pkg_add, pkg_create, pkg_delete, pkg_info, + pkg_updating, and pkg_version utilities have been removed. + &man.pkg.8; must now be used to install binary packages. &man.pkg.8; + is the next generation &os; package manager, also referred to as "pkgng". From 18f3ddcdee3af2f6ff14d8f9c55891b1ac669486 Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Thu, 19 Dec 2013 05:22:48 +0000 Subject: [PATCH 159/172] Fix doc build. Sponsored by: The FreeBSD Foundation --- release/doc/en_US.ISO8859-1/relnotes/article.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml index 2f88cb852f91..275f58e05686 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.xml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml @@ -540,7 +540,7 @@ The pkg_add, pkg_create, pkg_delete, pkg_info, pkg_updating, and pkg_version utilities have been removed. - &man.pkg.8; must now be used to install binary packages. &man.pkg.8; + &man.pkg.7; must now be used to install binary packages. &man.pkg.7; is the next generation &os; package manager, also referred to as "pkgng". From 72cad431b894792d06367622aaefd45e2c3f3cbf Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 19 Dec 2013 05:23:10 +0000 Subject: [PATCH 160/172] Fix readdir for the root directory on a FAT32 file system. The root directory is like any subdirectory and as such needs to use a real cluster number. To this end, keep a DE structure for the root in the DOS_FS structure and populate it accordingly. While here: o allow consecutive path separators by skipping them all. o add missing $FreeBSD$ keyword to dosfs.h. --- lib/libstand/dosfs.c | 18 +++++++++++++----- lib/libstand/dosfs.h | 3 +++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/libstand/dosfs.c b/lib/libstand/dosfs.c index f43b7213ee7e..72205a2c648a 100644 --- a/lib/libstand/dosfs.c +++ b/lib/libstand/dosfs.c @@ -162,6 +162,14 @@ dos_mount(DOS_FS *fs, struct open_file *fd) (void)dosunmount(fs); return(err); } + fs->root = dot[0]; + fs->root.name[0] = ' '; + if (fs->fatsz == 32) { + fs->root.clus[0] = fs->rdcl & 0xff; + fs->root.clus[1] = (fs->rdcl >> 8) & 0xff; + fs->root.dex.h_clus[0] = (fs->rdcl >> 16) & 0xff; + fs->root.dex.h_clus[1] = (fs->rdcl >> 24) & 0xff; + } return 0; } @@ -494,10 +502,12 @@ namede(DOS_FS *fs, const char *path, DOS_DE **dep) int err; err = 0; - de = dot; - if (*path == '/') - path++; + de = &fs->root; while (*path) { + while (*path == '/') + path++; + if (*path == '\0') + break; if (!(s = strchr(path, '/'))) s = strchr(path, 0); if ((n = s - path) > 255) @@ -509,8 +519,6 @@ namede(DOS_FS *fs, const char *path, DOS_DE **dep) return ENOTDIR; if ((err = lookup(fs, stclus(fs->fatsz, de), name, &de))) return err; - if (*path == '/') - path++; } *dep = de; return 0; diff --git a/lib/libstand/dosfs.h b/lib/libstand/dosfs.h index e44b6b51f288..9e5744de2e5c 100644 --- a/lib/libstand/dosfs.h +++ b/lib/libstand/dosfs.h @@ -23,6 +23,8 @@ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef DOSIO_H @@ -108,6 +110,7 @@ typedef struct { u_int lsndta; /* start of data area */ u_int fatsz; /* FAT entry size */ u_int xclus; /* maximum cluster number */ + DOS_DE root; } DOS_FS; typedef struct { From ad098e2975017e1af19297a1a8d0d3145f1f5df2 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 19 Dec 2013 05:28:43 +0000 Subject: [PATCH 161/172] Bump the loader version to 3.2 after various dosfs fixes (in particular). --- sys/boot/ia64/efi/version | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/boot/ia64/efi/version b/sys/boot/ia64/efi/version index 17d14ea1c70b..4f4203a7a050 100644 --- a/sys/boot/ia64/efi/version +++ b/sys/boot/ia64/efi/version @@ -3,6 +3,7 @@ $FreeBSD$ NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this file is important. Make sure the current version number is on line 6. +3.2: Various fixes to libstand, in particular dosfs. 3.1: Add the about, reboot and pbvm commands. I-cache coherency is maintained. 3.0: Add support for PBVM. From 4b4b90d5a8666f0f5165477d938ebb3e31cb9120 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Thu, 19 Dec 2013 06:41:30 +0000 Subject: [PATCH 162/172] Fix a regression that occurred with SVN revisions 259474 and 259476 where installation to 3-4+ (depending on vdev type) vdevs would result in odd error messages where the zpool `create' command appeared to repeat itself (an artifact of printf when you supply too many arguments -- caused by neglecting to properly quote the multi-word expansion of $*vdevs when creating the pool(s)). Example error below (taken from bsdinstall_log): DEBUG: zfs_create_boot: Creating root pool... DEBUG: zfs_create_boot: zpool create -o altroot=/mnt -m none -f "zroot" \ ada0p3.nop ada1p3.nopzpool create ada2p3.nop "ada3p3.nop" DEBUG: zfs_create_boot: retval=1 cannot open 'ada1p3.nopzpool': no such GEOM provider --- usr.sbin/bsdinstall/scripts/zfsboot | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 2a0460a89d7b..61a90cbf7b5a 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -979,7 +979,8 @@ zfs_create_boot() bootpool_options="$bootpool_options -m \"/$bootpool_name\" -f" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ "$bootpool_options" "$bootpool_name" \ - $bootpool_vdevtype $boot_vdevs || return $FAILURE + "$bootpool_vdevtype" "$boot_vdevs" || + return $FAILURE f_eval_catch $funcname mkdir "$MKDIR_P" "$bootpool/boot" || return $FAILURE @@ -1048,7 +1049,8 @@ zfs_create_boot() f_dprintf "$funcname: Creating root pool..." f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ "-o altroot=$BSDINSTALL_CHROOT -m none -f" \ - "$zroot_name" $zroot_vdevtype $zroot_vdevs + "$zroot_name" "$zroot_vdevtype" "$zroot_vdevs" || + return $FAILURE # Customize the zroot a bit... local option From 6311cc9efe05fa738d4209f985ac1ae80a85d2c8 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Thu, 19 Dec 2013 06:43:52 +0000 Subject: [PATCH 163/172] When using a bootpool, set the cachefile property so that it gets imported automatically upon reboot to the newly installed system. MFC after: 1 day --- usr.sbin/bsdinstall/scripts/zfsboot | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 61a90cbf7b5a..e1102b6c749f 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -1152,7 +1152,7 @@ zfs_create_boot() fi # While this is apparently not needed, it seems to help MBR - f_dprintf "$funcname: Configuring zpool.cache..." + f_dprintf "$funcname: Configuring zpool.cache for zroot..." f_eval_catch $funcname mkdir "$MKDIR_P" $BSDINSTALL_CHROOT/boot/zfs || return $FAILURE f_eval_catch $funcname zpool "$ZPOOL_SET" \ @@ -1174,6 +1174,12 @@ zfs_create_boot() # We're all done unless we should go on for boot pool [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS + # Set cachefile for boot pool so it auto-imports at system start + f_dprintf "$funcname: Configuring zpool.cache for boot pool..." + f_eval_catch $funcname zpool "$ZPOOL_SET" \ + "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \ + "$bootpool_name" || return $FAILURE + # Some additional geli(8) requirements for loader.conf(5) for option in \ 'zpool_cache_load=\"YES\"' \ From 53d5cc255d61c7482bb9423bad77891c3719885e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20E=C3=9Fer?= Date: Thu, 19 Dec 2013 09:01:46 +0000 Subject: [PATCH 164/172] Fix overflow for timeout values of more than 68 years, which is the maximum covered by sbintime (LONG_MAX seconds). Some programs use timeout values in excess of 1000 years. The conversion to sbintime caused wrap-around on overflow, which resulted in short or negative timeout values. This caused long delays on sockets opened by affected programs (e.g. OpenSSH). Kernels compiled without -fno-strict-overflow were not affected, apparently because the compiler tested the sign of the timeout value before performing the multiplication that lead to overflow. When the -fno-strict-overflow option was added to CFLAGS, this optimization was disabled and the test was performed on the result of the multiplication. Negative products were caught and resulted in EINVAL being returned, but wrap-around to positive values just shortened the timeout value to the residue of the result that could be represented by sbintime. The fix is to cap the timeout values at the maximum that can be represented by sbintime, which is 2^31 - 1 seconds or more than 68 years. After this change, the kernel can be compiled with -fno-strict-overflow with no ill effects. MFC after: 3 days --- sys/kern/kern_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index dfbba675a3b4..3981dcb30925 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -526,7 +526,8 @@ knote_fork(struct knlist *list, int pid) static __inline sbintime_t timer2sbintime(intptr_t data) { - + if (data > LLONG_MAX / SBT_1MS) + return LLONG_MAX; return (SBT_1MS * data); } From ea2705e8bfbd944b837f4a790aff683c68ff315d Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 19 Dec 2013 12:00:48 +0000 Subject: [PATCH 165/172] ttm_bo_vm_lookup_rb: actually make use of the red-black tree Previously the code would just iterate over the whole tree as if it were just a list. Without this change I would observe X server becoming more and more jerky over time. MFC after: 5 days --- sys/dev/drm2/ttm/ttm_bo_vm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c index b87380cfe1d9..83ec76ceab77 100644 --- a/sys/dev/drm2/ttm/ttm_bo_vm.c +++ b/sys/dev/drm2/ttm/ttm_bo_vm.c @@ -76,13 +76,16 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev, struct ttm_buffer_object *bo; struct ttm_buffer_object *best_bo = NULL; - RB_FOREACH(bo, ttm_bo_device_buffer_objects, &bdev->addr_space_rb) { + bo = RB_ROOT(&bdev->addr_space_rb); + while (bo != NULL) { cur_offset = bo->vm_node->start; if (page_start >= cur_offset) { best_bo = bo; if (page_start == cur_offset) break; - } + bo = RB_RIGHT(bo, vm_rb); + } else + bo = RB_LEFT(bo, vm_rb); } if (unlikely(best_bo == NULL)) From 0a036e525d2789e9d3a053c61eb06d98ee6c514c Mon Sep 17 00:00:00 2001 From: Aleksandr Rybalko Date: Thu, 19 Dec 2013 15:31:20 +0000 Subject: [PATCH 166/172] Enable mouse support for terminal clients (like dialog(1)). Sponsored by: The FreeBSD Foundation --- sys/dev/vt/vt.h | 2 +- sys/dev/vt/vt_core.c | 65 +++++++++++++++++++++++++++++++++++++++- sys/dev/vt/vt_sysmouse.c | 3 +- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index 7b573ae197c0..70a8e5900f66 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -412,7 +412,7 @@ int vtfont_load(vfnt_t *f, struct vt_font **ret); /* Sysmouse. */ void sysmouse_process_event(mouse_info_t *mi); #ifndef SC_NO_CUTPASTE -void vt_mouse_event(int type, int x, int y, int event, int cnt); +void vt_mouse_event(int type, int x, int y, int event, int cnt, int mlevel); void vt_mouse_state(int show); #endif #define VT_MOUSE_SHOW 1 diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 8cb2a5e66c21..873345bda608 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -1120,8 +1120,68 @@ finish_vt_acq(struct vt_window *vw) } #ifndef SC_NO_CUTPASTE +static void +vt_mouse_terminput_button(struct vt_device *vd, int button) +{ + struct vt_window *vw; + struct vt_font *vf; + char mouseb[6] = "\x1B[M"; + int i, x, y; + + vw = vd->vd_curwindow; + vf = vw->vw_font; + + /* Translate to char position. */ + x = vd->vd_mx / vf->vf_width; + y = vd->vd_my / vf->vf_height; + /* Avoid overflow. */ + x = MIN(x, 255 - '!'); + y = MIN(y, 255 - '!'); + + mouseb[3] = ' ' + button; + mouseb[4] = '!' + x; + mouseb[5] = '!' + y; + + for (i = 0; i < sizeof(mouseb); i++ ) + terminal_input_char(vw->vw_terminal, mouseb[i]); +} + +static void +vt_mouse_terminput(struct vt_device *vd, int type, int x, int y, int event, + int cnt) +{ + + switch (type) { + case MOUSE_BUTTON_EVENT: + if (cnt > 0) { + /* Mouse button pressed. */ + if (event & MOUSE_BUTTON1DOWN) + vt_mouse_terminput_button(vd, 0); + if (event & MOUSE_BUTTON2DOWN) + vt_mouse_terminput_button(vd, 1); + if (event & MOUSE_BUTTON3DOWN) + vt_mouse_terminput_button(vd, 2); + } else { + /* Mouse button released. */ + vt_mouse_terminput_button(vd, 3); + } + break; +#ifdef notyet + case MOUSE_MOTION_EVENT: + if (mouse->u.data.z < 0) { + /* Scroll up. */ + sc_mouse_input_button(vd, 64); + } else if (mouse->u.data.z > 0) { + /* Scroll down. */ + sc_mouse_input_button(vd, 65); + } + break; +#endif + } +} + void -vt_mouse_event(int type, int x, int y, int event, int cnt) +vt_mouse_event(int type, int x, int y, int event, int cnt, int mlevel) { struct vt_device *vd; struct vt_window *vw; @@ -1146,6 +1206,9 @@ vt_mouse_event(int type, int x, int y, int event, int cnt) * under mouse pointer when nothing changed. */ + if (mlevel > 0) + vt_mouse_terminput(vd, type, x, y, event, cnt); + switch (type) { case MOUSE_ACTION: case MOUSE_MOTION_EVENT: diff --git a/sys/dev/vt/vt_sysmouse.c b/sys/dev/vt/vt_sysmouse.c index c46887fd5e24..42fc5aa58e6c 100644 --- a/sys/dev/vt/vt_sysmouse.c +++ b/sys/dev/vt/vt_sysmouse.c @@ -192,7 +192,8 @@ sysmouse_process_event(mouse_info_t *mi) #ifndef SC_NO_CUTPASTE mtx_unlock(&sysmouse_lock); - vt_mouse_event(mi->operation, x, y, mi->u.event.id, mi->u.event.value); + vt_mouse_event(mi->operation, x, y, mi->u.event.id, mi->u.event.value, + sysmouse_level); return; #endif From 915b4b42aebc0b4bf0d70a620f3823802618d451 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Thu, 19 Dec 2013 18:27:32 +0000 Subject: [PATCH 167/172] gcc: backport upstream fix for issue with C++'s placement new Fixes GCC libstdc++/29286 Obtained from: gcc 4.3 (rev. 125603, 125653; GPLv2) MFC after: 2 weeks --- contrib/gcc/ChangeLog.gcc43 | 42 +++++++ contrib/gcc/cp/ChangeLog.gcc43 | 6 + contrib/gcc/cp/init.c | 77 +++++++++++- contrib/gcc/doc/c-tree.texi | 8 ++ contrib/gcc/expr.c | 7 ++ contrib/gcc/gimple-low.c | 1 + contrib/gcc/gimplify.c | 5 + contrib/gcc/omp-low.c | 1 + contrib/gcc/print-tree.c | 4 +- contrib/gcc/tree-gimple.c | 4 +- contrib/gcc/tree-inline.c | 7 ++ contrib/gcc/tree-pretty-print.c | 11 ++ contrib/gcc/tree-ssa-alias.c | 99 +++++++-------- contrib/gcc/tree-ssa-dce.c | 4 +- contrib/gcc/tree-ssa-operands.c | 4 + contrib/gcc/tree-ssa-structalias.c | 193 +++++++++++++++++++++++++++-- contrib/gcc/tree.def | 11 +- contrib/gcc/tree.h | 13 ++ 18 files changed, 435 insertions(+), 62 deletions(-) diff --git a/contrib/gcc/ChangeLog.gcc43 b/contrib/gcc/ChangeLog.gcc43 index 8537c3bc4ecd..a2523905eecf 100644 --- a/contrib/gcc/ChangeLog.gcc43 +++ b/contrib/gcc/ChangeLog.gcc43 @@ -65,6 +65,48 @@ fvisibility-ms-compat. * c.opt (fvisibility-ms-compat): New. +2007-06-12 Ian Lance Taylor (r125653) + Daniel Berlin + + PR libstdc++/29286 + * tree.def: Add CHANGE_DYNAMIC_TYPE_EXPR. + * tree.h (CHANGE_DYNAMIC_TYPE_NEW_TYPE): Define. + (CHANGE_DYNAMIC_TYPE_LOCATION): Define. + (DECL_NO_TBAA_P): Define. + (struct tree_decl_common): Add no_tbaa_flag field. + * tree-ssa-structalias.c (struct variable_info): Add + no_tbaa_pruning field. + (new_var_info): Initialize no_tbaa_pruning field. + (unify_nodes): Copy no_tbaa_pruning field. + (find_func_aliases): Handle CHANGE_DYNAMIC_TYPE_EXPR. + (dump_solution_for_var): Print no_tbaa_pruning flag. + (set_uids_in_ptset): Add no_tbaa_pruning parameter. Change all + callers. + (compute_tbaa_pruning): New static function. + (compute_points_to_sets): Remove CHANGE_DYNAMIC_TYPE_EXPR nodes. + Call compute_tbaa_pruning. + * tree-ssa-alias.c (may_alias_p): Test no_tbaa_flag for pointers. + * gimplify.c (gimplify_expr): Handle CHANGE_DYNAMIC_TYPE_EXPR. + * gimple-low.c (lower_stmt): Likewise. + * tree-gimple.c (is_gimple_stmt): Likewise. + * tree-ssa-operands.c (get_expr_operands): Likewise. + * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise. + * tree-inline.c (estimate_num_insns_1): Likewise. + (copy_result_decl_to_var): Likewise. + * expr.c (expand_expr_real_1): Likewise. + * tree-pretty-print.c (dump_generic_node): Likewise. + * tree-inline.c (copy_decl_to_var): Copy DECL_NO_TBAA_P flag. + * omp-low.c (omp_copy_decl_2): Likewise. + * print-tree.c (print_node): Print DECL_NO_TBAA_P flag. + * doc/c-tree.texi (Expression trees): Document + CHANGE_DYNAMIC_TYPE_EXPR. + +2007-06-09 Daniel Berlin (r125603) + + * tree-ssa-structalias.c (set_uids_in_ptset): Add is_deref'd + parameter, use it. + (find_what_p_points_to): Pass new parameter to set_uids_in_ptset. + 2007-06-05 Joerg Wunsch (r125346) PR preprocessor/23479 diff --git a/contrib/gcc/cp/ChangeLog.gcc43 b/contrib/gcc/cp/ChangeLog.gcc43 index 0aa70d1f7c6d..ae3005c8a3e4 100644 --- a/contrib/gcc/cp/ChangeLog.gcc43 +++ b/contrib/gcc/cp/ChangeLog.gcc43 @@ -25,6 +25,12 @@ * decl2.c (determine_visibility): Remove duplicate code for handling type info. +2007-06-12 Ian Lance Taylor (r125653) + + PR libstdc++/29286 + * init.c (avoid_placement_new_aliasing): New static function. + (build_new_1): Call it. + 2007-05-31 Daniel Berlin (r125239) * typeck.c (build_binary_op): Include types in error. diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c index 70bc76470f1c..667251d34f94 100644 --- a/contrib/gcc/cp/init.c +++ b/contrib/gcc/cp/init.c @@ -1,6 +1,7 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -1564,6 +1565,55 @@ build_raw_new_expr (tree placement, tree type, tree nelts, tree init, return new_expr; } +/* Make sure that there are no aliasing issues with T, a placement new + expression applied to PLACEMENT, by recording the change in dynamic + type. If placement new is inlined, as it is with libstdc++, and if + the type of the placement new differs from the type of the + placement location itself, then alias analysis may think it is OK + to interchange writes to the location from before the placement new + and from after the placement new. We have to prevent type-based + alias analysis from applying. PLACEMENT may be NULL, which means + that we couldn't capture it in a temporary variable, in which case + we use a memory clobber. */ + +static tree +avoid_placement_new_aliasing (tree t, tree placement) +{ + tree type_change; + + if (processing_template_decl) + return t; + + /* If we are not using type based aliasing, we don't have to do + anything. */ + if (!flag_strict_aliasing) + return t; + + /* If we have a pointer and a location, record the change in dynamic + type. Otherwise we need a general memory clobber. */ + if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE + && placement != NULL_TREE + && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE) + type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR, + TREE_TYPE (t), + placement); + else + { + /* Build a memory clobber. */ + type_change = build_stmt (ASM_EXPR, + build_string (0, ""), + NULL_TREE, + NULL_TREE, + tree_cons (NULL_TREE, + build_string (6, "memory"), + NULL_TREE)); + + ASM_VOLATILE_P (type_change) = 1; + } + + return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t); +} + /* Generate code for a new-expression, including calling the "operator new" function, initializing the object, and, if an exception occurs during construction, cleaning up. The arguments are as for @@ -1607,6 +1657,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, beginning of the storage allocated for an array-new expression in order to store the number of elements. */ tree cookie_size = NULL_TREE; + tree placement_var; /* True if the function we are calling is a placement allocation function. */ bool placement_allocation_fn_p; @@ -1700,6 +1751,20 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, alloc_fn = NULL_TREE; + /* If PLACEMENT is a simple pointer type, then copy it into + PLACEMENT_VAR. */ + if (processing_template_decl + || placement == NULL_TREE + || TREE_CHAIN (placement) != NULL_TREE + || TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) != POINTER_TYPE) + placement_var = NULL_TREE; + else + { + placement_var = get_temp_regvar (TREE_TYPE (TREE_VALUE (placement)), + TREE_VALUE (placement)); + placement = tree_cons (NULL_TREE, placement_var, NULL_TREE); + } + /* Allocate the object. */ if (! placement && TYPE_FOR_JAVA (elt_type)) { @@ -1792,7 +1857,12 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* In the simple case, we can stop now. */ pointer_type = build_pointer_type (type); if (!cookie_size && !is_initialized) - return build_nop (pointer_type, alloc_call); + { + rval = build_nop (pointer_type, alloc_call); + if (placement != NULL) + rval = avoid_placement_new_aliasing (rval, placement_var); + return rval; + } /* While we're working, use a pointer to the type we've actually allocated. Store the result of the call in a variable so that we @@ -2051,6 +2121,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* A new-expression is never an lvalue. */ gcc_assert (!lvalue_p (rval)); + if (placement != NULL) + rval = avoid_placement_new_aliasing (rval, placement_var); + return rval; } diff --git a/contrib/gcc/doc/c-tree.texi b/contrib/gcc/doc/c-tree.texi index c5877afdf49e..906ce75a9dff 100644 --- a/contrib/gcc/doc/c-tree.texi +++ b/contrib/gcc/doc/c-tree.texi @@ -1916,6 +1916,7 @@ This macro returns the attributes on the type @var{type}. @tindex TARGET_EXPR @tindex AGGR_INIT_EXPR @tindex VA_ARG_EXPR +@tindex CHANGE_DYNAMIC_TYPE_EXPR @tindex OMP_PARALLEL @tindex OMP_FOR @tindex OMP_SECTIONS @@ -2572,6 +2573,13 @@ mechanism. It represents expressions like @code{va_arg (ap, type)}. Its @code{TREE_TYPE} yields the tree representation for @code{type} and its sole argument yields the representation for @code{ap}. +@item CHANGE_DYNAMIC_TYPE_EXPR +Indicates the special aliasing required by C++ placement new. It has +two operands: a type and a location. It means that the dynamic type +of the location is changing to be the specified type. The alias +analysis code takes this into account when doing type based alias +analysis. + @item OMP_PARALLEL Represents @code{#pragma omp parallel [clause1 ... clauseN]}. It diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index 16e43aa3d742..6fbad0451069 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -8718,6 +8718,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* Lowered by gimplify.c. */ gcc_unreachable (); + case CHANGE_DYNAMIC_TYPE_EXPR: + /* This is ignored at the RTL level. The tree level set + DECL_POINTER_ALIAS_SET of any variable to be 0, which is + overkill for the RTL layer but is all that we can + represent. */ + return const0_rtx; + case EXC_PTR_EXPR: return get_exception_pointer (cfun); diff --git a/contrib/gcc/gimple-low.c b/contrib/gcc/gimple-low.c index c6a0312a2bea..15d18eac57fb 100644 --- a/contrib/gcc/gimple-low.c +++ b/contrib/gcc/gimple-low.c @@ -243,6 +243,7 @@ lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data) case GOTO_EXPR: case LABEL_EXPR: case SWITCH_EXPR: + case CHANGE_DYNAMIC_TYPE_EXPR: case OMP_FOR: case OMP_SECTIONS: case OMP_SECTION: diff --git a/contrib/gcc/gimplify.c b/contrib/gcc/gimplify.c index be45f478f9a8..b0270a9511f3 100644 --- a/contrib/gcc/gimplify.c +++ b/contrib/gcc/gimplify.c @@ -5748,6 +5748,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ret = GS_ALL_DONE; break; + case CHANGE_DYNAMIC_TYPE_EXPR: + ret = gimplify_expr (&CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p), + pre_p, post_p, is_gimple_reg, fb_lvalue); + break; + case OBJ_TYPE_REF: { enum gimplify_status r0, r1; diff --git a/contrib/gcc/omp-low.c b/contrib/gcc/omp-low.c index 49fb8c93fd7f..fe217735f4bb 100644 --- a/contrib/gcc/omp-low.c +++ b/contrib/gcc/omp-low.c @@ -518,6 +518,7 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var); DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var); + DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var); DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var); DECL_IGNORED_P (copy) = DECL_IGNORED_P (var); TREE_USED (copy) = 1; diff --git a/contrib/gcc/print-tree.c b/contrib/gcc/print-tree.c index ef87ab6abad2..553e07cb7ab7 100644 --- a/contrib/gcc/print-tree.c +++ b/contrib/gcc/print-tree.c @@ -401,7 +401,9 @@ print_node (FILE *file, const char *prefix, tree node, int indent) if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); if (DECL_PRESERVE_P (node)) - fputs (" preserve", file); + fputs (" preserve", file); + if (DECL_NO_TBAA_P (node)) + fputs (" no-tbaa", file); if (DECL_LANG_FLAG_0 (node)) fputs (" decl_0", file); if (DECL_LANG_FLAG_1 (node)) diff --git a/contrib/gcc/tree-gimple.c b/contrib/gcc/tree-gimple.c index 740f6735f7b8..11140c960856 100644 --- a/contrib/gcc/tree-gimple.c +++ b/contrib/gcc/tree-gimple.c @@ -1,5 +1,6 @@ /* Functions to analyze and validate GIMPLE trees. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Diego Novillo Rewritten by Jason Merrill @@ -215,6 +216,7 @@ is_gimple_stmt (tree t) case TRY_FINALLY_EXPR: case EH_FILTER_EXPR: case CATCH_EXPR: + case CHANGE_DYNAMIC_TYPE_EXPR: case ASM_EXPR: case RESX_EXPR: case PHI_NODE: diff --git a/contrib/gcc/tree-inline.c b/contrib/gcc/tree-inline.c index 1c0b79b7908f..e8e3886f0c91 100644 --- a/contrib/gcc/tree-inline.c +++ b/contrib/gcc/tree-inline.c @@ -1649,6 +1649,11 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; return NULL; + /* CHANGE_DYNAMIC_TYPE_EXPR explicitly expands to nothing. */ + case CHANGE_DYNAMIC_TYPE_EXPR: + *walk_subtrees = 0; + return NULL; + /* Try to estimate the cost of assignments. We have three cases to deal with: 1) Simple assignments to registers; @@ -2635,6 +2640,7 @@ copy_decl_to_var (tree decl, copy_body_data *id) TREE_READONLY (copy) = TREE_READONLY (decl); TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (decl); + DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl); return copy_decl_for_dup_finish (id, decl, copy); } @@ -2661,6 +2667,7 @@ copy_result_decl_to_var (tree decl, copy_body_data *id) { TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (decl); + DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl); } return copy_decl_for_dup_finish (id, decl, copy); diff --git a/contrib/gcc/tree-pretty-print.c b/contrib/gcc/tree-pretty-print.c index 5ce495b501f0..fdd9ff52d406 100644 --- a/contrib/gcc/tree-pretty-print.c +++ b/contrib/gcc/tree-pretty-print.c @@ -1443,6 +1443,17 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, is_expr = false; break; + case CHANGE_DYNAMIC_TYPE_EXPR: + pp_string (buffer, "<<>>"); + is_expr = false; + break; + case LABEL_EXPR: op0 = TREE_OPERAND (node, 0); /* If this is for break or continue, don't bother printing it. */ diff --git a/contrib/gcc/tree-ssa-alias.c b/contrib/gcc/tree-ssa-alias.c index c7007337241d..d9232b0c924e 100644 --- a/contrib/gcc/tree-ssa-alias.c +++ b/contrib/gcc/tree-ssa-alias.c @@ -1,5 +1,5 @@ /* Alias analysis for trees. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Diego Novillo This file is part of GCC. @@ -1961,28 +1961,29 @@ may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set, gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG); - alias_stats.tbaa_queries++; - - /* If the alias sets don't conflict then MEM cannot alias VAR. */ - if (!alias_sets_conflict_p (mem_alias_set, var_alias_set)) + if (!DECL_NO_TBAA_P (ptr)) { - alias_stats.alias_noalias++; - alias_stats.tbaa_resolved++; - return false; - } + alias_stats.tbaa_queries++; - /* If var is a record or union type, ptr cannot point into var - unless there is some operation explicit address operation in the - program that can reference a field of the ptr's dereferenced - type. This also assumes that the types of both var and ptr are - contained within the compilation unit, and that there is no fancy - addressing arithmetic associated with any of the types - involved. */ + /* If the alias sets don't conflict then MEM cannot alias VAR. */ + if (!alias_sets_conflict_p (mem_alias_set, var_alias_set)) + { + alias_stats.alias_noalias++; + alias_stats.tbaa_resolved++; + return false; + } - if ((mem_alias_set != 0) && (var_alias_set != 0)) - { - tree ptr_type = TREE_TYPE (ptr); - tree var_type = TREE_TYPE (var); + /* If VAR is a record or union type, PTR cannot point into VAR + unless there is some explicit address operation in the + program that can reference a field of the type pointed-to by + PTR. This also assumes that the types of both VAR and PTR + are contained within the compilation unit, and that there is + no fancy addressing arithmetic associated with any of the + types involved. */ + if (mem_alias_set != 0 && var_alias_set != 0) + { + tree ptr_type = TREE_TYPE (ptr); + tree var_type = TREE_TYPE (var); /* The star count is -1 if the type at the end of the pointer_to chain is not a record or union type. */ @@ -1991,41 +1992,41 @@ may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set, { int ptr_star_count = 0; - /* Ipa_type_escape_star_count_of_interesting_type is a little to - restrictive for the pointer type, need to allow pointers to - primitive types as long as those types cannot be pointers - to everything. */ - while (POINTER_TYPE_P (ptr_type)) - /* Strip the *'s off. */ - { - ptr_type = TREE_TYPE (ptr_type); - ptr_star_count++; - } - - /* There does not appear to be a better test to see if the - pointer type was one of the pointer to everything - types. */ - - if (ptr_star_count > 0) - { - alias_stats.structnoaddress_queries++; - if (ipa_type_escape_field_does_not_clobber_p (var_type, - TREE_TYPE (ptr))) + /* ipa_type_escape_star_count_of_interesting_type is a + little too restrictive for the pointer type, need to + allow pointers to primitive types as long as those + types cannot be pointers to everything. */ + while (POINTER_TYPE_P (ptr_type)) { + /* Strip the *s off. */ + ptr_type = TREE_TYPE (ptr_type); + ptr_star_count++; + } + + /* There does not appear to be a better test to see if + the pointer type was one of the pointer to everything + types. */ + if (ptr_star_count > 0) + { + alias_stats.structnoaddress_queries++; + if (ipa_type_escape_field_does_not_clobber_p (var_type, + TREE_TYPE (ptr))) + { + alias_stats.structnoaddress_resolved++; + alias_stats.alias_noalias++; + return false; + } + } + else if (ptr_star_count == 0) + { + /* If PTR_TYPE was not really a pointer to type, it cannot + alias. */ + alias_stats.structnoaddress_queries++; alias_stats.structnoaddress_resolved++; alias_stats.alias_noalias++; return false; } } - else if (ptr_star_count == 0) - { - /* If ptr_type was not really a pointer to type, it cannot - alias. */ - alias_stats.structnoaddress_queries++; - alias_stats.structnoaddress_resolved++; - alias_stats.alias_noalias++; - return false; - } } } diff --git a/contrib/gcc/tree-ssa-dce.c b/contrib/gcc/tree-ssa-dce.c index 684ea78f15c1..f8f52ea52961 100644 --- a/contrib/gcc/tree-ssa-dce.c +++ b/contrib/gcc/tree-ssa-dce.c @@ -1,5 +1,6 @@ /* Dead code elimination pass for the GNU compiler. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Ben Elliston and Andrew MacLeod Adapted to use control dependence by Steven Bosscher, SUSE Labs. @@ -307,6 +308,7 @@ mark_stmt_if_obviously_necessary (tree stmt, bool aggressive) case ASM_EXPR: case RESX_EXPR: case RETURN_EXPR: + case CHANGE_DYNAMIC_TYPE_EXPR: mark_stmt_necessary (stmt, true); return; diff --git a/contrib/gcc/tree-ssa-operands.c b/contrib/gcc/tree-ssa-operands.c index 3c24d2a938b5..a8ab58cfa2e0 100644 --- a/contrib/gcc/tree-ssa-operands.c +++ b/contrib/gcc/tree-ssa-operands.c @@ -2057,6 +2057,10 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) return; } + case CHANGE_DYNAMIC_TYPE_EXPR: + get_expr_operands (stmt, &CHANGE_DYNAMIC_TYPE_LOCATION (expr), opf_none); + return; + case BLOCK: case FUNCTION_DECL: case EXC_PTR_EXPR: diff --git a/contrib/gcc/tree-ssa-structalias.c b/contrib/gcc/tree-ssa-structalias.c index 29811ca0ade7..cfeea07afe4b 100644 --- a/contrib/gcc/tree-ssa-structalias.c +++ b/contrib/gcc/tree-ssa-structalias.c @@ -251,6 +251,10 @@ struct variable_info /* True if this is a heap variable. */ unsigned int is_heap_var:1; + /* True if we may not use TBAA to prune references to this + variable. This is used for C++ placement new. */ + unsigned int no_tbaa_pruning : 1; + /* Points-to set for this variable. */ bitmap solution; @@ -368,6 +372,7 @@ static varinfo_t new_var_info (tree t, unsigned int id, const char *name) { varinfo_t ret = pool_alloc (variable_info_pool); + tree var; ret->id = id; ret->name = name; @@ -378,6 +383,12 @@ new_var_info (tree t, unsigned int id, const char *name) ret->is_special_var = false; ret->is_unknown_size_var = false; ret->has_union = false; + var = t; + if (TREE_CODE (var) == SSA_NAME) + var = SSA_NAME_VAR (var); + ret->no_tbaa_pruning = (DECL_P (var) + && POINTER_TYPE_P (TREE_TYPE (var)) + && DECL_NO_TBAA_P (var)); ret->solution = BITMAP_ALLOC (&pta_obstack); ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack); ret->next = NULL; @@ -1221,6 +1232,9 @@ unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from, merge_graph_nodes (graph, to, from); merge_node_constraints (graph, to, from); + if (get_varinfo (from)->no_tbaa_pruning) + get_varinfo (to)->no_tbaa_pruning = true; + if (update_changed && TEST_BIT (changed, from)) { RESET_BIT (changed, from); @@ -3564,6 +3578,14 @@ find_func_aliases (tree origt) } } } + else if (TREE_CODE (t) == CHANGE_DYNAMIC_TYPE_EXPR) + { + unsigned int j; + + get_constraint_for (CHANGE_DYNAMIC_TYPE_LOCATION (t), &lhsc); + for (j = 0; VEC_iterate (ce_s, lhsc, j, c); ++j) + get_varinfo (c->var)->no_tbaa_pruning = true; + } /* After promoting variables and computing aliasing we will need to re-scan most statements. FIXME: Try to minimize the @@ -4250,7 +4272,10 @@ dump_solution_for_var (FILE *file, unsigned int var) { fprintf (file, "%s ", get_varinfo (i)->name); } - fprintf (file, "}\n"); + fprintf (file, "}"); + if (vi->no_tbaa_pruning) + fprintf (file, " no-tbaa-pruning"); + fprintf (file, "\n"); } } @@ -4422,10 +4447,15 @@ shared_bitmap_add (bitmap pt_vars) /* Set bits in INTO corresponding to the variable uids in solution set FROM, which came from variable PTR. For variables that are actually dereferenced, we also use type - based alias analysis to prune the points-to sets. */ + based alias analysis to prune the points-to sets. + IS_DEREFED is true if PTR was directly dereferenced, which we use to + help determine whether we are we are allowed to prune using TBAA. + If NO_TBAA_PRUNING is true, we do not perform any TBAA pruning of + the from set. */ static void -set_uids_in_ptset (tree ptr, bitmap into, bitmap from) +set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, + bool no_tbaa_pruning) { unsigned int i; bitmap_iterator bi; @@ -4462,7 +4492,8 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from) if (sft) { var_alias_set = get_alias_set (sft); - if (!vi->directly_dereferenced + if (no_tbaa_pruning + || (!is_derefed && !vi->directly_dereferenced) || alias_sets_conflict_p (ptr_alias_set, var_alias_set)) bitmap_set_bit (into, DECL_UID (sft)); } @@ -4476,7 +4507,8 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from) else { var_alias_set = get_alias_set (vi->decl); - if (!vi->directly_dereferenced + if (no_tbaa_pruning + || (!is_derefed && !vi->directly_dereferenced) || alias_sets_conflict_p (ptr_alias_set, var_alias_set)) bitmap_set_bit (into, DECL_UID (vi->decl)); } @@ -4564,7 +4596,9 @@ find_what_p_points_to (tree p) return false; finished_solution = BITMAP_GGC_ALLOC (); - set_uids_in_ptset (vi->decl, finished_solution, vi->solution); + set_uids_in_ptset (vi->decl, finished_solution, vi->solution, + vi->directly_dereferenced, + vi->no_tbaa_pruning); result = shared_bitmap_lookup (finished_solution); if (!result) @@ -4913,6 +4947,142 @@ remove_preds_and_fake_succs (constraint_graph_t graph) bitmap_obstack_release (&predbitmap_obstack); } +/* Compute the set of variables we can't TBAA prune. */ + +static void +compute_tbaa_pruning (void) +{ + unsigned int size = VEC_length (varinfo_t, varmap); + unsigned int i; + bool any; + + changed_count = 0; + changed = sbitmap_alloc (size); + sbitmap_zero (changed); + + /* Mark all initial no_tbaa_pruning nodes as changed. */ + any = false; + for (i = 0; i < size; ++i) + { + varinfo_t ivi = get_varinfo (i); + + if (find (i) == i && ivi->no_tbaa_pruning) + { + any = true; + if ((graph->succs[i] && !bitmap_empty_p (graph->succs[i])) + || VEC_length (constraint_t, graph->complex[i]) > 0) + { + SET_BIT (changed, i); + ++changed_count; + } + } + } + + while (changed_count > 0) + { + struct topo_info *ti = init_topo_info (); + ++stats.iterations; + + bitmap_obstack_initialize (&iteration_obstack); + + compute_topo_order (graph, ti); + + while (VEC_length (unsigned, ti->topo_order) != 0) + { + bitmap_iterator bi; + + i = VEC_pop (unsigned, ti->topo_order); + + /* If this variable is not a representative, skip it. */ + if (find (i) != i) + continue; + + /* If the node has changed, we need to process the complex + constraints and outgoing edges again. */ + if (TEST_BIT (changed, i)) + { + unsigned int j; + constraint_t c; + VEC(constraint_t,heap) *complex = graph->complex[i]; + + RESET_BIT (changed, i); + --changed_count; + + /* Process the complex copy constraints. */ + for (j = 0; VEC_iterate (constraint_t, complex, j, c); ++j) + { + if (c->lhs.type == SCALAR && c->rhs.type == SCALAR) + { + varinfo_t lhsvi = get_varinfo (find (c->lhs.var)); + + if (!lhsvi->no_tbaa_pruning) + { + lhsvi->no_tbaa_pruning = true; + if (!TEST_BIT (changed, lhsvi->id)) + { + SET_BIT (changed, lhsvi->id); + ++changed_count; + } + } + } + } + + /* Propagate to all successors. */ + EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi) + { + unsigned int to = find (j); + varinfo_t tovi = get_varinfo (to); + + /* Don't propagate to ourselves. */ + if (to == i) + continue; + + if (!tovi->no_tbaa_pruning) + { + tovi->no_tbaa_pruning = true; + if (!TEST_BIT (changed, to)) + { + SET_BIT (changed, to); + ++changed_count; + } + } + } + } + } + + free_topo_info (ti); + bitmap_obstack_release (&iteration_obstack); + } + + sbitmap_free (changed); + + if (any) + { + for (i = 0; i < size; ++i) + { + varinfo_t ivi = get_varinfo (i); + varinfo_t ivip = get_varinfo (find (i)); + + if (ivip->no_tbaa_pruning) + { + tree var = ivi->decl; + + if (TREE_CODE (var) == SSA_NAME) + var = SSA_NAME_VAR (var); + + if (POINTER_TYPE_P (TREE_TYPE (var))) + { + DECL_NO_TBAA_P (var) = 1; + + /* Tell the RTL layer that this pointer can alias + anything. */ + DECL_POINTER_ALIAS_SET (var) = 0; + } + } + } + } +} + /* Create points-to sets for the current function. See the comments at the start of the file for an algorithmic overview. */ @@ -4948,7 +5118,7 @@ compute_points_to_sets (struct alias_info *ai) } } - for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + for (bsi = bsi_start (bb); !bsi_end_p (bsi); ) { tree stmt = bsi_stmt (bsi); @@ -4959,6 +5129,13 @@ compute_points_to_sets (struct alias_info *ai) This is used when creating name tags and alias sets. */ update_alias_info (stmt, ai); + + /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now + been captured, and we can remove them. */ + if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR) + bsi_remove (&bsi, true); + else + bsi_next (&bsi); } } @@ -4991,6 +5168,8 @@ compute_points_to_sets (struct alias_info *ai) solve_graph (graph); + compute_tbaa_pruning (); + if (dump_file) dump_sa_points_to_info (dump_file); have_alias_info = true; diff --git a/contrib/gcc/tree.def b/contrib/gcc/tree.def index d3106a1fcb4d..966b834839f7 100644 --- a/contrib/gcc/tree.def +++ b/contrib/gcc/tree.def @@ -1,7 +1,7 @@ /* This file contains the definitions and documentation for the tree codes used in GCC. Copyright (C) 1987, 1988, 1993, 1995, 1997, 1998, 2000, 2001, 2004, 2005, - 2006 Free Software Foundation, Inc. + 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -880,6 +880,15 @@ DEFTREECODE (CATCH_EXPR, "catch_expr", tcc_statement, 2) expanding. */ DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", tcc_statement, 2) +/* Indicates a change in the dynamic type of a memory location. This + has no value and generates no executable code. It is only used for + type based alias analysis. This is generated by C++ placement new. + CHANGE_DYNAMIC_TYPE_NEW_TYPE, the first operand, is the new type. + CHNAGE_DYNAMIC_TYPE_LOCATION, the second operand, is the location + whose type is being changed. */ +DEFTREECODE (CHANGE_DYNAMIC_TYPE_EXPR, "change_dynamic_type_expr", + tcc_statement, 2) + /* Node used for describing a property that is known at compile time. */ DEFTREECODE (SCEV_KNOWN, "scev_known", tcc_expression, 0) diff --git a/contrib/gcc/tree.h b/contrib/gcc/tree.h index 6cfc3d375ccb..3c50f969d9e1 100644 --- a/contrib/gcc/tree.h +++ b/contrib/gcc/tree.h @@ -1548,6 +1548,12 @@ struct tree_constructor GTY(()) #define EH_FILTER_FAILURE(NODE) TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 1) #define EH_FILTER_MUST_NOT_THROW(NODE) TREE_STATIC (EH_FILTER_EXPR_CHECK (NODE)) +/* CHANGE_DYNAMIC_TYPE_EXPR accessors. */ +#define CHANGE_DYNAMIC_TYPE_NEW_TYPE(NODE) \ + TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 0) +#define CHANGE_DYNAMIC_TYPE_LOCATION(NODE) \ + TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 1) + /* OBJ_TYPE_REF accessors. */ #define OBJ_TYPE_REF_EXPR(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 0) #define OBJ_TYPE_REF_OBJECT(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 1) @@ -2538,6 +2544,11 @@ struct tree_struct_field_tag GTY(()) #define DECL_CALL_CLOBBERED(DECL) \ DECL_COMMON_CHECK (DECL)->decl_common.call_clobbered_flag +/* For a DECL with pointer type, this is set if Type Based Alias + Analysis should not be applied to this DECL. */ +#define DECL_NO_TBAA_P(DECL) \ + DECL_COMMON_CHECK (DECL)->decl_common.no_tbaa_flag + struct tree_decl_common GTY(()) { struct tree_decl_minimal common; @@ -2579,6 +2590,8 @@ struct tree_decl_common GTY(()) parm decl. */ unsigned gimple_reg_flag : 1; unsigned call_clobbered_flag : 1; + /* In a DECL with pointer type, set if no TBAA should be done. */ + unsigned no_tbaa_flag : 1; unsigned int align : 24; /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */ From fd093921ed26bbe5401670e5ba85b4c92aa9a8c6 Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Thu, 19 Dec 2013 20:15:49 +0000 Subject: [PATCH 168/172] Vendor import of tzdata2013i: Removed support for solar-time-based time zones Jordan stays at summer time this year. Fix historical data for Cuba Obtained from: ftp://ftp.iana.org/tz/releases/ --- asia | 30 ++-- northamerica | 8 +- solar87 | 390 -------------------------------------------------- solar88 | 390 -------------------------------------------------- solar89 | 395 --------------------------------------------------- 5 files changed, 28 insertions(+), 1185 deletions(-) delete mode 100644 solar87 delete mode 100644 solar88 delete mode 100644 solar89 diff --git a/asia b/asia index 580a179776a0..2867e643c61c 100644 --- a/asia +++ b/asia @@ -1380,12 +1380,22 @@ Zone Asia/Tokyo 9:18:59 - LMT 1887 Dec 31 15:00u # switch back to standard time this winter, so the will stay on DST # until about the same time next year (at least). # http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?NewsID=88950 -# -# From Paul Eggert (2013-09-21): -# It's looking like this change will be permanent; see -# Petra News Agency, Cancelling winter saved Jordan $7 million (2013-02-20) -# . -# So move Jordan to UTC+3 as of the abovementioned date. + +# From Steffen Thorsen (2013-12-11): +# Jordan Times and other sources say that Jordan is going back to +# UTC+2 on 2013-12-19 at midnight: +# http://jordantimes.com/govt-decides-to-switch-back-to-wintertime +# Official, in Arabic: +# http://www.petra.gov.jo/public_news/Nws_NewsDetails.aspx?Menu_ID=&Site_Id=2&lang=1&NewsID=133230&CatID=14 +# ... Our background/permalink about it +# http://www.timeanddate.com/news/time/jordan-reverses-dst-decision.html +# ... +# http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?lang=2&site_id=1&NewsID=133313&Type=P +# ... says midnight for the coming one and 1:00 for the ones in the future +# (and they will use DST again next year, using the normal schedule). + +# From Paul Eggert (2013-12-11): +# As Steffen suggested, consider the past 21-month experiment to be DST. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Jordan 1973 only - Jun 6 0:00 1:00 S @@ -1415,11 +1425,13 @@ Rule Jordan 2002 2012 - Mar lastThu 24:00 1:00 S Rule Jordan 2003 only - Oct 24 0:00s 0 - Rule Jordan 2004 only - Oct 15 0:00s 0 - Rule Jordan 2005 only - Sep lastFri 0:00s 0 - -Rule Jordan 2006 2012 - Oct lastFri 0:00s 0 - +Rule Jordan 2006 2011 - Oct lastFri 0:00s 0 - +Rule Jordan 2013 only - Dec 20 0:00 0 - +Rule Jordan 2014 max - Mar lastThu 24:00 1:00 S +Rule Jordan 2014 max - Oct lastFri 0:00s 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Amman 2:23:44 - LMT 1931 - 2:00 Jordan EE%sT 2012 Oct 26 0:00s - 3:00 - AST + 2:00 Jordan EE%sT # Kazakhstan diff --git a/northamerica b/northamerica index c3921d3857a0..83c521b83092 100644 --- a/northamerica +++ b/northamerica @@ -2665,6 +2665,11 @@ Zone America/Costa_Rica -5:36:13 - LMT 1890 # San Jose # to DST--and one more hour on 1999-04-04--when the announcers will have # returned to Baltimore, which switches on that date.) +# From Steffen Thorsen (2013-11-11): +# DST start in Cuba in 2004 ... does not follow the same rules as the +# years before. The correct date should be Sunday 2004-03-28 00:00 ... +# https://web.archive.org/web/20040402060750/http://www.granma.cu/espanol/2004/marzo/sab27/reloj.html + # From Evert van der Veer via Steffen Thorsen (2004-10-28): # Cuba is not going back to standard time this year. # From Paul Eggert (2006-03-22): @@ -2854,7 +2859,8 @@ Rule Cuba 1996 only - Oct 6 0:00s 0 S Rule Cuba 1997 only - Oct 12 0:00s 0 S Rule Cuba 1998 1999 - Mar lastSun 0:00s 1:00 D Rule Cuba 1998 2003 - Oct lastSun 0:00s 0 S -Rule Cuba 2000 2004 - Apr Sun>=1 0:00s 1:00 D +Rule Cuba 2000 2003 - Apr Sun>=1 0:00s 1:00 D +Rule Cuba 2004 only - Mar lastSun 0:00s 1:00 D Rule Cuba 2006 2010 - Oct lastSun 0:00s 0 S Rule Cuba 2007 only - Mar Sun>=8 0:00s 1:00 D Rule Cuba 2008 only - Mar Sun>=15 0:00s 1:00 D diff --git a/solar87 b/solar87 deleted file mode 100644 index 2299558164c5..000000000000 --- a/solar87 +++ /dev/null @@ -1,390 +0,0 @@ -#
-# This file is in the public domain, so clarified as of
-# 2009-05-17 by Arthur David Olson.
-
-# So much for footnotes about Saudi Arabia.
-# Apparent noon times below are for Riyadh; your mileage will vary.
-# Times were computed using formulas in the U.S. Naval Observatory's
-# Almanac for Computers 1987; the formulas "will give EqT to an accuracy of
-# [plus or minus two] seconds during the current year."
-#
-# Rounding to the nearest five seconds results in fewer than
-# 256 different "time types"--a limit that's faced because time types are
-# stored on disk as unsigned chars.
-
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	sol87	1987	only	-	Jan	1	12:03:20s -0:03:20 -
-Rule	sol87	1987	only	-	Jan	2	12:03:50s -0:03:50 -
-Rule	sol87	1987	only	-	Jan	3	12:04:15s -0:04:15 -
-Rule	sol87	1987	only	-	Jan	4	12:04:45s -0:04:45 -
-Rule	sol87	1987	only	-	Jan	5	12:05:10s -0:05:10 -
-Rule	sol87	1987	only	-	Jan	6	12:05:40s -0:05:40 -
-Rule	sol87	1987	only	-	Jan	7	12:06:05s -0:06:05 -
-Rule	sol87	1987	only	-	Jan	8	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Jan	9	12:06:55s -0:06:55 -
-Rule	sol87	1987	only	-	Jan	10	12:07:20s -0:07:20 -
-Rule	sol87	1987	only	-	Jan	11	12:07:45s -0:07:45 -
-Rule	sol87	1987	only	-	Jan	12	12:08:10s -0:08:10 -
-Rule	sol87	1987	only	-	Jan	13	12:08:30s -0:08:30 -
-Rule	sol87	1987	only	-	Jan	14	12:08:55s -0:08:55 -
-Rule	sol87	1987	only	-	Jan	15	12:09:15s -0:09:15 -
-Rule	sol87	1987	only	-	Jan	16	12:09:35s -0:09:35 -
-Rule	sol87	1987	only	-	Jan	17	12:09:55s -0:09:55 -
-Rule	sol87	1987	only	-	Jan	18	12:10:15s -0:10:15 -
-Rule	sol87	1987	only	-	Jan	19	12:10:35s -0:10:35 -
-Rule	sol87	1987	only	-	Jan	20	12:10:55s -0:10:55 -
-Rule	sol87	1987	only	-	Jan	21	12:11:10s -0:11:10 -
-Rule	sol87	1987	only	-	Jan	22	12:11:30s -0:11:30 -
-Rule	sol87	1987	only	-	Jan	23	12:11:45s -0:11:45 -
-Rule	sol87	1987	only	-	Jan	24	12:12:00s -0:12:00 -
-Rule	sol87	1987	only	-	Jan	25	12:12:15s -0:12:15 -
-Rule	sol87	1987	only	-	Jan	26	12:12:30s -0:12:30 -
-Rule	sol87	1987	only	-	Jan	27	12:12:40s -0:12:40 -
-Rule	sol87	1987	only	-	Jan	28	12:12:55s -0:12:55 -
-Rule	sol87	1987	only	-	Jan	29	12:13:05s -0:13:05 -
-Rule	sol87	1987	only	-	Jan	30	12:13:15s -0:13:15 -
-Rule	sol87	1987	only	-	Jan	31	12:13:25s -0:13:25 -
-Rule	sol87	1987	only	-	Feb	1	12:13:35s -0:13:35 -
-Rule	sol87	1987	only	-	Feb	2	12:13:40s -0:13:40 -
-Rule	sol87	1987	only	-	Feb	3	12:13:50s -0:13:50 -
-Rule	sol87	1987	only	-	Feb	4	12:13:55s -0:13:55 -
-Rule	sol87	1987	only	-	Feb	5	12:14:00s -0:14:00 -
-Rule	sol87	1987	only	-	Feb	6	12:14:05s -0:14:05 -
-Rule	sol87	1987	only	-	Feb	7	12:14:10s -0:14:10 -
-Rule	sol87	1987	only	-	Feb	8	12:14:10s -0:14:10 -
-Rule	sol87	1987	only	-	Feb	9	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	10	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	11	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	12	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	13	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	14	12:14:15s -0:14:15 -
-Rule	sol87	1987	only	-	Feb	15	12:14:10s -0:14:10 -
-Rule	sol87	1987	only	-	Feb	16	12:14:10s -0:14:10 -
-Rule	sol87	1987	only	-	Feb	17	12:14:05s -0:14:05 -
-Rule	sol87	1987	only	-	Feb	18	12:14:00s -0:14:00 -
-Rule	sol87	1987	only	-	Feb	19	12:13:55s -0:13:55 -
-Rule	sol87	1987	only	-	Feb	20	12:13:50s -0:13:50 -
-Rule	sol87	1987	only	-	Feb	21	12:13:45s -0:13:45 -
-Rule	sol87	1987	only	-	Feb	22	12:13:35s -0:13:35 -
-Rule	sol87	1987	only	-	Feb	23	12:13:30s -0:13:30 -
-Rule	sol87	1987	only	-	Feb	24	12:13:20s -0:13:20 -
-Rule	sol87	1987	only	-	Feb	25	12:13:10s -0:13:10 -
-Rule	sol87	1987	only	-	Feb	26	12:13:00s -0:13:00 -
-Rule	sol87	1987	only	-	Feb	27	12:12:50s -0:12:50 -
-Rule	sol87	1987	only	-	Feb	28	12:12:40s -0:12:40 -
-Rule	sol87	1987	only	-	Mar	1	12:12:30s -0:12:30 -
-Rule	sol87	1987	only	-	Mar	2	12:12:20s -0:12:20 -
-Rule	sol87	1987	only	-	Mar	3	12:12:05s -0:12:05 -
-Rule	sol87	1987	only	-	Mar	4	12:11:55s -0:11:55 -
-Rule	sol87	1987	only	-	Mar	5	12:11:40s -0:11:40 -
-Rule	sol87	1987	only	-	Mar	6	12:11:25s -0:11:25 -
-Rule	sol87	1987	only	-	Mar	7	12:11:15s -0:11:15 -
-Rule	sol87	1987	only	-	Mar	8	12:11:00s -0:11:00 -
-Rule	sol87	1987	only	-	Mar	9	12:10:45s -0:10:45 -
-Rule	sol87	1987	only	-	Mar	10	12:10:30s -0:10:30 -
-Rule	sol87	1987	only	-	Mar	11	12:10:15s -0:10:15 -
-Rule	sol87	1987	only	-	Mar	12	12:09:55s -0:09:55 -
-Rule	sol87	1987	only	-	Mar	13	12:09:40s -0:09:40 -
-Rule	sol87	1987	only	-	Mar	14	12:09:25s -0:09:25 -
-Rule	sol87	1987	only	-	Mar	15	12:09:10s -0:09:10 -
-Rule	sol87	1987	only	-	Mar	16	12:08:50s -0:08:50 -
-Rule	sol87	1987	only	-	Mar	17	12:08:35s -0:08:35 -
-Rule	sol87	1987	only	-	Mar	18	12:08:15s -0:08:15 -
-Rule	sol87	1987	only	-	Mar	19	12:08:00s -0:08:00 -
-Rule	sol87	1987	only	-	Mar	20	12:07:40s -0:07:40 -
-Rule	sol87	1987	only	-	Mar	21	12:07:25s -0:07:25 -
-Rule	sol87	1987	only	-	Mar	22	12:07:05s -0:07:05 -
-Rule	sol87	1987	only	-	Mar	23	12:06:50s -0:06:50 -
-Rule	sol87	1987	only	-	Mar	24	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Mar	25	12:06:10s -0:06:10 -
-Rule	sol87	1987	only	-	Mar	26	12:05:55s -0:05:55 -
-Rule	sol87	1987	only	-	Mar	27	12:05:35s -0:05:35 -
-Rule	sol87	1987	only	-	Mar	28	12:05:15s -0:05:15 -
-Rule	sol87	1987	only	-	Mar	29	12:05:00s -0:05:00 -
-Rule	sol87	1987	only	-	Mar	30	12:04:40s -0:04:40 -
-Rule	sol87	1987	only	-	Mar	31	12:04:25s -0:04:25 -
-Rule	sol87	1987	only	-	Apr	1	12:04:05s -0:04:05 -
-Rule	sol87	1987	only	-	Apr	2	12:03:45s -0:03:45 -
-Rule	sol87	1987	only	-	Apr	3	12:03:30s -0:03:30 -
-Rule	sol87	1987	only	-	Apr	4	12:03:10s -0:03:10 -
-Rule	sol87	1987	only	-	Apr	5	12:02:55s -0:02:55 -
-Rule	sol87	1987	only	-	Apr	6	12:02:35s -0:02:35 -
-Rule	sol87	1987	only	-	Apr	7	12:02:20s -0:02:20 -
-Rule	sol87	1987	only	-	Apr	8	12:02:05s -0:02:05 -
-Rule	sol87	1987	only	-	Apr	9	12:01:45s -0:01:45 -
-Rule	sol87	1987	only	-	Apr	10	12:01:30s -0:01:30 -
-Rule	sol87	1987	only	-	Apr	11	12:01:15s -0:01:15 -
-Rule	sol87	1987	only	-	Apr	12	12:00:55s -0:00:55 -
-Rule	sol87	1987	only	-	Apr	13	12:00:40s -0:00:40 -
-Rule	sol87	1987	only	-	Apr	14	12:00:25s -0:00:25 -
-Rule	sol87	1987	only	-	Apr	15	12:00:10s -0:00:10 -
-Rule	sol87	1987	only	-	Apr	16	11:59:55s 0:00:05 -
-Rule	sol87	1987	only	-	Apr	17	11:59:45s 0:00:15 -
-Rule	sol87	1987	only	-	Apr	18	11:59:30s 0:00:30 -
-Rule	sol87	1987	only	-	Apr	19	11:59:15s 0:00:45 -
-Rule	sol87	1987	only	-	Apr	20	11:59:05s 0:00:55 -
-Rule	sol87	1987	only	-	Apr	21	11:58:50s 0:01:10 -
-Rule	sol87	1987	only	-	Apr	22	11:58:40s 0:01:20 -
-Rule	sol87	1987	only	-	Apr	23	11:58:25s 0:01:35 -
-Rule	sol87	1987	only	-	Apr	24	11:58:15s 0:01:45 -
-Rule	sol87	1987	only	-	Apr	25	11:58:05s 0:01:55 -
-Rule	sol87	1987	only	-	Apr	26	11:57:55s 0:02:05 -
-Rule	sol87	1987	only	-	Apr	27	11:57:45s 0:02:15 -
-Rule	sol87	1987	only	-	Apr	28	11:57:35s 0:02:25 -
-Rule	sol87	1987	only	-	Apr	29	11:57:25s 0:02:35 -
-Rule	sol87	1987	only	-	Apr	30	11:57:15s 0:02:45 -
-Rule	sol87	1987	only	-	May	1	11:57:10s 0:02:50 -
-Rule	sol87	1987	only	-	May	2	11:57:00s 0:03:00 -
-Rule	sol87	1987	only	-	May	3	11:56:55s 0:03:05 -
-Rule	sol87	1987	only	-	May	4	11:56:50s 0:03:10 -
-Rule	sol87	1987	only	-	May	5	11:56:45s 0:03:15 -
-Rule	sol87	1987	only	-	May	6	11:56:40s 0:03:20 -
-Rule	sol87	1987	only	-	May	7	11:56:35s 0:03:25 -
-Rule	sol87	1987	only	-	May	8	11:56:30s 0:03:30 -
-Rule	sol87	1987	only	-	May	9	11:56:25s 0:03:35 -
-Rule	sol87	1987	only	-	May	10	11:56:25s 0:03:35 -
-Rule	sol87	1987	only	-	May	11	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	12	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	13	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	14	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	15	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	16	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	17	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	18	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	May	19	11:56:25s 0:03:35 -
-Rule	sol87	1987	only	-	May	20	11:56:25s 0:03:35 -
-Rule	sol87	1987	only	-	May	21	11:56:30s 0:03:30 -
-Rule	sol87	1987	only	-	May	22	11:56:35s 0:03:25 -
-Rule	sol87	1987	only	-	May	23	11:56:40s 0:03:20 -
-Rule	sol87	1987	only	-	May	24	11:56:45s 0:03:15 -
-Rule	sol87	1987	only	-	May	25	11:56:50s 0:03:10 -
-Rule	sol87	1987	only	-	May	26	11:56:55s 0:03:05 -
-Rule	sol87	1987	only	-	May	27	11:57:00s 0:03:00 -
-Rule	sol87	1987	only	-	May	28	11:57:10s 0:02:50 -
-Rule	sol87	1987	only	-	May	29	11:57:15s 0:02:45 -
-Rule	sol87	1987	only	-	May	30	11:57:25s 0:02:35 -
-Rule	sol87	1987	only	-	May	31	11:57:30s 0:02:30 -
-Rule	sol87	1987	only	-	Jun	1	11:57:40s 0:02:20 -
-Rule	sol87	1987	only	-	Jun	2	11:57:50s 0:02:10 -
-Rule	sol87	1987	only	-	Jun	3	11:58:00s 0:02:00 -
-Rule	sol87	1987	only	-	Jun	4	11:58:10s 0:01:50 -
-Rule	sol87	1987	only	-	Jun	5	11:58:20s 0:01:40 -
-Rule	sol87	1987	only	-	Jun	6	11:58:30s 0:01:30 -
-Rule	sol87	1987	only	-	Jun	7	11:58:40s 0:01:20 -
-Rule	sol87	1987	only	-	Jun	8	11:58:50s 0:01:10 -
-Rule	sol87	1987	only	-	Jun	9	11:59:05s 0:00:55 -
-Rule	sol87	1987	only	-	Jun	10	11:59:15s 0:00:45 -
-Rule	sol87	1987	only	-	Jun	11	11:59:30s 0:00:30 -
-Rule	sol87	1987	only	-	Jun	12	11:59:40s 0:00:20 -
-Rule	sol87	1987	only	-	Jun	13	11:59:50s 0:00:10 -
-Rule	sol87	1987	only	-	Jun	14	12:00:05s -0:00:05 -
-Rule	sol87	1987	only	-	Jun	15	12:00:15s -0:00:15 -
-Rule	sol87	1987	only	-	Jun	16	12:00:30s -0:00:30 -
-Rule	sol87	1987	only	-	Jun	17	12:00:45s -0:00:45 -
-Rule	sol87	1987	only	-	Jun	18	12:00:55s -0:00:55 -
-Rule	sol87	1987	only	-	Jun	19	12:01:10s -0:01:10 -
-Rule	sol87	1987	only	-	Jun	20	12:01:20s -0:01:20 -
-Rule	sol87	1987	only	-	Jun	21	12:01:35s -0:01:35 -
-Rule	sol87	1987	only	-	Jun	22	12:01:50s -0:01:50 -
-Rule	sol87	1987	only	-	Jun	23	12:02:00s -0:02:00 -
-Rule	sol87	1987	only	-	Jun	24	12:02:15s -0:02:15 -
-Rule	sol87	1987	only	-	Jun	25	12:02:25s -0:02:25 -
-Rule	sol87	1987	only	-	Jun	26	12:02:40s -0:02:40 -
-Rule	sol87	1987	only	-	Jun	27	12:02:50s -0:02:50 -
-Rule	sol87	1987	only	-	Jun	28	12:03:05s -0:03:05 -
-Rule	sol87	1987	only	-	Jun	29	12:03:15s -0:03:15 -
-Rule	sol87	1987	only	-	Jun	30	12:03:30s -0:03:30 -
-Rule	sol87	1987	only	-	Jul	1	12:03:40s -0:03:40 -
-Rule	sol87	1987	only	-	Jul	2	12:03:50s -0:03:50 -
-Rule	sol87	1987	only	-	Jul	3	12:04:05s -0:04:05 -
-Rule	sol87	1987	only	-	Jul	4	12:04:15s -0:04:15 -
-Rule	sol87	1987	only	-	Jul	5	12:04:25s -0:04:25 -
-Rule	sol87	1987	only	-	Jul	6	12:04:35s -0:04:35 -
-Rule	sol87	1987	only	-	Jul	7	12:04:45s -0:04:45 -
-Rule	sol87	1987	only	-	Jul	8	12:04:55s -0:04:55 -
-Rule	sol87	1987	only	-	Jul	9	12:05:05s -0:05:05 -
-Rule	sol87	1987	only	-	Jul	10	12:05:15s -0:05:15 -
-Rule	sol87	1987	only	-	Jul	11	12:05:20s -0:05:20 -
-Rule	sol87	1987	only	-	Jul	12	12:05:30s -0:05:30 -
-Rule	sol87	1987	only	-	Jul	13	12:05:40s -0:05:40 -
-Rule	sol87	1987	only	-	Jul	14	12:05:45s -0:05:45 -
-Rule	sol87	1987	only	-	Jul	15	12:05:50s -0:05:50 -
-Rule	sol87	1987	only	-	Jul	16	12:06:00s -0:06:00 -
-Rule	sol87	1987	only	-	Jul	17	12:06:05s -0:06:05 -
-Rule	sol87	1987	only	-	Jul	18	12:06:10s -0:06:10 -
-Rule	sol87	1987	only	-	Jul	19	12:06:15s -0:06:15 -
-Rule	sol87	1987	only	-	Jul	20	12:06:15s -0:06:15 -
-Rule	sol87	1987	only	-	Jul	21	12:06:20s -0:06:20 -
-Rule	sol87	1987	only	-	Jul	22	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Jul	23	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Jul	24	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Jul	25	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Jul	26	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Jul	27	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Jul	28	12:06:30s -0:06:30 -
-Rule	sol87	1987	only	-	Jul	29	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Jul	30	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Jul	31	12:06:25s -0:06:25 -
-Rule	sol87	1987	only	-	Aug	1	12:06:20s -0:06:20 -
-Rule	sol87	1987	only	-	Aug	2	12:06:15s -0:06:15 -
-Rule	sol87	1987	only	-	Aug	3	12:06:10s -0:06:10 -
-Rule	sol87	1987	only	-	Aug	4	12:06:05s -0:06:05 -
-Rule	sol87	1987	only	-	Aug	5	12:06:00s -0:06:00 -
-Rule	sol87	1987	only	-	Aug	6	12:05:55s -0:05:55 -
-Rule	sol87	1987	only	-	Aug	7	12:05:50s -0:05:50 -
-Rule	sol87	1987	only	-	Aug	8	12:05:40s -0:05:40 -
-Rule	sol87	1987	only	-	Aug	9	12:05:35s -0:05:35 -
-Rule	sol87	1987	only	-	Aug	10	12:05:25s -0:05:25 -
-Rule	sol87	1987	only	-	Aug	11	12:05:15s -0:05:15 -
-Rule	sol87	1987	only	-	Aug	12	12:05:05s -0:05:05 -
-Rule	sol87	1987	only	-	Aug	13	12:04:55s -0:04:55 -
-Rule	sol87	1987	only	-	Aug	14	12:04:45s -0:04:45 -
-Rule	sol87	1987	only	-	Aug	15	12:04:35s -0:04:35 -
-Rule	sol87	1987	only	-	Aug	16	12:04:25s -0:04:25 -
-Rule	sol87	1987	only	-	Aug	17	12:04:10s -0:04:10 -
-Rule	sol87	1987	only	-	Aug	18	12:04:00s -0:04:00 -
-Rule	sol87	1987	only	-	Aug	19	12:03:45s -0:03:45 -
-Rule	sol87	1987	only	-	Aug	20	12:03:30s -0:03:30 -
-Rule	sol87	1987	only	-	Aug	21	12:03:15s -0:03:15 -
-Rule	sol87	1987	only	-	Aug	22	12:03:00s -0:03:00 -
-Rule	sol87	1987	only	-	Aug	23	12:02:45s -0:02:45 -
-Rule	sol87	1987	only	-	Aug	24	12:02:30s -0:02:30 -
-Rule	sol87	1987	only	-	Aug	25	12:02:15s -0:02:15 -
-Rule	sol87	1987	only	-	Aug	26	12:02:00s -0:02:00 -
-Rule	sol87	1987	only	-	Aug	27	12:01:40s -0:01:40 -
-Rule	sol87	1987	only	-	Aug	28	12:01:25s -0:01:25 -
-Rule	sol87	1987	only	-	Aug	29	12:01:05s -0:01:05 -
-Rule	sol87	1987	only	-	Aug	30	12:00:50s -0:00:50 -
-Rule	sol87	1987	only	-	Aug	31	12:00:30s -0:00:30 -
-Rule	sol87	1987	only	-	Sep	1	12:00:10s -0:00:10 -
-Rule	sol87	1987	only	-	Sep	2	11:59:50s 0:00:10 -
-Rule	sol87	1987	only	-	Sep	3	11:59:35s 0:00:25 -
-Rule	sol87	1987	only	-	Sep	4	11:59:15s 0:00:45 -
-Rule	sol87	1987	only	-	Sep	5	11:58:55s 0:01:05 -
-Rule	sol87	1987	only	-	Sep	6	11:58:35s 0:01:25 -
-Rule	sol87	1987	only	-	Sep	7	11:58:15s 0:01:45 -
-Rule	sol87	1987	only	-	Sep	8	11:57:55s 0:02:05 -
-Rule	sol87	1987	only	-	Sep	9	11:57:30s 0:02:30 -
-Rule	sol87	1987	only	-	Sep	10	11:57:10s 0:02:50 -
-Rule	sol87	1987	only	-	Sep	11	11:56:50s 0:03:10 -
-Rule	sol87	1987	only	-	Sep	12	11:56:30s 0:03:30 -
-Rule	sol87	1987	only	-	Sep	13	11:56:10s 0:03:50 -
-Rule	sol87	1987	only	-	Sep	14	11:55:45s 0:04:15 -
-Rule	sol87	1987	only	-	Sep	15	11:55:25s 0:04:35 -
-Rule	sol87	1987	only	-	Sep	16	11:55:05s 0:04:55 -
-Rule	sol87	1987	only	-	Sep	17	11:54:45s 0:05:15 -
-Rule	sol87	1987	only	-	Sep	18	11:54:20s 0:05:40 -
-Rule	sol87	1987	only	-	Sep	19	11:54:00s 0:06:00 -
-Rule	sol87	1987	only	-	Sep	20	11:53:40s 0:06:20 -
-Rule	sol87	1987	only	-	Sep	21	11:53:15s 0:06:45 -
-Rule	sol87	1987	only	-	Sep	22	11:52:55s 0:07:05 -
-Rule	sol87	1987	only	-	Sep	23	11:52:35s 0:07:25 -
-Rule	sol87	1987	only	-	Sep	24	11:52:15s 0:07:45 -
-Rule	sol87	1987	only	-	Sep	25	11:51:55s 0:08:05 -
-Rule	sol87	1987	only	-	Sep	26	11:51:35s 0:08:25 -
-Rule	sol87	1987	only	-	Sep	27	11:51:10s 0:08:50 -
-Rule	sol87	1987	only	-	Sep	28	11:50:50s 0:09:10 -
-Rule	sol87	1987	only	-	Sep	29	11:50:30s 0:09:30 -
-Rule	sol87	1987	only	-	Sep	30	11:50:10s 0:09:50 -
-Rule	sol87	1987	only	-	Oct	1	11:49:50s 0:10:10 -
-Rule	sol87	1987	only	-	Oct	2	11:49:35s 0:10:25 -
-Rule	sol87	1987	only	-	Oct	3	11:49:15s 0:10:45 -
-Rule	sol87	1987	only	-	Oct	4	11:48:55s 0:11:05 -
-Rule	sol87	1987	only	-	Oct	5	11:48:35s 0:11:25 -
-Rule	sol87	1987	only	-	Oct	6	11:48:20s 0:11:40 -
-Rule	sol87	1987	only	-	Oct	7	11:48:00s 0:12:00 -
-Rule	sol87	1987	only	-	Oct	8	11:47:45s 0:12:15 -
-Rule	sol87	1987	only	-	Oct	9	11:47:25s 0:12:35 -
-Rule	sol87	1987	only	-	Oct	10	11:47:10s 0:12:50 -
-Rule	sol87	1987	only	-	Oct	11	11:46:55s 0:13:05 -
-Rule	sol87	1987	only	-	Oct	12	11:46:40s 0:13:20 -
-Rule	sol87	1987	only	-	Oct	13	11:46:25s 0:13:35 -
-Rule	sol87	1987	only	-	Oct	14	11:46:10s 0:13:50 -
-Rule	sol87	1987	only	-	Oct	15	11:45:55s 0:14:05 -
-Rule	sol87	1987	only	-	Oct	16	11:45:45s 0:14:15 -
-Rule	sol87	1987	only	-	Oct	17	11:45:30s 0:14:30 -
-Rule	sol87	1987	only	-	Oct	18	11:45:20s 0:14:40 -
-Rule	sol87	1987	only	-	Oct	19	11:45:05s 0:14:55 -
-Rule	sol87	1987	only	-	Oct	20	11:44:55s 0:15:05 -
-Rule	sol87	1987	only	-	Oct	21	11:44:45s 0:15:15 -
-Rule	sol87	1987	only	-	Oct	22	11:44:35s 0:15:25 -
-Rule	sol87	1987	only	-	Oct	23	11:44:25s 0:15:35 -
-Rule	sol87	1987	only	-	Oct	24	11:44:20s 0:15:40 -
-Rule	sol87	1987	only	-	Oct	25	11:44:10s 0:15:50 -
-Rule	sol87	1987	only	-	Oct	26	11:44:05s 0:15:55 -
-Rule	sol87	1987	only	-	Oct	27	11:43:55s 0:16:05 -
-Rule	sol87	1987	only	-	Oct	28	11:43:50s 0:16:10 -
-Rule	sol87	1987	only	-	Oct	29	11:43:45s 0:16:15 -
-Rule	sol87	1987	only	-	Oct	30	11:43:45s 0:16:15 -
-Rule	sol87	1987	only	-	Oct	31	11:43:40s 0:16:20 -
-Rule	sol87	1987	only	-	Nov	1	11:43:40s 0:16:20 -
-Rule	sol87	1987	only	-	Nov	2	11:43:35s 0:16:25 -
-Rule	sol87	1987	only	-	Nov	3	11:43:35s 0:16:25 -
-Rule	sol87	1987	only	-	Nov	4	11:43:35s 0:16:25 -
-Rule	sol87	1987	only	-	Nov	5	11:43:35s 0:16:25 -
-Rule	sol87	1987	only	-	Nov	6	11:43:40s 0:16:20 -
-Rule	sol87	1987	only	-	Nov	7	11:43:40s 0:16:20 -
-Rule	sol87	1987	only	-	Nov	8	11:43:45s 0:16:15 -
-Rule	sol87	1987	only	-	Nov	9	11:43:50s 0:16:10 -
-Rule	sol87	1987	only	-	Nov	10	11:43:55s 0:16:05 -
-Rule	sol87	1987	only	-	Nov	11	11:44:00s 0:16:00 -
-Rule	sol87	1987	only	-	Nov	12	11:44:05s 0:15:55 -
-Rule	sol87	1987	only	-	Nov	13	11:44:15s 0:15:45 -
-Rule	sol87	1987	only	-	Nov	14	11:44:20s 0:15:40 -
-Rule	sol87	1987	only	-	Nov	15	11:44:30s 0:15:30 -
-Rule	sol87	1987	only	-	Nov	16	11:44:40s 0:15:20 -
-Rule	sol87	1987	only	-	Nov	17	11:44:50s 0:15:10 -
-Rule	sol87	1987	only	-	Nov	18	11:45:05s 0:14:55 -
-Rule	sol87	1987	only	-	Nov	19	11:45:15s 0:14:45 -
-Rule	sol87	1987	only	-	Nov	20	11:45:30s 0:14:30 -
-Rule	sol87	1987	only	-	Nov	21	11:45:45s 0:14:15 -
-Rule	sol87	1987	only	-	Nov	22	11:46:00s 0:14:00 -
-Rule	sol87	1987	only	-	Nov	23	11:46:15s 0:13:45 -
-Rule	sol87	1987	only	-	Nov	24	11:46:30s 0:13:30 -
-Rule	sol87	1987	only	-	Nov	25	11:46:50s 0:13:10 -
-Rule	sol87	1987	only	-	Nov	26	11:47:10s 0:12:50 -
-Rule	sol87	1987	only	-	Nov	27	11:47:25s 0:12:35 -
-Rule	sol87	1987	only	-	Nov	28	11:47:45s 0:12:15 -
-Rule	sol87	1987	only	-	Nov	29	11:48:05s 0:11:55 -
-Rule	sol87	1987	only	-	Nov	30	11:48:30s 0:11:30 -
-Rule	sol87	1987	only	-	Dec	1	11:48:50s 0:11:10 -
-Rule	sol87	1987	only	-	Dec	2	11:49:10s 0:10:50 -
-Rule	sol87	1987	only	-	Dec	3	11:49:35s 0:10:25 -
-Rule	sol87	1987	only	-	Dec	4	11:50:00s 0:10:00 -
-Rule	sol87	1987	only	-	Dec	5	11:50:25s 0:09:35 -
-Rule	sol87	1987	only	-	Dec	6	11:50:50s 0:09:10 -
-Rule	sol87	1987	only	-	Dec	7	11:51:15s 0:08:45 -
-Rule	sol87	1987	only	-	Dec	8	11:51:40s 0:08:20 -
-Rule	sol87	1987	only	-	Dec	9	11:52:05s 0:07:55 -
-Rule	sol87	1987	only	-	Dec	10	11:52:30s 0:07:30 -
-Rule	sol87	1987	only	-	Dec	11	11:53:00s 0:07:00 -
-Rule	sol87	1987	only	-	Dec	12	11:53:25s 0:06:35 -
-Rule	sol87	1987	only	-	Dec	13	11:53:55s 0:06:05 -
-Rule	sol87	1987	only	-	Dec	14	11:54:25s 0:05:35 -
-Rule	sol87	1987	only	-	Dec	15	11:54:50s 0:05:10 -
-Rule	sol87	1987	only	-	Dec	16	11:55:20s 0:04:40 -
-Rule	sol87	1987	only	-	Dec	17	11:55:50s 0:04:10 -
-Rule	sol87	1987	only	-	Dec	18	11:56:20s 0:03:40 -
-Rule	sol87	1987	only	-	Dec	19	11:56:50s 0:03:10 -
-Rule	sol87	1987	only	-	Dec	20	11:57:20s 0:02:40 -
-Rule	sol87	1987	only	-	Dec	21	11:57:50s 0:02:10 -
-Rule	sol87	1987	only	-	Dec	22	11:58:20s 0:01:40 -
-Rule	sol87	1987	only	-	Dec	23	11:58:50s 0:01:10 -
-Rule	sol87	1987	only	-	Dec	24	11:59:20s 0:00:40 -
-Rule	sol87	1987	only	-	Dec	25	11:59:50s 0:00:10 -
-Rule	sol87	1987	only	-	Dec	26	12:00:20s -0:00:20 -
-Rule	sol87	1987	only	-	Dec	27	12:00:45s -0:00:45 -
-Rule	sol87	1987	only	-	Dec	28	12:01:15s -0:01:15 -
-Rule	sol87	1987	only	-	Dec	29	12:01:45s -0:01:45 -
-Rule	sol87	1987	only	-	Dec	30	12:02:15s -0:02:15 -
-Rule	sol87	1987	only	-	Dec	31	12:02:45s -0:02:45 -
-
-# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
-# Before and after 1987, we'll operate on local mean solar time.
-
-# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
-Zone	Asia/Riyadh87	3:07:04	-		zzz	1987
-			3:07:04	sol87		zzz	1988
-			3:07:04	-		zzz
-# For backward compatibility...
-Link	Asia/Riyadh87	Mideast/Riyadh87
diff --git a/solar88 b/solar88
deleted file mode 100644
index bb1d6ca97faa..000000000000
--- a/solar88
+++ /dev/null
@@ -1,390 +0,0 @@
-# 
-# This file is in the public domain, so clarified as of
-# 2009-05-17 by Arthur David Olson.
-
-# Apparent noon times below are for Riyadh; they're a bit off for other places.
-# Times were computed using formulas in the U.S. Naval Observatory's
-# Almanac for Computers 1988; the formulas "will give EqT to an accuracy of
-# [plus or minus two] seconds during the current year."
-#
-# Rounding to the nearest five seconds results in fewer than
-# 256 different "time types"--a limit that's faced because time types are
-# stored on disk as unsigned chars.
-
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	sol88	1988	only	-	Jan	1	12:03:15s -0:03:15 -
-Rule	sol88	1988	only	-	Jan	2	12:03:40s -0:03:40 -
-Rule	sol88	1988	only	-	Jan	3	12:04:10s -0:04:10 -
-Rule	sol88	1988	only	-	Jan	4	12:04:40s -0:04:40 -
-Rule	sol88	1988	only	-	Jan	5	12:05:05s -0:05:05 -
-Rule	sol88	1988	only	-	Jan	6	12:05:30s -0:05:30 -
-Rule	sol88	1988	only	-	Jan	7	12:06:00s -0:06:00 -
-Rule	sol88	1988	only	-	Jan	8	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jan	9	12:06:50s -0:06:50 -
-Rule	sol88	1988	only	-	Jan	10	12:07:15s -0:07:15 -
-Rule	sol88	1988	only	-	Jan	11	12:07:40s -0:07:40 -
-Rule	sol88	1988	only	-	Jan	12	12:08:05s -0:08:05 -
-Rule	sol88	1988	only	-	Jan	13	12:08:25s -0:08:25 -
-Rule	sol88	1988	only	-	Jan	14	12:08:50s -0:08:50 -
-Rule	sol88	1988	only	-	Jan	15	12:09:10s -0:09:10 -
-Rule	sol88	1988	only	-	Jan	16	12:09:30s -0:09:30 -
-Rule	sol88	1988	only	-	Jan	17	12:09:50s -0:09:50 -
-Rule	sol88	1988	only	-	Jan	18	12:10:10s -0:10:10 -
-Rule	sol88	1988	only	-	Jan	19	12:10:30s -0:10:30 -
-Rule	sol88	1988	only	-	Jan	20	12:10:50s -0:10:50 -
-Rule	sol88	1988	only	-	Jan	21	12:11:05s -0:11:05 -
-Rule	sol88	1988	only	-	Jan	22	12:11:25s -0:11:25 -
-Rule	sol88	1988	only	-	Jan	23	12:11:40s -0:11:40 -
-Rule	sol88	1988	only	-	Jan	24	12:11:55s -0:11:55 -
-Rule	sol88	1988	only	-	Jan	25	12:12:10s -0:12:10 -
-Rule	sol88	1988	only	-	Jan	26	12:12:25s -0:12:25 -
-Rule	sol88	1988	only	-	Jan	27	12:12:40s -0:12:40 -
-Rule	sol88	1988	only	-	Jan	28	12:12:50s -0:12:50 -
-Rule	sol88	1988	only	-	Jan	29	12:13:00s -0:13:00 -
-Rule	sol88	1988	only	-	Jan	30	12:13:10s -0:13:10 -
-Rule	sol88	1988	only	-	Jan	31	12:13:20s -0:13:20 -
-Rule	sol88	1988	only	-	Feb	1	12:13:30s -0:13:30 -
-Rule	sol88	1988	only	-	Feb	2	12:13:40s -0:13:40 -
-Rule	sol88	1988	only	-	Feb	3	12:13:45s -0:13:45 -
-Rule	sol88	1988	only	-	Feb	4	12:13:55s -0:13:55 -
-Rule	sol88	1988	only	-	Feb	5	12:14:00s -0:14:00 -
-Rule	sol88	1988	only	-	Feb	6	12:14:05s -0:14:05 -
-Rule	sol88	1988	only	-	Feb	7	12:14:10s -0:14:10 -
-Rule	sol88	1988	only	-	Feb	8	12:14:10s -0:14:10 -
-Rule	sol88	1988	only	-	Feb	9	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	10	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	11	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	12	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	13	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	14	12:14:15s -0:14:15 -
-Rule	sol88	1988	only	-	Feb	15	12:14:10s -0:14:10 -
-Rule	sol88	1988	only	-	Feb	16	12:14:10s -0:14:10 -
-Rule	sol88	1988	only	-	Feb	17	12:14:05s -0:14:05 -
-Rule	sol88	1988	only	-	Feb	18	12:14:00s -0:14:00 -
-Rule	sol88	1988	only	-	Feb	19	12:13:55s -0:13:55 -
-Rule	sol88	1988	only	-	Feb	20	12:13:50s -0:13:50 -
-Rule	sol88	1988	only	-	Feb	21	12:13:45s -0:13:45 -
-Rule	sol88	1988	only	-	Feb	22	12:13:40s -0:13:40 -
-Rule	sol88	1988	only	-	Feb	23	12:13:30s -0:13:30 -
-Rule	sol88	1988	only	-	Feb	24	12:13:20s -0:13:20 -
-Rule	sol88	1988	only	-	Feb	25	12:13:15s -0:13:15 -
-Rule	sol88	1988	only	-	Feb	26	12:13:05s -0:13:05 -
-Rule	sol88	1988	only	-	Feb	27	12:12:55s -0:12:55 -
-Rule	sol88	1988	only	-	Feb	28	12:12:45s -0:12:45 -
-Rule	sol88	1988	only	-	Feb	29	12:12:30s -0:12:30 -
-Rule	sol88	1988	only	-	Mar	1	12:12:20s -0:12:20 -
-Rule	sol88	1988	only	-	Mar	2	12:12:10s -0:12:10 -
-Rule	sol88	1988	only	-	Mar	3	12:11:55s -0:11:55 -
-Rule	sol88	1988	only	-	Mar	4	12:11:45s -0:11:45 -
-Rule	sol88	1988	only	-	Mar	5	12:11:30s -0:11:30 -
-Rule	sol88	1988	only	-	Mar	6	12:11:15s -0:11:15 -
-Rule	sol88	1988	only	-	Mar	7	12:11:00s -0:11:00 -
-Rule	sol88	1988	only	-	Mar	8	12:10:45s -0:10:45 -
-Rule	sol88	1988	only	-	Mar	9	12:10:30s -0:10:30 -
-Rule	sol88	1988	only	-	Mar	10	12:10:15s -0:10:15 -
-Rule	sol88	1988	only	-	Mar	11	12:10:00s -0:10:00 -
-Rule	sol88	1988	only	-	Mar	12	12:09:45s -0:09:45 -
-Rule	sol88	1988	only	-	Mar	13	12:09:30s -0:09:30 -
-Rule	sol88	1988	only	-	Mar	14	12:09:10s -0:09:10 -
-Rule	sol88	1988	only	-	Mar	15	12:08:55s -0:08:55 -
-Rule	sol88	1988	only	-	Mar	16	12:08:40s -0:08:40 -
-Rule	sol88	1988	only	-	Mar	17	12:08:20s -0:08:20 -
-Rule	sol88	1988	only	-	Mar	18	12:08:05s -0:08:05 -
-Rule	sol88	1988	only	-	Mar	19	12:07:45s -0:07:45 -
-Rule	sol88	1988	only	-	Mar	20	12:07:30s -0:07:30 -
-Rule	sol88	1988	only	-	Mar	21	12:07:10s -0:07:10 -
-Rule	sol88	1988	only	-	Mar	22	12:06:50s -0:06:50 -
-Rule	sol88	1988	only	-	Mar	23	12:06:35s -0:06:35 -
-Rule	sol88	1988	only	-	Mar	24	12:06:15s -0:06:15 -
-Rule	sol88	1988	only	-	Mar	25	12:06:00s -0:06:00 -
-Rule	sol88	1988	only	-	Mar	26	12:05:40s -0:05:40 -
-Rule	sol88	1988	only	-	Mar	27	12:05:20s -0:05:20 -
-Rule	sol88	1988	only	-	Mar	28	12:05:05s -0:05:05 -
-Rule	sol88	1988	only	-	Mar	29	12:04:45s -0:04:45 -
-Rule	sol88	1988	only	-	Mar	30	12:04:25s -0:04:25 -
-Rule	sol88	1988	only	-	Mar	31	12:04:10s -0:04:10 -
-Rule	sol88	1988	only	-	Apr	1	12:03:50s -0:03:50 -
-Rule	sol88	1988	only	-	Apr	2	12:03:35s -0:03:35 -
-Rule	sol88	1988	only	-	Apr	3	12:03:15s -0:03:15 -
-Rule	sol88	1988	only	-	Apr	4	12:03:00s -0:03:00 -
-Rule	sol88	1988	only	-	Apr	5	12:02:40s -0:02:40 -
-Rule	sol88	1988	only	-	Apr	6	12:02:25s -0:02:25 -
-Rule	sol88	1988	only	-	Apr	7	12:02:05s -0:02:05 -
-Rule	sol88	1988	only	-	Apr	8	12:01:50s -0:01:50 -
-Rule	sol88	1988	only	-	Apr	9	12:01:35s -0:01:35 -
-Rule	sol88	1988	only	-	Apr	10	12:01:15s -0:01:15 -
-Rule	sol88	1988	only	-	Apr	11	12:01:00s -0:01:00 -
-Rule	sol88	1988	only	-	Apr	12	12:00:45s -0:00:45 -
-Rule	sol88	1988	only	-	Apr	13	12:00:30s -0:00:30 -
-Rule	sol88	1988	only	-	Apr	14	12:00:15s -0:00:15 -
-Rule	sol88	1988	only	-	Apr	15	12:00:00s 0:00:00 -
-Rule	sol88	1988	only	-	Apr	16	11:59:45s 0:00:15 -
-Rule	sol88	1988	only	-	Apr	17	11:59:30s 0:00:30 -
-Rule	sol88	1988	only	-	Apr	18	11:59:20s 0:00:40 -
-Rule	sol88	1988	only	-	Apr	19	11:59:05s 0:00:55 -
-Rule	sol88	1988	only	-	Apr	20	11:58:55s 0:01:05 -
-Rule	sol88	1988	only	-	Apr	21	11:58:40s 0:01:20 -
-Rule	sol88	1988	only	-	Apr	22	11:58:30s 0:01:30 -
-Rule	sol88	1988	only	-	Apr	23	11:58:15s 0:01:45 -
-Rule	sol88	1988	only	-	Apr	24	11:58:05s 0:01:55 -
-Rule	sol88	1988	only	-	Apr	25	11:57:55s 0:02:05 -
-Rule	sol88	1988	only	-	Apr	26	11:57:45s 0:02:15 -
-Rule	sol88	1988	only	-	Apr	27	11:57:35s 0:02:25 -
-Rule	sol88	1988	only	-	Apr	28	11:57:30s 0:02:30 -
-Rule	sol88	1988	only	-	Apr	29	11:57:20s 0:02:40 -
-Rule	sol88	1988	only	-	Apr	30	11:57:10s 0:02:50 -
-Rule	sol88	1988	only	-	May	1	11:57:05s 0:02:55 -
-Rule	sol88	1988	only	-	May	2	11:56:55s 0:03:05 -
-Rule	sol88	1988	only	-	May	3	11:56:50s 0:03:10 -
-Rule	sol88	1988	only	-	May	4	11:56:45s 0:03:15 -
-Rule	sol88	1988	only	-	May	5	11:56:40s 0:03:20 -
-Rule	sol88	1988	only	-	May	6	11:56:35s 0:03:25 -
-Rule	sol88	1988	only	-	May	7	11:56:30s 0:03:30 -
-Rule	sol88	1988	only	-	May	8	11:56:25s 0:03:35 -
-Rule	sol88	1988	only	-	May	9	11:56:25s 0:03:35 -
-Rule	sol88	1988	only	-	May	10	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	11	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	12	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	13	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	14	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	15	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	16	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	17	11:56:20s 0:03:40 -
-Rule	sol88	1988	only	-	May	18	11:56:25s 0:03:35 -
-Rule	sol88	1988	only	-	May	19	11:56:25s 0:03:35 -
-Rule	sol88	1988	only	-	May	20	11:56:30s 0:03:30 -
-Rule	sol88	1988	only	-	May	21	11:56:35s 0:03:25 -
-Rule	sol88	1988	only	-	May	22	11:56:40s 0:03:20 -
-Rule	sol88	1988	only	-	May	23	11:56:45s 0:03:15 -
-Rule	sol88	1988	only	-	May	24	11:56:50s 0:03:10 -
-Rule	sol88	1988	only	-	May	25	11:56:55s 0:03:05 -
-Rule	sol88	1988	only	-	May	26	11:57:00s 0:03:00 -
-Rule	sol88	1988	only	-	May	27	11:57:05s 0:02:55 -
-Rule	sol88	1988	only	-	May	28	11:57:15s 0:02:45 -
-Rule	sol88	1988	only	-	May	29	11:57:20s 0:02:40 -
-Rule	sol88	1988	only	-	May	30	11:57:30s 0:02:30 -
-Rule	sol88	1988	only	-	May	31	11:57:40s 0:02:20 -
-Rule	sol88	1988	only	-	Jun	1	11:57:50s 0:02:10 -
-Rule	sol88	1988	only	-	Jun	2	11:57:55s 0:02:05 -
-Rule	sol88	1988	only	-	Jun	3	11:58:05s 0:01:55 -
-Rule	sol88	1988	only	-	Jun	4	11:58:15s 0:01:45 -
-Rule	sol88	1988	only	-	Jun	5	11:58:30s 0:01:30 -
-Rule	sol88	1988	only	-	Jun	6	11:58:40s 0:01:20 -
-Rule	sol88	1988	only	-	Jun	7	11:58:50s 0:01:10 -
-Rule	sol88	1988	only	-	Jun	8	11:59:00s 0:01:00 -
-Rule	sol88	1988	only	-	Jun	9	11:59:15s 0:00:45 -
-Rule	sol88	1988	only	-	Jun	10	11:59:25s 0:00:35 -
-Rule	sol88	1988	only	-	Jun	11	11:59:35s 0:00:25 -
-Rule	sol88	1988	only	-	Jun	12	11:59:50s 0:00:10 -
-Rule	sol88	1988	only	-	Jun	13	12:00:00s 0:00:00 -
-Rule	sol88	1988	only	-	Jun	14	12:00:15s -0:00:15 -
-Rule	sol88	1988	only	-	Jun	15	12:00:25s -0:00:25 -
-Rule	sol88	1988	only	-	Jun	16	12:00:40s -0:00:40 -
-Rule	sol88	1988	only	-	Jun	17	12:00:55s -0:00:55 -
-Rule	sol88	1988	only	-	Jun	18	12:01:05s -0:01:05 -
-Rule	sol88	1988	only	-	Jun	19	12:01:20s -0:01:20 -
-Rule	sol88	1988	only	-	Jun	20	12:01:30s -0:01:30 -
-Rule	sol88	1988	only	-	Jun	21	12:01:45s -0:01:45 -
-Rule	sol88	1988	only	-	Jun	22	12:02:00s -0:02:00 -
-Rule	sol88	1988	only	-	Jun	23	12:02:10s -0:02:10 -
-Rule	sol88	1988	only	-	Jun	24	12:02:25s -0:02:25 -
-Rule	sol88	1988	only	-	Jun	25	12:02:35s -0:02:35 -
-Rule	sol88	1988	only	-	Jun	26	12:02:50s -0:02:50 -
-Rule	sol88	1988	only	-	Jun	27	12:03:00s -0:03:00 -
-Rule	sol88	1988	only	-	Jun	28	12:03:15s -0:03:15 -
-Rule	sol88	1988	only	-	Jun	29	12:03:25s -0:03:25 -
-Rule	sol88	1988	only	-	Jun	30	12:03:40s -0:03:40 -
-Rule	sol88	1988	only	-	Jul	1	12:03:50s -0:03:50 -
-Rule	sol88	1988	only	-	Jul	2	12:04:00s -0:04:00 -
-Rule	sol88	1988	only	-	Jul	3	12:04:10s -0:04:10 -
-Rule	sol88	1988	only	-	Jul	4	12:04:25s -0:04:25 -
-Rule	sol88	1988	only	-	Jul	5	12:04:35s -0:04:35 -
-Rule	sol88	1988	only	-	Jul	6	12:04:45s -0:04:45 -
-Rule	sol88	1988	only	-	Jul	7	12:04:55s -0:04:55 -
-Rule	sol88	1988	only	-	Jul	8	12:05:05s -0:05:05 -
-Rule	sol88	1988	only	-	Jul	9	12:05:10s -0:05:10 -
-Rule	sol88	1988	only	-	Jul	10	12:05:20s -0:05:20 -
-Rule	sol88	1988	only	-	Jul	11	12:05:30s -0:05:30 -
-Rule	sol88	1988	only	-	Jul	12	12:05:35s -0:05:35 -
-Rule	sol88	1988	only	-	Jul	13	12:05:45s -0:05:45 -
-Rule	sol88	1988	only	-	Jul	14	12:05:50s -0:05:50 -
-Rule	sol88	1988	only	-	Jul	15	12:05:55s -0:05:55 -
-Rule	sol88	1988	only	-	Jul	16	12:06:00s -0:06:00 -
-Rule	sol88	1988	only	-	Jul	17	12:06:05s -0:06:05 -
-Rule	sol88	1988	only	-	Jul	18	12:06:10s -0:06:10 -
-Rule	sol88	1988	only	-	Jul	19	12:06:15s -0:06:15 -
-Rule	sol88	1988	only	-	Jul	20	12:06:20s -0:06:20 -
-Rule	sol88	1988	only	-	Jul	21	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jul	22	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jul	23	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jul	24	12:06:30s -0:06:30 -
-Rule	sol88	1988	only	-	Jul	25	12:06:30s -0:06:30 -
-Rule	sol88	1988	only	-	Jul	26	12:06:30s -0:06:30 -
-Rule	sol88	1988	only	-	Jul	27	12:06:30s -0:06:30 -
-Rule	sol88	1988	only	-	Jul	28	12:06:30s -0:06:30 -
-Rule	sol88	1988	only	-	Jul	29	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jul	30	12:06:25s -0:06:25 -
-Rule	sol88	1988	only	-	Jul	31	12:06:20s -0:06:20 -
-Rule	sol88	1988	only	-	Aug	1	12:06:15s -0:06:15 -
-Rule	sol88	1988	only	-	Aug	2	12:06:15s -0:06:15 -
-Rule	sol88	1988	only	-	Aug	3	12:06:10s -0:06:10 -
-Rule	sol88	1988	only	-	Aug	4	12:06:05s -0:06:05 -
-Rule	sol88	1988	only	-	Aug	5	12:05:55s -0:05:55 -
-Rule	sol88	1988	only	-	Aug	6	12:05:50s -0:05:50 -
-Rule	sol88	1988	only	-	Aug	7	12:05:45s -0:05:45 -
-Rule	sol88	1988	only	-	Aug	8	12:05:35s -0:05:35 -
-Rule	sol88	1988	only	-	Aug	9	12:05:25s -0:05:25 -
-Rule	sol88	1988	only	-	Aug	10	12:05:20s -0:05:20 -
-Rule	sol88	1988	only	-	Aug	11	12:05:10s -0:05:10 -
-Rule	sol88	1988	only	-	Aug	12	12:05:00s -0:05:00 -
-Rule	sol88	1988	only	-	Aug	13	12:04:50s -0:04:50 -
-Rule	sol88	1988	only	-	Aug	14	12:04:35s -0:04:35 -
-Rule	sol88	1988	only	-	Aug	15	12:04:25s -0:04:25 -
-Rule	sol88	1988	only	-	Aug	16	12:04:15s -0:04:15 -
-Rule	sol88	1988	only	-	Aug	17	12:04:00s -0:04:00 -
-Rule	sol88	1988	only	-	Aug	18	12:03:50s -0:03:50 -
-Rule	sol88	1988	only	-	Aug	19	12:03:35s -0:03:35 -
-Rule	sol88	1988	only	-	Aug	20	12:03:20s -0:03:20 -
-Rule	sol88	1988	only	-	Aug	21	12:03:05s -0:03:05 -
-Rule	sol88	1988	only	-	Aug	22	12:02:50s -0:02:50 -
-Rule	sol88	1988	only	-	Aug	23	12:02:35s -0:02:35 -
-Rule	sol88	1988	only	-	Aug	24	12:02:20s -0:02:20 -
-Rule	sol88	1988	only	-	Aug	25	12:02:00s -0:02:00 -
-Rule	sol88	1988	only	-	Aug	26	12:01:45s -0:01:45 -
-Rule	sol88	1988	only	-	Aug	27	12:01:30s -0:01:30 -
-Rule	sol88	1988	only	-	Aug	28	12:01:10s -0:01:10 -
-Rule	sol88	1988	only	-	Aug	29	12:00:50s -0:00:50 -
-Rule	sol88	1988	only	-	Aug	30	12:00:35s -0:00:35 -
-Rule	sol88	1988	only	-	Aug	31	12:00:15s -0:00:15 -
-Rule	sol88	1988	only	-	Sep	1	11:59:55s 0:00:05 -
-Rule	sol88	1988	only	-	Sep	2	11:59:35s 0:00:25 -
-Rule	sol88	1988	only	-	Sep	3	11:59:20s 0:00:40 -
-Rule	sol88	1988	only	-	Sep	4	11:59:00s 0:01:00 -
-Rule	sol88	1988	only	-	Sep	5	11:58:40s 0:01:20 -
-Rule	sol88	1988	only	-	Sep	6	11:58:20s 0:01:40 -
-Rule	sol88	1988	only	-	Sep	7	11:58:00s 0:02:00 -
-Rule	sol88	1988	only	-	Sep	8	11:57:35s 0:02:25 -
-Rule	sol88	1988	only	-	Sep	9	11:57:15s 0:02:45 -
-Rule	sol88	1988	only	-	Sep	10	11:56:55s 0:03:05 -
-Rule	sol88	1988	only	-	Sep	11	11:56:35s 0:03:25 -
-Rule	sol88	1988	only	-	Sep	12	11:56:15s 0:03:45 -
-Rule	sol88	1988	only	-	Sep	13	11:55:50s 0:04:10 -
-Rule	sol88	1988	only	-	Sep	14	11:55:30s 0:04:30 -
-Rule	sol88	1988	only	-	Sep	15	11:55:10s 0:04:50 -
-Rule	sol88	1988	only	-	Sep	16	11:54:50s 0:05:10 -
-Rule	sol88	1988	only	-	Sep	17	11:54:25s 0:05:35 -
-Rule	sol88	1988	only	-	Sep	18	11:54:05s 0:05:55 -
-Rule	sol88	1988	only	-	Sep	19	11:53:45s 0:06:15 -
-Rule	sol88	1988	only	-	Sep	20	11:53:25s 0:06:35 -
-Rule	sol88	1988	only	-	Sep	21	11:53:00s 0:07:00 -
-Rule	sol88	1988	only	-	Sep	22	11:52:40s 0:07:20 -
-Rule	sol88	1988	only	-	Sep	23	11:52:20s 0:07:40 -
-Rule	sol88	1988	only	-	Sep	24	11:52:00s 0:08:00 -
-Rule	sol88	1988	only	-	Sep	25	11:51:40s 0:08:20 -
-Rule	sol88	1988	only	-	Sep	26	11:51:15s 0:08:45 -
-Rule	sol88	1988	only	-	Sep	27	11:50:55s 0:09:05 -
-Rule	sol88	1988	only	-	Sep	28	11:50:35s 0:09:25 -
-Rule	sol88	1988	only	-	Sep	29	11:50:15s 0:09:45 -
-Rule	sol88	1988	only	-	Sep	30	11:49:55s 0:10:05 -
-Rule	sol88	1988	only	-	Oct	1	11:49:35s 0:10:25 -
-Rule	sol88	1988	only	-	Oct	2	11:49:20s 0:10:40 -
-Rule	sol88	1988	only	-	Oct	3	11:49:00s 0:11:00 -
-Rule	sol88	1988	only	-	Oct	4	11:48:40s 0:11:20 -
-Rule	sol88	1988	only	-	Oct	5	11:48:25s 0:11:35 -
-Rule	sol88	1988	only	-	Oct	6	11:48:05s 0:11:55 -
-Rule	sol88	1988	only	-	Oct	7	11:47:50s 0:12:10 -
-Rule	sol88	1988	only	-	Oct	8	11:47:30s 0:12:30 -
-Rule	sol88	1988	only	-	Oct	9	11:47:15s 0:12:45 -
-Rule	sol88	1988	only	-	Oct	10	11:47:00s 0:13:00 -
-Rule	sol88	1988	only	-	Oct	11	11:46:45s 0:13:15 -
-Rule	sol88	1988	only	-	Oct	12	11:46:30s 0:13:30 -
-Rule	sol88	1988	only	-	Oct	13	11:46:15s 0:13:45 -
-Rule	sol88	1988	only	-	Oct	14	11:46:00s 0:14:00 -
-Rule	sol88	1988	only	-	Oct	15	11:45:45s 0:14:15 -
-Rule	sol88	1988	only	-	Oct	16	11:45:35s 0:14:25 -
-Rule	sol88	1988	only	-	Oct	17	11:45:20s 0:14:40 -
-Rule	sol88	1988	only	-	Oct	18	11:45:10s 0:14:50 -
-Rule	sol88	1988	only	-	Oct	19	11:45:00s 0:15:00 -
-Rule	sol88	1988	only	-	Oct	20	11:44:45s 0:15:15 -
-Rule	sol88	1988	only	-	Oct	21	11:44:40s 0:15:20 -
-Rule	sol88	1988	only	-	Oct	22	11:44:30s 0:15:30 -
-Rule	sol88	1988	only	-	Oct	23	11:44:20s 0:15:40 -
-Rule	sol88	1988	only	-	Oct	24	11:44:10s 0:15:50 -
-Rule	sol88	1988	only	-	Oct	25	11:44:05s 0:15:55 -
-Rule	sol88	1988	only	-	Oct	26	11:44:00s 0:16:00 -
-Rule	sol88	1988	only	-	Oct	27	11:43:55s 0:16:05 -
-Rule	sol88	1988	only	-	Oct	28	11:43:50s 0:16:10 -
-Rule	sol88	1988	only	-	Oct	29	11:43:45s 0:16:15 -
-Rule	sol88	1988	only	-	Oct	30	11:43:40s 0:16:20 -
-Rule	sol88	1988	only	-	Oct	31	11:43:40s 0:16:20 -
-Rule	sol88	1988	only	-	Nov	1	11:43:35s 0:16:25 -
-Rule	sol88	1988	only	-	Nov	2	11:43:35s 0:16:25 -
-Rule	sol88	1988	only	-	Nov	3	11:43:35s 0:16:25 -
-Rule	sol88	1988	only	-	Nov	4	11:43:35s 0:16:25 -
-Rule	sol88	1988	only	-	Nov	5	11:43:40s 0:16:20 -
-Rule	sol88	1988	only	-	Nov	6	11:43:40s 0:16:20 -
-Rule	sol88	1988	only	-	Nov	7	11:43:45s 0:16:15 -
-Rule	sol88	1988	only	-	Nov	8	11:43:45s 0:16:15 -
-Rule	sol88	1988	only	-	Nov	9	11:43:50s 0:16:10 -
-Rule	sol88	1988	only	-	Nov	10	11:44:00s 0:16:00 -
-Rule	sol88	1988	only	-	Nov	11	11:44:05s 0:15:55 -
-Rule	sol88	1988	only	-	Nov	12	11:44:10s 0:15:50 -
-Rule	sol88	1988	only	-	Nov	13	11:44:20s 0:15:40 -
-Rule	sol88	1988	only	-	Nov	14	11:44:30s 0:15:30 -
-Rule	sol88	1988	only	-	Nov	15	11:44:40s 0:15:20 -
-Rule	sol88	1988	only	-	Nov	16	11:44:50s 0:15:10 -
-Rule	sol88	1988	only	-	Nov	17	11:45:00s 0:15:00 -
-Rule	sol88	1988	only	-	Nov	18	11:45:15s 0:14:45 -
-Rule	sol88	1988	only	-	Nov	19	11:45:25s 0:14:35 -
-Rule	sol88	1988	only	-	Nov	20	11:45:40s 0:14:20 -
-Rule	sol88	1988	only	-	Nov	21	11:45:55s 0:14:05 -
-Rule	sol88	1988	only	-	Nov	22	11:46:10s 0:13:50 -
-Rule	sol88	1988	only	-	Nov	23	11:46:30s 0:13:30 -
-Rule	sol88	1988	only	-	Nov	24	11:46:45s 0:13:15 -
-Rule	sol88	1988	only	-	Nov	25	11:47:05s 0:12:55 -
-Rule	sol88	1988	only	-	Nov	26	11:47:20s 0:12:40 -
-Rule	sol88	1988	only	-	Nov	27	11:47:40s 0:12:20 -
-Rule	sol88	1988	only	-	Nov	28	11:48:00s 0:12:00 -
-Rule	sol88	1988	only	-	Nov	29	11:48:25s 0:11:35 -
-Rule	sol88	1988	only	-	Nov	30	11:48:45s 0:11:15 -
-Rule	sol88	1988	only	-	Dec	1	11:49:05s 0:10:55 -
-Rule	sol88	1988	only	-	Dec	2	11:49:30s 0:10:30 -
-Rule	sol88	1988	only	-	Dec	3	11:49:55s 0:10:05 -
-Rule	sol88	1988	only	-	Dec	4	11:50:15s 0:09:45 -
-Rule	sol88	1988	only	-	Dec	5	11:50:40s 0:09:20 -
-Rule	sol88	1988	only	-	Dec	6	11:51:05s 0:08:55 -
-Rule	sol88	1988	only	-	Dec	7	11:51:35s 0:08:25 -
-Rule	sol88	1988	only	-	Dec	8	11:52:00s 0:08:00 -
-Rule	sol88	1988	only	-	Dec	9	11:52:25s 0:07:35 -
-Rule	sol88	1988	only	-	Dec	10	11:52:55s 0:07:05 -
-Rule	sol88	1988	only	-	Dec	11	11:53:20s 0:06:40 -
-Rule	sol88	1988	only	-	Dec	12	11:53:50s 0:06:10 -
-Rule	sol88	1988	only	-	Dec	13	11:54:15s 0:05:45 -
-Rule	sol88	1988	only	-	Dec	14	11:54:45s 0:05:15 -
-Rule	sol88	1988	only	-	Dec	15	11:55:15s 0:04:45 -
-Rule	sol88	1988	only	-	Dec	16	11:55:45s 0:04:15 -
-Rule	sol88	1988	only	-	Dec	17	11:56:15s 0:03:45 -
-Rule	sol88	1988	only	-	Dec	18	11:56:40s 0:03:20 -
-Rule	sol88	1988	only	-	Dec	19	11:57:10s 0:02:50 -
-Rule	sol88	1988	only	-	Dec	20	11:57:40s 0:02:20 -
-Rule	sol88	1988	only	-	Dec	21	11:58:10s 0:01:50 -
-Rule	sol88	1988	only	-	Dec	22	11:58:40s 0:01:20 -
-Rule	sol88	1988	only	-	Dec	23	11:59:10s 0:00:50 -
-Rule	sol88	1988	only	-	Dec	24	11:59:40s 0:00:20 -
-Rule	sol88	1988	only	-	Dec	25	12:00:10s -0:00:10 -
-Rule	sol88	1988	only	-	Dec	26	12:00:40s -0:00:40 -
-Rule	sol88	1988	only	-	Dec	27	12:01:10s -0:01:10 -
-Rule	sol88	1988	only	-	Dec	28	12:01:40s -0:01:40 -
-Rule	sol88	1988	only	-	Dec	29	12:02:10s -0:02:10 -
-Rule	sol88	1988	only	-	Dec	30	12:02:35s -0:02:35 -
-Rule	sol88	1988	only	-	Dec	31	12:03:05s -0:03:05 -
-
-# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
-# Before and after 1988, we'll operate on local mean solar time.
-
-# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
-Zone	Asia/Riyadh88	3:07:04	-		zzz	1988
-			3:07:04	sol88		zzz	1989
-			3:07:04	-		zzz
-# For backward compatibility...
-Link	Asia/Riyadh88	Mideast/Riyadh88
diff --git a/solar89 b/solar89
deleted file mode 100644
index af93235697f9..000000000000
--- a/solar89
+++ /dev/null
@@ -1,395 +0,0 @@
-# 
-# This file is in the public domain, so clarified as of
-# 2009-05-17 by Arthur David Olson.
-
-# Apparent noon times below are for Riyadh; they're a bit off for other places.
-# Times were computed using a formula provided by the U. S. Naval Observatory:
-#	eqt = -105.8 * sin(l) + 596.2 * sin(2 * l) + 4.4 * sin(3 * l)
-#		-12.7 * sin(4 * l) - 429.0 * cos(l) - 2.1 * cos (2 * l)
-#		+ 19.3 * cos(3 * l);
-# where l is the "mean longitude of the Sun" given by
-#	l = 279.642 degrees + 0.985647 * d
-# and d is the interval in days from January 0, 0 hours Universal Time
-# (equaling the day of the year plus the fraction of a day from zero hours).
-# The accuracy of the formula is plus or minus three seconds.
-#
-# Rounding to the nearest five seconds results in fewer than
-# 256 different "time types"--a limit that's faced because time types are
-# stored on disk as unsigned chars.
-
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	sol89	1989	only	-	Jan	1	12:03:35s -0:03:35 -
-Rule	sol89	1989	only	-	Jan	2	12:04:05s -0:04:05 -
-Rule	sol89	1989	only	-	Jan	3	12:04:30s -0:04:30 -
-Rule	sol89	1989	only	-	Jan	4	12:05:00s -0:05:00 -
-Rule	sol89	1989	only	-	Jan	5	12:05:25s -0:05:25 -
-Rule	sol89	1989	only	-	Jan	6	12:05:50s -0:05:50 -
-Rule	sol89	1989	only	-	Jan	7	12:06:15s -0:06:15 -
-Rule	sol89	1989	only	-	Jan	8	12:06:45s -0:06:45 -
-Rule	sol89	1989	only	-	Jan	9	12:07:10s -0:07:10 -
-Rule	sol89	1989	only	-	Jan	10	12:07:35s -0:07:35 -
-Rule	sol89	1989	only	-	Jan	11	12:07:55s -0:07:55 -
-Rule	sol89	1989	only	-	Jan	12	12:08:20s -0:08:20 -
-Rule	sol89	1989	only	-	Jan	13	12:08:45s -0:08:45 -
-Rule	sol89	1989	only	-	Jan	14	12:09:05s -0:09:05 -
-Rule	sol89	1989	only	-	Jan	15	12:09:25s -0:09:25 -
-Rule	sol89	1989	only	-	Jan	16	12:09:45s -0:09:45 -
-Rule	sol89	1989	only	-	Jan	17	12:10:05s -0:10:05 -
-Rule	sol89	1989	only	-	Jan	18	12:10:25s -0:10:25 -
-Rule	sol89	1989	only	-	Jan	19	12:10:45s -0:10:45 -
-Rule	sol89	1989	only	-	Jan	20	12:11:05s -0:11:05 -
-Rule	sol89	1989	only	-	Jan	21	12:11:20s -0:11:20 -
-Rule	sol89	1989	only	-	Jan	22	12:11:35s -0:11:35 -
-Rule	sol89	1989	only	-	Jan	23	12:11:55s -0:11:55 -
-Rule	sol89	1989	only	-	Jan	24	12:12:10s -0:12:10 -
-Rule	sol89	1989	only	-	Jan	25	12:12:20s -0:12:20 -
-Rule	sol89	1989	only	-	Jan	26	12:12:35s -0:12:35 -
-Rule	sol89	1989	only	-	Jan	27	12:12:50s -0:12:50 -
-Rule	sol89	1989	only	-	Jan	28	12:13:00s -0:13:00 -
-Rule	sol89	1989	only	-	Jan	29	12:13:10s -0:13:10 -
-Rule	sol89	1989	only	-	Jan	30	12:13:20s -0:13:20 -
-Rule	sol89	1989	only	-	Jan	31	12:13:30s -0:13:30 -
-Rule	sol89	1989	only	-	Feb	1	12:13:40s -0:13:40 -
-Rule	sol89	1989	only	-	Feb	2	12:13:45s -0:13:45 -
-Rule	sol89	1989	only	-	Feb	3	12:13:55s -0:13:55 -
-Rule	sol89	1989	only	-	Feb	4	12:14:00s -0:14:00 -
-Rule	sol89	1989	only	-	Feb	5	12:14:05s -0:14:05 -
-Rule	sol89	1989	only	-	Feb	6	12:14:10s -0:14:10 -
-Rule	sol89	1989	only	-	Feb	7	12:14:10s -0:14:10 -
-Rule	sol89	1989	only	-	Feb	8	12:14:15s -0:14:15 -
-Rule	sol89	1989	only	-	Feb	9	12:14:15s -0:14:15 -
-Rule	sol89	1989	only	-	Feb	10	12:14:20s -0:14:20 -
-Rule	sol89	1989	only	-	Feb	11	12:14:20s -0:14:20 -
-Rule	sol89	1989	only	-	Feb	12	12:14:20s -0:14:20 -
-Rule	sol89	1989	only	-	Feb	13	12:14:15s -0:14:15 -
-Rule	sol89	1989	only	-	Feb	14	12:14:15s -0:14:15 -
-Rule	sol89	1989	only	-	Feb	15	12:14:10s -0:14:10 -
-Rule	sol89	1989	only	-	Feb	16	12:14:10s -0:14:10 -
-Rule	sol89	1989	only	-	Feb	17	12:14:05s -0:14:05 -
-Rule	sol89	1989	only	-	Feb	18	12:14:00s -0:14:00 -
-Rule	sol89	1989	only	-	Feb	19	12:13:55s -0:13:55 -
-Rule	sol89	1989	only	-	Feb	20	12:13:50s -0:13:50 -
-Rule	sol89	1989	only	-	Feb	21	12:13:40s -0:13:40 -
-Rule	sol89	1989	only	-	Feb	22	12:13:35s -0:13:35 -
-Rule	sol89	1989	only	-	Feb	23	12:13:25s -0:13:25 -
-Rule	sol89	1989	only	-	Feb	24	12:13:15s -0:13:15 -
-Rule	sol89	1989	only	-	Feb	25	12:13:05s -0:13:05 -
-Rule	sol89	1989	only	-	Feb	26	12:12:55s -0:12:55 -
-Rule	sol89	1989	only	-	Feb	27	12:12:45s -0:12:45 -
-Rule	sol89	1989	only	-	Feb	28	12:12:35s -0:12:35 -
-Rule	sol89	1989	only	-	Mar	1	12:12:25s -0:12:25 -
-Rule	sol89	1989	only	-	Mar	2	12:12:10s -0:12:10 -
-Rule	sol89	1989	only	-	Mar	3	12:12:00s -0:12:00 -
-Rule	sol89	1989	only	-	Mar	4	12:11:45s -0:11:45 -
-Rule	sol89	1989	only	-	Mar	5	12:11:35s -0:11:35 -
-Rule	sol89	1989	only	-	Mar	6	12:11:20s -0:11:20 -
-Rule	sol89	1989	only	-	Mar	7	12:11:05s -0:11:05 -
-Rule	sol89	1989	only	-	Mar	8	12:10:50s -0:10:50 -
-Rule	sol89	1989	only	-	Mar	9	12:10:35s -0:10:35 -
-Rule	sol89	1989	only	-	Mar	10	12:10:20s -0:10:20 -
-Rule	sol89	1989	only	-	Mar	11	12:10:05s -0:10:05 -
-Rule	sol89	1989	only	-	Mar	12	12:09:50s -0:09:50 -
-Rule	sol89	1989	only	-	Mar	13	12:09:30s -0:09:30 -
-Rule	sol89	1989	only	-	Mar	14	12:09:15s -0:09:15 -
-Rule	sol89	1989	only	-	Mar	15	12:09:00s -0:09:00 -
-Rule	sol89	1989	only	-	Mar	16	12:08:40s -0:08:40 -
-Rule	sol89	1989	only	-	Mar	17	12:08:25s -0:08:25 -
-Rule	sol89	1989	only	-	Mar	18	12:08:05s -0:08:05 -
-Rule	sol89	1989	only	-	Mar	19	12:07:50s -0:07:50 -
-Rule	sol89	1989	only	-	Mar	20	12:07:30s -0:07:30 -
-Rule	sol89	1989	only	-	Mar	21	12:07:15s -0:07:15 -
-Rule	sol89	1989	only	-	Mar	22	12:06:55s -0:06:55 -
-Rule	sol89	1989	only	-	Mar	23	12:06:35s -0:06:35 -
-Rule	sol89	1989	only	-	Mar	24	12:06:20s -0:06:20 -
-Rule	sol89	1989	only	-	Mar	25	12:06:00s -0:06:00 -
-Rule	sol89	1989	only	-	Mar	26	12:05:40s -0:05:40 -
-Rule	sol89	1989	only	-	Mar	27	12:05:25s -0:05:25 -
-Rule	sol89	1989	only	-	Mar	28	12:05:05s -0:05:05 -
-Rule	sol89	1989	only	-	Mar	29	12:04:50s -0:04:50 -
-Rule	sol89	1989	only	-	Mar	30	12:04:30s -0:04:30 -
-Rule	sol89	1989	only	-	Mar	31	12:04:10s -0:04:10 -
-Rule	sol89	1989	only	-	Apr	1	12:03:55s -0:03:55 -
-Rule	sol89	1989	only	-	Apr	2	12:03:35s -0:03:35 -
-Rule	sol89	1989	only	-	Apr	3	12:03:20s -0:03:20 -
-Rule	sol89	1989	only	-	Apr	4	12:03:00s -0:03:00 -
-Rule	sol89	1989	only	-	Apr	5	12:02:45s -0:02:45 -
-Rule	sol89	1989	only	-	Apr	6	12:02:25s -0:02:25 -
-Rule	sol89	1989	only	-	Apr	7	12:02:10s -0:02:10 -
-Rule	sol89	1989	only	-	Apr	8	12:01:50s -0:01:50 -
-Rule	sol89	1989	only	-	Apr	9	12:01:35s -0:01:35 -
-Rule	sol89	1989	only	-	Apr	10	12:01:20s -0:01:20 -
-Rule	sol89	1989	only	-	Apr	11	12:01:05s -0:01:05 -
-Rule	sol89	1989	only	-	Apr	12	12:00:50s -0:00:50 -
-Rule	sol89	1989	only	-	Apr	13	12:00:35s -0:00:35 -
-Rule	sol89	1989	only	-	Apr	14	12:00:20s -0:00:20 -
-Rule	sol89	1989	only	-	Apr	15	12:00:05s -0:00:05 -
-Rule	sol89	1989	only	-	Apr	16	11:59:50s 0:00:10 -
-Rule	sol89	1989	only	-	Apr	17	11:59:35s 0:00:25 -
-Rule	sol89	1989	only	-	Apr	18	11:59:20s 0:00:40 -
-Rule	sol89	1989	only	-	Apr	19	11:59:10s 0:00:50 -
-Rule	sol89	1989	only	-	Apr	20	11:58:55s 0:01:05 -
-Rule	sol89	1989	only	-	Apr	21	11:58:45s 0:01:15 -
-Rule	sol89	1989	only	-	Apr	22	11:58:30s 0:01:30 -
-Rule	sol89	1989	only	-	Apr	23	11:58:20s 0:01:40 -
-Rule	sol89	1989	only	-	Apr	24	11:58:10s 0:01:50 -
-Rule	sol89	1989	only	-	Apr	25	11:58:00s 0:02:00 -
-Rule	sol89	1989	only	-	Apr	26	11:57:50s 0:02:10 -
-Rule	sol89	1989	only	-	Apr	27	11:57:40s 0:02:20 -
-Rule	sol89	1989	only	-	Apr	28	11:57:30s 0:02:30 -
-Rule	sol89	1989	only	-	Apr	29	11:57:20s 0:02:40 -
-Rule	sol89	1989	only	-	Apr	30	11:57:15s 0:02:45 -
-Rule	sol89	1989	only	-	May	1	11:57:05s 0:02:55 -
-Rule	sol89	1989	only	-	May	2	11:57:00s 0:03:00 -
-Rule	sol89	1989	only	-	May	3	11:56:50s 0:03:10 -
-Rule	sol89	1989	only	-	May	4	11:56:45s 0:03:15 -
-Rule	sol89	1989	only	-	May	5	11:56:40s 0:03:20 -
-Rule	sol89	1989	only	-	May	6	11:56:35s 0:03:25 -
-Rule	sol89	1989	only	-	May	7	11:56:30s 0:03:30 -
-Rule	sol89	1989	only	-	May	8	11:56:30s 0:03:30 -
-Rule	sol89	1989	only	-	May	9	11:56:25s 0:03:35 -
-Rule	sol89	1989	only	-	May	10	11:56:25s 0:03:35 -
-Rule	sol89	1989	only	-	May	11	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	12	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	13	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	14	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	15	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	16	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	17	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	May	18	11:56:25s 0:03:35 -
-Rule	sol89	1989	only	-	May	19	11:56:25s 0:03:35 -
-Rule	sol89	1989	only	-	May	20	11:56:30s 0:03:30 -
-Rule	sol89	1989	only	-	May	21	11:56:35s 0:03:25 -
-Rule	sol89	1989	only	-	May	22	11:56:35s 0:03:25 -
-Rule	sol89	1989	only	-	May	23	11:56:40s 0:03:20 -
-Rule	sol89	1989	only	-	May	24	11:56:45s 0:03:15 -
-Rule	sol89	1989	only	-	May	25	11:56:55s 0:03:05 -
-Rule	sol89	1989	only	-	May	26	11:57:00s 0:03:00 -
-Rule	sol89	1989	only	-	May	27	11:57:05s 0:02:55 -
-Rule	sol89	1989	only	-	May	28	11:57:15s 0:02:45 -
-Rule	sol89	1989	only	-	May	29	11:57:20s 0:02:40 -
-Rule	sol89	1989	only	-	May	30	11:57:30s 0:02:30 -
-Rule	sol89	1989	only	-	May	31	11:57:35s 0:02:25 -
-Rule	sol89	1989	only	-	Jun	1	11:57:45s 0:02:15 -
-Rule	sol89	1989	only	-	Jun	2	11:57:55s 0:02:05 -
-Rule	sol89	1989	only	-	Jun	3	11:58:05s 0:01:55 -
-Rule	sol89	1989	only	-	Jun	4	11:58:15s 0:01:45 -
-Rule	sol89	1989	only	-	Jun	5	11:58:25s 0:01:35 -
-Rule	sol89	1989	only	-	Jun	6	11:58:35s 0:01:25 -
-Rule	sol89	1989	only	-	Jun	7	11:58:45s 0:01:15 -
-Rule	sol89	1989	only	-	Jun	8	11:59:00s 0:01:00 -
-Rule	sol89	1989	only	-	Jun	9	11:59:10s 0:00:50 -
-Rule	sol89	1989	only	-	Jun	10	11:59:20s 0:00:40 -
-Rule	sol89	1989	only	-	Jun	11	11:59:35s 0:00:25 -
-Rule	sol89	1989	only	-	Jun	12	11:59:45s 0:00:15 -
-Rule	sol89	1989	only	-	Jun	13	12:00:00s 0:00:00 -
-Rule	sol89	1989	only	-	Jun	14	12:00:10s -0:00:10 -
-Rule	sol89	1989	only	-	Jun	15	12:00:25s -0:00:25 -
-Rule	sol89	1989	only	-	Jun	16	12:00:35s -0:00:35 -
-Rule	sol89	1989	only	-	Jun	17	12:00:50s -0:00:50 -
-Rule	sol89	1989	only	-	Jun	18	12:01:05s -0:01:05 -
-Rule	sol89	1989	only	-	Jun	19	12:01:15s -0:01:15 -
-Rule	sol89	1989	only	-	Jun	20	12:01:30s -0:01:30 -
-Rule	sol89	1989	only	-	Jun	21	12:01:40s -0:01:40 -
-Rule	sol89	1989	only	-	Jun	22	12:01:55s -0:01:55 -
-Rule	sol89	1989	only	-	Jun	23	12:02:10s -0:02:10 -
-Rule	sol89	1989	only	-	Jun	24	12:02:20s -0:02:20 -
-Rule	sol89	1989	only	-	Jun	25	12:02:35s -0:02:35 -
-Rule	sol89	1989	only	-	Jun	26	12:02:45s -0:02:45 -
-Rule	sol89	1989	only	-	Jun	27	12:03:00s -0:03:00 -
-Rule	sol89	1989	only	-	Jun	28	12:03:10s -0:03:10 -
-Rule	sol89	1989	only	-	Jun	29	12:03:25s -0:03:25 -
-Rule	sol89	1989	only	-	Jun	30	12:03:35s -0:03:35 -
-Rule	sol89	1989	only	-	Jul	1	12:03:45s -0:03:45 -
-Rule	sol89	1989	only	-	Jul	2	12:04:00s -0:04:00 -
-Rule	sol89	1989	only	-	Jul	3	12:04:10s -0:04:10 -
-Rule	sol89	1989	only	-	Jul	4	12:04:20s -0:04:20 -
-Rule	sol89	1989	only	-	Jul	5	12:04:30s -0:04:30 -
-Rule	sol89	1989	only	-	Jul	6	12:04:40s -0:04:40 -
-Rule	sol89	1989	only	-	Jul	7	12:04:50s -0:04:50 -
-Rule	sol89	1989	only	-	Jul	8	12:05:00s -0:05:00 -
-Rule	sol89	1989	only	-	Jul	9	12:05:10s -0:05:10 -
-Rule	sol89	1989	only	-	Jul	10	12:05:20s -0:05:20 -
-Rule	sol89	1989	only	-	Jul	11	12:05:25s -0:05:25 -
-Rule	sol89	1989	only	-	Jul	12	12:05:35s -0:05:35 -
-Rule	sol89	1989	only	-	Jul	13	12:05:40s -0:05:40 -
-Rule	sol89	1989	only	-	Jul	14	12:05:50s -0:05:50 -
-Rule	sol89	1989	only	-	Jul	15	12:05:55s -0:05:55 -
-Rule	sol89	1989	only	-	Jul	16	12:06:00s -0:06:00 -
-Rule	sol89	1989	only	-	Jul	17	12:06:05s -0:06:05 -
-Rule	sol89	1989	only	-	Jul	18	12:06:10s -0:06:10 -
-Rule	sol89	1989	only	-	Jul	19	12:06:15s -0:06:15 -
-Rule	sol89	1989	only	-	Jul	20	12:06:20s -0:06:20 -
-Rule	sol89	1989	only	-	Jul	21	12:06:20s -0:06:20 -
-Rule	sol89	1989	only	-	Jul	22	12:06:25s -0:06:25 -
-Rule	sol89	1989	only	-	Jul	23	12:06:25s -0:06:25 -
-Rule	sol89	1989	only	-	Jul	24	12:06:30s -0:06:30 -
-Rule	sol89	1989	only	-	Jul	25	12:06:30s -0:06:30 -
-Rule	sol89	1989	only	-	Jul	26	12:06:30s -0:06:30 -
-Rule	sol89	1989	only	-	Jul	27	12:06:30s -0:06:30 -
-Rule	sol89	1989	only	-	Jul	28	12:06:30s -0:06:30 -
-Rule	sol89	1989	only	-	Jul	29	12:06:25s -0:06:25 -
-Rule	sol89	1989	only	-	Jul	30	12:06:25s -0:06:25 -
-Rule	sol89	1989	only	-	Jul	31	12:06:20s -0:06:20 -
-Rule	sol89	1989	only	-	Aug	1	12:06:20s -0:06:20 -
-Rule	sol89	1989	only	-	Aug	2	12:06:15s -0:06:15 -
-Rule	sol89	1989	only	-	Aug	3	12:06:10s -0:06:10 -
-Rule	sol89	1989	only	-	Aug	4	12:06:05s -0:06:05 -
-Rule	sol89	1989	only	-	Aug	5	12:06:00s -0:06:00 -
-Rule	sol89	1989	only	-	Aug	6	12:05:50s -0:05:50 -
-Rule	sol89	1989	only	-	Aug	7	12:05:45s -0:05:45 -
-Rule	sol89	1989	only	-	Aug	8	12:05:35s -0:05:35 -
-Rule	sol89	1989	only	-	Aug	9	12:05:30s -0:05:30 -
-Rule	sol89	1989	only	-	Aug	10	12:05:20s -0:05:20 -
-Rule	sol89	1989	only	-	Aug	11	12:05:10s -0:05:10 -
-Rule	sol89	1989	only	-	Aug	12	12:05:00s -0:05:00 -
-Rule	sol89	1989	only	-	Aug	13	12:04:50s -0:04:50 -
-Rule	sol89	1989	only	-	Aug	14	12:04:40s -0:04:40 -
-Rule	sol89	1989	only	-	Aug	15	12:04:30s -0:04:30 -
-Rule	sol89	1989	only	-	Aug	16	12:04:15s -0:04:15 -
-Rule	sol89	1989	only	-	Aug	17	12:04:05s -0:04:05 -
-Rule	sol89	1989	only	-	Aug	18	12:03:50s -0:03:50 -
-Rule	sol89	1989	only	-	Aug	19	12:03:35s -0:03:35 -
-Rule	sol89	1989	only	-	Aug	20	12:03:25s -0:03:25 -
-Rule	sol89	1989	only	-	Aug	21	12:03:10s -0:03:10 -
-Rule	sol89	1989	only	-	Aug	22	12:02:55s -0:02:55 -
-Rule	sol89	1989	only	-	Aug	23	12:02:40s -0:02:40 -
-Rule	sol89	1989	only	-	Aug	24	12:02:20s -0:02:20 -
-Rule	sol89	1989	only	-	Aug	25	12:02:05s -0:02:05 -
-Rule	sol89	1989	only	-	Aug	26	12:01:50s -0:01:50 -
-Rule	sol89	1989	only	-	Aug	27	12:01:30s -0:01:30 -
-Rule	sol89	1989	only	-	Aug	28	12:01:15s -0:01:15 -
-Rule	sol89	1989	only	-	Aug	29	12:00:55s -0:00:55 -
-Rule	sol89	1989	only	-	Aug	30	12:00:40s -0:00:40 -
-Rule	sol89	1989	only	-	Aug	31	12:00:20s -0:00:20 -
-Rule	sol89	1989	only	-	Sep	1	12:00:00s 0:00:00 -
-Rule	sol89	1989	only	-	Sep	2	11:59:45s 0:00:15 -
-Rule	sol89	1989	only	-	Sep	3	11:59:25s 0:00:35 -
-Rule	sol89	1989	only	-	Sep	4	11:59:05s 0:00:55 -
-Rule	sol89	1989	only	-	Sep	5	11:58:45s 0:01:15 -
-Rule	sol89	1989	only	-	Sep	6	11:58:25s 0:01:35 -
-Rule	sol89	1989	only	-	Sep	7	11:58:05s 0:01:55 -
-Rule	sol89	1989	only	-	Sep	8	11:57:45s 0:02:15 -
-Rule	sol89	1989	only	-	Sep	9	11:57:20s 0:02:40 -
-Rule	sol89	1989	only	-	Sep	10	11:57:00s 0:03:00 -
-Rule	sol89	1989	only	-	Sep	11	11:56:40s 0:03:20 -
-Rule	sol89	1989	only	-	Sep	12	11:56:20s 0:03:40 -
-Rule	sol89	1989	only	-	Sep	13	11:56:00s 0:04:00 -
-Rule	sol89	1989	only	-	Sep	14	11:55:35s 0:04:25 -
-Rule	sol89	1989	only	-	Sep	15	11:55:15s 0:04:45 -
-Rule	sol89	1989	only	-	Sep	16	11:54:55s 0:05:05 -
-Rule	sol89	1989	only	-	Sep	17	11:54:35s 0:05:25 -
-Rule	sol89	1989	only	-	Sep	18	11:54:10s 0:05:50 -
-Rule	sol89	1989	only	-	Sep	19	11:53:50s 0:06:10 -
-Rule	sol89	1989	only	-	Sep	20	11:53:30s 0:06:30 -
-Rule	sol89	1989	only	-	Sep	21	11:53:10s 0:06:50 -
-Rule	sol89	1989	only	-	Sep	22	11:52:45s 0:07:15 -
-Rule	sol89	1989	only	-	Sep	23	11:52:25s 0:07:35 -
-Rule	sol89	1989	only	-	Sep	24	11:52:05s 0:07:55 -
-Rule	sol89	1989	only	-	Sep	25	11:51:45s 0:08:15 -
-Rule	sol89	1989	only	-	Sep	26	11:51:25s 0:08:35 -
-Rule	sol89	1989	only	-	Sep	27	11:51:05s 0:08:55 -
-Rule	sol89	1989	only	-	Sep	28	11:50:40s 0:09:20 -
-Rule	sol89	1989	only	-	Sep	29	11:50:20s 0:09:40 -
-Rule	sol89	1989	only	-	Sep	30	11:50:00s 0:10:00 -
-Rule	sol89	1989	only	-	Oct	1	11:49:45s 0:10:15 -
-Rule	sol89	1989	only	-	Oct	2	11:49:25s 0:10:35 -
-Rule	sol89	1989	only	-	Oct	3	11:49:05s 0:10:55 -
-Rule	sol89	1989	only	-	Oct	4	11:48:45s 0:11:15 -
-Rule	sol89	1989	only	-	Oct	5	11:48:30s 0:11:30 -
-Rule	sol89	1989	only	-	Oct	6	11:48:10s 0:11:50 -
-Rule	sol89	1989	only	-	Oct	7	11:47:50s 0:12:10 -
-Rule	sol89	1989	only	-	Oct	8	11:47:35s 0:12:25 -
-Rule	sol89	1989	only	-	Oct	9	11:47:20s 0:12:40 -
-Rule	sol89	1989	only	-	Oct	10	11:47:00s 0:13:00 -
-Rule	sol89	1989	only	-	Oct	11	11:46:45s 0:13:15 -
-Rule	sol89	1989	only	-	Oct	12	11:46:30s 0:13:30 -
-Rule	sol89	1989	only	-	Oct	13	11:46:15s 0:13:45 -
-Rule	sol89	1989	only	-	Oct	14	11:46:00s 0:14:00 -
-Rule	sol89	1989	only	-	Oct	15	11:45:50s 0:14:10 -
-Rule	sol89	1989	only	-	Oct	16	11:45:35s 0:14:25 -
-Rule	sol89	1989	only	-	Oct	17	11:45:20s 0:14:40 -
-Rule	sol89	1989	only	-	Oct	18	11:45:10s 0:14:50 -
-Rule	sol89	1989	only	-	Oct	19	11:45:00s 0:15:00 -
-Rule	sol89	1989	only	-	Oct	20	11:44:50s 0:15:10 -
-Rule	sol89	1989	only	-	Oct	21	11:44:40s 0:15:20 -
-Rule	sol89	1989	only	-	Oct	22	11:44:30s 0:15:30 -
-Rule	sol89	1989	only	-	Oct	23	11:44:20s 0:15:40 -
-Rule	sol89	1989	only	-	Oct	24	11:44:10s 0:15:50 -
-Rule	sol89	1989	only	-	Oct	25	11:44:05s 0:15:55 -
-Rule	sol89	1989	only	-	Oct	26	11:44:00s 0:16:00 -
-Rule	sol89	1989	only	-	Oct	27	11:43:50s 0:16:10 -
-Rule	sol89	1989	only	-	Oct	28	11:43:45s 0:16:15 -
-Rule	sol89	1989	only	-	Oct	29	11:43:40s 0:16:20 -
-Rule	sol89	1989	only	-	Oct	30	11:43:40s 0:16:20 -
-Rule	sol89	1989	only	-	Oct	31	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	1	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	2	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	3	11:43:30s 0:16:30 -
-Rule	sol89	1989	only	-	Nov	4	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	5	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	6	11:43:35s 0:16:25 -
-Rule	sol89	1989	only	-	Nov	7	11:43:40s 0:16:20 -
-Rule	sol89	1989	only	-	Nov	8	11:43:45s 0:16:15 -
-Rule	sol89	1989	only	-	Nov	9	11:43:50s 0:16:10 -
-Rule	sol89	1989	only	-	Nov	10	11:43:55s 0:16:05 -
-Rule	sol89	1989	only	-	Nov	11	11:44:00s 0:16:00 -
-Rule	sol89	1989	only	-	Nov	12	11:44:05s 0:15:55 -
-Rule	sol89	1989	only	-	Nov	13	11:44:15s 0:15:45 -
-Rule	sol89	1989	only	-	Nov	14	11:44:25s 0:15:35 -
-Rule	sol89	1989	only	-	Nov	15	11:44:35s 0:15:25 -
-Rule	sol89	1989	only	-	Nov	16	11:44:45s 0:15:15 -
-Rule	sol89	1989	only	-	Nov	17	11:44:55s 0:15:05 -
-Rule	sol89	1989	only	-	Nov	18	11:45:10s 0:14:50 -
-Rule	sol89	1989	only	-	Nov	19	11:45:20s 0:14:40 -
-Rule	sol89	1989	only	-	Nov	20	11:45:35s 0:14:25 -
-Rule	sol89	1989	only	-	Nov	21	11:45:50s 0:14:10 -
-Rule	sol89	1989	only	-	Nov	22	11:46:05s 0:13:55 -
-Rule	sol89	1989	only	-	Nov	23	11:46:25s 0:13:35 -
-Rule	sol89	1989	only	-	Nov	24	11:46:40s 0:13:20 -
-Rule	sol89	1989	only	-	Nov	25	11:47:00s 0:13:00 -
-Rule	sol89	1989	only	-	Nov	26	11:47:20s 0:12:40 -
-Rule	sol89	1989	only	-	Nov	27	11:47:35s 0:12:25 -
-Rule	sol89	1989	only	-	Nov	28	11:47:55s 0:12:05 -
-Rule	sol89	1989	only	-	Nov	29	11:48:20s 0:11:40 -
-Rule	sol89	1989	only	-	Nov	30	11:48:40s 0:11:20 -
-Rule	sol89	1989	only	-	Dec	1	11:49:00s 0:11:00 -
-Rule	sol89	1989	only	-	Dec	2	11:49:25s 0:10:35 -
-Rule	sol89	1989	only	-	Dec	3	11:49:50s 0:10:10 -
-Rule	sol89	1989	only	-	Dec	4	11:50:15s 0:09:45 -
-Rule	sol89	1989	only	-	Dec	5	11:50:35s 0:09:25 -
-Rule	sol89	1989	only	-	Dec	6	11:51:00s 0:09:00 -
-Rule	sol89	1989	only	-	Dec	7	11:51:30s 0:08:30 -
-Rule	sol89	1989	only	-	Dec	8	11:51:55s 0:08:05 -
-Rule	sol89	1989	only	-	Dec	9	11:52:20s 0:07:40 -
-Rule	sol89	1989	only	-	Dec	10	11:52:50s 0:07:10 -
-Rule	sol89	1989	only	-	Dec	11	11:53:15s 0:06:45 -
-Rule	sol89	1989	only	-	Dec	12	11:53:45s 0:06:15 -
-Rule	sol89	1989	only	-	Dec	13	11:54:10s 0:05:50 -
-Rule	sol89	1989	only	-	Dec	14	11:54:40s 0:05:20 -
-Rule	sol89	1989	only	-	Dec	15	11:55:10s 0:04:50 -
-Rule	sol89	1989	only	-	Dec	16	11:55:40s 0:04:20 -
-Rule	sol89	1989	only	-	Dec	17	11:56:05s 0:03:55 -
-Rule	sol89	1989	only	-	Dec	18	11:56:35s 0:03:25 -
-Rule	sol89	1989	only	-	Dec	19	11:57:05s 0:02:55 -
-Rule	sol89	1989	only	-	Dec	20	11:57:35s 0:02:25 -
-Rule	sol89	1989	only	-	Dec	21	11:58:05s 0:01:55 -
-Rule	sol89	1989	only	-	Dec	22	11:58:35s 0:01:25 -
-Rule	sol89	1989	only	-	Dec	23	11:59:05s 0:00:55 -
-Rule	sol89	1989	only	-	Dec	24	11:59:35s 0:00:25 -
-Rule	sol89	1989	only	-	Dec	25	12:00:05s -0:00:05 -
-Rule	sol89	1989	only	-	Dec	26	12:00:35s -0:00:35 -
-Rule	sol89	1989	only	-	Dec	27	12:01:05s -0:01:05 -
-Rule	sol89	1989	only	-	Dec	28	12:01:35s -0:01:35 -
-Rule	sol89	1989	only	-	Dec	29	12:02:00s -0:02:00 -
-Rule	sol89	1989	only	-	Dec	30	12:02:30s -0:02:30 -
-Rule	sol89	1989	only	-	Dec	31	12:03:00s -0:03:00 -
-
-# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
-# Before and after 1989, we'll operate on local mean solar time.
-
-# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
-Zone	Asia/Riyadh89	3:07:04	-		zzz	1989
-			3:07:04	sol89		zzz	1990
-			3:07:04	-		zzz
-# For backward compatibility...
-Link	Asia/Riyadh89	Mideast/Riyadh89

From 7455eb71a1727afb5280a732433f28f233c6706d Mon Sep 17 00:00:00 2001
From: Alexander Motin 
Date: Thu, 19 Dec 2013 21:31:28 +0000
Subject: [PATCH 169/172] Rework flow control for connection-oriented (TCP) RPC
 server.

  When processing receive buffer, write the amount of data, expected
in present request record, into socket's so_rcv.sb_lowat to make stack
aware about our needs.  When processing following upcalls, ignore them
until socket collect enough data to be read and processed in one turn.
  This change reduces number of context switches and other operations
in RPC stack during large NFS writes (especially via non-Jumbo networks)
by order of magnitude.

  After precessing current packet, take another look into the pending
buffer to find out whether the next packet had been already received.
If not, deactivate this port right there without making RPC code to
push this port to another thread just to find that there is nothing.
If the next packet is received partially, also deactivate the port, but
also update socket's so_rcv.sb_lowat to not be woken up prematurely.
  This change additionally reduces number of context switches per NFS
request about in half.
---
 sys/rpc/svc_vc.c | 241 ++++++++++++++++++++++-------------------------
 1 file changed, 114 insertions(+), 127 deletions(-)

diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index 8298c9589fc8..0adb3fdfbba2 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -381,15 +381,11 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 		 * We must re-test for new connections after taking
 		 * the lock to protect us in the case where a new
 		 * connection arrives after our call to accept fails
-		 * with EWOULDBLOCK. The pool lock protects us from
-		 * racing the upcall after our TAILQ_EMPTY() call
-		 * returns false.
+		 * with EWOULDBLOCK.
 		 */
 		ACCEPT_LOCK();
-		mtx_lock(&xprt->xp_pool->sp_lock);
 		if (TAILQ_EMPTY(&xprt->xp_socket->so_comp))
-			xprt_inactive_locked(xprt);
-		mtx_unlock(&xprt->xp_pool->sp_lock);
+			xprt_inactive(xprt);
 		ACCEPT_UNLOCK();
 		sx_xunlock(&xprt->xp_lock);
 		return (FALSE);
@@ -526,35 +522,14 @@ static enum xprt_stat
 svc_vc_stat(SVCXPRT *xprt)
 {
 	struct cf_conn *cd;
-	struct mbuf *m;
-	size_t n;
 
 	cd = (struct cf_conn *)(xprt->xp_p1);
 
 	if (cd->strm_stat == XPRT_DIED)
 		return (XPRT_DIED);
 
-	/*
-	 * Return XPRT_MOREREQS if we have buffered data and we are
-	 * mid-record or if we have enough data for a record
-	 * marker. Since this is only a hint, we read mpending and
-	 * resid outside the lock. We do need to take the lock if we
-	 * have to traverse the mbuf chain.
-	 */
-	if (cd->mpending) {
-		if (cd->resid)
-			return (XPRT_MOREREQS);
-		n = 0;
-		sx_xlock(&xprt->xp_lock);
-		m = cd->mpending;
-		while (m && n < sizeof(uint32_t)) {
-			n += m->m_len;
-			m = m->m_next;
-		}
-		sx_xunlock(&xprt->xp_lock);
-		if (n >= sizeof(uint32_t))
-			return (XPRT_MOREREQS);
-	}
+	if (cd->mreq != NULL && cd->resid == 0 && cd->eor)
+		return (XPRT_MOREREQS);
 
 	if (soreadable(xprt->xp_socket))
 		return (XPRT_MOREREQS);
@@ -575,6 +550,78 @@ svc_vc_backchannel_stat(SVCXPRT *xprt)
 	return (XPRT_IDLE);
 }
 
+/*
+ * If we have an mbuf chain in cd->mpending, try to parse a record from it,
+ * leaving the result in cd->mreq. If we don't have a complete record, leave
+ * the partial result in cd->mreq and try to read more from the socket.
+ */
+static void
+svc_vc_process_pending(SVCXPRT *xprt)
+{
+	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
+	struct socket *so = xprt->xp_socket;
+	struct mbuf *m;
+
+	/*
+	 * If cd->resid is non-zero, we have part of the
+	 * record already, otherwise we are expecting a record
+	 * marker.
+	 */
+	if (!cd->resid && cd->mpending) {
+		/*
+		 * See if there is enough data buffered to
+		 * make up a record marker. Make sure we can
+		 * handle the case where the record marker is
+		 * split across more than one mbuf.
+		 */
+		size_t n = 0;
+		uint32_t header;
+
+		m = cd->mpending;
+		while (n < sizeof(uint32_t) && m) {
+			n += m->m_len;
+			m = m->m_next;
+		}
+		if (n < sizeof(uint32_t)) {
+			so->so_rcv.sb_lowat = sizeof(uint32_t) - n;
+			return;
+		}
+		m_copydata(cd->mpending, 0, sizeof(header),
+		    (char *)&header);
+		header = ntohl(header);
+		cd->eor = (header & 0x80000000) != 0;
+		cd->resid = header & 0x7fffffff;
+		m_adj(cd->mpending, sizeof(uint32_t));
+	}
+
+	/*
+	 * Start pulling off mbufs from cd->mpending
+	 * until we either have a complete record or
+	 * we run out of data. We use m_split to pull
+	 * data - it will pull as much as possible and
+	 * split the last mbuf if necessary.
+	 */
+	while (cd->mpending && cd->resid) {
+		m = cd->mpending;
+		if (cd->mpending->m_next
+		    || cd->mpending->m_len > cd->resid)
+			cd->mpending = m_split(cd->mpending,
+			    cd->resid, M_WAITOK);
+		else
+			cd->mpending = NULL;
+		if (cd->mreq)
+			m_last(cd->mreq)->m_next = m;
+		else
+			cd->mreq = m;
+		while (m) {
+			cd->resid -= m->m_len;
+			m = m->m_next;
+		}
+	}
+
+	so->so_rcv.sb_lowat = imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2));
+}
+
 static bool_t
 svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
     struct sockaddr **addrp, struct mbuf **mp)
@@ -582,6 +629,7 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
 	struct uio uio;
 	struct mbuf *m;
+	struct socket* so = xprt->xp_socket;
 	XDR xdrs;
 	int error, rcvflag;
 
@@ -592,99 +640,40 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 	sx_xlock(&xprt->xp_lock);
 
 	for (;;) {
-		/*
-		 * If we have an mbuf chain in cd->mpending, try to parse a
-		 * record from it, leaving the result in cd->mreq. If we don't
-		 * have a complete record, leave the partial result in
-		 * cd->mreq and try to read more from the socket.
-		 */
-		if (cd->mpending) {
-			/*
-			 * If cd->resid is non-zero, we have part of the
-			 * record already, otherwise we are expecting a record
-			 * marker.
-			 */
-			if (!cd->resid) {
-				/*
-				 * See if there is enough data buffered to
-				 * make up a record marker. Make sure we can
-				 * handle the case where the record marker is
-				 * split across more than one mbuf.
-				 */
-				size_t n = 0;
-				uint32_t header;
+		/* If we have no request ready, check pending queue. */
+		while (cd->mpending &&
+		    (cd->mreq == NULL || cd->resid != 0 || !cd->eor))
+			svc_vc_process_pending(xprt);
 
-				m = cd->mpending;
-				while (n < sizeof(uint32_t) && m) {
-					n += m->m_len;
-					m = m->m_next;
-				}
-				if (n < sizeof(uint32_t))
-					goto readmore;
-				m_copydata(cd->mpending, 0, sizeof(header),
-				    (char *)&header);
-				header = ntohl(header);
-				cd->eor = (header & 0x80000000) != 0;
-				cd->resid = header & 0x7fffffff;
-				m_adj(cd->mpending, sizeof(uint32_t));
+		/* Process and return complete request in cd->mreq. */
+		if (cd->mreq != NULL && cd->resid == 0 && cd->eor) {
+
+			xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
+			cd->mreq = NULL;
+
+			/* Check for next request in a pending queue. */
+			svc_vc_process_pending(xprt);
+			if (cd->mreq == NULL || cd->resid != 0) {
+				SOCKBUF_LOCK(&so->so_rcv);
+				if (!soreadable(so))
+					xprt_inactive(xprt);
+				SOCKBUF_UNLOCK(&so->so_rcv);
 			}
 
-			/*
-			 * Start pulling off mbufs from cd->mpending
-			 * until we either have a complete record or
-			 * we run out of data. We use m_split to pull
-			 * data - it will pull as much as possible and
-			 * split the last mbuf if necessary.
-			 */
-			while (cd->mpending && cd->resid) {
-				m = cd->mpending;
-				if (cd->mpending->m_next
-				    || cd->mpending->m_len > cd->resid)
-					cd->mpending = m_split(cd->mpending,
-					    cd->resid, M_WAITOK);
-				else
-					cd->mpending = NULL;
-				if (cd->mreq)
-					m_last(cd->mreq)->m_next = m;
-				else
-					cd->mreq = m;
-				while (m) {
-					cd->resid -= m->m_len;
-					m = m->m_next;
-				}
-			}
+			sx_xunlock(&xprt->xp_lock);
 
-			/*
-			 * If cd->resid is zero now, we have managed to
-			 * receive a record fragment from the stream. Check
-			 * for the end-of-record mark to see if we need more.
-			 */
-			if (cd->resid == 0) {
-				if (!cd->eor)
-					continue;
-
-				/*
-				 * Success - we have a complete record in
-				 * cd->mreq.
-				 */
-				xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
-				cd->mreq = NULL;
-				sx_xunlock(&xprt->xp_lock);
-
-				if (! xdr_callmsg(&xdrs, msg)) {
-					XDR_DESTROY(&xdrs);
-					return (FALSE);
-				}
-
-				*addrp = NULL;
-				*mp = xdrmbuf_getall(&xdrs);
+			if (! xdr_callmsg(&xdrs, msg)) {
 				XDR_DESTROY(&xdrs);
-
-				return (TRUE);
+				return (FALSE);
 			}
+
+			*addrp = NULL;
+			*mp = xdrmbuf_getall(&xdrs);
+			XDR_DESTROY(&xdrs);
+
+			return (TRUE);
 		}
 
-	readmore:
 		/*
 		 * The socket upcall calls xprt_active() which will eventually
 		 * cause the server to call us here. We attempt to
@@ -697,8 +686,7 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 		uio.uio_td = curthread;
 		m = NULL;
 		rcvflag = MSG_DONTWAIT;
-		error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL,
-		    &rcvflag);
+		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
 
 		if (error == EWOULDBLOCK) {
 			/*
@@ -706,25 +694,23 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 			 * taking the lock to protect us in the case
 			 * where a new packet arrives on the socket
 			 * after our call to soreceive fails with
-			 * EWOULDBLOCK. The pool lock protects us from
-			 * racing the upcall after our soreadable()
-			 * call returns false.
+			 * EWOULDBLOCK.
 			 */
-			mtx_lock(&xprt->xp_pool->sp_lock);
-			if (!soreadable(xprt->xp_socket))
-				xprt_inactive_locked(xprt);
-			mtx_unlock(&xprt->xp_pool->sp_lock);
+			SOCKBUF_LOCK(&so->so_rcv);
+			if (!soreadable(so))
+				xprt_inactive(xprt);
+			SOCKBUF_UNLOCK(&so->so_rcv);
 			sx_xunlock(&xprt->xp_lock);
 			return (FALSE);
 		}
 
 		if (error) {
-			SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
+			SOCKBUF_LOCK(&so->so_rcv);
 			if (xprt->xp_upcallset) {
 				xprt->xp_upcallset = 0;
-				soupcall_clear(xprt->xp_socket, SO_RCV);
+				soupcall_clear(so, SO_RCV);
 			}
-			SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
+			SOCKBUF_UNLOCK(&so->so_rcv);
 			xprt_inactive(xprt);
 			cd->strm_stat = XPRT_DIED;
 			sx_xunlock(&xprt->xp_lock);
@@ -908,7 +894,8 @@ svc_vc_soupcall(struct socket *so, void *arg, int waitflag)
 {
 	SVCXPRT *xprt = (SVCXPRT *) arg;
 
-	xprt_active(xprt);
+	if (soreadable(xprt->xp_socket))
+		xprt_active(xprt);
 	return (SU_OK);
 }
 

From 774e8d906fab53914fed5248cc1278c7439abd91 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20E=C3=9Fer?= 
Date: Thu, 19 Dec 2013 21:35:33 +0000
Subject: [PATCH 170/172] Fix compilation on 32 bit architectures and use
 INT64_MAX instead of LONG_MAX for the upper bound check.

---
 sys/kern/kern_event.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 3981dcb30925..4113dc1fbe1a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -523,11 +523,14 @@ knote_fork(struct knlist *list, int pid)
  * XXX: EVFILT_TIMER should perhaps live in kern_time.c beside the
  * interval timer support code.
  */
-static __inline sbintime_t 
+static __inline sbintime_t
 timer2sbintime(intptr_t data)
 {
-	if (data > LLONG_MAX / SBT_1MS)
-		return LLONG_MAX;
+
+#ifdef __LP64__
+	if (data > INT64_MAX / SBT_1MS)
+		return INT64_MAX;
+#endif
 	return (SBT_1MS * data);
 }
 

From 7c5710dbaf3dd64ba2b9fe7e16b32b5fdc5c83bd Mon Sep 17 00:00:00 2001
From: "Andrey V. Elsukov" 
Date: Thu, 19 Dec 2013 22:13:12 +0000
Subject: [PATCH 171/172] Prevent users from deactivating the last component of
 a mirror.

PR:		184985
MFC after:	1 week
---
 sys/geom/mirror/g_mirror_ctl.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c
index 1748d7b9d6b1..29bc56c62c33 100644
--- a/sys/geom/mirror/g_mirror_ctl.c
+++ b/sys/geom/mirror/g_mirror_ctl.c
@@ -695,7 +695,7 @@ g_mirror_ctl_deactivate(struct gctl_req *req, struct g_class *mp)
 	const char *name;
 	char param[16];
 	int *nargs;
-	u_int i;
+	u_int i, active;
 
 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
 	if (nargs == NULL) {
@@ -716,6 +716,7 @@ g_mirror_ctl_deactivate(struct gctl_req *req, struct g_class *mp)
 		gctl_error(req, "No such device: %s.", name);
 		return;
 	}
+	active = g_mirror_ndisks(sc, G_MIRROR_DISK_STATE_ACTIVE);
 	for (i = 1; i < (u_int)*nargs; i++) {
 		snprintf(param, sizeof(param), "arg%u", i);
 		name = gctl_get_asciiparam(req, param);
@@ -728,6 +729,16 @@ g_mirror_ctl_deactivate(struct gctl_req *req, struct g_class *mp)
 			gctl_error(req, "No such provider: %s.", name);
 			continue;
 		}
+		if (disk->d_state == G_MIRROR_DISK_STATE_ACTIVE) {
+			if (active > 1)
+				active--;
+			else {
+				gctl_error(req, "%s: Can't deactivate the "
+				    "last ACTIVE component %s.",
+				    sc->sc_geom->name, name);
+				continue;
+			}
+		}
 		disk->d_flags |= G_MIRROR_DISK_FLAG_INACTIVE;
 		disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC;
 		g_mirror_update_metadata(disk);

From 851d84f1b536fa6a9ac4f028dd4445d822ae875b Mon Sep 17 00:00:00 2001
From: Neel Natu 
Date: Thu, 19 Dec 2013 22:27:28 +0000
Subject: [PATCH 172/172] Add an option to ignore accesses by the guest to
 unimplemented MSRs.

Also, ignore a couple of SandyBridge uncore PMC MSRs that Centos 6.4 writes
to during boot.

Reviewed by:	grehan
---
 usr.sbin/bhyve/bhyve.8    |  4 +++-
 usr.sbin/bhyve/bhyverun.c | 50 ++++++++++++++++++++++++++++++---------
 usr.sbin/bhyve/xmsr.c     | 17 +++++++++++--
 usr.sbin/bhyve/xmsr.h     |  1 +
 4 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index b83211a67f27..8e817cfcab36 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -32,7 +32,7 @@
 .Nd "run a guest operating system inside a virtual machine"
 .Sh SYNOPSIS
 .Nm
-.Op Fl aehAHPW
+.Op Fl aehwAHPW
 .Op Fl c Ar numcpus
 .Op Fl g Ar gdbport
 .Op Fl p Ar pinnedcpu
@@ -229,6 +229,8 @@ Force
 .Nm
 to exit when a guest issues an access to an I/O port that is not emulated.
 This is intended for debug purposes.
+.It Fl w 
+Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes.
 .It Fl h
 Print help message and exit.
 .It Ar vmname
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 0ea2904b6f3c..7afac4938ef6 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -87,6 +87,7 @@ static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
 static int virtio_msix = 1;
 
 static int strictio;
+static int strictmsr = 1;
 
 static int acpi;
 
@@ -122,7 +123,7 @@ usage(int code)
 {
 
         fprintf(stderr,
-                "Usage: %s [-aehAHIPW] [-g ] [-s ] [-S ]\n"
+                "Usage: %s [-aehwAHIPW] [-g ] [-s ] [-S ]\n"
 		"       %*s [-c vcpus] [-p pincpu] [-m mem] [-l ] \n"
 		"       -a: local apic is in XAPIC mode (default is X2APIC)\n"
 		"       -A: create an ACPI table\n"
@@ -137,7 +138,8 @@ usage(int code)
 		"       -s:  PCI slot config\n"
 		"       -S:  legacy PCI slot config\n"
 		"       -l: LPC device configuration\n"
-		"       -m: memory size in MB\n",
+		"       -m: memory size in MB\n"
+		"       -w: ignore unimplemented MSRs\n",
 		progname, (int)strlen(progname), "");
 
 	exit(code);
@@ -310,20 +312,43 @@ vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 static int
 vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
-	fprintf(stderr, "vm exit rdmsr 0x%x, cpu %d\n", vme->u.msr.code,
-	    *pvcpu);
-	return (VMEXIT_ABORT);
+	uint64_t val;
+	uint32_t eax, edx;
+	int error;
+
+	val = 0;
+	error = emulate_rdmsr(ctx, *pvcpu, vme->u.msr.code, &val);
+	if (error != 0) {
+		fprintf(stderr, "rdmsr to register %#x on vcpu %d\n",
+		    vme->u.msr.code, *pvcpu);
+		if (strictmsr)
+			return (VMEXIT_ABORT);
+	}
+
+	eax = val;
+	error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RAX, eax);
+	assert(error == 0);
+
+	edx = val >> 32;
+	error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RDX, edx);
+	assert(error == 0);
+
+	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
-	int newcpu;
-	int retval = VMEXIT_CONTINUE;
+	int error;
 
-	newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
-
-        return (retval);
+	error = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code, vme->u.msr.wval);
+	if (error != 0) {
+		fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n",
+		    vme->u.msr.code, vme->u.msr.wval, *pvcpu);
+		if (strictmsr)
+			return (VMEXIT_ABORT);
+	}
+	return (VMEXIT_CONTINUE);
 }
 
 static int
@@ -577,7 +602,7 @@ main(int argc, char *argv[])
 	guest_ncpus = 1;
 	memsize = 256 * MB;
 
-	while ((c = getopt(argc, argv, "abehAHIPWp:g:c:s:S:m:l:")) != -1) {
+	while ((c = getopt(argc, argv, "abehwAHIPWp:g:c:s:S:m:l:")) != -1) {
 		switch (c) {
 		case 'a':
 			disable_x2apic = 1;
@@ -636,6 +661,9 @@ main(int argc, char *argv[])
 		case 'e':
 			strictio = 1;
 			break;
+		case 'w':
+			strictmsr = 0;
+			break;
 		case 'W':
 			virtio_msix = 0;
 			break;
diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c
index 9c05f0230c9b..ba94125a0900 100644
--- a/usr.sbin/bhyve/xmsr.c
+++ b/usr.sbin/bhyve/xmsr.c
@@ -43,6 +43,19 @@ int
 emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val)
 {
 
-	printf("Unknown WRMSR code %x, val %lx, cpu %d\n", code, val, vcpu);
-	exit(1);
+	switch (code) {
+	case 0xd04:			/* Sandy Bridge uncore PMC MSRs */
+	case 0xc24:
+		return (0);
+	default:
+		break;
+	}
+	return (-1);
+}
+
+int
+emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val)
+{
+
+	return (-1);
 }
diff --git a/usr.sbin/bhyve/xmsr.h b/usr.sbin/bhyve/xmsr.h
index 8cebcea0cd55..b097cf885357 100644
--- a/usr.sbin/bhyve/xmsr.h
+++ b/usr.sbin/bhyve/xmsr.h
@@ -30,5 +30,6 @@
 #define	_XMSR_H_
 
 int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val);
+int emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val);
 
 #endif